1 ; Test STOCs that are presented as selects. 2 ; 3 ; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s 4 5 declare void @foo(i32 *) 6 7 ; Test the simple case, with the loaded value first. 8 define void @f1(i32 *%ptr, i32 %alt, i32 %limit) { 9 ; CHECK-LABEL: f1: 10 ; CHECK: clfi %r4, 42 11 ; CHECK: stoche %r3, 0(%r2) 12 ; CHECK: br %r14 13 %cond = icmp ult i32 %limit, 42 14 %orig = load i32 *%ptr 15 %res = select i1 %cond, i32 %orig, i32 %alt 16 store i32 %res, i32 *%ptr 17 ret void 18 } 19 20 ; ...and with the loaded value second 21 define void @f2(i32 *%ptr, i32 %alt, i32 %limit) { 22 ; CHECK-LABEL: f2: 23 ; CHECK: clfi %r4, 42 24 ; CHECK: stocl %r3, 0(%r2) 25 ; CHECK: br %r14 26 %cond = icmp ult i32 %limit, 42 27 %orig = load i32 *%ptr 28 %res = select i1 %cond, i32 %alt, i32 %orig 29 store i32 %res, i32 *%ptr 30 ret void 31 } 32 33 ; Test cases where the value is explicitly sign-extended to 64 bits, with the 34 ; loaded value first. 35 define void @f3(i32 *%ptr, i64 %alt, i32 %limit) { 36 ; CHECK-LABEL: f3: 37 ; CHECK: clfi %r4, 42 38 ; CHECK: stoche %r3, 0(%r2) 39 ; CHECK: br %r14 40 %cond = icmp ult i32 %limit, 42 41 %orig = load i32 *%ptr 42 %ext = sext i32 %orig to i64 43 %res = select i1 %cond, i64 %ext, i64 %alt 44 %trunc = trunc i64 %res to i32 45 store i32 %trunc, i32 *%ptr 46 ret void 47 } 48 49 ; ...and with the loaded value second 50 define void @f4(i32 *%ptr, i64 %alt, i32 %limit) { 51 ; CHECK-LABEL: f4: 52 ; CHECK: clfi %r4, 42 53 ; CHECK: stocl %r3, 0(%r2) 54 ; CHECK: br %r14 55 %cond = icmp ult i32 %limit, 42 56 %orig = load i32 *%ptr 57 %ext = sext i32 %orig to i64 58 %res = select i1 %cond, i64 %alt, i64 %ext 59 %trunc = trunc i64 %res to i32 60 store i32 %trunc, i32 *%ptr 61 ret void 62 } 63 64 ; Test cases where the value is explicitly zero-extended to 32 bits, with the 65 ; loaded value first. 66 define void @f5(i32 *%ptr, i64 %alt, i32 %limit) { 67 ; CHECK-LABEL: f5: 68 ; CHECK: clfi %r4, 42 69 ; CHECK: stoche %r3, 0(%r2) 70 ; CHECK: br %r14 71 %cond = icmp ult i32 %limit, 42 72 %orig = load i32 *%ptr 73 %ext = zext i32 %orig to i64 74 %res = select i1 %cond, i64 %ext, i64 %alt 75 %trunc = trunc i64 %res to i32 76 store i32 %trunc, i32 *%ptr 77 ret void 78 } 79 80 ; ...and with the loaded value second 81 define void @f6(i32 *%ptr, i64 %alt, i32 %limit) { 82 ; CHECK-LABEL: f6: 83 ; CHECK: clfi %r4, 42 84 ; CHECK: stocl %r3, 0(%r2) 85 ; CHECK: br %r14 86 %cond = icmp ult i32 %limit, 42 87 %orig = load i32 *%ptr 88 %ext = zext i32 %orig to i64 89 %res = select i1 %cond, i64 %alt, i64 %ext 90 %trunc = trunc i64 %res to i32 91 store i32 %trunc, i32 *%ptr 92 ret void 93 } 94 95 ; Check the high end of the aligned STOC range. 96 define void @f7(i32 *%base, i32 %alt, i32 %limit) { 97 ; CHECK-LABEL: f7: 98 ; CHECK: clfi %r4, 42 99 ; CHECK: stoche %r3, 524284(%r2) 100 ; CHECK: br %r14 101 %ptr = getelementptr i32 *%base, i64 131071 102 %cond = icmp ult i32 %limit, 42 103 %orig = load i32 *%ptr 104 %res = select i1 %cond, i32 %orig, i32 %alt 105 store i32 %res, i32 *%ptr 106 ret void 107 } 108 109 ; Check the next word up. Other sequences besides this one would be OK. 110 define void @f8(i32 *%base, i32 %alt, i32 %limit) { 111 ; CHECK-LABEL: f8: 112 ; CHECK: agfi %r2, 524288 113 ; CHECK: clfi %r4, 42 114 ; CHECK: stoche %r3, 0(%r2) 115 ; CHECK: br %r14 116 %ptr = getelementptr i32 *%base, i64 131072 117 %cond = icmp ult i32 %limit, 42 118 %orig = load i32 *%ptr 119 %res = select i1 %cond, i32 %orig, i32 %alt 120 store i32 %res, i32 *%ptr 121 ret void 122 } 123 124 ; Check the low end of the STOC range. 125 define void @f9(i32 *%base, i32 %alt, i32 %limit) { 126 ; CHECK-LABEL: f9: 127 ; CHECK: clfi %r4, 42 128 ; CHECK: stoche %r3, -524288(%r2) 129 ; CHECK: br %r14 130 %ptr = getelementptr i32 *%base, i64 -131072 131 %cond = icmp ult i32 %limit, 42 132 %orig = load i32 *%ptr 133 %res = select i1 %cond, i32 %orig, i32 %alt 134 store i32 %res, i32 *%ptr 135 ret void 136 } 137 138 ; Check the next word down, with the same comments as f8. 139 define void @f10(i32 *%base, i32 %alt, i32 %limit) { 140 ; CHECK-LABEL: f10: 141 ; CHECK: agfi %r2, -524292 142 ; CHECK: clfi %r4, 42 143 ; CHECK: stoche %r3, 0(%r2) 144 ; CHECK: br %r14 145 %ptr = getelementptr i32 *%base, i64 -131073 146 %cond = icmp ult i32 %limit, 42 147 %orig = load i32 *%ptr 148 %res = select i1 %cond, i32 %orig, i32 %alt 149 store i32 %res, i32 *%ptr 150 ret void 151 } 152 153 ; Try a frame index base. 154 define void @f11(i32 %alt, i32 %limit) { 155 ; CHECK-LABEL: f11: 156 ; CHECK: brasl %r14, foo@PLT 157 ; CHECK: stoche {{%r[0-9]+}}, {{[0-9]+}}(%r15) 158 ; CHECK: brasl %r14, foo@PLT 159 ; CHECK: br %r14 160 %ptr = alloca i32 161 call void @foo(i32 *%ptr) 162 %cond = icmp ult i32 %limit, 42 163 %orig = load i32 *%ptr 164 %res = select i1 %cond, i32 %orig, i32 %alt 165 store i32 %res, i32 *%ptr 166 call void @foo(i32 *%ptr) 167 ret void 168 } 169 170 ; Test that conditionally-executed stores do not use STOC, since STOC 171 ; is allowed to trap even when the condition is false. 172 define void @f12(i32 %a, i32 %b, i32 *%dest) { 173 ; CHECK-LABEL: f12: 174 ; CHECK-NOT: stoc 175 ; CHECK: br %r14 176 entry: 177 %cmp = icmp ule i32 %a, %b 178 br i1 %cmp, label %store, label %exit 179 180 store: 181 store i32 %b, i32 *%dest 182 br label %exit 183 184 exit: 185 ret void 186 } 187