381 lines · plain
1; Test 8-bit conditional stores that are presented as selects. The volatile2; tests require z10, which use a branch instead of a LOCR.3;4; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s5 6declare void @foo(ptr)7 8; Test the simple case, with the loaded value first.9define void @f1(ptr %ptr, i8 %alt, i32 %limit) {10; CHECK-LABEL: f1:11; CHECK-NOT: %r212; CHECK: blr %r1413; CHECK-NOT: %r214; CHECK: stc %r3, 0(%r2)15; CHECK: br %r1416 %cond = icmp ult i32 %limit, 42017 %orig = load i8, ptr %ptr18 %res = select i1 %cond, i8 %orig, i8 %alt19 store i8 %res, ptr %ptr20 ret void21}22 23; ...and with the loaded value second24define void @f2(ptr %ptr, i8 %alt, i32 %limit) {25; CHECK-LABEL: f2:26; CHECK-NOT: %r227; CHECK: bher %r1428; CHECK-NOT: %r229; CHECK: stc %r3, 0(%r2)30; CHECK: br %r1431 %cond = icmp ult i32 %limit, 42032 %orig = load i8, ptr %ptr33 %res = select i1 %cond, i8 %alt, i8 %orig34 store i8 %res, ptr %ptr35 ret void36}37 38; Test cases where the value is explicitly sign-extended to 32 bits, with the39; loaded value first.40define void @f3(ptr %ptr, i32 %alt, i32 %limit) {41; CHECK-LABEL: f3:42; CHECK-NOT: %r243; CHECK: blr %r1444; CHECK-NOT: %r245; CHECK: stc %r3, 0(%r2)46; CHECK: br %r1447 %cond = icmp ult i32 %limit, 42048 %orig = load i8, ptr %ptr49 %ext = sext i8 %orig to i3250 %res = select i1 %cond, i32 %ext, i32 %alt51 %trunc = trunc i32 %res to i852 store i8 %trunc, ptr %ptr53 ret void54}55 56; ...and with the loaded value second57define void @f4(ptr %ptr, i32 %alt, i32 %limit) {58; CHECK-LABEL: f4:59; CHECK-NOT: %r260; CHECK: bher %r1461; CHECK-NOT: %r262; CHECK: stc %r3, 0(%r2)63; CHECK: br %r1464 %cond = icmp ult i32 %limit, 42065 %orig = load i8, ptr %ptr66 %ext = sext i8 %orig to i3267 %res = select i1 %cond, i32 %alt, i32 %ext68 %trunc = trunc i32 %res to i869 store i8 %trunc, ptr %ptr70 ret void71}72 73; Test cases where the value is explicitly zero-extended to 32 bits, with the74; loaded value first.75define void @f5(ptr %ptr, i32 %alt, i32 %limit) {76; CHECK-LABEL: f5:77; CHECK-NOT: %r278; CHECK: blr %r1479; CHECK-NOT: %r280; CHECK: stc %r3, 0(%r2)81; CHECK: br %r1482 %cond = icmp ult i32 %limit, 42083 %orig = load i8, ptr %ptr84 %ext = zext i8 %orig to i3285 %res = select i1 %cond, i32 %ext, i32 %alt86 %trunc = trunc i32 %res to i887 store i8 %trunc, ptr %ptr88 ret void89}90 91; ...and with the loaded value second92define void @f6(ptr %ptr, i32 %alt, i32 %limit) {93; CHECK-LABEL: f6:94; CHECK-NOT: %r295; CHECK: bher %r1496; CHECK-NOT: %r297; CHECK: stc %r3, 0(%r2)98; CHECK: br %r1499 %cond = icmp ult i32 %limit, 420100 %orig = load i8, ptr %ptr101 %ext = zext i8 %orig to i32102 %res = select i1 %cond, i32 %alt, i32 %ext103 %trunc = trunc i32 %res to i8104 store i8 %trunc, ptr %ptr105 ret void106}107 108; Test cases where the value is explicitly sign-extended to 64 bits, with the109; loaded value first.110define void @f7(ptr %ptr, i64 %alt, i32 %limit) {111; CHECK-LABEL: f7:112; CHECK-NOT: %r2113; CHECK: blr %r14114; CHECK-NOT: %r2115; CHECK: stc %r3, 0(%r2)116; CHECK: br %r14117 %cond = icmp ult i32 %limit, 420118 %orig = load i8, ptr %ptr119 %ext = sext i8 %orig to i64120 %res = select i1 %cond, i64 %ext, i64 %alt121 %trunc = trunc i64 %res to i8122 store i8 %trunc, ptr %ptr123 ret void124}125 126; ...and with the loaded value second127define void @f8(ptr %ptr, i64 %alt, i32 %limit) {128; CHECK-LABEL: f8:129; CHECK-NOT: %r2130; CHECK: bher %r14131; CHECK-NOT: %r2132; CHECK: stc %r3, 0(%r2)133; CHECK: br %r14134 %cond = icmp ult i32 %limit, 420135 %orig = load i8, ptr %ptr136 %ext = sext i8 %orig to i64137 %res = select i1 %cond, i64 %alt, i64 %ext138 %trunc = trunc i64 %res to i8139 store i8 %trunc, ptr %ptr140 ret void141}142 143; Test cases where the value is explicitly zero-extended to 64 bits, with the144; loaded value first.145define void @f9(ptr %ptr, i64 %alt, i32 %limit) {146; CHECK-LABEL: f9:147; CHECK-NOT: %r2148; CHECK: blr %r14149; CHECK-NOT: %r2150; CHECK: stc %r3, 0(%r2)151; CHECK: br %r14152 %cond = icmp ult i32 %limit, 420153 %orig = load i8, ptr %ptr154 %ext = zext i8 %orig to i64155 %res = select i1 %cond, i64 %ext, i64 %alt156 %trunc = trunc i64 %res to i8157 store i8 %trunc, ptr %ptr158 ret void159}160 161; ...and with the loaded value second162define void @f10(ptr %ptr, i64 %alt, i32 %limit) {163; CHECK-LABEL: f10:164; CHECK-NOT: %r2165; CHECK: bher %r14166; CHECK-NOT: %r2167; CHECK: stc %r3, 0(%r2)168; CHECK: br %r14169 %cond = icmp ult i32 %limit, 420170 %orig = load i8, ptr %ptr171 %ext = zext i8 %orig to i64172 %res = select i1 %cond, i64 %alt, i64 %ext173 %trunc = trunc i64 %res to i8174 store i8 %trunc, ptr %ptr175 ret void176}177 178; Check the high end of the STC range.179define void @f11(ptr %base, i8 %alt, i32 %limit) {180; CHECK-LABEL: f11:181; CHECK-NOT: %r2182; CHECK: blr %r14183; CHECK-NOT: %r2184; CHECK: stc %r3, 4095(%r2)185; CHECK: br %r14186 %ptr = getelementptr i8, ptr %base, i64 4095187 %cond = icmp ult i32 %limit, 420188 %orig = load i8, ptr %ptr189 %res = select i1 %cond, i8 %orig, i8 %alt190 store i8 %res, ptr %ptr191 ret void192}193 194; Check the next byte up, which should use STCY instead of STC.195define void @f12(ptr %base, i8 %alt, i32 %limit) {196; CHECK-LABEL: f12:197; CHECK-NOT: %r2198; CHECK: blr %r14199; CHECK-NOT: %r2200; CHECK: stcy %r3, 4096(%r2)201; CHECK: br %r14202 %ptr = getelementptr i8, ptr %base, i64 4096203 %cond = icmp ult i32 %limit, 420204 %orig = load i8, ptr %ptr205 %res = select i1 %cond, i8 %orig, i8 %alt206 store i8 %res, ptr %ptr207 ret void208}209 210; Check the high end of the STCY range.211define void @f13(ptr %base, i8 %alt, i32 %limit) {212; CHECK-LABEL: f13:213; CHECK-NOT: %r2214; CHECK: blr %r14215; CHECK-NOT: %r2216; CHECK: stcy %r3, 524287(%r2)217; CHECK: br %r14218 %ptr = getelementptr i8, ptr %base, i64 524287219 %cond = icmp ult i32 %limit, 420220 %orig = load i8, ptr %ptr221 %res = select i1 %cond, i8 %orig, i8 %alt222 store i8 %res, ptr %ptr223 ret void224}225 226; Check the next byte up, which needs separate address logic.227; Other sequences besides this one would be OK.228define void @f14(ptr %base, i8 %alt, i32 %limit) {229; CHECK-LABEL: f14:230; CHECK-NOT: %r2231; CHECK: blr %r14232; CHECK-NOT: %r2233; CHECK: agfi %r2, 524288234; CHECK: stc %r3, 0(%r2)235; CHECK: br %r14236 %ptr = getelementptr i8, ptr %base, i64 524288237 %cond = icmp ult i32 %limit, 420238 %orig = load i8, ptr %ptr239 %res = select i1 %cond, i8 %orig, i8 %alt240 store i8 %res, ptr %ptr241 ret void242}243 244; Check the low end of the STCY range.245define void @f15(ptr %base, i8 %alt, i32 %limit) {246; CHECK-LABEL: f15:247; CHECK-NOT: %r2248; CHECK: blr %r14249; CHECK-NOT: %r2250; CHECK: stcy %r3, -524288(%r2)251; CHECK: br %r14252 %ptr = getelementptr i8, ptr %base, i64 -524288253 %cond = icmp ult i32 %limit, 420254 %orig = load i8, ptr %ptr255 %res = select i1 %cond, i8 %orig, i8 %alt256 store i8 %res, ptr %ptr257 ret void258}259 260; Check the next byte down, which needs separate address logic.261; Other sequences besides this one would be OK.262define void @f16(ptr %base, i8 %alt, i32 %limit) {263; CHECK-LABEL: f16:264; CHECK-NOT: %r2265; CHECK: blr %r14266; CHECK-NOT: %r2267; CHECK: agfi %r2, -524289268; CHECK: stc %r3, 0(%r2)269; CHECK: br %r14270 %ptr = getelementptr i8, ptr %base, i64 -524289271 %cond = icmp ult i32 %limit, 420272 %orig = load i8, ptr %ptr273 %res = select i1 %cond, i8 %orig, i8 %alt274 store i8 %res, ptr %ptr275 ret void276}277 278; Check that STCY allows an index.279define void @f17(i64 %base, i64 %index, i8 %alt, i32 %limit) {280; CHECK-LABEL: f17:281; CHECK-NOT: %r2282; CHECK: blr %r14283; CHECK-NOT: %r2284; CHECK: stcy %r4, 4096(%r3,%r2)285; CHECK: br %r14286 %add1 = add i64 %base, %index287 %add2 = add i64 %add1, 4096288 %ptr = inttoptr i64 %add2 to ptr289 %cond = icmp ult i32 %limit, 420290 %orig = load i8, ptr %ptr291 %res = select i1 %cond, i8 %orig, i8 %alt292 store i8 %res, ptr %ptr293 ret void294}295 296; Check that volatile loads are not matched.297define void @f18(ptr %ptr, i8 %alt, i32 %limit) {298; CHECK-LABEL: f18:299; CHECK: lb {{%r[0-5]}}, 0(%r2)300; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]301; CHECK: [[LABEL]]:302; CHECK: stc {{%r[0-5]}}, 0(%r2)303; CHECK: br %r14304 %cond = icmp ult i32 %limit, 420305 %orig = load volatile i8, ptr %ptr306 %res = select i1 %cond, i8 %orig, i8 %alt307 store i8 %res, ptr %ptr308 ret void309}310 311; ...likewise stores. In this case we should have a conditional load into %r3.312define void @f19(ptr %ptr, i8 %alt, i32 %limit) {313; CHECK-LABEL: f19:314; CHECK: jhe [[LABEL:[^ ]*]]315; CHECK: lb %r3, 0(%r2)316; CHECK: [[LABEL]]:317; CHECK: stc %r3, 0(%r2)318; CHECK: br %r14319 %cond = icmp ult i32 %limit, 420320 %orig = load i8, ptr %ptr321 %res = select i1 %cond, i8 %orig, i8 %alt322 store volatile i8 %res, ptr %ptr323 ret void324}325 326; Check that atomic loads are not matched. The transformation is OK for327; the "unordered" case tested here, but since we don't try to handle atomic328; operations at all in this context, it seems better to assert that than329; to restrict the test to a stronger ordering.330define void @f20(ptr %ptr, i8 %alt, i32 %limit) {331; FIXME: should use a normal load instead of CS.332; CHECK-LABEL: f20:333; CHECK: lb {{%r[0-9]+}}, 0(%r2)334; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]335; CHECK: [[LABEL]]:336; CHECK: stc {{%r[0-9]+}}, 0(%r2)337; CHECK: br %r14338 %cond = icmp ult i32 %limit, 420339 %orig = load atomic i8, ptr %ptr unordered, align 1340 %res = select i1 %cond, i8 %orig, i8 %alt341 store i8 %res, ptr %ptr342 ret void343}344 345; ...likewise stores.346define void @f21(ptr %ptr, i8 %alt, i32 %limit) {347; FIXME: should use a normal store instead of CS.348; CHECK-LABEL: f21:349; CHECK: jhe [[LABEL:[^ ]*]]350; CHECK: lb %r3, 0(%r2)351; CHECK: [[LABEL]]:352; CHECK: stc %r3, 0(%r2)353; CHECK: br %r14354 %cond = icmp ult i32 %limit, 420355 %orig = load i8, ptr %ptr356 %res = select i1 %cond, i8 %orig, i8 %alt357 store atomic i8 %res, ptr %ptr unordered, align 1358 ret void359}360 361; Try a frame index base.362define void @f22(i8 %alt, i32 %limit) {363; CHECK-LABEL: f22:364; CHECK: brasl %r14, foo@PLT365; CHECK-NOT: %r15366; CHECK: jl [[LABEL:[^ ]*]]367; CHECK-NOT: %r15368; CHECK: stc {{%r[0-9]+}}, {{[0-9]+}}(%r15)369; CHECK: [[LABEL]]:370; CHECK: brasl %r14, foo@PLT371; CHECK: br %r14372 %ptr = alloca i8373 call void @foo(ptr %ptr)374 %cond = icmp ult i32 %limit, 420375 %orig = load i8, ptr %ptr376 %res = select i1 %cond, i8 %orig, i8 %alt377 store i8 %res, ptr %ptr378 call void @foo(ptr %ptr)379 ret void380}381