diff options
-rw-r--r-- | llvm/include/llvm/Target/TargetLowering.h | 7 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 12 | ||||
-rw-r--r-- | llvm/lib/Target/ARM/ARMISelLowering.cpp | 9 | ||||
-rw-r--r-- | llvm/test/CodeGen/ARM/divmod-eabi.ll | 19 |
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: |