summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorDiana Picus <diana.picus@linaro.org>2016-07-18 06:48:25 +0000
committerDiana Picus <diana.picus@linaro.org>2016-07-18 06:48:25 +0000
commit774d157a5d1a2a03d7d6c724b987588b5c3bb279 (patch)
tree1c1edcffbbe6e6caa5c27805e41bbea3b42ab87b /llvm/lib/Target
parent197228927a84a15e7ca9d30ddc37113078239501 (diff)
downloadbcm5719-llvm-774d157a5d1a2a03d7d6c724b987588b5c3bb279.tar.gz
bcm5719-llvm-774d157a5d1a2a03d7d6c724b987588b5c3bb279.zip
[ARM] Honour ABI for rem under -O0 for EABI, GNUEABI, Android and Musl
At higher optimization levels, we generate the libcall for DIVREM_Ix, which is fine: aeabi_{u|i}divmod. At -O0 we generate the one for REM_Ix, which is the default {u}mod{q|h|s|d}i3. This commit makes sure that we don't generate REM_Ix calls for ABIs that don't support them (i.e. where we need to use DIVREM_Ix instead). This is achieved by bailing out of FastISel, which can't handle non-double multi-reg returns, and letting the legalization infrastructure expand the REM_Ix calls. It also updates the divmod-eabi.ll test to run under -O0 as well, and adds some Windows checks to it to make sure we don't break things for it. Fixes PR27068 Differential Revision: https://reviews.llvm.org/D21926 llvm-svn: 275773
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/ARM/ARMFastISel.cpp7
-rw-r--r--llvm/lib/Target/ARM/ARMISelLowering.cpp1
-rw-r--r--llvm/lib/Target/ARM/ARMISelLowering.h6
3 files changed, 14 insertions, 0 deletions
diff --git a/llvm/lib/Target/ARM/ARMFastISel.cpp b/llvm/lib/Target/ARM/ARMFastISel.cpp
index 0f11ac9a3a0..13724da5d4f 100644
--- a/llvm/lib/Target/ARM/ARMFastISel.cpp
+++ b/llvm/lib/Target/ARM/ARMFastISel.cpp
@@ -1718,6 +1718,13 @@ bool ARMFastISel::SelectRem(const Instruction *I, bool isSigned) {
if (!isTypeLegal(Ty, VT))
return false;
+ // Many ABIs do not provide a libcall for standalone remainder, so we need to
+ // use divrem (see the RTABI 4.3.1). Since FastISel can't handle non-double
+ // multi-reg returns, we'll have to bail out.
+ if (!TLI.hasStandaloneRem(VT)) {
+ return false;
+ }
+
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
if (VT == MVT::i8)
LC = isSigned ? RTLIB::SREM_I8 : RTLIB::UREM_I8;
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index ef019f98726..d6e7caf98a8 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -806,6 +806,7 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI()) {
setOperationAction(ISD::SREM, MVT::i64, Custom);
setOperationAction(ISD::UREM, MVT::i64, Custom);
+ HasStandaloneRem = false;
setLibcallName(RTLIB::SDIVREM_I8, "__aeabi_idivmod");
setLibcallName(RTLIB::SDIVREM_I16, "__aeabi_idivmod");
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h
index 1461ae6f673..4906686616b 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.h
+++ b/llvm/lib/Target/ARM/ARMISelLowering.h
@@ -478,6 +478,10 @@ namespace llvm {
return true;
}
+ bool hasStandaloneRem(EVT VT) const override {
+ return HasStandaloneRem;
+ }
+
protected:
std::pair<const TargetRegisterClass *, uint8_t>
findRepresentativeClass(const TargetRegisterInfo *TRI,
@@ -500,6 +504,8 @@ namespace llvm {
// check.
bool InsertFencesForAtomic;
+ bool HasStandaloneRem = true;
+
void addTypeForNEON(MVT VT, MVT PromotedLdStVT, MVT PromotedBitwiseVT);
void addDRTypeForNEON(MVT VT);
void addQRTypeForNEON(MVT VT);
OpenPOWER on IntegriCloud