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 6declare void @foo(i32 *) 7 8; Test the simple case. 9define 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. 24define 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. 39define 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. 55define 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. 72define 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. 88define 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. 106define 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. 123define 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. 141define void @f9(i32 %limit, i32 *%ptr) { 142; CHECK-LABEL: f9: 143; CHECK-NOT: loc 144; CHECK: lfh 145; CHECK: br %r14 146entry: 147 %easy = call i32 asm "stepa $0", "=h"() 148 %cmp = icmp ule i32 %easy, %limit 149 br i1 %cmp, label %load, label %exit 150 151load: 152 %other = load i32, i32 *%ptr 153 br label %exit 154 155exit: 156 %res = phi i32 [ %easy, %entry ], [ %other, %load ] 157 call void asm sideeffect "stepb $0", "h"(i32 %res) 158 ret void 159} 160