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.fma.f64(double %f1, double %f2, double %f3) 7 8define double @f1(double %f1, double %f2, double %acc) { 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 = fsub double -0.0, %acc 15 %res = call double @llvm.fma.f64 (double %f1, double %f2, double %negacc) 16 ret double %res 17} 18 19define double @f2(double %f1, double *%ptr, double %acc) { 20; CHECK-LABEL: f2: 21; CHECK: msdb %f2, %f0, 0(%r2) 22; CHECK: ldr %f0, %f2 23; CHECK: br %r14 24 %f2 = load double , double *%ptr 25 %negacc = fsub double -0.0, %acc 26 %res = call double @llvm.fma.f64 (double %f1, double %f2, double %negacc) 27 ret double %res 28} 29 30define double @f3(double %f1, double *%base, double %acc) { 31; CHECK-LABEL: f3: 32; CHECK: msdb %f2, %f0, 4088(%r2) 33; CHECK: ldr %f0, %f2 34; CHECK: br %r14 35 %ptr = getelementptr double, double *%base, i64 511 36 %f2 = load double , double *%ptr 37 %negacc = fsub double -0.0, %acc 38 %res = call double @llvm.fma.f64 (double %f1, double %f2, double %negacc) 39 ret double %res 40} 41 42define double @f4(double %f1, double *%base, double %acc) { 43; The important thing here is that we don't generate an out-of-range 44; displacement. Other sequences besides this one would be OK. 45; 46; CHECK-LABEL: f4: 47; CHECK: aghi %r2, 4096 48; CHECK: msdb %f2, %f0, 0(%r2) 49; CHECK: ldr %f0, %f2 50; CHECK: br %r14 51 %ptr = getelementptr double, double *%base, i64 512 52 %f2 = load double , double *%ptr 53 %negacc = fsub double -0.0, %acc 54 %res = call double @llvm.fma.f64 (double %f1, double %f2, double %negacc) 55 ret double %res 56} 57 58define double @f5(double %f1, double *%base, double %acc) { 59; Here too the important thing is that we don't generate an out-of-range 60; displacement. Other sequences besides this one would be OK. 61; 62; CHECK-LABEL: f5: 63; CHECK: aghi %r2, -8 64; CHECK: msdb %f2, %f0, 0(%r2) 65; CHECK: ldr %f0, %f2 66; CHECK: br %r14 67 %ptr = getelementptr double, double *%base, i64 -1 68 %f2 = load double , double *%ptr 69 %negacc = fsub double -0.0, %acc 70 %res = call double @llvm.fma.f64 (double %f1, double %f2, double %negacc) 71 ret double %res 72} 73 74define double @f6(double %f1, double *%base, i64 %index, double %acc) { 75; CHECK-LABEL: f6: 76; CHECK: sllg %r1, %r3, 3 77; CHECK: msdb %f2, %f0, 0(%r1,%r2) 78; CHECK: ldr %f0, %f2 79; CHECK: br %r14 80 %ptr = getelementptr double, double *%base, i64 %index 81 %f2 = load double , double *%ptr 82 %negacc = fsub double -0.0, %acc 83 %res = call double @llvm.fma.f64 (double %f1, double %f2, double %negacc) 84 ret double %res 85} 86 87define double @f7(double %f1, double *%base, i64 %index, double %acc) { 88; CHECK-LABEL: f7: 89; CHECK: sllg %r1, %r3, 3 90; CHECK: msdb %f2, %f0, 4088({{%r1,%r2|%r2,%r1}}) 91; CHECK: ldr %f0, %f2 92; CHECK: br %r14 93 %index2 = add i64 %index, 511 94 %ptr = getelementptr double, double *%base, i64 %index2 95 %f2 = load double , double *%ptr 96 %negacc = fsub double -0.0, %acc 97 %res = call double @llvm.fma.f64 (double %f1, double %f2, double %negacc) 98 ret double %res 99} 100 101define double @f8(double %f1, double *%base, i64 %index, double %acc) { 102; CHECK-LABEL: f8: 103; CHECK: sllg %r1, %r3, 3 104; CHECK: lay %r1, 4096({{%r1,%r2|%r2,%r1}}) 105; CHECK: msdb %f2, %f0, 0(%r1) 106; CHECK: ldr %f0, %f2 107; CHECK: br %r14 108 %index2 = add i64 %index, 512 109 %ptr = getelementptr double, double *%base, i64 %index2 110 %f2 = load double , double *%ptr 111 %negacc = fsub double -0.0, %acc 112 %res = call double @llvm.fma.f64 (double %f1, double %f2, double %negacc) 113 ret double %res 114} 115