310 lines · plain
1; Test 32-bit conditional stores that are presented as selects.2;3; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 | FileCheck %s4 5declare void @foo(ptr)6 7; Test the simple case, with the loaded value first.8define void @f1(ptr %ptr, i32 %alt, i32 %limit) {9; CHECK-LABEL: f1:10; CHECK-NOT: %r211; CHECK: blr %r1412; CHECK-NOT: %r213; CHECK: st %r3, 0(%r2)14; CHECK: br %r1415 %cond = icmp ult i32 %limit, 42016 %orig = load i32, ptr %ptr17 %res = select i1 %cond, i32 %orig, i32 %alt18 store i32 %res, ptr %ptr19 ret void20}21 22; ...and with the loaded value second23define void @f2(ptr %ptr, i32 %alt, i32 %limit) {24; CHECK-LABEL: f2:25; CHECK-NOT: %r226; CHECK: bher %r1427; CHECK-NOT: %r228; CHECK: st %r3, 0(%r2)29; CHECK: br %r1430 %cond = icmp ult i32 %limit, 42031 %orig = load i32, ptr %ptr32 %res = select i1 %cond, i32 %alt, i32 %orig33 store i32 %res, ptr %ptr34 ret void35}36 37; Test cases where the value is explicitly sign-extended to 64 bits, with the38; loaded value first.39define void @f3(ptr %ptr, i64 %alt, i32 %limit) {40; CHECK-LABEL: f3:41; CHECK-NOT: %r242; CHECK: blr %r1443; CHECK-NOT: %r244; CHECK: st %r3, 0(%r2)45; CHECK: br %r1446 %cond = icmp ult i32 %limit, 42047 %orig = load i32, ptr %ptr48 %ext = sext i32 %orig to i6449 %res = select i1 %cond, i64 %ext, i64 %alt50 %trunc = trunc i64 %res to i3251 store i32 %trunc, ptr %ptr52 ret void53}54 55; ...and with the loaded value second56define void @f4(ptr %ptr, i64 %alt, i32 %limit) {57; CHECK-LABEL: f4:58; CHECK-NOT: %r259; CHECK: bher %r1460; CHECK-NOT: %r261; CHECK: st %r3, 0(%r2)62; CHECK: br %r1463 %cond = icmp ult i32 %limit, 42064 %orig = load i32, ptr %ptr65 %ext = sext i32 %orig to i6466 %res = select i1 %cond, i64 %alt, i64 %ext67 %trunc = trunc i64 %res to i3268 store i32 %trunc, ptr %ptr69 ret void70}71 72; Test cases where the value is explicitly zero-extended to 32 bits, with the73; loaded value first.74define void @f5(ptr %ptr, i64 %alt, i32 %limit) {75; CHECK-LABEL: f5:76; CHECK-NOT: %r277; CHECK: blr %r1478; CHECK-NOT: %r279; CHECK: st %r3, 0(%r2)80; CHECK: br %r1481 %cond = icmp ult i32 %limit, 42082 %orig = load i32, ptr %ptr83 %ext = zext i32 %orig to i6484 %res = select i1 %cond, i64 %ext, i64 %alt85 %trunc = trunc i64 %res to i3286 store i32 %trunc, ptr %ptr87 ret void88}89 90; ...and with the loaded value second91define void @f6(ptr %ptr, i64 %alt, i32 %limit) {92; CHECK-LABEL: f6:93; CHECK-NOT: %r294; CHECK: bher %r1495; CHECK-NOT: %r296; CHECK: st %r3, 0(%r2)97; CHECK: br %r1498 %cond = icmp ult i32 %limit, 42099 %orig = load i32, ptr %ptr100 %ext = zext i32 %orig to i64101 %res = select i1 %cond, i64 %alt, i64 %ext102 %trunc = trunc i64 %res to i32103 store i32 %trunc, ptr %ptr104 ret void105}106 107; Check the high end of the aligned ST range.108define void @f7(ptr %base, i32 %alt, i32 %limit) {109; CHECK-LABEL: f7:110; CHECK-NOT: %r2111; CHECK: blr %r14112; CHECK-NOT: %r2113; CHECK: st %r3, 4092(%r2)114; CHECK: br %r14115 %ptr = getelementptr i32, ptr %base, i64 1023116 %cond = icmp ult i32 %limit, 420117 %orig = load i32, ptr %ptr118 %res = select i1 %cond, i32 %orig, i32 %alt119 store i32 %res, ptr %ptr120 ret void121}122 123; Check the next word up, which should use STY instead of ST.124define void @f8(ptr %base, i32 %alt, i32 %limit) {125; CHECK-LABEL: f8:126; CHECK-NOT: %r2127; CHECK: blr %r14128; CHECK-NOT: %r2129; CHECK: sty %r3, 4096(%r2)130; CHECK: br %r14131 %ptr = getelementptr i32, ptr %base, i64 1024132 %cond = icmp ult i32 %limit, 420133 %orig = load i32, ptr %ptr134 %res = select i1 %cond, i32 %orig, i32 %alt135 store i32 %res, ptr %ptr136 ret void137}138 139; Check the high end of the aligned STY range.140define void @f9(ptr %base, i32 %alt, i32 %limit) {141; CHECK-LABEL: f9:142; CHECK-NOT: %r2143; CHECK: blr %r14144; CHECK-NOT: %r2145; CHECK: sty %r3, 524284(%r2)146; CHECK: br %r14147 %ptr = getelementptr i32, ptr %base, i64 131071148 %cond = icmp ult i32 %limit, 420149 %orig = load i32, ptr %ptr150 %res = select i1 %cond, i32 %orig, i32 %alt151 store i32 %res, ptr %ptr152 ret void153}154 155; Check the next word up, which needs separate address logic.156; Other sequences besides this one would be OK.157define void @f10(ptr %base, i32 %alt, i32 %limit) {158; CHECK-LABEL: f10:159; CHECK-NOT: %r2160; CHECK: blr %r14161; CHECK-NOT: %r2162; CHECK: agfi %r2, 524288163; CHECK: st %r3, 0(%r2)164; CHECK: br %r14165 %ptr = getelementptr i32, ptr %base, i64 131072166 %cond = icmp ult i32 %limit, 420167 %orig = load i32, ptr %ptr168 %res = select i1 %cond, i32 %orig, i32 %alt169 store i32 %res, ptr %ptr170 ret void171}172 173; Check the low end of the STY range.174define void @f11(ptr %base, i32 %alt, i32 %limit) {175; CHECK-LABEL: f11:176; CHECK-NOT: %r2177; CHECK: blr %r14178; CHECK-NOT: %r2179; CHECK: sty %r3, -524288(%r2)180; CHECK: br %r14181 %ptr = getelementptr i32, ptr %base, i64 -131072182 %cond = icmp ult i32 %limit, 420183 %orig = load i32, ptr %ptr184 %res = select i1 %cond, i32 %orig, i32 %alt185 store i32 %res, ptr %ptr186 ret void187}188 189; Check the next word down, which needs separate address logic.190; Other sequences besides this one would be OK.191define void @f12(ptr %base, i32 %alt, i32 %limit) {192; CHECK-LABEL: f12:193; CHECK-NOT: %r2194; CHECK: blr %r14195; CHECK-NOT: %r2196; CHECK: agfi %r2, -524292197; CHECK: st %r3, 0(%r2)198; CHECK: br %r14199 %ptr = getelementptr i32, ptr %base, i64 -131073200 %cond = icmp ult i32 %limit, 420201 %orig = load i32, ptr %ptr202 %res = select i1 %cond, i32 %orig, i32 %alt203 store i32 %res, ptr %ptr204 ret void205}206 207; Check that STY allows an index.208define void @f13(i64 %base, i64 %index, i32 %alt, i32 %limit) {209; CHECK-LABEL: f13:210; CHECK-NOT: %r2211; CHECK: blr %r14212; CHECK-NOT: %r2213; CHECK: sty %r4, 4096(%r3,%r2)214; CHECK: br %r14215 %add1 = add i64 %base, %index216 %add2 = add i64 %add1, 4096217 %ptr = inttoptr i64 %add2 to ptr218 %cond = icmp ult i32 %limit, 420219 %orig = load i32, ptr %ptr220 %res = select i1 %cond, i32 %orig, i32 %alt221 store i32 %res, ptr %ptr222 ret void223}224 225; Check that volatile loads are not matched.226define void @f14(ptr %ptr, i32 %alt, i32 %limit) {227; CHECK-LABEL: f14:228; CHECK: l {{%r[0-5]}}, 0(%r2)229; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]230; CHECK: [[LABEL]]:231; CHECK: st {{%r[0-5]}}, 0(%r2)232; CHECK: br %r14233 %cond = icmp ult i32 %limit, 420234 %orig = load volatile i32, ptr %ptr235 %res = select i1 %cond, i32 %orig, i32 %alt236 store i32 %res, ptr %ptr237 ret void238}239 240; ...likewise stores. In this case we should have a conditional load into %r3.241define void @f15(ptr %ptr, i32 %alt, i32 %limit) {242; CHECK-LABEL: f15:243; CHECK: jhe [[LABEL:[^ ]*]]244; CHECK: l %r3, 0(%r2)245; CHECK: [[LABEL]]:246; CHECK: st %r3, 0(%r2)247; CHECK: br %r14248 %cond = icmp ult i32 %limit, 420249 %orig = load i32, ptr %ptr250 %res = select i1 %cond, i32 %orig, i32 %alt251 store volatile i32 %res, ptr %ptr252 ret void253}254 255; Check that atomic loads are not matched. The transformation is OK for256; the "unordered" case tested here, but since we don't try to handle atomic257; operations at all in this context, it seems better to assert that than258; to restrict the test to a stronger ordering.259define void @f16(ptr %ptr, i32 %alt, i32 %limit) {260; FIXME: should use a normal load instead of CS.261; CHECK-LABEL: f16:262; CHECK: l {{%r[0-5]}}, 0(%r2)263; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]264; CHECK: [[LABEL]]:265; CHECK: st {{%r[0-5]}}, 0(%r2)266; CHECK: br %r14267 %cond = icmp ult i32 %limit, 420268 %orig = load atomic i32, ptr %ptr unordered, align 4269 %res = select i1 %cond, i32 %orig, i32 %alt270 store i32 %res, ptr %ptr271 ret void272}273 274; ...likewise stores.275define void @f17(ptr %ptr, i32 %alt, i32 %limit) {276; FIXME: should use a normal store instead of CS.277; CHECK-LABEL: f17:278; CHECK: jhe [[LABEL:[^ ]*]]279; CHECK: l %r3, 0(%r2)280; CHECK: [[LABEL]]:281; CHECK: st %r3, 0(%r2)282; CHECK: br %r14283 %cond = icmp ult i32 %limit, 420284 %orig = load i32, ptr %ptr285 %res = select i1 %cond, i32 %orig, i32 %alt286 store atomic i32 %res, ptr %ptr unordered, align 4287 ret void288}289 290; Try a frame index base.291define void @f18(i32 %alt, i32 %limit) {292; CHECK-LABEL: f18:293; CHECK: brasl %r14, foo@PLT294; CHECK-NOT: %r15295; CHECK: jl [[LABEL:[^ ]*]]296; CHECK-NOT: %r15297; CHECK: st {{%r[0-9]+}}, {{[0-9]+}}(%r15)298; CHECK: [[LABEL]]:299; CHECK: brasl %r14, foo@PLT300; CHECK: br %r14301 %ptr = alloca i32302 call void @foo(ptr %ptr)303 %cond = icmp ult i32 %limit, 420304 %orig = load i32, ptr %ptr305 %res = select i1 %cond, i32 %orig, i32 %alt306 store i32 %res, ptr %ptr307 call void @foo(ptr %ptr)308 ret void309}310