mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-14 07:31:47 +00:00
ARM: address WoA division overflow crash
Disable custom handling of signed 32-bit and 64-bit integer divide. Add test cases for both 32-bit and 64-bit integer overflow crashes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@253865 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4c91939703
commit
ee54187984
@ -395,6 +395,8 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
|
||||
{ RTLIB::SINTTOFP_I64_F64, "__i64tod", CallingConv::ARM_AAPCS_VFP },
|
||||
{ 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::SDIV_I64, "__rt_sdiv64", CallingConv::ARM_AAPCS_VFP },
|
||||
};
|
||||
|
||||
for (const auto &LC : LibraryCalls) {
|
||||
@ -782,10 +784,8 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
|
||||
}
|
||||
|
||||
if (Subtarget->isTargetWindows() && !Subtarget->hasDivide()) {
|
||||
setOperationAction(ISD::SDIV, MVT::i32, Custom);
|
||||
setOperationAction(ISD::UDIV, MVT::i32, Custom);
|
||||
|
||||
setOperationAction(ISD::SDIV, MVT::i64, Custom);
|
||||
setOperationAction(ISD::UDIV, MVT::i64, Custom);
|
||||
}
|
||||
|
||||
@ -6667,7 +6667,6 @@ 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) &&
|
||||
@ -6678,10 +6677,7 @@ SDValue ARMTargetLowering::LowerWindowsDIVLibCall(SDValue Op, SelectionDAG &DAG,
|
||||
const auto &TLI = DAG.getTargetLoweringInfo();
|
||||
|
||||
const char *Name = nullptr;
|
||||
if (Signed)
|
||||
Name = (VT == MVT::i32) ? "__rt_sdiv" : "__rt_sdiv64";
|
||||
else
|
||||
Name = (VT == MVT::i32) ? "__rt_udiv" : "__rt_udiv64";
|
||||
Name = (VT == MVT::i32) ? "__rt_udiv" : "__rt_udiv64";
|
||||
|
||||
SDValue ES = DAG.getExternalSymbol(Name, TLI.getPointerTy(DL));
|
||||
|
||||
@ -6703,8 +6699,8 @@ SDValue ARMTargetLowering::LowerWindowsDIVLibCall(SDValue Op, SelectionDAG &DAG,
|
||||
return LowerCallTo(CLI).first;
|
||||
}
|
||||
|
||||
SDValue ARMTargetLowering::LowerDIV_Windows(SDValue Op, SelectionDAG &DAG,
|
||||
bool Signed) const {
|
||||
SDValue ARMTargetLowering::LowerDIV_Windows(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
assert(Op.getValueType() == MVT::i32 &&
|
||||
"unexpected type for custom lowering DIV");
|
||||
SDLoc dl(Op);
|
||||
@ -6712,11 +6708,11 @@ SDValue ARMTargetLowering::LowerDIV_Windows(SDValue Op, SelectionDAG &DAG,
|
||||
SDValue DBZCHK = DAG.getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other,
|
||||
DAG.getEntryNode(), Op.getOperand(1));
|
||||
|
||||
return LowerWindowsDIVLibCall(Op, DAG, Signed, DBZCHK);
|
||||
return LowerWindowsDIVLibCall(Op, DAG, DBZCHK);
|
||||
}
|
||||
|
||||
void ARMTargetLowering::ExpandDIV_Windows(
|
||||
SDValue Op, SelectionDAG &DAG, bool Signed,
|
||||
SDValue Op, SelectionDAG &DAG,
|
||||
SmallVectorImpl<SDValue> &Results) const {
|
||||
const auto &DL = DAG.getDataLayout();
|
||||
const auto &TLI = DAG.getTargetLoweringInfo();
|
||||
@ -6734,7 +6730,7 @@ void ARMTargetLowering::ExpandDIV_Windows(
|
||||
SDValue DBZCHK =
|
||||
DAG.getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other, DAG.getEntryNode(), Or);
|
||||
|
||||
SDValue Result = LowerWindowsDIVLibCall(Op, DAG, Signed, DBZCHK);
|
||||
SDValue Result = LowerWindowsDIVLibCall(Op, DAG, DBZCHK);
|
||||
|
||||
SDValue Lower = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Result);
|
||||
SDValue Upper = DAG.getNode(ISD::SRL, dl, MVT::i64, Result,
|
||||
@ -6835,13 +6831,10 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG);
|
||||
case ISD::FLT_ROUNDS_: return LowerFLT_ROUNDS_(Op, DAG);
|
||||
case ISD::MUL: return LowerMUL(Op, DAG);
|
||||
case ISD::SDIV:
|
||||
if (Subtarget->isTargetWindows())
|
||||
return LowerDIV_Windows(Op, DAG, /* Signed */ true);
|
||||
return LowerSDIV(Op, DAG);
|
||||
case ISD::SDIV: return LowerSDIV(Op, DAG);
|
||||
case ISD::UDIV:
|
||||
if (Subtarget->isTargetWindows())
|
||||
return LowerDIV_Windows(Op, DAG, /* Signed */ false);
|
||||
return LowerDIV_Windows(Op, DAG);
|
||||
return LowerUDIV(Op, DAG);
|
||||
case ISD::ADDC:
|
||||
case ISD::ADDE:
|
||||
@ -6894,10 +6887,8 @@ 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, N->getOpcode() == ISD::SDIV,
|
||||
Results);
|
||||
return ExpandDIV_Windows(SDValue(N, 0), DAG, Results);
|
||||
}
|
||||
if (Res.getNode())
|
||||
Results.push_back(Res);
|
||||
|
@ -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, bool Signed) const;
|
||||
void ExpandDIV_Windows(SDValue Op, SelectionDAG &DAG, bool Signed,
|
||||
SDValue LowerDIV_Windows(SDValue Op, SelectionDAG &DAG) const;
|
||||
void ExpandDIV_Windows(SDValue Op, SelectionDAG &DAG,
|
||||
SmallVectorImpl<SDValue> &Results) const;
|
||||
SDValue LowerWindowsDIVLibCall(SDValue Op, SelectionDAG &DAG, bool Signed,
|
||||
SDValue LowerWindowsDIVLibCall(SDValue Op, SelectionDAG &DAG,
|
||||
SDValue &Chain) const;
|
||||
SDValue LowerREM(SDNode *N, SelectionDAG &DAG) const;
|
||||
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
@ -1,17 +1,6 @@
|
||||
; RUN: llc -mtriple thumbv7-windows-itanium -filetype asm -o - %s | FileCheck %s
|
||||
; RUN: llc -mtriple thumbv7-windows-msvc -filetype asm -o - %s | FileCheck %s
|
||||
|
||||
define arm_aapcs_vfpcc i32 @sdiv32(i32 %divisor, i32 %divident) {
|
||||
entry:
|
||||
%div = sdiv i32 %divident, %divisor
|
||||
ret i32 %div
|
||||
}
|
||||
|
||||
; CHECK-LABEL: sdiv32:
|
||||
; CHECK: cbz r0
|
||||
; CHECK: bl __rt_sdiv
|
||||
; CHECK: udf.w #249
|
||||
|
||||
define arm_aapcs_vfpcc i32 @udiv32(i32 %divisor, i32 %divident) {
|
||||
entry:
|
||||
%div = udiv i32 %divident, %divisor
|
||||
@ -23,18 +12,6 @@ entry:
|
||||
; CHECK: bl __rt_udiv
|
||||
; CHECK: udf.w #249
|
||||
|
||||
define arm_aapcs_vfpcc i64 @sdiv64(i64 %divisor, i64 %divident) {
|
||||
entry:
|
||||
%div = sdiv i64 %divident, %divisor
|
||||
ret i64 %div
|
||||
}
|
||||
|
||||
; CHECK-LABEL: sdiv64:
|
||||
; CHECK: orr.w r12, r0, r1
|
||||
; CHECK-NEXT: cbz r12
|
||||
; CHECK: bl __rt_sdiv64
|
||||
; CHECK: udf.w #249
|
||||
|
||||
define arm_aapcs_vfpcc i64 @udiv64(i64 %divisor, i64 %divident) {
|
||||
entry:
|
||||
%div = udiv i64 %divident, %divisor
|
||||
|
@ -1,6 +1,24 @@
|
||||
; RUN: llc -mtriple thumbv7-windows-itanium -filetype asm -o - %s | FileCheck %s
|
||||
; RUN: llc -mtriple thumbv7-windows-msvc -filetype asm -o - %s | FileCheck %s
|
||||
|
||||
define arm_aapcs_vfpcc i32 @sdiv32(i32 %divisor, i32 %divident) {
|
||||
entry:
|
||||
%div = sdiv i32 %divident, %divisor
|
||||
ret i32 %div
|
||||
}
|
||||
|
||||
; CHECK-LABEL: sdiv32
|
||||
; CHECK: b __rt_sdiv
|
||||
|
||||
define arm_aapcs_vfpcc i64 @sdiv64(i64 %divisor, i64 %divident) {
|
||||
entry:
|
||||
%div = sdiv i64 %divident, %divisor
|
||||
ret i64 %div
|
||||
}
|
||||
|
||||
; CHECK-LABEL: sdiv64
|
||||
; CHECK: bl __rt_sdiv64
|
||||
|
||||
define arm_aapcs_vfpcc i64 @stoi64(float %f) {
|
||||
entry:
|
||||
%conv = fptosi float %f to i64
|
||||
|
39
test/CodeGen/ARM/Windows/overflow.ll
Normal file
39
test/CodeGen/ARM/Windows/overflow.ll
Normal file
@ -0,0 +1,39 @@
|
||||
; RUN: llc -mtriple thumbv7-windows-gnu -filetype asm -o - %s
|
||||
|
||||
define i32 @divoverflow32(i32 %a, i32 %b) {
|
||||
%1 = alloca i32, align 4
|
||||
%2 = alloca i32, align 4
|
||||
%3 = load i32, i32* %1, align 4
|
||||
%4 = load i32, i32* %2, align 4
|
||||
%5 = sub nsw i32 0, %4
|
||||
%6 = sdiv i32 -2147483647, %3
|
||||
%7 = icmp sgt i32 %5, %6
|
||||
br i1 %7, label %8, label %9
|
||||
call void (...) @abort_impl32()
|
||||
unreachable
|
||||
%10 = load i32, i32* %1, align 4
|
||||
%11 = load i32, i32* %2, align 4
|
||||
%12 = mul nsw i32 %10, %11
|
||||
ret i32 %12
|
||||
}
|
||||
|
||||
declare void @abort_impl32(...)
|
||||
|
||||
define i64 @divoverflow64(i64 %a, i64 %b) {
|
||||
%1 = alloca i64, align 8
|
||||
%2 = alloca i64, align 8
|
||||
%3 = load i64, i64* %1, align 8
|
||||
%4 = load i64, i64* %2, align 8
|
||||
%5 = sub nsw i64 0, %4
|
||||
%6 = sdiv i64 -9223372036854775808, %3
|
||||
%7 = icmp sgt i64 %5, %6
|
||||
br i1 %7, label %8, label %9
|
||||
call void (...) @abort_impl64()
|
||||
unreachable
|
||||
%10 = load i64, i64* %1, align 8
|
||||
%11 = load i64, i64* %2, align 8
|
||||
%12 = mul nsw i64 %10, %11
|
||||
ret i64 %12
|
||||
}
|
||||
|
||||
declare void @abort_impl64(...)
|
Loading…
Reference in New Issue
Block a user