205 lines · plain
1; Test f64 conditional stores that are presented as selects.2;3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s4 5declare void @foo(ptr)6 7; Test with the loaded value first.8define void @f1(ptr %ptr, double %alt, i32 %limit) {9; CHECK-LABEL: f1:10; CHECK-NOT: %r211; CHECK: blr %r1412; CHECK-NOT: %r213; CHECK: std %f0, 0(%r2)14; CHECK: br %r1415 %cond = icmp ult i32 %limit, 42016 %orig = load double, ptr %ptr17 %res = select i1 %cond, double %orig, double %alt18 store double %res, ptr %ptr19 ret void20}21 22; ...and with the loaded value second23define void @f2(ptr %ptr, double %alt, i32 %limit) {24; CHECK-LABEL: f2:25; CHECK-NOT: %r226; CHECK: bher %r1427; CHECK-NOT: %r228; CHECK: std %f0, 0(%r2)29; CHECK: br %r1430 %cond = icmp ult i32 %limit, 42031 %orig = load double, ptr %ptr32 %res = select i1 %cond, double %alt, double %orig33 store double %res, ptr %ptr34 ret void35}36 37; Check the high end of the aligned STD range.38define void @f3(ptr %base, double %alt, i32 %limit) {39; CHECK-LABEL: f3:40; CHECK-NOT: %r241; CHECK: blr %r1442; CHECK-NOT: %r243; CHECK: std %f0, 4088(%r2)44; CHECK: br %r1445 %ptr = getelementptr double, ptr %base, i64 51146 %cond = icmp ult i32 %limit, 42047 %orig = load double, ptr %ptr48 %res = select i1 %cond, double %orig, double %alt49 store double %res, ptr %ptr50 ret void51}52 53; Check the next doubleword up, which should use STDY instead of STD.54define void @f4(ptr %base, double %alt, i32 %limit) {55; CHECK-LABEL: f4:56; CHECK-NOT: %r257; CHECK: blr %r1458; CHECK-NOT: %r259; CHECK: stdy %f0, 4096(%r2)60; CHECK: br %r1461 %ptr = getelementptr double, ptr %base, i64 51262 %cond = icmp ult i32 %limit, 42063 %orig = load double, ptr %ptr64 %res = select i1 %cond, double %orig, double %alt65 store double %res, ptr %ptr66 ret void67}68 69; Check the high end of the aligned STDY range.70define void @f5(ptr %base, double %alt, i32 %limit) {71; CHECK-LABEL: f5:72; CHECK-NOT: %r273; CHECK: blr %r1474; CHECK-NOT: %r275; CHECK: stdy %f0, 524280(%r2)76; CHECK: br %r1477 %ptr = getelementptr double, ptr %base, i64 6553578 %cond = icmp ult i32 %limit, 42079 %orig = load double, ptr %ptr80 %res = select i1 %cond, double %orig, double %alt81 store double %res, ptr %ptr82 ret void83}84 85; Check the next doubleword up, which needs separate address logic.86; Other sequences besides this one would be OK.87define void @f6(ptr %base, double %alt, i32 %limit) {88; CHECK-LABEL: f6:89; CHECK-NOT: %r290; CHECK: blr %r1491; CHECK-NOT: %r292; CHECK: agfi %r2, 52428893; CHECK: std %f0, 0(%r2)94; CHECK: br %r1495 %ptr = getelementptr double, ptr %base, i64 6553696 %cond = icmp ult i32 %limit, 42097 %orig = load double, ptr %ptr98 %res = select i1 %cond, double %orig, double %alt99 store double %res, ptr %ptr100 ret void101}102 103; Check the low end of the STDY range.104define void @f7(ptr %base, double %alt, i32 %limit) {105; CHECK-LABEL: f7:106; CHECK-NOT: %r2107; CHECK: blr %r14108; CHECK-NOT: %r2109; CHECK: stdy %f0, -524288(%r2)110; CHECK: br %r14111 %ptr = getelementptr double, ptr %base, i64 -65536112 %cond = icmp ult i32 %limit, 420113 %orig = load double, ptr %ptr114 %res = select i1 %cond, double %orig, double %alt115 store double %res, ptr %ptr116 ret void117}118 119; Check the next doubleword down, which needs separate address logic.120; Other sequences besides this one would be OK.121define void @f8(ptr %base, double %alt, i32 %limit) {122; CHECK-LABEL: f8:123; CHECK-NOT: %r2124; CHECK: blr %r14125; CHECK-NOT: %r2126; CHECK: agfi %r2, -524296127; CHECK: std %f0, 0(%r2)128; CHECK: br %r14129 %ptr = getelementptr double, ptr %base, i64 -65537130 %cond = icmp ult i32 %limit, 420131 %orig = load double, ptr %ptr132 %res = select i1 %cond, double %orig, double %alt133 store double %res, ptr %ptr134 ret void135}136 137; Check that STDY allows an index.138define void @f9(i64 %base, i64 %index, double %alt, i32 %limit) {139; CHECK-LABEL: f9:140; CHECK-NOT: %r2141; CHECK: blr %r14142; CHECK-NOT: %r2143; CHECK: stdy %f0, 524287(%r3,%r2)144; CHECK: br %r14145 %add1 = add i64 %base, %index146 %add2 = add i64 %add1, 524287147 %ptr = inttoptr i64 %add2 to ptr148 %cond = icmp ult i32 %limit, 420149 %orig = load double, ptr %ptr150 %res = select i1 %cond, double %orig, double %alt151 store double %res, ptr %ptr152 ret void153}154 155; Check that volatile loads are not matched.156define void @f10(ptr %ptr, double %alt, i32 %limit) {157; CHECK-LABEL: f10:158; CHECK: ld {{%f[0-5]}}, 0(%r2)159; CHECK: {{jl|jnl}} [[LABEL:[^ ]*]]160; CHECK: [[LABEL]]:161; CHECK: std {{%f[0-5]}}, 0(%r2)162; CHECK: br %r14163 %cond = icmp ult i32 %limit, 420164 %orig = load volatile double, ptr %ptr165 %res = select i1 %cond, double %orig, double %alt166 store double %res, ptr %ptr167 ret void168}169 170; ...likewise stores. In this case we should have a conditional load into %f0.171define void @f11(ptr %ptr, double %alt, i32 %limit) {172; CHECK-LABEL: f11:173; CHECK: jhe [[LABEL:[^ ]*]]174; CHECK: ld %f0, 0(%r2)175; CHECK: [[LABEL]]:176; CHECK: std %f0, 0(%r2)177; CHECK: br %r14178 %cond = icmp ult i32 %limit, 420179 %orig = load double, ptr %ptr180 %res = select i1 %cond, double %orig, double %alt181 store volatile double %res, ptr %ptr182 ret void183}184 185; Try a frame index base.186define void @f12(double %alt, i32 %limit) {187; CHECK-LABEL: f12:188; CHECK: brasl %r14, foo@PLT189; CHECK-NOT: %r15190; CHECK: jl [[LABEL:[^ ]*]]191; CHECK-NOT: %r15192; CHECK: std {{%f[0-9]+}}, {{[0-9]+}}(%r15)193; CHECK: [[LABEL]]:194; CHECK: brasl %r14, foo@PLT195; CHECK: br %r14196 %ptr = alloca double197 call void @foo(ptr %ptr)198 %cond = icmp ult i32 %limit, 420199 %orig = load double, ptr %ptr200 %res = select i1 %cond, double %orig, double %alt201 store double %res, ptr %ptr202 call void @foo(ptr %ptr)203 ret void204}205