1 ; Test 64-bit conditional stores that are presented as selects. 2 ; 3 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s 4 5 declare void @foo(i64 *) 6 7 ; Test with the loaded value first. 8 define void @f1(i64 *%ptr, i64 %alt, i32 %limit) { 9 ; CHECK-LABEL: f1: 10 ; CHECK-NOT: %r2 11 ; CHECK: jl [[LABEL:[^ ]*]] 12 ; CHECK-NOT: %r2 13 ; CHECK: stg %r3, 0(%r2) 14 ; CHECK: [[LABEL]]: 15 ; CHECK: br %r14 16 %cond = icmp ult i32 %limit, 42 17 %orig = load i64 *%ptr 18 %res = select i1 %cond, i64 %orig, i64 %alt 19 store i64 %res, i64 *%ptr 20 ret void 21 } 22 23 ; ...and with the loaded value second 24 define void @f2(i64 *%ptr, i64 %alt, i32 %limit) { 25 ; CHECK-LABEL: f2: 26 ; CHECK-NOT: %r2 27 ; CHECK: jhe [[LABEL:[^ ]*]] 28 ; CHECK-NOT: %r2 29 ; CHECK: stg %r3, 0(%r2) 30 ; CHECK: [[LABEL]]: 31 ; CHECK: br %r14 32 %cond = icmp ult i32 %limit, 42 33 %orig = load i64 *%ptr 34 %res = select i1 %cond, i64 %alt, i64 %orig 35 store i64 %res, i64 *%ptr 36 ret void 37 } 38 39 ; Check the high end of the aligned STG range. 40 define void @f3(i64 *%base, i64 %alt, i32 %limit) { 41 ; CHECK-LABEL: f3: 42 ; CHECK-NOT: %r2 43 ; CHECK: jl [[LABEL:[^ ]*]] 44 ; CHECK-NOT: %r2 45 ; CHECK: stg %r3, 524280(%r2) 46 ; CHECK: [[LABEL]]: 47 ; CHECK: br %r14 48 %ptr = getelementptr i64 *%base, i64 65535 49 %cond = icmp ult i32 %limit, 42 50 %orig = load i64 *%ptr 51 %res = select i1 %cond, i64 %orig, i64 %alt 52 store i64 %res, i64 *%ptr 53 ret void 54 } 55 56 ; Check the next doubleword up, which needs separate address logic. 57 ; Other sequences besides this one would be OK. 58 define void @f4(i64 *%base, i64 %alt, i32 %limit) { 59 ; CHECK-LABEL: f4: 60 ; CHECK-NOT: %r2 61 ; CHECK: jl [[LABEL:[^ ]*]] 62 ; CHECK-NOT: %r2 63 ; CHECK: agfi %r2, 524288 64 ; CHECK: stg %r3, 0(%r2) 65 ; CHECK: [[LABEL]]: 66 ; CHECK: br %r14 67 %ptr = getelementptr i64 *%base, i64 65536 68 %cond = icmp ult i32 %limit, 42 69 %orig = load i64 *%ptr 70 %res = select i1 %cond, i64 %orig, i64 %alt 71 store i64 %res, i64 *%ptr 72 ret void 73 } 74 75 ; Check the low end of the STG range. 76 define void @f5(i64 *%base, i64 %alt, i32 %limit) { 77 ; CHECK-LABEL: f5: 78 ; CHECK-NOT: %r2 79 ; CHECK: jl [[LABEL:[^ ]*]] 80 ; CHECK-NOT: %r2 81 ; CHECK: stg %r3, -524288(%r2) 82 ; CHECK: [[LABEL]]: 83 ; CHECK: br %r14 84 %ptr = getelementptr i64 *%base, i64 -65536 85 %cond = icmp ult i32 %limit, 42 86 %orig = load i64 *%ptr 87 %res = select i1 %cond, i64 %orig, i64 %alt 88 store i64 %res, i64 *%ptr 89 ret void 90 } 91 92 ; Check the next doubleword down, which needs separate address logic. 93 ; Other sequences besides this one would be OK. 94 define void @f6(i64 *%base, i64 %alt, i32 %limit) { 95 ; CHECK-LABEL: f6: 96 ; CHECK-NOT: %r2 97 ; CHECK: jl [[LABEL:[^ ]*]] 98 ; CHECK-NOT: %r2 99 ; CHECK: agfi %r2, -524296 100 ; CHECK: stg %r3, 0(%r2) 101 ; CHECK: [[LABEL]]: 102 ; CHECK: br %r14 103 %ptr = getelementptr i64 *%base, i64 -65537 104 %cond = icmp ult i32 %limit, 42 105 %orig = load i64 *%ptr 106 %res = select i1 %cond, i64 %orig, i64 %alt 107 store i64 %res, i64 *%ptr 108 ret void 109 } 110 111 ; Check that STG allows an index. 112 define void @f7(i64 %base, i64 %index, i64 %alt, i32 %limit) { 113 ; CHECK-LABEL: f7: 114 ; CHECK-NOT: %r2 115 ; CHECK: jl [[LABEL:[^ ]*]] 116 ; CHECK-NOT: %r2 117 ; CHECK: stg %r4, 524287(%r3,%r2) 118 ; CHECK: [[LABEL]]: 119 ; CHECK: br %r14 120 %add1 = add i64 %base, %index 121 %add2 = add i64 %add1, 524287 122 %ptr = inttoptr i64 %add2 to i64 * 123 %cond = icmp ult i32 %limit, 42 124 %orig = load i64 *%ptr 125 %res = select i1 %cond, i64 %orig, i64 %alt 126 store i64 %res, i64 *%ptr 127 ret void 128 } 129 130 ; Check that volatile loads are not matched. 131 define void @f8(i64 *%ptr, i64 %alt, i32 %limit) { 132 ; CHECK-LABEL: f8: 133 ; CHECK: lg {{%r[0-5]}}, 0(%r2) 134 ; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]] 135 ; CHECK: [[LABEL]]: 136 ; CHECK: stg {{%r[0-5]}}, 0(%r2) 137 ; CHECK: br %r14 138 %cond = icmp ult i32 %limit, 42 139 %orig = load volatile i64 *%ptr 140 %res = select i1 %cond, i64 %orig, i64 %alt 141 store i64 %res, i64 *%ptr 142 ret void 143 } 144 145 ; ...likewise stores. In this case we should have a conditional load into %r3. 146 define void @f9(i64 *%ptr, i64 %alt, i32 %limit) { 147 ; CHECK-LABEL: f9: 148 ; CHECK: jhe [[LABEL:[^ ]*]] 149 ; CHECK: lg %r3, 0(%r2) 150 ; CHECK: [[LABEL]]: 151 ; CHECK: stg %r3, 0(%r2) 152 ; CHECK: br %r14 153 %cond = icmp ult i32 %limit, 42 154 %orig = load i64 *%ptr 155 %res = select i1 %cond, i64 %orig, i64 %alt 156 store volatile i64 %res, i64 *%ptr 157 ret void 158 } 159 160 ; Check that atomic loads are not matched. The transformation is OK for 161 ; the "unordered" case tested here, but since we don't try to handle atomic 162 ; operations at all in this context, it seems better to assert that than 163 ; to restrict the test to a stronger ordering. 164 define void @f10(i64 *%ptr, i64 %alt, i32 %limit) { 165 ; FIXME: should use a normal load instead of CSG. 166 ; CHECK-LABEL: f10: 167 ; CHECK: csg {{%r[0-5]}}, {{%r[0-5]}}, 0(%r2) 168 ; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]] 169 ; CHECK: [[LABEL]]: 170 ; CHECK: stg {{%r[0-5]}}, 0(%r2) 171 ; CHECK: br %r14 172 %cond = icmp ult i32 %limit, 42 173 %orig = load atomic i64 *%ptr unordered, align 8 174 %res = select i1 %cond, i64 %orig, i64 %alt 175 store i64 %res, i64 *%ptr 176 ret void 177 } 178 179 ; ...likewise stores. 180 define void @f11(i64 *%ptr, i64 %alt, i32 %limit) { 181 ; FIXME: should use a normal store instead of CSG. 182 ; CHECK-LABEL: f11: 183 ; CHECK: jhe [[LABEL:[^ ]*]] 184 ; CHECK: lg %r3, 0(%r2) 185 ; CHECK: [[LABEL]]: 186 ; CHECK: csg {{%r[0-5]}}, %r3, 0(%r2) 187 ; CHECK: br %r14 188 %cond = icmp ult i32 %limit, 42 189 %orig = load i64 *%ptr 190 %res = select i1 %cond, i64 %orig, i64 %alt 191 store atomic i64 %res, i64 *%ptr unordered, align 8 192 ret void 193 } 194 195 ; Try a frame index base. 196 define void @f12(i64 %alt, i32 %limit) { 197 ; CHECK-LABEL: f12: 198 ; CHECK: brasl %r14, foo@PLT 199 ; CHECK-NOT: %r15 200 ; CHECK: jl [[LABEL:[^ ]*]] 201 ; CHECK-NOT: %r15 202 ; CHECK: stg {{%r[0-9]+}}, {{[0-9]+}}(%r15) 203 ; CHECK: [[LABEL]]: 204 ; CHECK: brasl %r14, foo@PLT 205 ; CHECK: br %r14 206 %ptr = alloca i64 207 call void @foo(i64 *%ptr) 208 %cond = icmp ult i32 %limit, 42 209 %orig = load i64 *%ptr 210 %res = select i1 %cond, i64 %orig, i64 %alt 211 store i64 %res, i64 *%ptr 212 call void @foo(i64 *%ptr) 213 ret void 214 } 215