1; Test f64 conditional stores that are presented as selects. 2; 3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s 4 5declare void @foo(double *) 6 7; Test with the loaded value first. 8define void @f1(double *%ptr, double %alt, i32 %limit) { 9; CHECK-LABEL: f1: 10; CHECK-NOT: %r2 11; CHECK: blr %r14 12; CHECK-NOT: %r2 13; CHECK: std %f0, 0(%r2) 14; CHECK: br %r14 15 %cond = icmp ult i32 %limit, 420 16 %orig = load double, double *%ptr 17 %res = select i1 %cond, double %orig, double %alt 18 store double %res, double *%ptr 19 ret void 20} 21 22; ...and with the loaded value second 23define void @f2(double *%ptr, double %alt, i32 %limit) { 24; CHECK-LABEL: f2: 25; CHECK-NOT: %r2 26; CHECK: bher %r14 27; CHECK-NOT: %r2 28; CHECK: std %f0, 0(%r2) 29; CHECK: br %r14 30 %cond = icmp ult i32 %limit, 420 31 %orig = load double, double *%ptr 32 %res = select i1 %cond, double %alt, double %orig 33 store double %res, double *%ptr 34 ret void 35} 36 37; Check the high end of the aligned STD range. 38define void @f3(double *%base, double %alt, i32 %limit) { 39; CHECK-LABEL: f3: 40; CHECK-NOT: %r2 41; CHECK: blr %r14 42; CHECK-NOT: %r2 43; CHECK: std %f0, 4088(%r2) 44; CHECK: br %r14 45 %ptr = getelementptr double, double *%base, i64 511 46 %cond = icmp ult i32 %limit, 420 47 %orig = load double, double *%ptr 48 %res = select i1 %cond, double %orig, double %alt 49 store double %res, double *%ptr 50 ret void 51} 52 53; Check the next doubleword up, which should use STDY instead of STD. 54define void @f4(double *%base, double %alt, i32 %limit) { 55; CHECK-LABEL: f4: 56; CHECK-NOT: %r2 57; CHECK: blr %r14 58; CHECK-NOT: %r2 59; CHECK: stdy %f0, 4096(%r2) 60; CHECK: br %r14 61 %ptr = getelementptr double, double *%base, i64 512 62 %cond = icmp ult i32 %limit, 420 63 %orig = load double, double *%ptr 64 %res = select i1 %cond, double %orig, double %alt 65 store double %res, double *%ptr 66 ret void 67} 68 69; Check the high end of the aligned STDY range. 70define void @f5(double *%base, double %alt, i32 %limit) { 71; CHECK-LABEL: f5: 72; CHECK-NOT: %r2 73; CHECK: blr %r14 74; CHECK-NOT: %r2 75; CHECK: stdy %f0, 524280(%r2) 76; CHECK: br %r14 77 %ptr = getelementptr double, double *%base, i64 65535 78 %cond = icmp ult i32 %limit, 420 79 %orig = load double, double *%ptr 80 %res = select i1 %cond, double %orig, double %alt 81 store double %res, double *%ptr 82 ret void 83} 84 85; Check the next doubleword up, which needs separate address logic. 86; Other sequences besides this one would be OK. 87define void @f6(double *%base, double %alt, i32 %limit) { 88; CHECK-LABEL: f6: 89; CHECK-NOT: %r2 90; CHECK: blr %r14 91; CHECK-NOT: %r2 92; CHECK: agfi %r2, 524288 93; CHECK: std %f0, 0(%r2) 94; CHECK: br %r14 95 %ptr = getelementptr double, double *%base, i64 65536 96 %cond = icmp ult i32 %limit, 420 97 %orig = load double, double *%ptr 98 %res = select i1 %cond, double %orig, double %alt 99 store double %res, double *%ptr 100 ret void 101} 102 103; Check the low end of the STDY range. 104define void @f7(double *%base, double %alt, i32 %limit) { 105; CHECK-LABEL: f7: 106; CHECK-NOT: %r2 107; CHECK: blr %r14 108; CHECK-NOT: %r2 109; CHECK: stdy %f0, -524288(%r2) 110; CHECK: br %r14 111 %ptr = getelementptr double, double *%base, i64 -65536 112 %cond = icmp ult i32 %limit, 420 113 %orig = load double, double *%ptr 114 %res = select i1 %cond, double %orig, double %alt 115 store double %res, double *%ptr 116 ret void 117} 118 119; Check the next doubleword down, which needs separate address logic. 120; Other sequences besides this one would be OK. 121define void @f8(double *%base, double %alt, i32 %limit) { 122; CHECK-LABEL: f8: 123; CHECK-NOT: %r2 124; CHECK: blr %r14 125; CHECK-NOT: %r2 126; CHECK: agfi %r2, -524296 127; CHECK: std %f0, 0(%r2) 128; CHECK: br %r14 129 %ptr = getelementptr double, double *%base, i64 -65537 130 %cond = icmp ult i32 %limit, 420 131 %orig = load double, double *%ptr 132 %res = select i1 %cond, double %orig, double %alt 133 store double %res, double *%ptr 134 ret void 135} 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: %r2 141; CHECK: blr %r14 142; CHECK-NOT: %r2 143; CHECK: stdy %f0, 524287(%r3,%r2) 144; CHECK: br %r14 145 %add1 = add i64 %base, %index 146 %add2 = add i64 %add1, 524287 147 %ptr = inttoptr i64 %add2 to double * 148 %cond = icmp ult i32 %limit, 420 149 %orig = load double, double *%ptr 150 %res = select i1 %cond, double %orig, double %alt 151 store double %res, double *%ptr 152 ret void 153} 154 155; Check that volatile loads are not matched. 156define void @f10(double *%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 %r14 163 %cond = icmp ult i32 %limit, 420 164 %orig = load volatile double, double *%ptr 165 %res = select i1 %cond, double %orig, double %alt 166 store double %res, double *%ptr 167 ret void 168} 169 170; ...likewise stores. In this case we should have a conditional load into %f0. 171define void @f11(double *%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 %r14 178 %cond = icmp ult i32 %limit, 420 179 %orig = load double, double *%ptr 180 %res = select i1 %cond, double %orig, double %alt 181 store volatile double %res, double *%ptr 182 ret void 183} 184 185; Try a frame index base. 186define void @f12(double %alt, i32 %limit) { 187; CHECK-LABEL: f12: 188; CHECK: brasl %r14, foo@PLT 189; CHECK-NOT: %r15 190; CHECK: jl [[LABEL:[^ ]*]] 191; CHECK-NOT: %r15 192; CHECK: std {{%f[0-9]+}}, {{[0-9]+}}(%r15) 193; CHECK: [[LABEL]]: 194; CHECK: brasl %r14, foo@PLT 195; CHECK: br %r14 196 %ptr = alloca double 197 call void @foo(double *%ptr) 198 %cond = icmp ult i32 %limit, 420 199 %orig = load double, double *%ptr 200 %res = select i1 %cond, double %orig, double %alt 201 store double %res, double *%ptr 202 call void @foo(double *%ptr) 203 ret void 204} 205