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 6 declare double @llvm.fma.f64(double %f1, double %f2, double %f3) 7 8 define 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 19 define 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 30 define 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 42 define 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 58 define 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 74 define 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 87 define 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 101 define 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