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