1; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 \ 2; RUN: | FileCheck -check-prefix=CHECK -check-prefix=CHECK-SCALAR %s 3; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 \ 4; RUN: | FileCheck -check-prefix=CHECK -check-prefix=CHECK-VECTOR %s 5 6declare double @llvm.experimental.constrained.fma.f64(double %f1, double %f2, double %f3, metadata, metadata) 7 8define double @f1(double %f1, double %f2, double %acc) #0 { 9; CHECK-LABEL: f1: 10; CHECK-SCALAR: msdbr %f4, %f0, %f2 11; CHECK-SCALAR: ldr %f0, %f4 12; CHECK-VECTOR: wfmsdb %f0, %f0, %f2, %f4 13; CHECK: br %r14 14 %negacc = fneg double %acc 15 %res = call double @llvm.experimental.constrained.fma.f64 ( 16 double %f1, double %f2, double %negacc, 17 metadata !"round.dynamic", 18 metadata !"fpexcept.strict") #0 19 ret double %res 20} 21 22define double @f2(double %f1, double *%ptr, double %acc) #0 { 23; CHECK-LABEL: f2: 24; CHECK: msdb %f2, %f0, 0(%r2) 25; CHECK: ldr %f0, %f2 26; CHECK: br %r14 27 %f2 = load double, double *%ptr 28 %negacc = fneg double %acc 29 %res = call double @llvm.experimental.constrained.fma.f64 ( 30 double %f1, double %f2, double %negacc, 31 metadata !"round.dynamic", 32 metadata !"fpexcept.strict") #0 33 ret double %res 34} 35 36define double @f3(double %f1, double *%base, double %acc) #0 { 37; CHECK-LABEL: f3: 38; CHECK: msdb %f2, %f0, 4088(%r2) 39; CHECK: ldr %f0, %f2 40; CHECK: br %r14 41 %ptr = getelementptr double, double *%base, i64 511 42 %f2 = load double, double *%ptr 43 %negacc = fneg double %acc 44 %res = call double @llvm.experimental.constrained.fma.f64 ( 45 double %f1, double %f2, double %negacc, 46 metadata !"round.dynamic", 47 metadata !"fpexcept.strict") #0 48 ret double %res 49} 50 51define double @f4(double %f1, double *%base, double %acc) #0 { 52; The important thing here is that we don't generate an out-of-range 53; displacement. Other sequences besides this one would be OK. 54; 55; CHECK-LABEL: f4: 56; CHECK: aghi %r2, 4096 57; CHECK: msdb %f2, %f0, 0(%r2) 58; CHECK: ldr %f0, %f2 59; CHECK: br %r14 60 %ptr = getelementptr double, double *%base, i64 512 61 %f2 = load double, double *%ptr 62 %negacc = fneg double %acc 63 %res = call double @llvm.experimental.constrained.fma.f64 ( 64 double %f1, double %f2, double %negacc, 65 metadata !"round.dynamic", 66 metadata !"fpexcept.strict") #0 67 ret double %res 68} 69 70define double @f5(double %f1, double *%base, double %acc) #0 { 71; Here too the important thing is that we don't generate an out-of-range 72; displacement. Other sequences besides this one would be OK. 73; 74; CHECK-LABEL: f5: 75; CHECK: aghi %r2, -8 76; CHECK: msdb %f2, %f0, 0(%r2) 77; CHECK: ldr %f0, %f2 78; CHECK: br %r14 79 %ptr = getelementptr double, double *%base, i64 -1 80 %f2 = load double, double *%ptr 81 %negacc = fneg double %acc 82 %res = call double @llvm.experimental.constrained.fma.f64 ( 83 double %f1, double %f2, double %negacc, 84 metadata !"round.dynamic", 85 metadata !"fpexcept.strict") #0 86 ret double %res 87} 88 89define double @f6(double %f1, double *%base, i64 %index, double %acc) #0 { 90; CHECK-LABEL: f6: 91; CHECK: sllg %r1, %r3, 3 92; CHECK: msdb %f2, %f0, 0(%r1,%r2) 93; CHECK: ldr %f0, %f2 94; CHECK: br %r14 95 %ptr = getelementptr double, double *%base, i64 %index 96 %f2 = load double, double *%ptr 97 %negacc = fneg double %acc 98 %res = call double @llvm.experimental.constrained.fma.f64 ( 99 double %f1, double %f2, double %negacc, 100 metadata !"round.dynamic", 101 metadata !"fpexcept.strict") #0 102 ret double %res 103} 104 105define double @f7(double %f1, double *%base, i64 %index, double %acc) #0 { 106; CHECK-LABEL: f7: 107; CHECK: sllg %r1, %r3, 3 108; CHECK: msdb %f2, %f0, 4088({{%r1,%r2|%r2,%r1}}) 109; CHECK: ldr %f0, %f2 110; CHECK: br %r14 111 %index2 = add i64 %index, 511 112 %ptr = getelementptr double, double *%base, i64 %index2 113 %f2 = load double, double *%ptr 114 %negacc = fneg double %acc 115 %res = call double @llvm.experimental.constrained.fma.f64 ( 116 double %f1, double %f2, double %negacc, 117 metadata !"round.dynamic", 118 metadata !"fpexcept.strict") #0 119 ret double %res 120} 121 122define double @f8(double %f1, double *%base, i64 %index, double %acc) #0 { 123; CHECK-LABEL: f8: 124; CHECK: sllg %r1, %r3, 3 125; CHECK: lay %r1, 4096({{%r1,%r2|%r2,%r1}}) 126; CHECK: msdb %f2, %f0, 0(%r1) 127; CHECK: ldr %f0, %f2 128; CHECK: br %r14 129 %index2 = add i64 %index, 512 130 %ptr = getelementptr double, double *%base, i64 %index2 131 %f2 = load double, double *%ptr 132 %negacc = fneg double %acc 133 %res = call double @llvm.experimental.constrained.fma.f64 ( 134 double %f1, double %f2, double %negacc, 135 metadata !"round.dynamic", 136 metadata !"fpexcept.strict") #0 137 ret double %res 138} 139 140attributes #0 = { strictfp } 141