diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -16528,6 +16528,15 @@ assert(!(DstSz == 32 && Subtarget->hasFP16()) && "With FP16, 16 to 32 conversion is legal!"); + // Converting from 32 -> 64 is valid if we have FP64. + if (SrcSz == 32 && DstSz == 64 && Subtarget->hasFP64()) { + // FIXME: Remove this when we have strict fp instruction selection patterns + if (IsStrict) { + DAG.mutateStrictFPToFP(Op.getNode()); + } + return Op; + } + // Either we are converting from 16 -> 64, without FP16 and/or // FP.double-precision or without Armv8-fp. So we must do it in two // steps. diff --git a/llvm/test/CodeGen/ARM/fp-intrinsics.ll b/llvm/test/CodeGen/ARM/fp-intrinsics.ll --- a/llvm/test/CodeGen/ARM/fp-intrinsics.ll +++ b/llvm/test/CodeGen/ARM/fp-intrinsics.ll @@ -1,7 +1,11 @@ -; RUN: llc -mtriple=armv8a-none-eabi %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-DP +; RUN: llc -mtriple=armv8a-none-eabi %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-DP,CHECK-SP-V8,CHECK-DP-V8 ; RUN: llc -mtriple=thumbv8m.main-none-eabi %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NOSP,CHECK-NODP -; RUN: llc -mtriple=thumbv8m.main-none-eabi %s -o - -mattr=fp-armv8 | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-DP -; RUN: llc -mtriple=thumbv8m.main-none-eabi %s -o - -mattr=fp-armv8sp | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-NODP +; RUN: llc -mtriple=thumbv8m.main-none-eabi %s -o - -mattr=fp-armv8 | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-DP,CHECK-SP-V8,CHECK-DP-V8 +; RUN: llc -mtriple=thumbv8m.main-none-eabi %s -o - -mattr=fp-armv8sp | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-NODP,CHECK-SP-V8 +; RUN: llc -mtriple=armv7a-none-eabi %s -o - -mattr=vfp4 | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-DP,CHECK-SP-NOV8,CHECK-DP-NOV8 +; RUN: llc -mtriple=thumbv7m-none-eabi %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NOSP,CHECK-NODP +; RUN: llc -mtriple=thumbv7m-none-eabi %s -o - -mattr=vfp4 | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-DP,CHECK-SP-NOV8,CHECK-DP-NOV8 +; RUN: llc -mtriple=thumbv7m-none-eabi %s -o - -mattr=vfp4sp | FileCheck %s --check-prefixes=CHECK,CHECK-SP,CHECK-NODP,CHECK-SP-NOV8 ; Check that constrained fp intrinsics are correctly lowered. In particular ; check that the valid combinations of single-precision and double-precision @@ -149,7 +153,8 @@ ; CHECK-LABEL: rint_f32: ; CHECK-NOSP: bl rintf -; CHECK-SP: vrintx.f32 +; CHECK-SP-NOV8: bl rintf +; CHECK-SP-V8: vrintx.f32 define float @rint_f32(float %x) #0 { %val = call float @llvm.experimental.constrained.rint.f32(float %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 ret float %val @@ -157,7 +162,8 @@ ; CHECK-LABEL: nearbyint_f32: ; CHECK-NOSP: bl nearbyintf -; CHECK-SP: vrintr.f32 +; CHECK-SP-NOV8: bl nearbyintf +; CHECK-SP-V8: vrintr.f32 define float @nearbyint_f32(float %x) #0 { %val = call float @llvm.experimental.constrained.nearbyint.f32(float %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 ret float %val @@ -179,7 +185,8 @@ ; CHECK-LABEL: maxnum_f32: ; CHECK-NOSP: bl fmaxf -; CHECK-SP: vmaxnm.f32 +; CHECK-SP-NOV8: bl fmaxf +; CHECK-SP-V8: vmaxnm.f32 define float @maxnum_f32(float %x, float %y) #0 { %val = call float @llvm.experimental.constrained.maxnum.f32(float %x, float %y, metadata !"fpexcept.strict") #0 ret float %val @@ -187,7 +194,8 @@ ; CHECK-LABEL: minnum_f32: ; CHECK-NOSP: bl fminf -; CHECK-SP: vminnm.f32 +; CHECK-SP-NOV8: bl fminf +; CHECK-SP-V8: vminnm.f32 define float @minnum_f32(float %x, float %y) #0 { %val = call float @llvm.experimental.constrained.minnum.f32(float %x, float %y, metadata !"fpexcept.strict") #0 ret float %val @@ -195,7 +203,8 @@ ; CHECK-LABEL: ceil_f32: ; CHECK-NOSP: bl ceilf -; CHECK-SP: vrintp.f32 +; CHECK-SP-NOV8: bl ceilf +; CHECK-SP-V8: vrintp.f32 define float @ceil_f32(float %x) #0 { %val = call float @llvm.experimental.constrained.ceil.f32(float %x, metadata !"fpexcept.strict") #0 ret float %val @@ -203,7 +212,8 @@ ; CHECK-LABEL: floor_f32: ; CHECK-NOSP: bl floorf -; CHECK-SP: vrintm.f32 +; CHECK-SP-NOV8: bl floorf +; CHECK-SP-V8: vrintm.f32 define float @floor_f32(float %x) #0 { %val = call float @llvm.experimental.constrained.floor.f32(float %x, metadata !"fpexcept.strict") #0 ret float %val @@ -225,7 +235,8 @@ ; CHECK-LABEL: round_f32: ; CHECK-NOSP: bl roundf -; CHECK-SP: vrinta.f32 +; CHECK-SP-NOV8: bl roundf +; CHECK-SP-V8: vrinta.f32 define float @round_f32(float %x) #0 { %val = call float @llvm.experimental.constrained.round.f32(float %x, metadata !"fpexcept.strict") #0 ret float %val @@ -233,7 +244,8 @@ ; CHECK-LABEL: trunc_f32: ; CHECK-NOSP: bl truncf -; CHECK-SP: vrintz.f32 +; CHECK-SP-NOV8: bl truncf +; CHECK-SP-V8: vrintz.f32 define float @trunc_f32(float %x) #0 { %val = call float @llvm.experimental.constrained.trunc.f32(float %x, metadata !"fpexcept.strict") #0 ret float %val @@ -598,7 +610,8 @@ ; CHECK-LABEL: rint_f64: ; CHECK-NODP: bl rint -; CHECK-DP: vrintx.f64 +; CHECK-DP-NOV8: bl rint +; CHECK-DP-V8: vrintx.f64 define double @rint_f64(double %x) #0 { %val = call double @llvm.experimental.constrained.rint.f64(double %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 ret double %val @@ -606,7 +619,8 @@ ; CHECK-LABEL: nearbyint_f64: ; CHECK-NODP: bl nearbyint -; CHECK-DP: vrintr.f64 +; CHECK-DP-NOV8: bl nearbyint +; CHECK-DP-V8: vrintr.f64 define double @nearbyint_f64(double %x) #0 { %val = call double @llvm.experimental.constrained.nearbyint.f64(double %x, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 ret double %val @@ -628,7 +642,8 @@ ; CHECK-LABEL: maxnum_f64: ; CHECK-NODP: bl fmax -; CHECK-DP: vmaxnm.f64 +; CHECK-DP-NOV8: bl fmax +; CHECK-DP-V8: vmaxnm.f64 define double @maxnum_f64(double %x, double %y) #0 { %val = call double @llvm.experimental.constrained.maxnum.f64(double %x, double %y, metadata !"fpexcept.strict") #0 ret double %val @@ -636,7 +651,8 @@ ; CHECK-LABEL: minnum_f64: ; CHECK-NODP: bl fmin -; CHECK-DP: vminnm.f64 +; CHECK-DP-NOV8: bl fmin +; CHECK-DP-V8: vminnm.f64 define double @minnum_f64(double %x, double %y) #0 { %val = call double @llvm.experimental.constrained.minnum.f64(double %x, double %y, metadata !"fpexcept.strict") #0 ret double %val @@ -644,7 +660,8 @@ ; CHECK-LABEL: ceil_f64: ; CHECK-NODP: bl ceil -; CHECK-DP: vrintp.f64 +; CHECK-DP-NOV8: bl ceil +; CHECK-DP-V8: vrintp.f64 define double @ceil_f64(double %x) #0 { %val = call double @llvm.experimental.constrained.ceil.f64(double %x, metadata !"fpexcept.strict") #0 ret double %val @@ -652,7 +669,8 @@ ; CHECK-LABEL: floor_f64: ; CHECK-NODP: bl floor -; CHECK-DP: vrintm.f64 +; CHECK-DP-NOV8: bl floor +; CHECK-DP-V8: vrintm.f64 define double @floor_f64(double %x) #0 { %val = call double @llvm.experimental.constrained.floor.f64(double %x, metadata !"fpexcept.strict") #0 ret double %val @@ -674,7 +692,8 @@ ; CHECK-LABEL: round_f64: ; CHECK-NODP: bl round -; CHECK-DP: vrinta.f64 +; CHECK-DP-NOV8: bl round +; CHECK-DP-V8: vrinta.f64 define double @round_f64(double %x) #0 { %val = call double @llvm.experimental.constrained.round.f64(double %x, metadata !"fpexcept.strict") #0 ret double %val @@ -682,7 +701,8 @@ ; CHECK-LABEL: trunc_f64: ; CHECK-NODP: bl trunc -; CHECK-DP: vrintz.f64 +; CHECK-DP-NOV8: bl trunc +; CHECK-DP-V8: vrintz.f64 define double @trunc_f64(double %x) #0 { %val = call double @llvm.experimental.constrained.trunc.f64(double %x, metadata !"fpexcept.strict") #0 ret double %val