Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -980,19 +980,31 @@ 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"); + if (Subtarget->isTargetWindows()) { + setLibcallName(RTLIB::SDIVREM_I8, "__rt_sdiv"); + setLibcallName(RTLIB::SDIVREM_I16, "__rt_sdiv"); + setLibcallName(RTLIB::SDIVREM_I32, "__rt_sdiv"); + setLibcallName(RTLIB::SDIVREM_I64, "__rt_sdiv64"); + setLibcallName(RTLIB::UDIVREM_I8, "__rt_udiv"); + setLibcallName(RTLIB::UDIVREM_I16, "__rt_udiv"); + setLibcallName(RTLIB::UDIVREM_I32, "__rt_udiv"); + setLibcallName(RTLIB::UDIVREM_I64, "__rt_udiv64"); + } else { + 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"); + } setLibcallCallingConv(RTLIB::SDIVREM_I8, CallingConv::ARM_AAPCS); setLibcallCallingConv(RTLIB::SDIVREM_I16, CallingConv::ARM_AAPCS); @@ -12406,7 +12418,7 @@ } 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"); @@ -12423,12 +12435,15 @@ 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) && @@ -12442,7 +12457,8 @@ SDValue InChain = DAG.getEntryNode(); TargetLowering::ArgListTy Args = getDivRemArgList(Op.getNode(), - DAG.getContext()); + DAG.getContext(), + Subtarget); SDValue Callee = DAG.getExternalSymbol(getLibcallName(LC), getPointerTy(DAG.getDataLayout())); @@ -12450,6 +12466,19 @@ Type *RetTy = (Type*)StructType::get(Ty, Ty, nullptr); SDLoc dl(Op); + if (Subtarget->isTargetWindows()) { + SDValue Denom = Op->getOperand(1); + if (VT == MVT::i64) { + 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)); + Denom = DAG.getNode(ISD::OR, dl, MVT::i32, Lo, Hi); + } + + InChain = DAG.getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other, InChain, Denom); + } + TargetLowering::CallLoweringInfo CLI(DAG); CLI.setDebugLoc(dl).setChain(InChain) .setCallee(getLibcallCallingConv(LC), RetTy, Callee, std::move(Args)) @@ -12482,11 +12511,26 @@ 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())); + SDLoc dl(N); + if (Subtarget->isTargetWindows()) { + SDValue Denom = N->getOperand(1); + if (N->getValueType(0) == MVT::i64) { + SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, N->getOperand(1), + DAG.getConstant(0, dl, MVT::i32)); + SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i32, N->getOperand(1), + DAG.getConstant(1, dl, MVT::i32)); + Denom = DAG.getNode(ISD::OR, dl, MVT::i32, Lo, Hi); + } + + InChain = DAG.getNode(ARMISD::WIN__DBZCHK, dl, MVT::Other, InChain, Denom); + } + // Lower call CallLoweringInfo CLI(DAG); CLI.setChain(InChain) Index: test/CodeGen/ARM/Windows/dbzchk.ll =================================================================== --- test/CodeGen/ARM/Windows/dbzchk.ll +++ test/CodeGen/ARM/Windows/dbzchk.ll @@ -72,11 +72,8 @@ ; 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: 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 @@ -136,12 +133,8 @@ ; CHECK-CFG-ASM-LABEL: h: ; CHECK-CFG-ASM: cbz r{{[0-9]}}, .LBB2_2 -; CHECK-CFG-ASM: b .LBB2_4 ; 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} +; CHECK-CFG-ASM: pop {{{.*}}, pc} ; RUN: llc -O0 -mtriple thumbv7--windows-itanium -verify-machineinstrs -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-WIN__DBZCHK @@ -182,11 +175,4 @@ } ; 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 Index: test/CodeGen/ARM/divmod-eabi.ll =================================================================== --- test/CodeGen/ARM/divmod-eabi.ll +++ test/CodeGen/ARM/divmod-eabi.ll @@ -42,15 +42,13 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 }