summaryrefslogtreecommitdiff
path: root/lib/Target/ARM
diff options
context:
space:
mode:
authorMartell Malone <martellmalone@gmail.com>2015-11-26 15:34:03 +0000
committerMartell Malone <martellmalone@gmail.com>2015-11-26 15:34:03 +0000
commit937e2d588c6509301ae609b3b8fd9c7c72d348de (patch)
tree1396e8401e99d55eb9667acee27b8e47d27986ff /lib/Target/ARM
parent0981e5a6cec9a4c79a06af37d025bb1faeeb7ff7 (diff)
ARM: address WOA unsigned division overflow crash
Building on r253865 the crash is not limited to signed overflows. Disable custom handling of unsigned 32-bit and 64-bit integer divide. Add test cases for both 32-bit and 64-bit unsigned integer overflow. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254158 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/ARM')
-rw-r--r--lib/Target/ARM/ARMISelLowering.cpp33
-rw-r--r--lib/Target/ARM/ARMISelLowering.h6
2 files changed, 19 insertions, 20 deletions
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp
index 7366697343e..0cc41812d71 100644
--- a/lib/Target/ARM/ARMISelLowering.cpp
+++ b/lib/Target/ARM/ARMISelLowering.cpp
@@ -396,7 +396,9 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
{ RTLIB::UINTTOFP_I64_F32, "__u64tos", CallingConv::ARM_AAPCS_VFP },
{ RTLIB::UINTTOFP_I64_F64, "__u64tod", CallingConv::ARM_AAPCS_VFP },
{ RTLIB::SDIV_I32, "__rt_sdiv", CallingConv::ARM_AAPCS_VFP },
+ { RTLIB::UDIV_I32, "__rt_udiv", CallingConv::ARM_AAPCS_VFP },
{ RTLIB::SDIV_I64, "__rt_sdiv64", CallingConv::ARM_AAPCS_VFP },
+ { RTLIB::UDIV_I64, "__rt_udiv64", CallingConv::ARM_AAPCS_VFP },
};
for (const auto &LC : LibraryCalls) {
@@ -783,12 +785,6 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::UDIV, MVT::i32, LibCall);
}
- if (Subtarget->isTargetWindows() && !Subtarget->hasDivide()) {
- setOperationAction(ISD::UDIV, MVT::i32, Custom);
-
- setOperationAction(ISD::UDIV, MVT::i64, Custom);
- }
-
setOperationAction(ISD::SREM, MVT::i32, Expand);
setOperationAction(ISD::UREM, MVT::i32, Expand);
// Register based DivRem for AEABI (RTABI 4.2)
@@ -6660,6 +6656,7 @@ SDValue ARMTargetLowering::LowerFSINCOS(SDValue Op, SelectionDAG &DAG) const {
}
SDValue ARMTargetLowering::LowerWindowsDIVLibCall(SDValue Op, SelectionDAG &DAG,
+ bool Signed,
SDValue &Chain) const {
EVT VT = Op.getValueType();
assert((VT == MVT::i32 || VT == MVT::i64) &&
@@ -6670,7 +6667,10 @@ SDValue ARMTargetLowering::LowerWindowsDIVLibCall(SDValue Op, SelectionDAG &DAG,
const auto &TLI = DAG.getTargetLoweringInfo();
const char *Name = nullptr;
- Name = (VT == MVT::i32) ? "__rt_udiv" : "__rt_udiv64";
+ if (Signed)
+ Name = (VT == MVT::i32) ? "__rt_sdiv" : "__rt_sdiv64";
+ else
+ Name = (VT == MVT::i32) ? "__rt_udiv" : "__rt_udiv64";
SDValue ES = DAG.getExternalSymbol(Name, TLI.getPointerTy(DL));
@@ -6692,8 +6692,8 @@ SDValue ARMTargetLowering::LowerWindowsDIVLibCall(SDValue Op, SelectionDAG &DAG,
return LowerCallTo(CLI).first;
}
-SDValue ARMTargetLowering::LowerDIV_Windows(SDValue Op,
- SelectionDAG &DAG) const {
+SDValue ARMTargetLowering::LowerDIV_Windows(SDValue Op, SelectionDAG &DAG,
+ bool Signed) const {
assert(Op.getValueType() == MVT::i32 &&
"unexpected type for custom lowering DIV");
SDLoc dl(Op);
@@ -6701,11 +6701,11 @@ SDValue ARMTargetLowering::LowerDIV_Windows(SDValue Op,
SDValue DBZCHK = DAG.getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other,
DAG.getEntryNode(), Op.getOperand(1));
- return LowerWindowsDIVLibCall(Op, DAG, DBZCHK);
+ return LowerWindowsDIVLibCall(Op, DAG, Signed, DBZCHK);
}
void ARMTargetLowering::ExpandDIV_Windows(
- SDValue Op, SelectionDAG &DAG,
+ SDValue Op, SelectionDAG &DAG, bool Signed,
SmallVectorImpl<SDValue> &Results) const {
const auto &DL = DAG.getDataLayout();
const auto &TLI = DAG.getTargetLoweringInfo();
@@ -6723,7 +6723,7 @@ void ARMTargetLowering::ExpandDIV_Windows(
SDValue DBZCHK =
DAG.getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other, DAG.getEntryNode(), Or);
- SDValue Result = LowerWindowsDIVLibCall(Op, DAG, DBZCHK);
+ SDValue Result = LowerWindowsDIVLibCall(Op, DAG, Signed, DBZCHK);
SDValue Lower = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Result);
SDValue Upper = DAG.getNode(ISD::SRL, dl, MVT::i64, Result,
@@ -6825,10 +6825,7 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::FLT_ROUNDS_: return LowerFLT_ROUNDS_(Op, DAG);
case ISD::MUL: return LowerMUL(Op, DAG);
case ISD::SDIV: return LowerSDIV(Op, DAG);
- case ISD::UDIV:
- if (Subtarget->isTargetWindows())
- return LowerDIV_Windows(Op, DAG);
- return LowerUDIV(Op, DAG);
+ case ISD::UDIV: return LowerUDIV(Op, DAG);
case ISD::ADDC:
case ISD::ADDE:
case ISD::SUBC:
@@ -6880,8 +6877,10 @@ void ARMTargetLowering::ReplaceNodeResults(SDNode *N,
ReplaceREADCYCLECOUNTER(N, Results, DAG, Subtarget);
return;
case ISD::UDIV:
+ case ISD::SDIV:
assert(Subtarget->isTargetWindows() && "can only expand DIV on Windows");
- return ExpandDIV_Windows(SDValue(N, 0), DAG, Results);
+ return ExpandDIV_Windows(SDValue(N, 0), DAG, N->getOpcode() == ISD::SDIV,
+ Results);
}
if (Res.getNode())
Results.push_back(Res);
diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h
index 03f99d43e41..b764624f149 100644
--- a/lib/Target/ARM/ARMISelLowering.h
+++ b/lib/Target/ARM/ARMISelLowering.h
@@ -543,10 +543,10 @@ namespace llvm {
const ARMSubtarget *ST) const;
SDValue LowerFSINCOS(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerDivRem(SDValue Op, SelectionDAG &DAG) const;
- SDValue LowerDIV_Windows(SDValue Op, SelectionDAG &DAG) const;
- void ExpandDIV_Windows(SDValue Op, SelectionDAG &DAG,
+ SDValue LowerDIV_Windows(SDValue Op, SelectionDAG &DAG, bool Signed) const;
+ void ExpandDIV_Windows(SDValue Op, SelectionDAG &DAG, bool Signed,
SmallVectorImpl<SDValue> &Results) const;
- SDValue LowerWindowsDIVLibCall(SDValue Op, SelectionDAG &DAG,
+ SDValue LowerWindowsDIVLibCall(SDValue Op, SelectionDAG &DAG, bool Signed,
SDValue &Chain) const;
SDValue LowerREM(SDNode *N, SelectionDAG &DAG) const;
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;