1 ; Test f64 conditional stores that are presented as selects. 2 ; 3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s 4 5 declare void @foo(double *) 6 7 ; Test with the loaded value first. 8 define 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 , 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 24 define 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 , 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. 40 define 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, double *%base, i64 511 49 %cond = icmp ult i32 %limit, 420 50 %orig = load double , 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. 57 define 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, double *%base, i64 512 66 %cond = icmp ult i32 %limit, 420 67 %orig = load double , 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. 74 define 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, double *%base, i64 65535 83 %cond = icmp ult i32 %limit, 420 84 %orig = load double , 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. 92 define 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, double *%base, i64 65536 102 %cond = icmp ult i32 %limit, 420 103 %orig = load double , 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. 110 define 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, double *%base, i64 -65536 119 %cond = icmp ult i32 %limit, 420 120 %orig = load double , 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. 128 define 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, double *%base, i64 -65537 138 %cond = icmp ult i32 %limit, 420 139 %orig = load double , 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. 146 define 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 , 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. 165 define 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 , 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. 180 define 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 , 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. 195 define 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 , 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