1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 03:33:20 +01:00

[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
This commit is contained in:
Diana Picus 2017-04-18 08:32:27 +00:00
parent 507db3264b
commit 93efa79fb7
2 changed files with 40 additions and 1 deletions

View File

@ -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);

View File

@ -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
}