ARM: address WOA unsigned division overflow crash
authorMartell Malone <martellmalone@gmail.com>
Thu, 26 Nov 2015 15:34:03 +0000 (15:34 +0000)
committerMartell Malone <martellmalone@gmail.com>
Thu, 26 Nov 2015 15:34:03 +0000 (15:34 +0000)
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

lib/Target/ARM/ARMISelLowering.cpp
lib/Target/ARM/ARMISelLowering.h
test/CodeGen/ARM/Windows/division.ll
test/CodeGen/ARM/Windows/libcalls.ll
test/CodeGen/ARM/Windows/overflow.ll

index 7366697343e9e3bb94e717a877136ac0784b57b2..0cc41812d71cd4d0aeba84f282c7839e02025e67 100644 (file)
@@ -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);
index 03f99d43e41b07911608bb911b05b45a8360daa9..b764624f1492283c3efd8a209d1b8c68d86de129 100644 (file)
@@ -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;
index 9ff3b7c781cf5cfff72d757531c696d2ee4c7a35..b3ef9c6d278b67904afb6c81cf2218f48a60a39f 100644 (file)
@@ -1,6 +1,15 @@
 ; 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 i32 @udiv32(i32 %divisor, i32 %divident) {
 entry:
   %div = udiv i32 %divident, %divisor
@@ -8,9 +17,16 @@ entry:
 }
 
 ; CHECK-LABEL: udiv32:
-; CHECK: cbz r0
-; CHECK: bl __rt_udiv
-; CHECK: udf.w #249
+; CHECK: b __rt_udiv
+
+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 @udiv64(i64 %divisor, i64 %divident) {
 entry:
@@ -19,8 +35,4 @@ entry:
 }
 
 ; CHECK-LABEL: udiv64:
-; CHECK: orr.w r12, r0, r1
-; CHECK-NEXT: cbz r12
 ; CHECK: bl __rt_udiv64
-; CHECK: udf.w #249
-
index fcc4ef016c2bd104225aee1ed6942a3a64f8d133..d8b498a40d97c9d5d98976f415f5a4f942497d89 100644 (file)
@@ -1,24 +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: 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
index 23f5ee52224c7754e6378f701facaeba86ce6f92..5f74f25ac2242b510e5b8bc4afe9d91b22985278 100644 (file)
@@ -1,6 +1,6 @@
 ; RUN: llc -mtriple thumbv7-windows-gnu -filetype asm -o - %s
 
-define i32 @divoverflow32(i32 %a, i32 %b) {
+define i32 @divsoverflow32(i32 %a, i32 %b) {
   %1 = alloca i32, align 4
   %2 = alloca i32, align 4
   %3 = load i32, i32* %1, align 4
@@ -9,7 +9,7 @@ define i32 @divoverflow32(i32 %a, i32 %b) {
   %6 = sdiv i32 -2147483647, %3
   %7 = icmp sgt i32 %5, %6
   br i1 %7, label %8, label %9
-  call void (...) @abort_impl32()
+  call void (...) @abort_simpl32()
   unreachable
   %10 = load i32, i32* %1, align 4
   %11 = load i32, i32* %2, align 4
@@ -17,9 +17,9 @@ define i32 @divoverflow32(i32 %a, i32 %b) {
   ret i32 %12
 }
 
-declare void @abort_impl32(...)
+declare void @abort_simpl32(...)
 
-define i64 @divoverflow64(i64 %a, i64 %b) {
+define i64 @divsoverflow64(i64 %a, i64 %b) {
   %1 = alloca i64, align 8
   %2 = alloca i64, align 8
   %3 = load i64, i64* %1, align 8
@@ -28,7 +28,7 @@ define i64 @divoverflow64(i64 %a, i64 %b) {
   %6 = sdiv i64 -9223372036854775808, %3
   %7 = icmp sgt i64 %5, %6
   br i1 %7, label %8, label %9
-  call void (...) @abort_impl64()
+  call void (...) @abort_simpl64()
   unreachable
   %10 = load i64, i64* %1, align 8
   %11 = load i64, i64* %2, align 8
@@ -36,4 +36,42 @@ define i64 @divoverflow64(i64 %a, i64 %b) {
   ret i64 %12
 }
 
-declare void @abort_impl64(...)
+declare void @abort_simpl64(...)
+
+define i32 @divuoverflow32(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 = udiv i32 4294967296, %3
+  %7 = icmp sgt i32 %5, %6
+  br i1 %7, label %8, label %9
+  call void (...) @abort_uimpl32()
+  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_uimpl32(...)
+
+define i64 @divuoverflow64(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 = udiv i64 18446744073709551616, %3
+  %7 = icmp sgt i64 %5, %6
+  br i1 %7, label %8, label %9
+  call void (...) @abort_uimpl64()
+  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_uimpl64(...)