summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDiana Picus <diana.picus@linaro.org>2017-04-18 08:32:27 +0000
committerDiana Picus <diana.picus@linaro.org>2017-04-18 08:32:27 +0000
commite2626bb7c29ea12d23e908c512ec64c2bb87abba (patch)
tree5cb24015719e4a908d097beeacad3c0cd5957d72
parentfb73eb0324e85c2ffcaef44b7be70df4f1fbb3ce (diff)
downloadbcm5719-llvm-e2626bb7c29ea12d23e908c512ec64c2bb87abba.tar.gz
bcm5719-llvm-e2626bb7c29ea12d23e908c512ec64c2bb87abba.zip
[ARM] Check for correct HW div when lowering divmod
For subtargets that use the custom lowering for divmod, e.g. gnueabi, we used to check if the subtarget has hardware divide and then lower to a div-mul-sub sequence if true, or to a libcall if false. However, judging by the usage of hasDivide vs hasDivideInARMMode, it seems that hasDivide only refers to Thumb. For instance, in the ARMTargetLowering constructor, the code that specifies whether to use libcalls for (S|U)DIV looks like this: bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivide() : Subtarget->hasDivideInARMMode(); In the case of divmod for arm-gnueabi, using only hasDivide() to determine what to do means that instead of lowering to __aeabi_idivmod to get the remainder, we lower to div-mul-sub and then further lower the div to __aeabi_idiv. Even worse, if we have hardware divide in ARM but not in Thumb, we generate a libcall instead of using it (this is not an issue in practice since AFAICT none of the cores that we support have hardware divide in ARM but not Thumb). This patch fixes the code dealing with custom lowering to take into account the mode (Thumb or ARM) when deciding whether or not hardware division is available. Differential Revision: https://reviews.llvm.org/D32005 llvm-svn: 300536
-rw-r--r--llvm/lib/Target/ARM/ARMISelLowering.cpp4
-rw-r--r--llvm/test/CodeGen/ARM/divmod-hwdiv.ll37
2 files changed, 40 insertions, 1 deletions
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index e697c8ca533..1cc7da3c9a0 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -13052,7 +13052,9 @@ SDValue ARMTargetLowering::LowerDivRem(SDValue Op, SelectionDAG &DAG) const {
// rem = a - b * div
// return {div, rem}
// This should be lowered into UDIV/SDIV + MLS later on.
- if (Subtarget->hasDivide() && Op->getValueType(0).isSimple() &&
+ bool hasDivide = Subtarget->isThumb() ? Subtarget->hasDivide()
+ : Subtarget->hasDivideInARMMode();
+ if (hasDivide && Op->getValueType(0).isSimple() &&
Op->getSimpleValueType(0) == MVT::i32) {
unsigned DivOpcode = isSigned ? ISD::SDIV : ISD::UDIV;
const SDValue Dividend = Op->getOperand(0);
diff --git a/llvm/test/CodeGen/ARM/divmod-hwdiv.ll b/llvm/test/CodeGen/ARM/divmod-hwdiv.ll
new file mode 100644
index 00000000000..4cc316ffa3e
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/divmod-hwdiv.ll
@@ -0,0 +1,37 @@
+; The hwdiv subtarget feature should only influence thumb, not arm.
+; RUN: llc < %s -mtriple=arm-gnueabi -mattr=+hwdiv | FileCheck %s -check-prefixes=ALL,AEABI-NOHWDIV
+; RUN: llc < %s -mtriple=arm-gnueabi -mattr=-hwdiv | FileCheck %s -check-prefixes=ALL,AEABI-NOHWDIV
+; RUN: llc < %s -mtriple=thumbv7-gnueabi -mattr=+hwdiv | FileCheck %s -check-prefixes=ALL,THUMB-HWDIV
+; RUN: llc < %s -mtriple=thumbv7-gnueabi -mattr=-hwdiv | FileCheck %s -check-prefixes=ALL,AEABI-NOHWDIV
+
+; The hwdiv-arm subtarget feature should only influence arm, not thumb.
+; RUN: llc < %s -mtriple=arm-gnueabi -mattr=+hwdiv-arm | FileCheck %s -check-prefixes=ALL,ARM-HWDIV
+; RUN: llc < %s -mtriple=arm-gnueabi -mattr=-hwdiv-arm | FileCheck %s -check-prefixes=ALL,AEABI-NOHWDIV
+; RUN: llc < %s -mtriple=thumbv7-gnueabi -mattr=+hwdiv-arm | FileCheck %s -check-prefixes=ALL,AEABI-NOHWDIV
+; RUN: llc < %s -mtriple=thumbv7-gnueabi -mattr=-hwdiv-arm | FileCheck %s -check-prefixes=ALL,AEABI-NOHWDIV
+
+define arm_aapcscc i32 @test_i32_srem(i32 %x, i32 %y) {
+; ALL-LABEL: test_i32_srem:
+; ARM-HWDIV: sdiv [[Q:r[0-9]+]], r0, r1
+; ARM-HWDIV: mul [[P:r[0-9]+]], [[Q]], r1
+; ARM-HWDIV: sub r0, r0, [[P]]
+; THUMB-HWDIV: sdiv [[Q:r[0-9]+]], r0, r1
+; THUMB-HWDIV: mls r0, [[Q]], r1, r0
+; AEABI-NOHWDIV: bl __aeabi_idivmod
+; AEABI-NOHWDIV: mov r0, r1
+ %r = srem i32 %x, %y
+ ret i32 %r
+}
+
+define arm_aapcscc i32 @test_i32_urem(i32 %x, i32 %y) {
+; ALL-LABEL: test_i32_urem:
+; ARM-HWDIV: udiv [[Q:r[0-9]+]], r0, r1
+; ARM-HWDIV: mul [[P:r[0-9]+]], [[Q]], r1
+; ARM-HWDIV: sub r0, r0, [[P]]
+; THUMB-HWDIV: udiv [[Q:r[0-9]+]], r0, r1
+; THUMB-HWDIV: mls r0, [[Q]], r1, r0
+; AEABI-NOHWDIV: bl __aeabi_uidivmod
+; AEABI-NOHWDIV: mov r0, r1
+ %r = urem i32 %x, %y
+ ret i32 %r
+}
OpenPOWER on IntegriCloud