Home | History | Annotate | Download | only in SystemZ
      1 ; Test LOCFH.  See comments in asm-18.ll about testing high-word operations.
      2 ;
      3 ; RUN: llc < %s -verify-machineinstrs -mtriple=s390x-linux-gnu -mcpu=z13 \
      4 ; RUN:   -no-integrated-as | FileCheck -allow-deprecated-dag-overlap %s
      5 
      6 declare void @foo(i32 *)
      7 
      8 ; Test the simple case.
      9 define void @f1(i32 *%ptr, i32 %limit) {
     10 ; CHECK-LABEL: f1:
     11 ; CHECK-DAG: stepa [[REG:%r[0-5]]]
     12 ; CHECK-DAG: clfi %r3, 42
     13 ; CHECK: locfhhe [[REG]], 0(%r2)
     14 ; CHECK: br %r14
     15   %easy = call i32 asm "stepa $0", "=h"()
     16   %cond = icmp ult i32 %limit, 42
     17   %other = load i32, i32 *%ptr
     18   %res = select i1 %cond, i32 %easy, i32 %other
     19   call void asm sideeffect "stepb $0", "h"(i32 %res)
     20   ret void
     21 }
     22 
     23 ; ...and again with the operands swapped.
     24 define void @f2(i32 *%ptr, i32 %limit) {
     25 ; CHECK-LABEL: f2:
     26 ; CHECK-DAG: stepa [[REG:%r[0-5]]]
     27 ; CHECK-DAG: clfi %r3, 42
     28 ; CHECK: locfhl [[REG]], 0(%r2)
     29 ; CHECK: br %r14
     30   %easy = call i32 asm "stepa $0", "=h"()
     31   %cond = icmp ult i32 %limit, 42
     32   %other = load i32, i32 *%ptr
     33   %res = select i1 %cond, i32 %other, i32 %easy
     34   call void asm sideeffect "stepb $0", "h"(i32 %res)
     35   ret void
     36 }
     37 
     38 ; Check the high end of the aligned LOC range.
     39 define void @f3(i32 *%base, i32 %limit) {
     40 ; CHECK-LABEL: f3:
     41 ; CHECK-DAG: stepa [[REG:%r[0-5]]]
     42 ; CHECK-DAG: clfi %r3, 42
     43 ; CHECK: locfhhe [[REG]], 524284(%r2)
     44 ; CHECK: br %r14
     45   %easy = call i32 asm "stepa $0", "=h"()
     46   %ptr = getelementptr i32, i32 *%base, i64 131071
     47   %cond = icmp ult i32 %limit, 42
     48   %other = load i32, i32 *%ptr
     49   %res = select i1 %cond, i32 %easy, i32 %other
     50   call void asm sideeffect "stepb $0", "h"(i32 %res)
     51   ret void
     52 }
     53 
     54 ; Check the next word up.  Other sequences besides this one would be OK.
     55 define void @f4(i32 *%base, i32 %limit) {
     56 ; CHECK-LABEL: f4:
     57 ; CHECK-DAG: stepa [[REG:%r[0-5]]]
     58 ; CHECK-DAG: agfi %r2, 524288
     59 ; CHECK-DAG: clfi %r3, 42
     60 ; CHECK: locfhhe [[REG]], 0(%r2)
     61 ; CHECK: br %r14
     62   %easy = call i32 asm "stepa $0", "=h"()
     63   %ptr = getelementptr i32, i32 *%base, i64 131072
     64   %cond = icmp ult i32 %limit, 42
     65   %other = load i32, i32 *%ptr
     66   %res = select i1 %cond, i32 %easy, i32 %other
     67   call void asm sideeffect "stepb $0", "h"(i32 %res)
     68   ret void
     69 }
     70 
     71 ; Check the low end of the LOC range.
     72 define void @f5(i32 *%base, i32 %limit) {
     73 ; CHECK-LABEL: f5:
     74 ; CHECK-DAG: stepa [[REG:%r[0-5]]]
     75 ; CHECK-DAG: clfi %r3, 42
     76 ; CHECK: locfhhe [[REG]], -524288(%r2)
     77 ; CHECK: br %r14
     78   %easy = call i32 asm "stepa $0", "=h"()
     79   %ptr = getelementptr i32, i32 *%base, i64 -131072
     80   %cond = icmp ult i32 %limit, 42
     81   %other = load i32, i32 *%ptr
     82   %res = select i1 %cond, i32 %easy, i32 %other
     83   call void asm sideeffect "stepb $0", "h"(i32 %res)
     84   ret void
     85 }
     86 
     87 ; Check the next word down, with the same comments as f4.
     88 define void @f6(i32 *%base, i32 %limit) {
     89 ; CHECK-LABEL: f6:
     90 ; CHECK-DAG: stepa [[REG:%r[0-5]]]
     91 ; CHECK-DAG: clfi %r3, 42
     92 ; CHECK-DAG: agfi %r2, -524292
     93 ; CHECK-DAG: clfi %r3, 42
     94 ; CHECK: locfhhe [[REG]], 0(%r2)
     95 ; CHECK: br %r14
     96   %easy = call i32 asm "stepa $0", "=h"()
     97   %ptr = getelementptr i32, i32 *%base, i64 -131073
     98   %cond = icmp ult i32 %limit, 42
     99   %other = load i32, i32 *%ptr
    100   %res = select i1 %cond, i32 %easy, i32 %other
    101   call void asm sideeffect "stepb $0", "h"(i32 %res)
    102   ret void
    103 }
    104 
    105 ; Try a frame index base.
    106 define void @f7(i32 %alt, i32 %limit) {
    107 ; CHECK-LABEL: f7:
    108 ; CHECK: brasl %r14, foo@PLT
    109 ; CHECK: stepa [[REG:%r[0-5]]]
    110 ; CHECK: locfhhe [[REG]], {{[0-9]+}}(%r15)
    111 ; CHECK: br %r14
    112   %ptr = alloca i32
    113   call void @foo(i32 *%ptr)
    114   %easy = call i32 asm "stepa $0", "=h"()
    115   %cond = icmp ult i32 %limit, 42
    116   %other = load i32, i32 *%ptr
    117   %res = select i1 %cond, i32 %easy, i32 %other
    118   call void asm sideeffect "stepb $0", "h"(i32 %res)
    119   ret void
    120 }
    121 
    122 ; Try a case when an index is involved.
    123 define void @f8(i32 %limit, i64 %base, i64 %index) {
    124 ; CHECK-LABEL: f8:
    125 ; CHECK-DAG: stepa [[REG:%r[0-5]]]
    126 ; CHECK-DAG: clfi %r2, 42
    127 ; CHECK: locfhhe [[REG]], 0({{%r[1-5]}})
    128 ; CHECK: br %r14
    129   %easy = call i32 asm "stepa $0", "=h"()
    130   %add = add i64 %base, %index
    131   %ptr = inttoptr i64 %add to i32 *
    132   %cond = icmp ult i32 %limit, 42
    133   %other = load i32, i32 *%ptr
    134   %res = select i1 %cond, i32 %easy, i32 %other
    135   call void asm sideeffect "stepb $0", "h"(i32 %res)
    136   ret void
    137 }
    138 
    139 ; Test that conditionally-executed loads do not use LOC, since it is allowed
    140 ; to trap even when the condition is false.
    141 define void @f9(i32 %limit, i32 *%ptr) {
    142 ; CHECK-LABEL: f9:
    143 ; CHECK-NOT: loc
    144 ; CHECK: lfh
    145 ; CHECK: br %r14
    146 entry:
    147   %easy = call i32 asm "stepa $0", "=h"()
    148   %cmp = icmp ule i32 %easy, %limit
    149   br i1 %cmp, label %load, label %exit
    150 
    151 load:
    152   %other = load i32, i32 *%ptr
    153   br label %exit
    154 
    155 exit:
    156   %res = phi i32 [ %easy, %entry ], [ %other, %load ]
    157   call void asm sideeffect "stepb $0", "h"(i32 %res)
    158   ret void
    159 }
    160