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