setOperationAction(ISD::UREM, MVT::i32, Expand);
// Register based DivRem for AEABI (RTABI 4.2)
if (Subtarget->isTargetAEABI() || Subtarget->isTargetAndroid() ||
- Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI() ||
- Subtarget->isTargetWindows()) {
+ Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI()) {
setOperationAction(ISD::SREM, MVT::i64, Custom);
setOperationAction(ISD::UREM, MVT::i64, Custom);
HasStandaloneRem = false;
- 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");
+ 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);
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<SDValue> &Results) const {
"unexpected type for custom lowering DIV");
SDLoc dl(Op);
- SDValue DBZCHK = WinDBZCheckDenominator(DAG, Op.getNode(), DAG.getEntryNode());
+ 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 Result = LowerWindowsDIVLibCall(Op, DAG, Signed, DBZCHK);
}
static TargetLowering::ArgListTy getDivRemArgList(
- const SDNode *N, LLVMContext *Context, const ARMSubtarget *Subtarget) {
+ const SDNode *N, LLVMContext *Context) {
assert((N->getOpcode() == ISD::SDIVREM || N->getOpcode() == ISD::UDIVREM ||
N->getOpcode() == ISD::SREM || N->getOpcode() == ISD::UREM) &&
"Unhandled Opcode in 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->isTargetWindows()) &&
+ Subtarget->isTargetGNUAEABI() || Subtarget->isTargetMuslAEABI()) &&
"Register-based DivRem lowering only");
unsigned Opcode = Op->getOpcode();
assert((Opcode == ISD::SDIVREM || Opcode == ISD::UDIVREM) &&
SDValue InChain = DAG.getEntryNode();
TargetLowering::ArgListTy Args = getDivRemArgList(Op.getNode(),
- DAG.getContext(),
- Subtarget);
+ DAG.getContext());
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);
-
TargetLowering::CallLoweringInfo CLI(DAG);
CLI.setDebugLoc(dl).setChain(InChain)
.setCallee(getLibcallCallingConv(LC), RetTy, Callee, std::move(Args))
RTLIB::Libcall LC = getDivRemLibcall(N, N->getValueType(0).getSimpleVT().
SimpleTy);
SDValue InChain = DAG.getEntryNode();
- TargetLowering::ArgListTy Args = getDivRemArgList(N, DAG.getContext(),
- Subtarget);
+ TargetLowering::ArgListTy Args = getDivRemArgList(N, DAG.getContext());
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)
; DARWIN-DEFAULT: add [[sum:r[0-9]+]], r0, [[div]]
; DARWIN-O0: mov [[rem:r[0-9]+]], r0
; WINDOWS: __rt_sdiv
-; WINDOWS: __rt_sdiv
-; WINDOWS-DEFAULT: add [[sum:r[0-9]+]], r1
-; WINDOWS-O0: mov [[rem:r[0-9]+]], r1
+; 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]],
%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
; DARWIN-O0: add [[sum:r[0-9]+]], [[rem]], [[div]]
; DARWIN-O0: add [[res:r[0-9]+]], [[sum]], r0
; DARWIN: sxth r0, [[res]]
-; 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]]
+; WINDOWS-O0: adds [[sum:r[0-9]+]], [[rem]], [[div]]
+; WINDOWS: add [[rem1]], [[sum]]
+; WINDOWS: sxth [[res:r[0-9]+]], [[rem1]]
ret i16 %conv14
}
; WINDOWS: __rt_sdiv
; WINDOWS: mov [[div:r[0-9]+]], r0
; WINDOWS: __rt_sdiv
-; WINDOWS-DEFAULT: add [[div]], r1
+; WINDOWS: mls [[rem:r[0-9]+]], r0,
+; WINDOWS-DEFAULT: add [[div]], [[rem]]
%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: adds r0, [[div]], r1
+; WINDOWS-DEFAULT: add [[rem1]], [[div]]
; WINDOWS-O0: adds [[sum:r[0-9]+]], [[rem]], [[div]]
-; WINDOWS-O0: add [[sum]], r1
+; WINDOWS-O0: add [[rem1]], [[sum]]
ret i32 %add2
}
; WINDOWS: __rt_udiv
; WINDOWS: mov [[div:r[0-9]+]], r0
; WINDOWS: __rt_udiv
-; WINDOWS-DEFAULT: add [[div]], r1
+; WINDOWS: mls [[rem:r[0-9]+]], r0,
+; WINDOWS-DEFAULT: add [[div]], [[rem]]
%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: adds [[sum:r[0-9]+]], [[div]], r1
-; WINDOWS-O0: adds [[sum:r[0-9]+]],
-; WINDOWS-O0: add [[sum]], r1
+; WINDOWS-DEFAULT: add [[rem1]], [[div]]
+; WINDOWS-O0: adds [[sum:r[0-9]+]], [[rem]], [[div]]
+; WINDOWS-O0: add [[rem1]], [[sum]]
ret i32 %add2
}
; 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 r0, r0, r2
-; WINDOWS: adcs r1, r3
+; WINDOWS: adds.w r0, r0, [[div1]]
+; WINDOWS: adc.w r1, r1, [[div2]]
ret i64 %add
}
; 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: adds r0, r1, [[div]]
+; WINDOWS: add [[rem]], [[div]]
ret i16 %add
}
; 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: adds r0, r1, [[div]]
+; WINDOWS: add [[rem]], [[div]]
ret i32 %add
}
; WINDOWS: __rt_sdiv
ret i32 %rem
; EABI: mov r0, r1
-; WINDOWS: mov r0, r1
+; WINDOWS: mls r0, r0,
}
define i32 @g3(i32 %a, i32 %b) {
; DARWIN: __modsi3
; DARWIN: mov [[sum:r[0-9]+]], r0
; WINDOWS: __rt_sdiv
-; WINDOWS: mov [[rem:r[0-9]+]], r1
+; WINDOWS: mls [[rem:r[0-9]+]], r0,
%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: adds r0, r1, [[rem]]
+; WINDOWS: add [[rem1]], [[rem]]
ret i32 %add
}
; 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: adds r0, r1, [[div]]
+; WINDOWS: add [[rem]], [[div]]
ret i32 %add
}