diff options
author | Tim Northover <tnorthover@apple.com> | 2017-02-23 22:35:00 +0000 |
---|---|---|
committer | Tim Northover <tnorthover@apple.com> | 2017-02-23 22:35:00 +0000 |
commit | 063a56e81c89dfbf7896c71c8cd849b911eb7098 (patch) | |
tree | 1aab79ee7cf41c79efcf2d847aff161623d3c925 /llvm | |
parent | 5cd9a9bf8c1859fcc8f67bcb2e73e0da1ee4d72c (diff) | |
download | bcm5719-llvm-063a56e81c89dfbf7896c71c8cd849b911eb7098.tar.gz bcm5719-llvm-063a56e81c89dfbf7896c71c8cd849b911eb7098.zip |
ARM: make sure FastISel bails on f64 operations for Cortex-M4.
FastISel wasn't checking the isFPOnlySP subtarget feature before emitting
double-precision operations, so it got completely invalid CodeGen for doubles
on Cortex-M4F.
The normal ISel testing wasn't spectacular either so I added a second RUN line
to improve that while I was in the area.
llvm-svn: 296031
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/Target/ARM/ARMFastISel.cpp | 21 | ||||
-rw-r--r-- | llvm/test/CodeGen/ARM/fp-only-sp.ll | 62 |
2 files changed, 75 insertions, 8 deletions
diff --git a/llvm/lib/Target/ARM/ARMFastISel.cpp b/llvm/lib/Target/ARM/ARMFastISel.cpp index b484ce00962..6638edfa05c 100644 --- a/llvm/lib/Target/ARM/ARMFastISel.cpp +++ b/llvm/lib/Target/ARM/ARMFastISel.cpp @@ -1350,8 +1350,10 @@ bool ARMFastISel::ARMEmitCmp(const Value *Src1Value, const Value *Src2Value, if (!SrcEVT.isSimple()) return false; MVT SrcVT = SrcEVT.getSimpleVT(); - bool isFloat = (Ty->isFloatTy() || Ty->isDoubleTy()); - if (isFloat && !Subtarget->hasVFP2()) + if (Ty->isFloatTy() && !Subtarget->hasVFP2()) + return false; + + if (Ty->isDoubleTy() && (!Subtarget->hasVFP2() || Subtarget->isFPOnlySP())) return false; // Check to see if the 2nd operand is a constant that we can encode directly @@ -1501,7 +1503,7 @@ bool ARMFastISel::SelectCmp(const Instruction *I) { bool ARMFastISel::SelectFPExt(const Instruction *I) { // Make sure we have VFP and that we're extending float to double. - if (!Subtarget->hasVFP2()) return false; + if (!Subtarget->hasVFP2() || Subtarget->isFPOnlySP()) return false; Value *V = I->getOperand(0); if (!I->getType()->isDoubleTy() || @@ -1520,7 +1522,7 @@ bool ARMFastISel::SelectFPExt(const Instruction *I) { bool ARMFastISel::SelectFPTrunc(const Instruction *I) { // Make sure we have VFP and that we're truncating double to float. - if (!Subtarget->hasVFP2()) return false; + if (!Subtarget->hasVFP2() || Subtarget->isFPOnlySP()) return false; Value *V = I->getOperand(0); if (!(I->getType()->isFloatTy() && @@ -1571,7 +1573,8 @@ bool ARMFastISel::SelectIToFP(const Instruction *I, bool isSigned) { unsigned Opc; if (Ty->isFloatTy()) Opc = isSigned ? ARM::VSITOS : ARM::VUITOS; - else if (Ty->isDoubleTy()) Opc = isSigned ? ARM::VSITOD : ARM::VUITOD; + else if (Ty->isDoubleTy() && !Subtarget->isFPOnlySP()) + Opc = isSigned ? ARM::VSITOD : ARM::VUITOD; else return false; unsigned ResultReg = createResultReg(TLI.getRegClassFor(DstVT)); @@ -1596,7 +1599,8 @@ bool ARMFastISel::SelectFPToI(const Instruction *I, bool isSigned) { unsigned Opc; Type *OpTy = I->getOperand(0)->getType(); if (OpTy->isFloatTy()) Opc = isSigned ? ARM::VTOSIZS : ARM::VTOUIZS; - else if (OpTy->isDoubleTy()) Opc = isSigned ? ARM::VTOSIZD : ARM::VTOUIZD; + else if (OpTy->isDoubleTy() && !Subtarget->isFPOnlySP()) + Opc = isSigned ? ARM::VTOSIZD : ARM::VTOUIZD; else return false; // f64->s32/u32 or f32->s32/u32 both need an intermediate f32 reg. @@ -1800,8 +1804,9 @@ bool ARMFastISel::SelectBinaryFPOp(const Instruction *I, unsigned ISDOpcode) { // if we have them. // FIXME: It'd be nice to use NEON instructions. Type *Ty = I->getType(); - bool isFloat = (Ty->isDoubleTy() || Ty->isFloatTy()); - if (isFloat && !Subtarget->hasVFP2()) + if (Ty->isFloatTy() && !Subtarget->hasVFP2()) + return false; + if (Ty->isDoubleTy() && (!Subtarget->hasVFP2() || Subtarget->isFPOnlySP())) return false; unsigned Opc; diff --git a/llvm/test/CodeGen/ARM/fp-only-sp.ll b/llvm/test/CodeGen/ARM/fp-only-sp.ll new file mode 100644 index 00000000000..2c7b2acbde9 --- /dev/null +++ b/llvm/test/CodeGen/ARM/fp-only-sp.ll @@ -0,0 +1,62 @@ +; RUN: llc -mtriple=thumbv7em-apple-macho -mcpu=cortex-m4 %s -o - -O0 | FileCheck %s +; RUN: llc -mtriple=thumbv7em-apple-macho -mcpu=cortex-m4 %s -o - | FileCheck %s + +; Note: vldr and vstr really do have 64-bit variants even with fp-only-sp +define void @test_load_store(double* %addr) { +; CHECK-LABEL: test_load_store: +; CHECK: vldr [[TMP:d[0-9]+]], [r0] +; CHECK: vstr [[TMP]], [r0] + %val = load volatile double, double* %addr + store volatile double %val, double* %addr + ret void +} + +define void @test_cmp(double %l, double %r, i1* %addr.dst) { +; CHECK-LABEL: test_cmp: +; CHECK: bl ___eqdf2 + %res = fcmp oeq double %l, %r + store i1 %res, i1* %addr.dst + ret void +} + +define void @test_ext(float %in, double* %addr) { +; CHECK-LABEL: test_ext: +; CHECK: bl ___extendsfdf2 + %res = fpext float %in to double + store double %res, double* %addr + ret void +} + +define void @test_trunc(double %in, float* %addr) { +; CHECK-LABEL: test_trunc: +; CHECK: bl ___truncdfsf2 + %res = fptrunc double %in to float + store float %res, float* %addr + ret void +} + +define void @test_itofp(i32 %in, double* %addr) { +; CHECK-LABEL: test_itofp: +; CHECK: bl ___floatsidf + %res = sitofp i32 %in to double + store double %res, double* %addr +; %res = fptoui double %tmp to i32 + ret void +} + +define i32 @test_fptoi(double* %addr) { +; CHECK-LABEL: test_fptoi: +; CHECK: bl ___fixunsdfsi + %val = load double, double* %addr + %res = fptoui double %val to i32 + ret i32 %res +} + +define void @test_binop(double* %addr) { +; CHECK-LABEL: test_binop: +; CHECK: bl ___adddf3 + %in = load double, double* %addr + %res = fadd double %in, %in + store double %res, double* %addr + ret void +} |