summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/Target/TargetLowering.h7
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp12
-rw-r--r--llvm/lib/Target/ARM/ARMISelLowering.cpp9
-rw-r--r--llvm/test/CodeGen/ARM/divmod-eabi.ll19
4 files changed, 42 insertions, 5 deletions
diff --git a/llvm/include/llvm/Target/TargetLowering.h b/llvm/include/llvm/Target/TargetLowering.h
index ad3e26c7207..649a8b606be 100644
--- a/llvm/include/llvm/Target/TargetLowering.h
+++ b/llvm/include/llvm/Target/TargetLowering.h
@@ -571,6 +571,13 @@ public:
getOperationAction(Op, VT) == Promote);
}
+ /// Return true if the specified operation is ilegal but has a custom lowering
+ /// on that type. This is used to help guide high-level lowering
+ /// decisions.
+ bool isOperationCustom(unsigned Op, EVT VT) const {
+ return (!isTypeLegal(VT) && getOperationAction(Op, VT) == Custom);
+ }
+
/// Return true if the specified operation is illegal on this target or
/// unlikely to be made legal with custom lowering. This is used to help guide
/// high-level lowering decisions.
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 76187e29116..dfae183723f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -2155,14 +2155,18 @@ SDValue DAGCombiner::useDivRem(SDNode *Node) {
if (Node->use_empty())
return SDValue(); // This is a dead node, leave it alone.
+ unsigned Opcode = Node->getOpcode();
+ bool isSigned = (Opcode == ISD::SDIV) || (Opcode == ISD::SREM);
+ unsigned DivRemOpc = isSigned ? ISD::SDIVREM : ISD::UDIVREM;
+
+ // 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();
- bool isSigned = (Opcode == ISD::SDIV) || (Opcode == ISD::SREM);
+ if (!TLI.isTypeLegal(VT) && !TLI.isOperationCustom(DivRemOpc, VT))
+ return SDValue();
- unsigned DivRemOpc = isSigned ? ISD::SDIVREM : ISD::UDIVREM;
// If DIVREM is going to get expanded into a libcall,
// but there is no libcall available, then don't combine.
if (!TLI.isOperationLegalOrCustom(DivRemOpc, VT) &&
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 479b6d29be9..a0bf9179427 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -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;
diff --git a/llvm/test/CodeGen/ARM/divmod-eabi.ll b/llvm/test/CodeGen/ARM/divmod-eabi.ll
index 35f2014317b..778a82038d7 100644
--- a/llvm/test/CodeGen/ARM/divmod-eabi.ll
+++ b/llvm/test/CodeGen/ARM/divmod-eabi.ll
@@ -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
@@ -97,6 +99,21 @@ entry:
ret i64 %add
}
+define i16 @shortf(i16 %a, i16 %b) {
+; EABI-LABEL: shortf:
+; DARWIN-LABEL: shortf:
+entry:
+ %div = sdiv i16 %a, %b
+ %rem = srem i16 %a, %b
+; EABI: __aeabi_idivmod
+; DARWIN: ___divsi3
+; DARWIN: mov [[div1:r[0-9]+]], r0
+; DARWIN: __modsi3
+ %add = add nsw i16 %rem, %div
+; DARWIN: add r0{{.*}}[[div1]]
+ ret i16 %add
+}
+
define i32 @g1(i32 %a, i32 %b) {
; EABI-LABEL: g1:
; DARWIN-LABEL: g1:
OpenPOWER on IntegriCloud