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