208 lines · plain
1; Test 64-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 with the loaded value first.8define void @f1(ptr %ptr, i64 %alt, i32 %limit) {9; CHECK-LABEL: f1:10; CHECK-NOT: %r211; CHECK: blr %r1412; CHECK-NOT: %r213; CHECK: stg %r3, 0(%r2)14; CHECK: br %r1415 %cond = icmp ult i32 %limit, 42016 %orig = load i64, ptr %ptr17 %res = select i1 %cond, i64 %orig, i64 %alt18 store i64 %res, ptr %ptr19 ret void20}21 22; ...and with the loaded value second23define void @f2(ptr %ptr, i64 %alt, i32 %limit) {24; CHECK-LABEL: f2:25; CHECK-NOT: %r226; CHECK: bher %r1427; CHECK-NOT: %r228; CHECK: stg %r3, 0(%r2)29; CHECK: br %r1430 %cond = icmp ult i32 %limit, 42031 %orig = load i64, ptr %ptr32 %res = select i1 %cond, i64 %alt, i64 %orig33 store i64 %res, ptr %ptr34 ret void35}36 37; Check the high end of the aligned STG range.38define void @f3(ptr %base, i64 %alt, i32 %limit) {39; CHECK-LABEL: f3:40; CHECK-NOT: %r241; CHECK: blr %r1442; CHECK-NOT: %r243; CHECK: stg %r3, 524280(%r2)44; CHECK: br %r1445 %ptr = getelementptr i64, ptr %base, i64 6553546 %cond = icmp ult i32 %limit, 42047 %orig = load i64, ptr %ptr48 %res = select i1 %cond, i64 %orig, i64 %alt49 store i64 %res, ptr %ptr50 ret void51}52 53; Check the next doubleword up, which needs separate address logic.54; Other sequences besides this one would be OK.55define void @f4(ptr %base, i64 %alt, i32 %limit) {56; CHECK-LABEL: f4:57; CHECK-NOT: %r258; CHECK: blr %r1459; CHECK-NOT: %r260; CHECK: agfi %r2, 52428861; CHECK: stg %r3, 0(%r2)62; CHECK: br %r1463 %ptr = getelementptr i64, ptr %base, i64 6553664 %cond = icmp ult i32 %limit, 42065 %orig = load i64, ptr %ptr66 %res = select i1 %cond, i64 %orig, i64 %alt67 store i64 %res, ptr %ptr68 ret void69}70 71; Check the low end of the STG range.72define void @f5(ptr %base, i64 %alt, i32 %limit) {73; CHECK-LABEL: f5:74; CHECK-NOT: %r275; CHECK: blr %r1476; CHECK-NOT: %r277; CHECK: stg %r3, -524288(%r2)78; CHECK: br %r1479 %ptr = getelementptr i64, ptr %base, i64 -6553680 %cond = icmp ult i32 %limit, 42081 %orig = load i64, ptr %ptr82 %res = select i1 %cond, i64 %orig, i64 %alt83 store i64 %res, ptr %ptr84 ret void85}86 87; Check the next doubleword down, which needs separate address logic.88; Other sequences besides this one would be OK.89define void @f6(ptr %base, i64 %alt, i32 %limit) {90; CHECK-LABEL: f6:91; CHECK-NOT: %r292; CHECK: blr %r1493; CHECK-NOT: %r294; CHECK: agfi %r2, -52429695; CHECK: stg %r3, 0(%r2)96; CHECK: br %r1497 %ptr = getelementptr i64, ptr %base, i64 -6553798 %cond = icmp ult i32 %limit, 42099 %orig = load i64, ptr %ptr100 %res = select i1 %cond, i64 %orig, i64 %alt101 store i64 %res, ptr %ptr102 ret void103}104 105; Check that STG allows an index.106define void @f7(i64 %base, i64 %index, i64 %alt, i32 %limit) {107; CHECK-LABEL: f7:108; CHECK-NOT: %r2109; CHECK: blr %r14110; CHECK-NOT: %r2111; CHECK: stg %r4, 524287(%r3,%r2)112; CHECK: br %r14113 %add1 = add i64 %base, %index114 %add2 = add i64 %add1, 524287115 %ptr = inttoptr i64 %add2 to ptr116 %cond = icmp ult i32 %limit, 420117 %orig = load i64, ptr %ptr118 %res = select i1 %cond, i64 %orig, i64 %alt119 store i64 %res, ptr %ptr120 ret void121}122 123; Check that volatile loads are not matched.124define void @f8(ptr %ptr, i64 %alt, i32 %limit) {125; CHECK-LABEL: f8:126; CHECK: lg {{%r[0-5]}}, 0(%r2)127; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]128; CHECK: [[LABEL]]:129; CHECK: stg {{%r[0-5]}}, 0(%r2)130; CHECK: br %r14131 %cond = icmp ult i32 %limit, 420132 %orig = load volatile i64, ptr %ptr133 %res = select i1 %cond, i64 %orig, i64 %alt134 store i64 %res, ptr %ptr135 ret void136}137 138; ...likewise stores. In this case we should have a conditional load into %r3.139define void @f9(ptr %ptr, i64 %alt, i32 %limit) {140; CHECK-LABEL: f9:141; CHECK: jhe [[LABEL:[^ ]*]]142; CHECK: lg %r3, 0(%r2)143; CHECK: [[LABEL]]:144; CHECK: stg %r3, 0(%r2)145; CHECK: br %r14146 %cond = icmp ult i32 %limit, 420147 %orig = load i64, ptr %ptr148 %res = select i1 %cond, i64 %orig, i64 %alt149 store volatile i64 %res, ptr %ptr150 ret void151}152 153; Check that atomic loads are not matched. The transformation is OK for154; the "unordered" case tested here, but since we don't try to handle atomic155; operations at all in this context, it seems better to assert that than156; to restrict the test to a stronger ordering.157define void @f10(ptr %ptr, i64 %alt, i32 %limit) {158; FIXME: should use a normal load instead of CSG.159; CHECK-LABEL: f10:160; CHECK: lg {{%r[0-5]}}, 0(%r2)161; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]162; CHECK: [[LABEL]]:163; CHECK: stg {{%r[0-5]}}, 0(%r2)164; CHECK: br %r14165 %cond = icmp ult i32 %limit, 420166 %orig = load atomic i64, ptr %ptr unordered, align 8167 %res = select i1 %cond, i64 %orig, i64 %alt168 store i64 %res, ptr %ptr169 ret void170}171 172; ...likewise stores.173define void @f11(ptr %ptr, i64 %alt, i32 %limit) {174; FIXME: should use a normal store instead of CSG.175; CHECK-LABEL: f11:176; CHECK: jhe [[LABEL:[^ ]*]]177; CHECK: lg %r3, 0(%r2)178; CHECK: [[LABEL]]:179; CHECK: stg %r3, 0(%r2)180; CHECK: br %r14181 %cond = icmp ult i32 %limit, 420182 %orig = load i64, ptr %ptr183 %res = select i1 %cond, i64 %orig, i64 %alt184 store atomic i64 %res, ptr %ptr unordered, align 8185 ret void186}187 188; Try a frame index base.189define void @f12(i64 %alt, i32 %limit) {190; CHECK-LABEL: f12:191; CHECK: brasl %r14, foo@PLT192; CHECK-NOT: %r15193; CHECK: jl [[LABEL:[^ ]*]]194; CHECK-NOT: %r15195; CHECK: stg {{%r[0-9]+}}, {{[0-9]+}}(%r15)196; CHECK: [[LABEL]]:197; CHECK: brasl %r14, foo@PLT198; CHECK: br %r14199 %ptr = alloca i64200 call void @foo(ptr %ptr)201 %cond = icmp ult i32 %limit, 420202 %orig = load i64, ptr %ptr203 %res = select i1 %cond, i64 %orig, i64 %alt204 store i64 %res, ptr %ptr205 call void @foo(ptr %ptr)206 ret void207}208