1; Test STOCs that are presented as selects. 2; 3; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s 4 5declare void @foo(i32 *) 6 7; Test the simple case, with the loaded value first. 8define 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 , 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 21define 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 , 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. 35define 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 , 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 50define 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 , 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. 66define 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 , 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 81define 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 , 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. 96define 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, i32 *%base, i64 131071 102 %cond = icmp ult i32 %limit, 42 103 %orig = load i32 , 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. 110define 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, i32 *%base, i64 131072 117 %cond = icmp ult i32 %limit, 42 118 %orig = load i32 , 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. 125define 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, i32 *%base, i64 -131072 131 %cond = icmp ult i32 %limit, 42 132 %orig = load i32 , 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. 139define 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, i32 *%base, i64 -131073 146 %cond = icmp ult i32 %limit, 42 147 %orig = load i32 , 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. 154define 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 , 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. 172define void @f12(i32 %a, i32 %b, i32 *%dest) { 173; CHECK-LABEL: f12: 174; CHECK-NOT: stoc 175; CHECK: br %r14 176entry: 177 %cmp = icmp ule i32 %a, %b 178 br i1 %cmp, label %store, label %exit 179 180store: 181 store i32 %b, i32 *%dest 182 br label %exit 183 184exit: 185 ret void 186} 187