[ARM] Merging 64-bit divmod lib calls into one
When div+rem calls on the same arguments are found, the ARM back-end merges the two calls into one __aeabi_divmod call for up to 32-bits values. However, for 64-bit values, which also have a lib call (__aeabi_ldivmod), it wasn't merging the calls, and thus calling ldivmod twice and spilling the temporary results, which generated pretty bad code. This patch legalises 64-bit lib calls for divmod, so that now all the spilling and the second call are gone. It also relaxes the DivRem combiner a bit on the legal type check, since it was already checking for isLegalOrCustom on every value, so the extra check for isTypeLegal was redundant. This patch fixes PR17193 (and a long time FIXME in the tests). llvm-svn: 262507
This commit is contained in:
parent
cbbaeb1307
commit
93e42d9934
|
@ -2153,8 +2153,9 @@ SDValue DAGCombiner::useDivRem(SDNode *Node) {
|
|||
if (Node->use_empty())
|
||||
return SDValue(); // This is a dead node, leave it alone.
|
||||
|
||||
// DivMod lib calls can still work on non-legal types if using lib-calls.
|
||||
EVT VT = Node->getValueType(0);
|
||||
if (!TLI.isTypeLegal(VT))
|
||||
if (VT.isVector() || !VT.isInteger())
|
||||
return SDValue();
|
||||
|
||||
unsigned Opcode = Node->getOpcode();
|
||||
|
|
|
@ -809,6 +809,8 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
|
|||
|
||||
setOperationAction(ISD::SDIVREM, MVT::i32, Custom);
|
||||
setOperationAction(ISD::UDIVREM, MVT::i32, Custom);
|
||||
setOperationAction(ISD::SDIVREM, MVT::i64, Custom);
|
||||
setOperationAction(ISD::UDIVREM, MVT::i64, Custom);
|
||||
} else {
|
||||
setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
|
||||
setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
|
||||
|
@ -7054,6 +7056,13 @@ void ARMTargetLowering::ReplaceNodeResults(SDNode *N,
|
|||
case ISD::UREM:
|
||||
Res = LowerREM(N, DAG);
|
||||
break;
|
||||
case ISD::SDIVREM:
|
||||
case ISD::UDIVREM:
|
||||
Res = LowerDivRem(SDValue(N, 0), DAG);
|
||||
assert(Res.getNumOperands() == 2 && "DivRem needs two values");
|
||||
Results.push_back(Res.getValue(0));
|
||||
Results.push_back(Res.getValue(1));
|
||||
return;
|
||||
case ISD::READCYCLECOUNTER:
|
||||
ReplaceREADCYCLECOUNTER(N, Results, DAG, Subtarget);
|
||||
return;
|
||||
|
|
|
@ -79,7 +79,6 @@ entry:
|
|||
ret i32 %add2
|
||||
}
|
||||
|
||||
; FIXME: AEABI is not lowering long u/srem into u/ldivmod
|
||||
define i64 @longf(i64 %a, i64 %b) {
|
||||
; EABI-LABEL: longf:
|
||||
; DARWIN-LABEL: longf:
|
||||
|
@ -87,6 +86,9 @@ entry:
|
|||
%div = sdiv i64 %a, %b
|
||||
%rem = srem i64 %a, %b
|
||||
; EABI: __aeabi_ldivmod
|
||||
; EABI-NEXT: adds r0
|
||||
; EABI-NEXT: adc r1
|
||||
; EABI-NOT: __aeabi_ldivmod
|
||||
; DARWIN: ___divdi3
|
||||
; DARWIN: mov [[div1:r[0-9]+]], r0
|
||||
; DARWIN: mov [[div2:r[0-9]+]], r1
|
||||
|
|
Loading…
Reference in New Issue