[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())
|
if (Node->use_empty())
|
||||||
return SDValue(); // This is a dead node, leave it alone.
|
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);
|
EVT VT = Node->getValueType(0);
|
||||||
if (!TLI.isTypeLegal(VT))
|
if (VT.isVector() || !VT.isInteger())
|
||||||
return SDValue();
|
return SDValue();
|
||||||
|
|
||||||
unsigned Opcode = Node->getOpcode();
|
unsigned Opcode = Node->getOpcode();
|
||||||
|
|
|
@ -809,6 +809,8 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
|
||||||
|
|
||||||
setOperationAction(ISD::SDIVREM, MVT::i32, Custom);
|
setOperationAction(ISD::SDIVREM, MVT::i32, Custom);
|
||||||
setOperationAction(ISD::UDIVREM, MVT::i32, Custom);
|
setOperationAction(ISD::UDIVREM, MVT::i32, Custom);
|
||||||
|
setOperationAction(ISD::SDIVREM, MVT::i64, Custom);
|
||||||
|
setOperationAction(ISD::UDIVREM, MVT::i64, Custom);
|
||||||
} else {
|
} else {
|
||||||
setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
|
setOperationAction(ISD::SDIVREM, MVT::i32, Expand);
|
||||||
setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
|
setOperationAction(ISD::UDIVREM, MVT::i32, Expand);
|
||||||
|
@ -7054,6 +7056,13 @@ void ARMTargetLowering::ReplaceNodeResults(SDNode *N,
|
||||||
case ISD::UREM:
|
case ISD::UREM:
|
||||||
Res = LowerREM(N, DAG);
|
Res = LowerREM(N, DAG);
|
||||||
break;
|
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:
|
case ISD::READCYCLECOUNTER:
|
||||||
ReplaceREADCYCLECOUNTER(N, Results, DAG, Subtarget);
|
ReplaceREADCYCLECOUNTER(N, Results, DAG, Subtarget);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -79,7 +79,6 @@ entry:
|
||||||
ret i32 %add2
|
ret i32 %add2
|
||||||
}
|
}
|
||||||
|
|
||||||
; FIXME: AEABI is not lowering long u/srem into u/ldivmod
|
|
||||||
define i64 @longf(i64 %a, i64 %b) {
|
define i64 @longf(i64 %a, i64 %b) {
|
||||||
; EABI-LABEL: longf:
|
; EABI-LABEL: longf:
|
||||||
; DARWIN-LABEL: longf:
|
; DARWIN-LABEL: longf:
|
||||||
|
@ -87,6 +86,9 @@ entry:
|
||||||
%div = sdiv i64 %a, %b
|
%div = sdiv i64 %a, %b
|
||||||
%rem = srem i64 %a, %b
|
%rem = srem i64 %a, %b
|
||||||
; EABI: __aeabi_ldivmod
|
; EABI: __aeabi_ldivmod
|
||||||
|
; EABI-NEXT: adds r0
|
||||||
|
; EABI-NEXT: adc r1
|
||||||
|
; EABI-NOT: __aeabi_ldivmod
|
||||||
; DARWIN: ___divdi3
|
; DARWIN: ___divdi3
|
||||||
; DARWIN: mov [[div1:r[0-9]+]], r0
|
; DARWIN: mov [[div1:r[0-9]+]], r0
|
||||||
; DARWIN: mov [[div2:r[0-9]+]], r1
|
; DARWIN: mov [[div2:r[0-9]+]], r1
|
||||||
|
|
Loading…
Reference in New Issue