diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 3c99675a473..b9b37396187 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -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 &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); diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index b764624f149..03f99d43e41 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, 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 &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; diff --git a/test/CodeGen/ARM/Windows/division.ll b/test/CodeGen/ARM/Windows/division.ll index 098226e3f33..9ff3b7c781c 100644 --- a/test/CodeGen/ARM/Windows/division.ll +++ b/test/CodeGen/ARM/Windows/division.ll @@ -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 diff --git a/test/CodeGen/ARM/Windows/libcalls.ll b/test/CodeGen/ARM/Windows/libcalls.ll index d8b498a40d9..fcc4ef016c2 100644 --- a/test/CodeGen/ARM/Windows/libcalls.ll +++ b/test/CodeGen/ARM/Windows/libcalls.ll @@ -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 diff --git a/test/CodeGen/ARM/Windows/overflow.ll b/test/CodeGen/ARM/Windows/overflow.ll new file mode 100644 index 00000000000..23f5ee52224 --- /dev/null +++ b/test/CodeGen/ARM/Windows/overflow.ll @@ -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(...)