From be1357f467a95637e2108010896b246ac3945fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Tue, 1 Nov 2016 11:13:50 +0200 Subject: [PATCH] Backport more llvm patches from current master This fixes up handling of divisions on ARM/Windows, and consistently does calls to helper functions using the windows/msvc names, instead of the libgcc naming. --- patches/llvm-0007.patch | 361 ++++++++++++++++++++++++++++++++++++++++ patches/llvm-0008.patch | 250 ++++++++++++++++++++++++++++ patches/llvm-0009.patch | 186 +++++++++++++++++++++ 3 files changed, 797 insertions(+) create mode 100644 patches/llvm-0007.patch create mode 100644 patches/llvm-0008.patch create mode 100644 patches/llvm-0009.patch diff --git a/patches/llvm-0007.patch b/patches/llvm-0007.patch new file mode 100644 index 0000000..26bd553 --- /dev/null +++ b/patches/llvm-0007.patch @@ -0,0 +1,361 @@ +From ed632cebfe6b046152e3f353c7a70ae4c4efea52 Mon Sep 17 00:00:00 2001 +From: Martin Storsjo +Date: Fri, 7 Oct 2016 13:28:53 +0000 +Subject: [PATCH 7/9] [ARM] Reapply: Use __rt_div functions for divrem on + Windows + +Reapplying r283383 after revert in r283442. The additional fix +is a getting rid of a stray space in a function name, in the +refactoring part of the commit. + +This avoids falling back to calling out to the GCC rem functions +(__moddi3, __umoddi3) when targeting Windows. + +The __rt_div functions have flipped the two arguments compared +to the __aeabi_divmod functions. To match MSVC, we emit a +check for division by zero before actually calling the library +function (even if the library function itself also might do +the same check). + +Not all calls to __rt_div functions for division are currently +merged with calls to the same function with the same parameters +for the remainder. This is more wasteful than a div + mls as before, +but avoids calls to __moddi3. + +Differential Revision: https://reviews.llvm.org/D25332 + +Cherry-picked from SVN trunk commit 283550, git mirror commit +c3339a54ac77. +--- + lib/Target/ARM/ARMISelLowering.cpp | 66 ++++++++++++++++++++++++++------------ + test/CodeGen/ARM/Windows/dbzchk.ll | 2 +- + test/CodeGen/ARM/divmod-eabi.ll | 56 +++++++++++++------------------- + 3 files changed, 68 insertions(+), 56 deletions(-) + +diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp +index 3cfcb1e..8db9f54 100644 +--- a/lib/Target/ARM/ARMISelLowering.cpp ++++ b/lib/Target/ARM/ARMISelLowering.cpp +@@ -803,19 +803,26 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM, + setOperationAction(ISD::UREM, MVT::i32, Expand); + // Register based DivRem for AEABI (RTABI 4.2) + if (Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() || +- Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI()) { ++ Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() || ++ Subtarget->isTargetWindows()) { + setOperationAction(ISD::SREM, MVT::i64, Custom); + setOperationAction(ISD::UREM, MVT::i64, Custom); + HasStandaloneRem = false; + +- setLibcallName(RTLIB::SDIVREM_I8, "__aeabi_idivmod"); +- setLibcallName(RTLIB::SDIVREM_I16, "__aeabi_idivmod"); +- setLibcallName(RTLIB::SDIVREM_I32, "__aeabi_idivmod"); +- setLibcallName(RTLIB::SDIVREM_I64, "__aeabi_ldivmod"); +- setLibcallName(RTLIB::UDIVREM_I8, "__aeabi_uidivmod"); +- setLibcallName(RTLIB::UDIVREM_I16, "__aeabi_uidivmod"); +- setLibcallName(RTLIB::UDIVREM_I32, "__aeabi_uidivmod"); +- setLibcallName(RTLIB::UDIVREM_I64, "__aeabi_uldivmod"); ++ for (const auto &LC : ++ {RTLIB::SDIVREM_I8, RTLIB::SDIVREM_I16, RTLIB::SDIVREM_I32}) ++ setLibcallName(LC, Subtarget->isTargetWindows() ? "__rt_sdiv" ++ : "__aeabi_idivmod"); ++ setLibcallName(RTLIB::SDIVREM_I64, Subtarget->isTargetWindows() ++ ? "__rt_sdiv64" ++ : "__aeabi_ldivmod"); ++ for (const auto &LC : ++ {RTLIB::UDIVREM_I8, RTLIB::UDIVREM_I16, RTLIB::UDIVREM_I32}) ++ setLibcallName(LC, Subtarget->isTargetWindows() ? "__rt_udiv" ++ : "__aeabi_uidivmod"); ++ setLibcallName(RTLIB::UDIVREM_I64, Subtarget->isTargetWindows() ++ ? "__rt_udiv64" ++ : "__aeabi_uldivmod"); + + setLibcallCallingConv(RTLIB::SDIVREM_I8, CallingConv::ARM_AAPCS); + setLibcallCallingConv(RTLIB::SDIVREM_I16, CallingConv::ARM_AAPCS); +@@ -7029,6 +7036,19 @@ SDValue ARMTargetLowering::LowerDIV_Windows(SDValue Op, SelectionDAG &DAG, + return LowerWindowsDIVLibCall(Op, DAG, Signed, DBZCHK); + } + ++static SDValue WinDBZCheckDenominator(SelectionDAG &DAG, SDNode *N, SDValue InChain) { ++ SDLoc DL(N); ++ SDValue Op = N->getOperand(1); ++ if (N->getValueType(0) == MVT::i32) ++ return DAG.getNode(ARMISD::WIN__DBZCHK, DL, MVT::Other, InChain, Op); ++ SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, Op, ++ DAG.getConstant(0, DL, MVT::i32)); ++ SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, Op, ++ DAG.getConstant(1, DL, MVT::i32)); ++ return DAG.getNode(ARMISD::WIN__DBZCHK, DL, MVT::Other, InChain, ++ DAG.getNode(ISD::OR, DL, MVT::i32, Lo, Hi)); ++} ++ + void ARMTargetLowering::ExpandDIV_Windows( + SDValue Op, SelectionDAG &DAG, bool Signed, + SmallVectorImpl &Results) const { +@@ -7039,14 +7059,7 @@ void ARMTargetLowering::ExpandDIV_Windows( + "unexpected type for custom lowering DIV"); + SDLoc dl(Op); + +- SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Op.getOperand(1), +- DAG.getConstant(0, dl, MVT::i32)); +- SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, Op.getOperand(1), +- DAG.getConstant(1, dl, MVT::i32)); +- SDValue Or = DAG.getNode(ISD::OR, dl, MVT::i32, Lo, Hi); +- +- SDValue DBZCHK = +- DAG.getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other, DAG.getEntryNode(), Or); ++ SDValue DBZCHK = WinDBZCheckDenominator(DAG, Op.getNode(), DAG.getEntryNode()); + + SDValue Result = LowerWindowsDIVLibCall(Op, DAG, Signed, DBZCHK); + +@@ -12043,7 +12056,7 @@ static RTLIB::Libcall getDivRemLibcall( + } + + static TargetLowering::ArgListTy getDivRemArgList( +- const SDNode *N, LLVMContext *Context) { ++ const SDNode *N, LLVMContext *Context, const ARMSubtarget *Subtarget) { + assert((N->getOpcode() == ISD::SDIVREM || N->getOpcode() == ISD::UDIVREM || + N->getOpcode() == ISD::SREM || N->getOpcode() == ISD::UREM) && + "Unhandled Opcode in getDivRemArgList"); +@@ -12060,12 +12073,15 @@ static TargetLowering::ArgListTy getDivRemArgList( + Entry.isZExt = !isSigned; + Args.push_back(Entry); + } ++ if (Subtarget->isTargetWindows() && Args.size() >= 2) ++ std::swap(Args[0], Args[1]); + return Args; + } + + SDValue ARMTargetLowering::LowerDivRem(SDValue Op, SelectionDAG &DAG) const { + assert((Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() || +- Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI()) && ++ Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() || ++ Subtarget->isTargetWindows()) && + "Register-based DivRem lowering only"); + unsigned Opcode = Op->getOpcode(); + assert((Opcode == ISD::SDIVREM || Opcode == ISD::UDIVREM) && +@@ -12079,13 +12095,17 @@ SDValue ARMTargetLowering::LowerDivRem(SDValue Op, SelectionDAG &DAG) const { + SDValue InChain = DAG.getEntryNode(); + + TargetLowering::ArgListTy Args = getDivRemArgList(Op.getNode(), +- DAG.getContext()); ++ DAG.getContext(), ++ Subtarget); + + SDValue Callee = DAG.getExternalSymbol(getLibcallName(LC), + getPointerTy(DAG.getDataLayout())); + + Type *RetTy = (Type*)StructType::get(Ty, Ty, nullptr); + ++ if (Subtarget->isTargetWindows()) ++ InChain = WinDBZCheckDenominator(DAG, Op.getNode(), InChain); ++ + SDLoc dl(Op); + TargetLowering::CallLoweringInfo CLI(DAG); + CLI.setDebugLoc(dl).setChain(InChain) +@@ -12119,11 +12139,15 @@ SDValue ARMTargetLowering::LowerREM(SDNode *N, SelectionDAG &DAG) const { + RTLIB::Libcall LC = getDivRemLibcall(N, N->getValueType(0).getSimpleVT(). + SimpleTy); + SDValue InChain = DAG.getEntryNode(); +- TargetLowering::ArgListTy Args = getDivRemArgList(N, DAG.getContext()); ++ TargetLowering::ArgListTy Args = getDivRemArgList(N, DAG.getContext(), ++ Subtarget); + bool isSigned = N->getOpcode() == ISD::SREM; + SDValue Callee = DAG.getExternalSymbol(getLibcallName(LC), + getPointerTy(DAG.getDataLayout())); + ++ if (Subtarget->isTargetWindows()) ++ InChain = WinDBZCheckDenominator(DAG, N, InChain); ++ + // Lower call + CallLoweringInfo CLI(DAG); + CLI.setChain(InChain) +diff --git a/test/CodeGen/ARM/Windows/dbzchk.ll b/test/CodeGen/ARM/Windows/dbzchk.ll +index 599a7cf..c078e09 100644 +--- a/test/CodeGen/ARM/Windows/dbzchk.ll ++++ b/test/CodeGen/ARM/Windows/dbzchk.ll +@@ -141,7 +141,7 @@ attributes #0 = { optsize } + ; CHECK-CFG-ASM-NEXT: udf.w #249 + ; CHECK-CFG-ASM-LABEL: .LBB2_4: + ; CHECK-CFG-ASM: bl __rt_udiv +-; CHECK-CFG-ASM: pop.w {{{.*}}, r11, pc} ++; CHECK-CFG-ASM: pop.w {r11, pc} + + ; RUN: llc -O0 -mtriple thumbv7--windows-itanium -verify-machineinstrs -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-WIN__DBZCHK + +diff --git a/test/CodeGen/ARM/divmod-eabi.ll b/test/CodeGen/ARM/divmod-eabi.ll +index 1e4c8fc..ce5a1df 100644 +--- a/test/CodeGen/ARM/divmod-eabi.ll ++++ b/test/CodeGen/ARM/divmod-eabi.ll +@@ -42,15 +42,13 @@ entry: + ; DARWIN-DEFAULT: add [[sum:r[0-9]+]], r0, [[div]] + ; DARWIN-O0: mov [[rem:r[0-9]+]], r0 + ; WINDOWS: __rt_sdiv +-; WINDOWS-DEFAULT: mls [[rem:r[0-9]+]], r0, +-; WINDOWS-DEFAULT: adds [[sum:r[0-9]+]], [[rem]], r0 +-; WINDOWS-O0: mov [[div:r[0-9]+]], r0 +-; WINDOWS-O0: mls [[rem:r[0-9]+]], [[div]], ++; WINDOWS: __rt_sdiv ++; WINDOWS-DEFAULT: add [[sum:r[0-9]+]], r1 ++; WINDOWS-O0: mov [[rem:r[0-9]+]], r1 + %rem8 = srem i32 %conv1, %conv + ; EABI: __aeabi_idivmod + ; DARWIN: __modsi3 + ; WINDOWS: __rt_sdiv +-; WINDOWS: mls [[rem1:r[0-9]+]], r0, + %add = add nsw i32 %rem, %div + %add13 = add nsw i32 %add, %rem8 + %conv14 = trunc i32 %add13 to i16 +@@ -60,9 +58,10 @@ entry: + ; DARWIN-O0: add [[sum:r[0-9]+]], [[rem]], [[div]] + ; DARWIN-O0: add [[res:r[0-9]+]], [[sum]], r0 + ; DARWIN: sxth r0, [[res]] +-; WINDOWS-O0: adds [[sum:r[0-9]+]], [[rem]], [[div]] +-; WINDOWS: add [[rem1]], [[sum]] +-; WINDOWS: sxth [[res:r[0-9]+]], [[rem1]] ++; WINDOWS-DEFAULT: adds [[sum1:r[0-9]+]], [[sum]], r1 ++; WINDOWS-O0: adds [[sum:r[0-9]+]], [[rem]], ++; WINDOWS-O0: add [[sum1:r[0-9]+]], r1 ++; WINDOWS: sxth [[res:r[0-9]+]], [[sum1]] + ret i16 %conv14 + } + +@@ -84,22 +83,20 @@ entry: + ; WINDOWS: __rt_sdiv + ; WINDOWS: mov [[div:r[0-9]+]], r0 + ; WINDOWS: __rt_sdiv +-; WINDOWS: mls [[rem:r[0-9]+]], r0, +-; WINDOWS-DEFAULT: add [[div]], [[rem]] ++; WINDOWS-DEFAULT: add [[div]], r1 + %rem1 = srem i32 %b, %a + ; EABI: __aeabi_idivmod + ; DARWIN: __modsi3 + ; WINDOWS: __rt_sdiv +-; WINDOWS: mls [[rem1:r[0-9]+]], r0, + %add = add nsw i32 %rem, %div + %add2 = add nsw i32 %add, %rem1 + ; EABI: add r0{{.*}}r1 + ; DARWIN-DEFAULT: add r0, [[sum]], r0 + ; DARWIN-O0: add [[sum:r[0-9]+]], [[rem]], [[div]] + ; DARWIN-O0: add [[res:r[0-9]+]], [[sum]], r0 +-; WINDOWS-DEFAULT: add [[rem1]], [[div]] ++; WINDOWS-DEFAULT: adds r0, [[div]], r1 + ; WINDOWS-O0: adds [[sum:r[0-9]+]], [[rem]], [[div]] +-; WINDOWS-O0: add [[rem1]], [[sum]] ++; WINDOWS-O0: add [[sum]], r1 + ret i32 %add2 + } + +@@ -119,22 +116,20 @@ entry: + ; WINDOWS: __rt_udiv + ; WINDOWS: mov [[div:r[0-9]+]], r0 + ; WINDOWS: __rt_udiv +-; WINDOWS: mls [[rem:r[0-9]+]], r0, +-; WINDOWS-DEFAULT: add [[div]], [[rem]] ++; WINDOWS-DEFAULT: add [[div]], r1 + %rem1 = urem i32 %b, %a + ; EABI: __aeabi_uidivmod + ; DARWIN: __umodsi3 + ; WINDOWS: __rt_udiv +-; WINDOWS: mls [[rem1:r[0-9]+]], r0, + %add = add nuw i32 %rem, %div + %add2 = add nuw i32 %add, %rem1 + ; EABI: add r0{{.*}}r1 + ; DARWIN-DEFAULT: add r0, [[sum]], r0 + ; DARWIN-O0: add [[sum:r[0-9]+]], [[rem]], [[div]] + ; DARWIN-O0: add [[res:r[0-9]+]], [[sum]], r0 +-; WINDOWS-DEFAULT: add [[rem1]], [[div]] +-; WINDOWS-O0: adds [[sum:r[0-9]+]], [[rem]], [[div]] +-; WINDOWS-O0: add [[rem1]], [[sum]] ++; WINDOWS-DEFAULT: adds [[sum:r[0-9]+]], [[div]], r1 ++; WINDOWS-O0: adds [[sum:r[0-9]+]], ++; WINDOWS-O0: add [[sum]], r1 + ret i32 %add2 + } + +@@ -154,14 +149,11 @@ entry: + ; DARWIN: mov [[div2:r[0-9]+]], r1 + ; DARWIN: __moddi3 + ; WINDOWS: __rt_sdiv64 +-; WINDOWS: mov [[div1:r[0-9]+]], r0 +-; WINDOWS: mov [[div2:r[0-9]+]], r1 +-; WINDOWS: __moddi3 + %add = add nsw i64 %rem, %div + ; DARWIN: adds r0{{.*}}[[div1]] + ; DARWIN: adc r1{{.*}}[[div2]] +-; WINDOWS: adds.w r0, r0, [[div1]] +-; WINDOWS: adc.w r1, r1, [[div2]] ++; WINDOWS: adds r0, r0, r2 ++; WINDOWS: adcs r1, r3 + ret i64 %add + } + +@@ -179,11 +171,10 @@ entry: + ; WINDOWS: __rt_sdiv + ; WINDOWS: mov [[div:r[0-9]+]], r0 + ; WINDOWS: __rt_sdiv +-; WINDOWS: mls [[rem:r[0-9]+]], r0, + %add = add nsw i16 %rem, %div + ; EABI: add r0, r1 + ; DARWIN: add r0{{.*}}[[div1]] +-; WINDOWS: add [[rem]], [[div]] ++; WINDOWS: adds r0, r1, [[div]] + ret i16 %add + } + +@@ -201,11 +192,10 @@ entry: + ; WINDOWS: __rt_sdiv + ; WINDOWS: mov [[div:r[0-9]+]], r0 + ; WINDOWS: __rt_sdiv +-; WINDOWS: mls [[rem:r[0-9]+]], r0, + %add = add nsw i32 %rem, %div + ; EABI: add r0{{.*}}r1 + ; DARWIN: add r0{{.*}}[[sum]] +-; WINDOWS: add [[rem]], [[div]] ++; WINDOWS: adds r0, r1, [[div]] + ret i32 %add + } + +@@ -221,7 +211,7 @@ entry: + ; WINDOWS: __rt_sdiv + ret i32 %rem + ; EABI: mov r0, r1 +-; WINDOWS: mls r0, r0, ++; WINDOWS: mov r0, r1 + } + + define i32 @g3(i32 %a, i32 %b) { +@@ -235,16 +225,15 @@ entry: + ; DARWIN: __modsi3 + ; DARWIN: mov [[sum:r[0-9]+]], r0 + ; WINDOWS: __rt_sdiv +-; WINDOWS: mls [[rem:r[0-9]+]], r0, ++; WINDOWS: mov [[rem:r[0-9]+]], r1 + %rem1 = srem i32 %b, %rem + ; EABI: __aeabi_idivmod + ; DARWIN: __modsi3 + ; WINDOWS: __rt_sdiv +-; WINDOWS: mls [[rem1:r[0-9]+]], r0, + %add = add nsw i32 %rem1, %rem + ; EABI: add r0, r1, [[mod]] + ; DARWIN: add r0{{.*}}[[sum]] +-; WINDOWS: add [[rem1]], [[rem]] ++; WINDOWS: adds r0, r1, [[rem]] + ret i32 %add + } + +@@ -264,10 +253,9 @@ entry: + ; EABI: __aeabi_idivmod + ; DARWIN: __modsi3 + ; WINDOWS: __rt_sdiv +-; WINDOWS: mls [[rem:r[0-9]+]], r0, + %add = add nsw i32 %rem, %div + ; EABI: add r0, r1, [[div]] + ; DARWIN: add r0{{.*}}[[sum]] +-; WINDOWS: add [[rem]], [[div]] ++; WINDOWS: adds r0, r1, [[div]] + ret i32 %add + } +-- +2.7.4 + diff --git a/patches/llvm-0008.patch b/patches/llvm-0008.patch new file mode 100644 index 0000000..6e94c9d --- /dev/null +++ b/patches/llvm-0008.patch @@ -0,0 +1,250 @@ +From a6c33deef382981590bd9298b492b612bcbae521 Mon Sep 17 00:00:00 2001 +From: Saleem Abdulrasool +Date: Thu, 27 Oct 2016 16:59:22 +0000 +Subject: [PATCH 8/9] ARM: ensure that the Windows DBZ check is in range + +The Windows ARM target expects the compiler to emit a division-by-zero check. +The check would use the form of: + + cmp r?, #0 + cbz .Ltrap + b .Lbody + .Lbody: + ... + .Ltrap: + udf #249 @ __brkdiv0 + +This works great most of the time. However, if the body of the function is +greater than 127 bytes, the branch target limitation of cbz becomes an issue. +This occurs in the unoptimized code generation cases sometimes (like in +compiler-rt). + +Since this is a matter of correctness, possibly pay a small penalty instead. We +now form this slightly differently: + + cbnz .Lbody + udf #249 @ __brkdiv0 + .Lbody: + ... + +The positive case is through the branch instead of being the next instruction. +However, because of the basic block layout, the negated branch is going to be +a short distance always (2 bytes away, after the inserted __brkdiv0). + +The new t__brkdiv0 instruction is required to explicitly mark the instruction as +a terminator as the generic UDF instruction is not a terminator. + +Addresses PR30532! + +Cherry-picked from SVN trunk commit 285312, git mirror commit +b5143b06a12b5. +--- + lib/Target/ARM/ARMISelLowering.cpp | 11 +++------ + lib/Target/ARM/ARMInstrThumb.td | 7 ++++++ + test/CodeGen/ARM/Windows/dbzchk.ll | 38 +++++++++++------------------- + test/CodeGen/ARM/Windows/division-range.ll | 15 ++++++++++++ + test/CodeGen/ARM/Windows/division.ll | 20 +++++++--------- + 5 files changed, 47 insertions(+), 44 deletions(-) + create mode 100644 test/CodeGen/ARM/Windows/division-range.ll + +diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp +index 8db9f54..f7b09fa 100644 +--- a/lib/Target/ARM/ARMISelLowering.cpp ++++ b/lib/Target/ARM/ARMISelLowering.cpp +@@ -8215,16 +8215,11 @@ ARMTargetLowering::EmitLowered__dbzchk(MachineInstr &MI, + std::next(MachineBasicBlock::iterator(MI)), MBB->end()); + ContBB->transferSuccessorsAndUpdatePHIs(MBB); + +- MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock(); +- MF->push_back(TrapBB); +- BuildMI(TrapBB, DL, TII->get(ARM::t2UDF)).addImm(249); +- MBB->addSuccessor(TrapBB); +- +- BuildMI(*MBB, MI, DL, TII->get(ARM::tCBZ)) ++ BuildMI(*MBB, MI, DL, TII->get(ARM::tCBNZ)) + .addReg(MI.getOperand(0).getReg()) +- .addMBB(TrapBB); +- AddDefaultPred(BuildMI(*MBB, MI, DL, TII->get(ARM::t2B)).addMBB(ContBB)); ++ .addMBB(ContBB); + MBB->addSuccessor(ContBB); ++ BuildMI(*MBB, MI, DL, TII->get(ARM::t__brkdiv0)); + + MI.eraseFromParent(); + return ContBB; +diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td +index 93a174f..6c759a1 100644 +--- a/lib/Target/ARM/ARMInstrThumb.td ++++ b/lib/Target/ARM/ARMInstrThumb.td +@@ -1259,6 +1259,13 @@ def tUDF : TI<(outs), (ins imm0_255:$imm8), IIC_Br, "udf\t$imm8", + let Inst{7-0} = imm8; + } + ++def t__brkdiv0 : TI<(outs), (ins), IIC_Br, "__brkdiv0", ++ [(int_arm_undefined 249)]>, Encoding16, ++ Requires<[IsThumb, IsWindows]> { ++ let Inst = 0xdef9; ++ let isTerminator = 1; ++} ++ + // Zero-extend byte + def tUXTB : // A8.6.262 + T1pIMiscEncode<{0,0,1,0,1,1,?}, (outs tGPR:$Rd), (ins tGPR:$Rm), +diff --git a/test/CodeGen/ARM/Windows/dbzchk.ll b/test/CodeGen/ARM/Windows/dbzchk.ll +index c078e09..af23cb2 100644 +--- a/test/CodeGen/ARM/Windows/dbzchk.ll ++++ b/test/CodeGen/ARM/Windows/dbzchk.ll +@@ -33,15 +33,12 @@ return: + } + + ; CHECK-DIV-DAG: BB#0 +-; CHECK-DIV-DAG: Successors according to CFG: BB#5({{.*}}) BB#4 ++; CHECK-DIV-DAG: Successors according to CFG: BB#1({{.*}}) BB#2 + ; CHECK-DIV-DAG: BB#1 + ; CHECK-DIV-DAG: Successors according to CFG: BB#3 + ; CHECK-DIV-DAG: BB#2 + ; CHECK-DIV-DAG: Successors according to CFG: BB#3 + ; CHECK-DIV-DAG: BB#3 +-; CHECK-DIV-DAG: BB#4 +-; CHECK-DIV-DAG: Successors according to CFG: BB#1({{.*}}) BB#2 +-; CHECK-DIV-DAG: BB#5 + + ; RUN: llc -mtriple thumbv7--windows-itanium -print-machineinstrs=expand-isel-pseudos -verify-machineinstrs -o /dev/null %s 2>&1 | FileCheck %s -check-prefix CHECK-MOD + +@@ -72,11 +69,10 @@ return: + ; CHECK-MOD-DAG: BB#0 + ; CHECK-MOD-DAG: Successors according to CFG: BB#2({{.*}}) BB#1 + ; CHECK-MOD-DAG: BB#1 +-; CHECK-MOD-DAG: Successors according to CFG: BB#4({{.*}}) BB#3 +-; CHECK-MOD-DAG: BB#2 ++; CHECK-MOD-DAG: Successors according to CFG: BB#3 + ; CHECK-MOD-DAG: BB#3 + ; CHECK-MOD-DAG: Successors according to CFG: BB#2 +-; CHECK-MOD-DAG: BB#4 ++; CHECK-MOD-DAG: BB#2 + + ; RUN: llc -mtriple thumbv7--windows-itanium -print-machineinstrs=expand-isel-pseudos -verify-machineinstrs -filetype asm -o /dev/null %s 2>&1 | FileCheck %s -check-prefix CHECK-CFG + ; RUN: llc -mtriple thumbv7--windows-itanium -print-machineinstrs=expand-isel-pseudos -verify-machineinstrs -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-CFG-ASM +@@ -123,25 +119,19 @@ attributes #0 = { optsize } + ; CHECK-CFG-DAG: t2B + + ; CHECK-CFG-DAG: BB#2 +-; CHECK-CFG-DAG: tCBZ %vreg{{[0-9]}}, +-; CHECK-CFG-DAG: t2B ++; CHECK-CFG-DAG: tCBNZ %vreg{{[0-9]}}, ++; CHECK-CFG-DAG: t__brkdiv0 + + ; CHECK-CFG-DAG: BB#4 + + ; CHECK-CFG-DAG: BB#3 + ; CHECK-CFG-DAG: tBX_RET + +-; CHECK-CFG-DAG: BB#5 +-; CHECK-CFG-DAG: t2UDF 249 +- + ; CHECK-CFG-ASM-LABEL: h: +-; CHECK-CFG-ASM: cbz r{{[0-9]}}, .LBB2_2 +-; CHECK-CFG-ASM: b .LBB2_4 ++; CHECK-CFG-ASM: cbnz r{{[0-9]}}, .LBB2_2 ++; CHECK-CFG-ASM: __brkdiv0 + ; CHECK-CFG-ASM-LABEL: .LBB2_2: +-; CHECK-CFG-ASM-NEXT: udf.w #249 +-; CHECK-CFG-ASM-LABEL: .LBB2_4: + ; CHECK-CFG-ASM: bl __rt_udiv +-; CHECK-CFG-ASM: pop.w {r11, pc} + + ; RUN: llc -O0 -mtriple thumbv7--windows-itanium -verify-machineinstrs -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-WIN__DBZCHK + +@@ -182,11 +172,11 @@ return: + } + + ; CHECK-WIN__DBZCHK-LABEL: j: +-; CHECK-WIN__DBZCHK: cbz r{{[0-7]}}, .LBB +-; CHECK-WIN__DBZCHK-NOT: cbz r8, .LBB +-; CHECK-WIN__DBZCHK-NOT: cbz r9, .LBB +-; CHECK-WIN__DBZCHK-NOT: cbz r10, .LBB +-; CHECK-WIN__DBZCHK-NOT: cbz r11, .LBB +-; CHECK-WIN__DBZCHK-NOT: cbz ip, .LBB +-; CHECK-WIN__DBZCHK-NOT: cbz lr, .LBB ++; CHECK-WIN__DBZCHK: cbnz r{{[0-7]}}, .LBB ++; CHECK-WIN__DBZCHK-NOT: cbnz r8, .LBB ++; CHECK-WIN__DBZCHK-NOT: cbnz r9, .LBB ++; CHECK-WIN__DBZCHK-NOT: cbnz r10, .LBB ++; CHECK-WIN__DBZCHK-NOT: cbnz r11, .LBB ++; CHECK-WIN__DBZCHK-NOT: cbnz ip, .LBB ++; CHECK-WIN__DBZCHK-NOT: cbnz lr, .LBB + +diff --git a/test/CodeGen/ARM/Windows/division-range.ll b/test/CodeGen/ARM/Windows/division-range.ll +new file mode 100644 +index 0000000..9b1920c +--- /dev/null ++++ b/test/CodeGen/ARM/Windows/division-range.ll +@@ -0,0 +1,15 @@ ++; RUN: llc -O0 -mtriple thumbv7--windows-itanium -filetype obj -o - %s | llvm-objdump -disassemble - | FileCheck %s ++ ++declare i32 @llvm.arm.space(i32, i32) ++ ++define arm_aapcs_vfpcc i32 @f(i32 %n, i32 %d) local_unnamed_addr { ++entry: ++ %div = sdiv i32 %n, %d ++ call i32 @llvm.arm.space(i32 128, i32 undef) ++ ret i32 %div ++} ++ ++; CHECK: cbnz r1, #0 ++; CHECK: __brkdiv0 ++; CHECK: bl ++ +diff --git a/test/CodeGen/ARM/Windows/division.ll b/test/CodeGen/ARM/Windows/division.ll +index f4704ea..b149cb0 100644 +--- a/test/CodeGen/ARM/Windows/division.ll ++++ b/test/CodeGen/ARM/Windows/division.ll +@@ -8,9 +8,8 @@ entry: + } + + ; CHECK-LABEL: sdiv32: +-; CHECK: cbz r0 +-; CHECK: b +-; CHECK: udf.w #249 ++; CHECK: cbnz r0 ++; CHECK: __brkdiv0 + ; CHECK: bl __rt_sdiv + + define arm_aapcs_vfpcc i32 @udiv32(i32 %divisor, i32 %divident) { +@@ -20,9 +19,8 @@ entry: + } + + ; CHECK-LABEL: udiv32: +-; CHECK: cbz r0 +-; CHECK: b +-; CHECK: udf.w #249 ++; CHECK: cbnz r0 ++; CHECK: __brkdiv0 + ; CHECK: bl __rt_udiv + + define arm_aapcs_vfpcc i64 @sdiv64(i64 %divisor, i64 %divident) { +@@ -33,9 +31,8 @@ entry: + + ; CHECK-LABEL: sdiv64: + ; CHECK: orr.w r4, r0, r1 +-; CHECK-NEXT: cbz r4 +-; CHECK: b +-; CHECK: udf.w #249 ++; CHECK-NEXT: cbnz r4 ++; CHECK: __brkdiv0 + ; CHECK: bl __rt_sdiv64 + + define arm_aapcs_vfpcc i64 @udiv64(i64 %divisor, i64 %divident) { +@@ -46,8 +43,7 @@ entry: + + ; CHECK-LABEL: udiv64: + ; CHECK: orr.w r4, r0, r1 +-; CHECK-NEXT: cbz r4 +-; CHECK: b +-; CHECK: udf.w #249 ++; CHECK-NEXT: cbnz r4 ++; CHECK: __brkdiv0 + ; CHECK: bl __rt_udiv64 + +-- +2.7.4 + diff --git a/patches/llvm-0009.patch b/patches/llvm-0009.patch new file mode 100644 index 0000000..cf7e9fd --- /dev/null +++ b/patches/llvm-0009.patch @@ -0,0 +1,186 @@ +From 20692f7f7548e98523818db6d83ca66e3ae0dedc Mon Sep 17 00:00:00 2001 +From: Saleem Abdulrasool +Date: Mon, 31 Oct 2016 22:12:37 +0000 +Subject: [PATCH 9/9] CodeGen: further loosen -O0 CG for WoA division + +Generate the slowest possible codepath for noopt CodeGen. Even trying to be +clever with the negated jump can cause out-of-range jumps. Use a wide branch +instead. Although the code is modelled simplistically, the later optimizations +would recombine the branching into `cbz` if possible. This re-enables the +previous optimization as well as hopefully gives us working code in all cases. + +Addresses PR30356! + +Cherry-picked from SVN trunk commit 285649, git mirror commit +f185e91e2bc8. +--- + lib/Target/ARM/ARMISelLowering.cpp | 18 ++++++++++++----- + test/CodeGen/ARM/Windows/dbzchk.ll | 31 ++++++++++++++++-------------- + test/CodeGen/ARM/Windows/division-range.ll | 4 ++-- + test/CodeGen/ARM/Windows/division.ll | 20 +++++++++---------- + 4 files changed, 42 insertions(+), 31 deletions(-) + +diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp +index f7b09fa..6d4e6d7 100644 +--- a/lib/Target/ARM/ARMISelLowering.cpp ++++ b/lib/Target/ARM/ARMISelLowering.cpp +@@ -8214,12 +8214,20 @@ ARMTargetLowering::EmitLowered__dbzchk(MachineInstr &MI, + ContBB->splice(ContBB->begin(), MBB, + std::next(MachineBasicBlock::iterator(MI)), MBB->end()); + ContBB->transferSuccessorsAndUpdatePHIs(MBB); +- +- BuildMI(*MBB, MI, DL, TII->get(ARM::tCBNZ)) +- .addReg(MI.getOperand(0).getReg()) +- .addMBB(ContBB); + MBB->addSuccessor(ContBB); +- BuildMI(*MBB, MI, DL, TII->get(ARM::t__brkdiv0)); ++ ++ MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock(); ++ BuildMI(TrapBB, DL, TII->get(ARM::t__brkdiv0)); ++ MF->push_back(TrapBB); ++ MBB->addSuccessor(TrapBB); ++ ++ AddDefaultPred(BuildMI(*MBB, MI, DL, TII->get(ARM::tCMPi8)) ++ .addReg(MI.getOperand(0).getReg()) ++ .addImm(0)); ++ BuildMI(*MBB, MI, DL, TII->get(ARM::t2Bcc)) ++ .addMBB(TrapBB) ++ .addImm(ARMCC::EQ) ++ .addReg(ARM::CPSR); + + MI.eraseFromParent(); + return ContBB; +diff --git a/test/CodeGen/ARM/Windows/dbzchk.ll b/test/CodeGen/ARM/Windows/dbzchk.ll +index af23cb2..aea3799 100644 +--- a/test/CodeGen/ARM/Windows/dbzchk.ll ++++ b/test/CodeGen/ARM/Windows/dbzchk.ll +@@ -75,7 +75,7 @@ return: + ; CHECK-MOD-DAG: BB#2 + + ; RUN: llc -mtriple thumbv7--windows-itanium -print-machineinstrs=expand-isel-pseudos -verify-machineinstrs -filetype asm -o /dev/null %s 2>&1 | FileCheck %s -check-prefix CHECK-CFG +-; RUN: llc -mtriple thumbv7--windows-itanium -print-machineinstrs=expand-isel-pseudos -verify-machineinstrs -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-CFG-ASM ++; RUN: llc -mtriple thumbv7--windows-itanium -verify-machineinstrs -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-CFG-ASM + + ; unsigned c; + ; extern unsigned long g(void); +@@ -119,21 +119,24 @@ attributes #0 = { optsize } + ; CHECK-CFG-DAG: t2B + + ; CHECK-CFG-DAG: BB#2 +-; CHECK-CFG-DAG: tCBNZ %vreg{{[0-9]}}, +-; CHECK-CFG-DAG: t__brkdiv0 ++; CHECK-CFG-DAG: tCMPi8 %vreg{{[0-9]}}, 0 ++; CHECK-CFG-DAG: t2Bcc + + ; CHECK-CFG-DAG: BB#4 + + ; CHECK-CFG-DAG: BB#3 + ; CHECK-CFG-DAG: tBX_RET + ++; CHECK-CFG-DAG: BB#5 ++; CHECK-CFG-DAG: t__brkdiv0 ++ + ; CHECK-CFG-ASM-LABEL: h: +-; CHECK-CFG-ASM: cbnz r{{[0-9]}}, .LBB2_2 +-; CHECK-CFG-ASM: __brkdiv0 +-; CHECK-CFG-ASM-LABEL: .LBB2_2: ++; CHECK-CFG-ASM: cbz r{{[0-9]}}, .LBB2_4 + ; CHECK-CFG-ASM: bl __rt_udiv ++; CHECK-CFG-ASM-LABEL: .LBB2_4: ++; CHECK-CFG-ASM: __brkdiv0 + +-; RUN: llc -O0 -mtriple thumbv7--windows-itanium -verify-machineinstrs -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-WIN__DBZCHK ++; RUN: llc -O1 -mtriple thumbv7--windows-itanium -verify-machineinstrs -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-WIN__DBZCHK + + ; long k(void); + ; int l(void); +@@ -172,11 +175,11 @@ return: + } + + ; CHECK-WIN__DBZCHK-LABEL: j: +-; CHECK-WIN__DBZCHK: cbnz r{{[0-7]}}, .LBB +-; CHECK-WIN__DBZCHK-NOT: cbnz r8, .LBB +-; CHECK-WIN__DBZCHK-NOT: cbnz r9, .LBB +-; CHECK-WIN__DBZCHK-NOT: cbnz r10, .LBB +-; CHECK-WIN__DBZCHK-NOT: cbnz r11, .LBB +-; CHECK-WIN__DBZCHK-NOT: cbnz ip, .LBB +-; CHECK-WIN__DBZCHK-NOT: cbnz lr, .LBB ++; CHECK-WIN__DBZCHK: cbz r{{[0-7]}}, .LBB ++; CHECK-WIN__DBZCHK-NOT: cbz r8, .LBB ++; CHECK-WIN__DBZCHK-NOT: cbz r9, .LBB ++; CHECK-WIN__DBZCHK-NOT: cbz r10, .LBB ++; CHECK-WIN__DBZCHK-NOT: cbz r11, .LBB ++; CHECK-WIN__DBZCHK-NOT: cbz ip, .LBB ++; CHECK-WIN__DBZCHK-NOT: cbz lr, .LBB + +diff --git a/test/CodeGen/ARM/Windows/division-range.ll b/test/CodeGen/ARM/Windows/division-range.ll +index 9b1920c..b14339e 100644 +--- a/test/CodeGen/ARM/Windows/division-range.ll ++++ b/test/CodeGen/ARM/Windows/division-range.ll +@@ -9,7 +9,7 @@ entry: + ret i32 %div + } + +-; CHECK: cbnz r1, #0 +-; CHECK: __brkdiv0 ++; CHECK: cmp r1, #0 ++; CHECK: beq # + ; CHECK: bl + +diff --git a/test/CodeGen/ARM/Windows/division.ll b/test/CodeGen/ARM/Windows/division.ll +index b149cb0..10f86b0 100644 +--- a/test/CodeGen/ARM/Windows/division.ll ++++ b/test/CodeGen/ARM/Windows/division.ll +@@ -8,9 +8,9 @@ entry: + } + + ; CHECK-LABEL: sdiv32: +-; CHECK: cbnz r0 +-; CHECK: __brkdiv0 ++; CHECK: cbz r0 + ; CHECK: bl __rt_sdiv ++; CHECK: __brkdiv0 + + define arm_aapcs_vfpcc i32 @udiv32(i32 %divisor, i32 %divident) { + entry: +@@ -19,9 +19,9 @@ entry: + } + + ; CHECK-LABEL: udiv32: +-; CHECK: cbnz r0 +-; CHECK: __brkdiv0 ++; CHECK: cbz r0 + ; CHECK: bl __rt_udiv ++; CHECK: __brkdiv0 + + define arm_aapcs_vfpcc i64 @sdiv64(i64 %divisor, i64 %divident) { + entry: +@@ -30,10 +30,10 @@ entry: + } + + ; CHECK-LABEL: sdiv64: +-; CHECK: orr.w r4, r0, r1 +-; CHECK-NEXT: cbnz r4 +-; CHECK: __brkdiv0 ++; CHECK: orrs.w r4, r0, r1 ++; CHECK-NEXT: beq + ; CHECK: bl __rt_sdiv64 ++; CHECK: __brkdiv0 + + define arm_aapcs_vfpcc i64 @udiv64(i64 %divisor, i64 %divident) { + entry: +@@ -42,8 +42,8 @@ entry: + } + + ; CHECK-LABEL: udiv64: +-; CHECK: orr.w r4, r0, r1 +-; CHECK-NEXT: cbnz r4 +-; CHECK: __brkdiv0 ++; CHECK: orrs.w r4, r0, r1 ++; CHECK-NEXT: beq + ; CHECK: bl __rt_udiv64 ++; CHECK: __brkdiv0 + +-- +2.7.4 +