1; Test strict floating-point truncations. 2; 3; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 \ 4; RUN: | FileCheck -check-prefix=CHECK -check-prefix=CHECK-SCALAR %s 5; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 \ 6; RUN: | FileCheck -check-prefix=CHECK -check-prefix=CHECK-VECTOR %s 7 8declare float @llvm.experimental.constrained.fptrunc.f32.f64(double, metadata, metadata) 9declare float @llvm.experimental.constrained.fptrunc.f32.f128(fp128, metadata, metadata) 10declare double @llvm.experimental.constrained.fptrunc.f64.f128(fp128, metadata, metadata) 11 12declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata) 13declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata) 14 15; Test f64->f32. 16define float @f1(double %d1, double %d2) #0 { 17; CHECK-LABEL: f1: 18; CHECK-SCALAR: ledbr %f0, %f2 19; CHECK-VECTOR: ledbra %f0, 0, %f2, 0 20; CHECK: br %r14 21 %res = call float @llvm.experimental.constrained.fptrunc.f32.f64( 22 double %d2, 23 metadata !"round.dynamic", 24 metadata !"fpexcept.strict") #0 25 ret float %res 26} 27 28; Test f128->f32. 29define float @f2(fp128 *%ptr) #0 { 30; CHECK-LABEL: f2: 31; CHECK: lexbr %f0, %f0 32; CHECK: br %r14 33 %val = load fp128, fp128 *%ptr 34 %res = call float @llvm.experimental.constrained.fptrunc.f32.f128( 35 fp128 %val, 36 metadata !"round.dynamic", 37 metadata !"fpexcept.strict") #0 38 ret float %res 39} 40 41; Make sure that we don't use %f0 as the destination of LEXBR when %f2 42; is still live. 43define void @f3(float *%dst, fp128 *%ptr, float %d1, float %d2) #0 { 44; CHECK-LABEL: f3: 45; CHECK: lexbr %f1, %f1 46; CHECK: aebr %f1, %f2 47; CHECK: ste %f1, 0(%r2) 48; CHECK: br %r14 49 %val = load fp128, fp128 *%ptr 50 %conv = call float @llvm.experimental.constrained.fptrunc.f32.f128( 51 fp128 %val, 52 metadata !"round.dynamic", 53 metadata !"fpexcept.strict") #0 54 %res = call float @llvm.experimental.constrained.fadd.f32( 55 float %conv, float %d2, 56 metadata !"round.dynamic", 57 metadata !"fpexcept.strict") #0 58 store float %res, float *%dst 59 ret void 60} 61 62; Test f128->f64. 63define double @f4(fp128 *%ptr) #0 { 64; CHECK-LABEL: f4: 65; CHECK: ldxbr %f0, %f0 66; CHECK: br %r14 67 %val = load fp128, fp128 *%ptr 68 %res = call double @llvm.experimental.constrained.fptrunc.f64.f128( 69 fp128 %val, 70 metadata !"round.dynamic", 71 metadata !"fpexcept.strict") #0 72 ret double %res 73} 74 75; Like f3, but for f128->f64. 76define void @f5(double *%dst, fp128 *%ptr, double %d1, double %d2) #0 { 77; CHECK-LABEL: f5: 78; CHECK: ldxbr %f1, %f1 79; CHECK-SCALAR: adbr %f1, %f2 80; CHECK-SCALAR: std %f1, 0(%r2) 81; CHECK-VECTOR: wfadb [[REG:%f[0-9]+]], %f1, %f2 82; CHECK-VECTOR: std [[REG]], 0(%r2) 83; CHECK: br %r14 84 %val = load fp128, fp128 *%ptr 85 %conv = call double @llvm.experimental.constrained.fptrunc.f64.f128( 86 fp128 %val, 87 metadata !"round.dynamic", 88 metadata !"fpexcept.strict") #0 89 %res = call double @llvm.experimental.constrained.fadd.f64( 90 double %conv, double %d2, 91 metadata !"round.dynamic", 92 metadata !"fpexcept.strict") #0 93 store double %res, double *%dst 94 ret void 95} 96 97attributes #0 = { strictfp } 98