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