/// ExpandOp - Expand the specified SDValue into its two component pieces
/// Lo&Hi. Note that the Op MUST be an expanded type. As a result of this,
- /// the LegalizeNodes map is filled in for any results that are not expanded,
+ /// the LegalizedNodes map is filled in for any results that are not expanded,
/// the ExpandedNodes map is filled in for any results that are expanded, and
/// the Lo/Hi values are returned. This applies to integer types and Vector
/// types.
SmallPtrSet<SDNode*, 32> &NodesLeadingTo);
void LegalizeSetCCOperands(SDValue &LHS, SDValue &RHS, SDValue &CC);
+ void LegalizeSetCCCondCode(MVT VT, SDValue &LHS, SDValue &RHS, SDValue &CC);
+ void LegalizeSetCC(MVT VT, SDValue &LHS, SDValue &RHS, SDValue &CC) {
+ LegalizeSetCCOperands(LHS, RHS, CC);
+ LegalizeSetCCCondCode(VT, LHS, RHS, CC);
+ }
SDValue ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, bool isSigned,
SDValue &Hi);
// practice however, this causes us to run out of stack space on large basic
// blocks. To avoid this problem, compute an ordering of the nodes where each
// node is only legalized after all of its operands are legalized.
- std::vector<SDNode *> TopOrder;
- unsigned N = DAG.AssignTopologicalOrder(TopOrder);
- for (unsigned i = N; i != 0; --i)
- HandleOp(SDValue(TopOrder[i-1], 0));
- TopOrder.clear();
+ DAG.AssignTopologicalOrder();
+ for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
+ E = prior(DAG.allnodes_end()); I != next(E); ++I)
+ HandleOp(SDValue(I, 0));
// Finally, it's possible the root changed. Get the new root.
SDValue OldRoot = DAG.getRoot();
if (!UseCP) {
if (VT!=MVT::f64 && VT!=MVT::f32)
assert(0 && "Invalid type expansion");
- return DAG.getConstant(LLVMC->getValueAPF().convertToAPInt(),
+ return DAG.getConstant(LLVMC->getValueAPF().bitcastToAPInt(),
(VT == MVT::f64) ? MVT::i64 : MVT::i32);
}
if (CFP->isValueValidForType(SVT, CFP->getValueAPF()) &&
// Only do this if the target has a native EXTLOAD instruction from
// smaller type.
- TLI.isLoadXLegal(ISD::EXTLOAD, SVT) &&
+ TLI.isLoadExtLegal(ISD::EXTLOAD, SVT) &&
TLI.ShouldShrinkFPConstant(OrigVT)) {
const Type *SType = SVT.getTypeForMVT();
LLVMC = cast<ConstantFP>(ConstantExpr::getFPTrunc(LLVMC, SType));
}
SDValue CPIdx = DAG.getConstantPool(LLVMC, TLI.getPointerTy());
+ unsigned Alignment = 1 << cast<ConstantPoolSDNode>(CPIdx)->getAlignment();
if (Extend)
return DAG.getExtLoad(ISD::EXTLOAD, OrigVT, DAG.getEntryNode(),
CPIdx, PseudoSourceValue::getConstantPool(),
- 0, VT);
+ 0, VT, false, Alignment);
return DAG.getLoad(OrigVT, DAG.getEntryNode(), CPIdx,
- PseudoSourceValue::getConstantPool(), 0);
+ PseudoSourceValue::getConstantPool(), 0, false, Alignment);
}
case TargetLowering::Custom:
Result = TLI.LowerOperation(Result, DAG);
break;
- case TargetLowering::Expand:
- Result = SDValue(TLI.ReplaceNodeResults(Op.getNode(), DAG),0);
- break;
case TargetLowering::Legal:
break;
}
// Chain the dynamic stack allocation so that it doesn't modify the stack
// pointer when other instructions are using the stack.
- Chain = DAG.getCALLSEQ_START(Chain,
- DAG.getConstant(0, TLI.getPointerTy()));
+ Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(0, true));
SDValue Size = Tmp2.getOperand(1);
SDValue SP = DAG.getCopyFromReg(Chain, SPReg, VT);
Tmp1 = DAG.getNode(ISD::SUB, VT, SP, Size); // Value
Chain = DAG.getCopyToReg(Chain, SPReg, Tmp1); // Output chain
- Tmp2 =
- DAG.getCALLSEQ_END(Chain,
- DAG.getConstant(0, TLI.getPointerTy()),
- DAG.getConstant(0, TLI.getPointerTy()),
- SDValue());
+ Tmp2 = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(0, true),
+ DAG.getIntPtrConstant(0, true), SDValue());
Tmp1 = LegalizeOp(Tmp1);
Tmp2 = LegalizeOp(Tmp2);
Tmp3 = Node->getOperand(3); // RHS
Tmp4 = Node->getOperand(1); // CC
- LegalizeSetCCOperands(Tmp2, Tmp3, Tmp4);
+ LegalizeSetCC(Node->getValueType(0), Tmp2, Tmp3, Tmp4);
LastCALLSEQ_END = DAG.getEntryNode();
- // If we didn't get both a LHS and RHS back from LegalizeSetCCOperands,
+ // If we didn't get both a LHS and RHS back from LegalizeSetCC,
// the LHS is a legal SETCC itself. In this case, we need to compare
// the result against zero to select between true and false values.
if (Tmp3.getNode() == 0) {
// nice to have an effective generic way of getting these benefits...
// Until such a way is found, don't insist on promoting i1 here.
(SrcVT != MVT::i1 ||
- TLI.getLoadXAction(ExtType, MVT::i1) == TargetLowering::Promote)) {
+ TLI.getLoadExtAction(ExtType, MVT::i1) == TargetLowering::Promote)) {
// Promote to a byte-sized load if not loading an integral number of
// bytes. For example, promote EXTLOAD:i20 -> EXTLOAD:i24.
unsigned NewWidth = SrcVT.getStoreSizeInBits();
Tmp1 = LegalizeOp(Result);
Tmp2 = LegalizeOp(Ch);
} else {
- switch (TLI.getLoadXAction(ExtType, SrcVT)) {
+ switch (TLI.getLoadExtAction(ExtType, SrcVT)) {
default: assert(0 && "This action is not supported yet!");
case TargetLowering::Custom:
isCustom = true;
if (CFP->getValueType(0) == MVT::f32 &&
getTypeAction(MVT::i32) == Legal) {
Tmp3 = DAG.getConstant(CFP->getValueAPF().
- convertToAPInt().zextOrTrunc(32),
+ bitcastToAPInt().zextOrTrunc(32),
MVT::i32);
Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
SVOffset, isVolatile, Alignment);
} else if (CFP->getValueType(0) == MVT::f64) {
// If this target supports 64-bit registers, do a single 64-bit store.
if (getTypeAction(MVT::i64) == Legal) {
- Tmp3 = DAG.getConstant(CFP->getValueAPF().convertToAPInt().
+ Tmp3 = DAG.getConstant(CFP->getValueAPF().bitcastToAPInt().
zextOrTrunc(64), MVT::i64);
Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
SVOffset, isVolatile, Alignment);
// Otherwise, if the target supports 32-bit registers, use 2 32-bit
// stores. If the target supports neither 32- nor 64-bits, this
// xform is certainly not worth it.
- const APInt &IntVal =CFP->getValueAPF().convertToAPInt();
+ const APInt &IntVal =CFP->getValueAPF().bitcastToAPInt();
SDValue Lo = DAG.getConstant(APInt(IntVal).trunc(32), MVT::i32);
SDValue Hi = DAG.getConstant(IntVal.lshr(32).trunc(32), MVT::i32);
if (TLI.isBigEndian()) std::swap(Lo, Hi);
ExpandOp(ST->getValue(), Lo, Hi);
IncrementSize = Hi.getNode() ? Hi.getValueType().getSizeInBits()/8 : 0;
- if (TLI.isBigEndian())
+ if (Hi.getNode() && TLI.isBigEndian())
std::swap(Lo, Hi);
}
Tmp4 = LegalizeOp(Node->getOperand(3)); // False
SDValue CC = Node->getOperand(4);
- LegalizeSetCCOperands(Tmp1, Tmp2, CC);
+ LegalizeSetCC(Node->getValueType(0), Tmp1, Tmp2, CC);
- // If we didn't get both a LHS and RHS back from LegalizeSetCCOperands,
+ // If we didn't get both a LHS and RHS back from LegalizeSetCC,
// the LHS is a legal SETCC itself. In this case, we need to compare
// the result against zero to select between true and false values.
if (Tmp2.getNode() == 0) {
Tmp1 = Node->getOperand(0);
Tmp2 = Node->getOperand(1);
Tmp3 = Node->getOperand(2);
- LegalizeSetCCOperands(Tmp1, Tmp2, Tmp3);
+ LegalizeSetCC(Node->getValueType(0), Tmp1, Tmp2, Tmp3);
// If we had to Expand the SetCC operands into a SELECT node, then it may
// not always be possible to return a true LHS & RHS. In this case, just
}
if (Node->getOpcode() == ISD::MULHS &&
TLI.isOperationLegal(ISD::SMUL_LOHI, VT)) {
- Result = SDValue(DAG.getNode(ISD::SMUL_LOHI, VTs, Tmp1, Tmp2).getNode(), 1);
+ Result = SDValue(DAG.getNode(ISD::SMUL_LOHI, VTs, Tmp1, Tmp2).getNode(),
+ 1);
break;
}
if (Node->getOpcode() == ISD::MULHU &&
TLI.isOperationLegal(ISD::UMUL_LOHI, VT)) {
- Result = SDValue(DAG.getNode(ISD::UMUL_LOHI, VTs, Tmp1, Tmp2).getNode(), 1);
+ Result = SDValue(DAG.getNode(ISD::UMUL_LOHI, VTs, Tmp1, Tmp2).getNode(),
+ 1);
break;
}
if (Node->getOpcode() == ISD::SDIV &&
TLI.isOperationLegal(ISD::SDIVREM, VT)) {
- Result = SDValue(DAG.getNode(ISD::SDIVREM, VTs, Tmp1, Tmp2).getNode(), 0);
+ Result = SDValue(DAG.getNode(ISD::SDIVREM, VTs, Tmp1, Tmp2).getNode(),
+ 0);
break;
}
if (Node->getOpcode() == ISD::UDIV &&
TLI.isOperationLegal(ISD::UDIVREM, VT)) {
- Result = SDValue(DAG.getNode(ISD::UDIVREM, VTs, Tmp1, Tmp2).getNode(), 0);
+ Result = SDValue(DAG.getNode(ISD::UDIVREM, VTs, Tmp1, Tmp2).getNode(),
+ 0);
break;
}
isSigned = Node->getOpcode() == ISD::SDIV;
}
break;
+ case ISD::MUL:
+ if (VT == MVT::i32)
+ LC = RTLIB::MUL_I32;
+ break;
case ISD::FPOW:
LC = GetFPLibCall(VT, RTLIB::POW_F32, RTLIB::POW_F64, RTLIB::POW_F80,
RTLIB::POW_PPCF128);
TargetLowering::ArgListTy Args;
std::pair<SDValue,SDValue> CallResult =
TLI.LowerCallTo(Tmp1, Type::VoidTy,
- false, false, false, CallingConv::C, false,
+ false, false, false, false, CallingConv::C, false,
DAG.getExternalSymbol("abort", TLI.getPointerTy()),
Args, DAG);
Result = CallResult.second;
DAG.getValueType(VT));
Tmp2 = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Tmp2,
DAG.getValueType(VT));
+ Tmp1 = LegalizeOp(Tmp1); // Relegalize new nodes.
+ Tmp2 = LegalizeOp(Tmp2); // Relegalize new nodes.
break;
}
}
RHS = Tmp2;
}
+/// LegalizeSetCCCondCode - Legalize a SETCC with given LHS and RHS and
+/// condition code CC on the current target. This routine assumes LHS and rHS
+/// have already been legalized by LegalizeSetCCOperands. It expands SETCC with
+/// illegal condition code into AND / OR of multiple SETCC values.
+void SelectionDAGLegalize::LegalizeSetCCCondCode(MVT VT,
+ SDValue &LHS, SDValue &RHS,
+ SDValue &CC) {
+ MVT OpVT = LHS.getValueType();
+ ISD::CondCode CCCode = cast<CondCodeSDNode>(CC)->get();
+ switch (TLI.getCondCodeAction(CCCode, OpVT)) {
+ default: assert(0 && "Unknown condition code action!");
+ case TargetLowering::Legal:
+ // Nothing to do.
+ break;
+ case TargetLowering::Expand: {
+ ISD::CondCode CC1 = ISD::SETCC_INVALID, CC2 = ISD::SETCC_INVALID;
+ unsigned Opc = 0;
+ switch (CCCode) {
+ default: assert(0 && "Don't know how to expand this condition!"); abort();
+ case ISD::SETOEQ: CC1 = ISD::SETEQ; CC2 = ISD::SETO; Opc = ISD::AND; break;
+ case ISD::SETOGT: CC1 = ISD::SETGT; CC2 = ISD::SETO; Opc = ISD::AND; break;
+ case ISD::SETOGE: CC1 = ISD::SETGE; CC2 = ISD::SETO; Opc = ISD::AND; break;
+ case ISD::SETOLT: CC1 = ISD::SETLT; CC2 = ISD::SETO; Opc = ISD::AND; break;
+ case ISD::SETOLE: CC1 = ISD::SETLE; CC2 = ISD::SETO; Opc = ISD::AND; break;
+ case ISD::SETONE: CC1 = ISD::SETNE; CC2 = ISD::SETO; Opc = ISD::AND; break;
+ case ISD::SETUEQ: CC1 = ISD::SETEQ; CC2 = ISD::SETUO; Opc = ISD::OR; break;
+ case ISD::SETUGT: CC1 = ISD::SETGT; CC2 = ISD::SETUO; Opc = ISD::OR; break;
+ case ISD::SETUGE: CC1 = ISD::SETGE; CC2 = ISD::SETUO; Opc = ISD::OR; break;
+ case ISD::SETULT: CC1 = ISD::SETLT; CC2 = ISD::SETUO; Opc = ISD::OR; break;
+ case ISD::SETULE: CC1 = ISD::SETLE; CC2 = ISD::SETUO; Opc = ISD::OR; break;
+ case ISD::SETUNE: CC1 = ISD::SETNE; CC2 = ISD::SETUO; Opc = ISD::OR; break;
+ // FIXME: Implement more expansions.
+ }
+
+ SDValue SetCC1 = DAG.getSetCC(VT, LHS, RHS, CC1);
+ SDValue SetCC2 = DAG.getSetCC(VT, LHS, RHS, CC2);
+ LHS = DAG.getNode(Opc, VT, SetCC1, SetCC2);
+ RHS = SDValue();
+ CC = SDValue();
+ break;
+ }
+ }
+}
+
/// EmitStackConvert - Emit a store/load combination to the stack. This stores
/// SrcOp to a stack slot of type SlotVT, truncating it if needed. It then does
/// a load from the stack slot to DestVT, extending it if needed.
}
Constant *CP = ConstantVector::get(CV);
SDValue CPIdx = DAG.getConstantPool(CP, TLI.getPointerTy());
+ unsigned Alignment = 1 << cast<ConstantPoolSDNode>(CPIdx)->getAlignment();
return DAG.getLoad(VT, DAG.getEntryNode(), CPIdx,
- PseudoSourceValue::getConstantPool(), 0);
+ PseudoSourceValue::getConstantPool(), 0,
+ false, Alignment);
}
if (SplatValue.getNode()) { // Splat of one value?
// Splice the libcall in wherever FindInputOutputChains tells us to.
const Type *RetTy = Node->getValueType(0).getTypeForMVT();
std::pair<SDValue,SDValue> CallInfo =
- TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, CallingConv::C,
- false, Callee, Args, DAG);
+ TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false,
+ CallingConv::C, false, Callee, Args, DAG);
// Legalize the call sequence, starting with the chain. This will advance
// the LastCALLSEQ_END to the legalized version of the CALLSEQ_END node that
DestTy.getVectorNumElements() / 2);
SDValue LoResult = LegalizeINT_TO_FP(SDValue(), isSigned, SplitDestTy, Lo);
SDValue HiResult = LegalizeINT_TO_FP(SDValue(), isSigned, SplitDestTy, Hi);
- return LegalizeOp(DAG.getNode(ISD::CONCAT_VECTORS, DestTy, LoResult, HiResult));
+ return LegalizeOp(DAG.getNode(ISD::CONCAT_VECTORS, DestTy, LoResult,
+ HiResult));
}
// Special case for i32 source to take advantage of UINTTOFP_I32_F32, etc.
Hi = Source;
}
+ // Check to see if the target has a custom way to lower this. If so, use it.
+ // (Note we've already expanded the operand in this case.)
+ switch (TLI.getOperationAction(ISD::UINT_TO_FP, SourceVT)) {
+ default: assert(0 && "This action not implemented for this operation!");
+ case TargetLowering::Legal:
+ case TargetLowering::Expand:
+ break; // This case is handled below.
+ case TargetLowering::Custom: {
+ SDValue NV = TLI.LowerOperation(DAG.getNode(ISD::UINT_TO_FP, DestTy,
+ Source), DAG);
+ if (NV.getNode())
+ return LegalizeOp(NV);
+ break; // The target decided this was legal after all
+ }
+ }
+
// If this is unsigned, and not supported, first perform the conversion to
// signed, then adjust the result if the sign bit is set.
SDValue SignedConv = ExpandIntToFP(true, DestTy, Source);
static Constant *FudgeFactor = ConstantInt::get(Type::Int64Ty, FF);
SDValue CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy());
+ unsigned Alignment = 1 << cast<ConstantPoolSDNode>(CPIdx)->getAlignment();
CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset);
+ Alignment = std::min(Alignment, 4u);
SDValue FudgeInReg;
if (DestTy == MVT::f32)
FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx,
- PseudoSourceValue::getConstantPool(), 0);
+ PseudoSourceValue::getConstantPool(), 0,
+ false, Alignment);
else if (DestTy.bitsGT(MVT::f32))
// FIXME: Avoid the extend by construction the right constantpool?
FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, DestTy, DAG.getEntryNode(),
CPIdx,
PseudoSourceValue::getConstantPool(), 0,
- MVT::f32);
+ MVT::f32, false, Alignment);
else
assert(0 && "Unexpected conversion");
static Constant *FudgeFactor = ConstantInt::get(Type::Int64Ty, FF);
SDValue CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy());
+ unsigned Alignment = 1 << cast<ConstantPoolSDNode>(CPIdx)->getAlignment();
CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset);
+ Alignment = std::min(Alignment, 4u);
SDValue FudgeInReg;
if (DestVT == MVT::f32)
FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx,
- PseudoSourceValue::getConstantPool(), 0);
+ PseudoSourceValue::getConstantPool(), 0,
+ false, Alignment);
else {
FudgeInReg =
LegalizeOp(DAG.getExtLoad(ISD::EXTLOAD, DestVT,
DAG.getEntryNode(), CPIdx,
PseudoSourceValue::getConstantPool(), 0,
- MVT::f32));
+ MVT::f32, false, Alignment));
}
return DAG.getNode(ISD::FADD, DestVT, Tmp1, FudgeInReg);
/// ExpandOp - Expand the specified SDValue into its two component pieces
/// Lo&Hi. Note that the Op MUST be an expanded type. As a result of this, the
-/// LegalizeNodes map is filled in for any results that are not expanded, the
+/// LegalizedNodes map is filled in for any results that are not expanded, the
/// ExpandedNodes map is filled in for any results that are expanded, and the
/// Lo/Hi values are returned.
void SelectionDAGLegalize::ExpandOp(SDValue Op, SDValue &Lo, SDValue &Hi){
case ISD::ConstantFP: {
ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Node);
if (CFP->getValueType(0) == MVT::ppcf128) {
- APInt api = CFP->getValueAPF().convertToAPInt();
+ APInt api = CFP->getValueAPF().bitcastToAPInt();
Lo = DAG.getConstantFP(APFloat(APInt(64, 1, &api.getRawData()[1])),
MVT::f64);
Hi = DAG.getConstantFP(APFloat(APInt(64, 1, &api.getRawData()[0])),
break;
}
- // FIXME: should the LOAD_BIN and SWAP atomics get here too? Probably.
- case ISD::ATOMIC_CMP_SWAP_8:
- case ISD::ATOMIC_CMP_SWAP_16:
- case ISD::ATOMIC_CMP_SWAP_32:
case ISD::ATOMIC_CMP_SWAP_64: {
+ // This operation does not need a loop.
SDValue Tmp = TLI.LowerOperation(Op, DAG);
assert(Tmp.getNode() && "Node must be custom expanded!");
ExpandOp(Tmp.getValue(0), Lo, Hi);
break;
}
-
+ case ISD::ATOMIC_LOAD_ADD_64:
+ case ISD::ATOMIC_LOAD_SUB_64:
+ case ISD::ATOMIC_LOAD_AND_64:
+ case ISD::ATOMIC_LOAD_OR_64:
+ case ISD::ATOMIC_LOAD_XOR_64:
+ case ISD::ATOMIC_LOAD_NAND_64:
+ case ISD::ATOMIC_SWAP_64: {
+ // These operations require a loop to be generated. We can't do that yet,
+ // so substitute a target-dependent pseudo and expand that later.
+ SDValue In2Lo, In2Hi, In2;
+ ExpandOp(Op.getOperand(2), In2Lo, In2Hi);
+ In2 = DAG.getNode(ISD::BUILD_PAIR, VT, In2Lo, In2Hi);
+ AtomicSDNode* Anode = cast<AtomicSDNode>(Node);
+ SDValue Replace =
+ DAG.getAtomic(Op.getOpcode(), Op.getOperand(0), Op.getOperand(1), In2,
+ Anode->getSrcValue(), Anode->getAlignment());
+ SDValue Result = TLI.LowerOperation(Replace, DAG);
+ ExpandOp(Result.getValue(0), Lo, Hi);
+ // Remember that we legalized the chain.
+ AddLegalizedOperand(SDValue(Node,1), LegalizeOp(Result.getValue(1)));
+ break;
+ }
// These operators cannot be expanded directly, emit them as calls to
// library functions.
break;
}
}
-
// Expand the subcomponents.
SDValue LHSL, LHSH, RHSL, RHSH;
ExpandOp(Node->getOperand(0), LHSL, LHSH);
LoOps[1] = RHSL;
HiOps[0] = LHSH;
HiOps[1] = RHSH;
- if (Node->getOpcode() == ISD::ADD) {
- Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2);
- HiOps[2] = Lo.getValue(1);
- Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3);
+
+ //cascaded check to see if any smaller size has a a carry flag.
+ unsigned OpV = Node->getOpcode() == ISD::ADD ? ISD::ADDC : ISD::SUBC;
+ bool hasCarry = false;
+ for (unsigned BitSize = NVT.getSizeInBits(); BitSize != 0; BitSize /= 2) {
+ MVT AVT = MVT::getIntegerVT(BitSize);
+ if (TLI.isOperationLegal(OpV, AVT)) {
+ hasCarry = true;
+ break;
+ }
+ }
+
+ if(hasCarry) {
+ if (Node->getOpcode() == ISD::ADD) {
+ Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2);
+ HiOps[2] = Lo.getValue(1);
+ Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3);
+ } else {
+ Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2);
+ HiOps[2] = Lo.getValue(1);
+ Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3);
+ }
+ break;
} else {
- Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2);
- HiOps[2] = Lo.getValue(1);
- Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3);
+ if (Node->getOpcode() == ISD::ADD) {
+ Lo = DAG.getNode(ISD::ADD, VTList, LoOps, 2);
+ Hi = DAG.getNode(ISD::ADD, VTList, HiOps, 2);
+ SDValue Cmp1 = DAG.getSetCC(TLI.getSetCCResultType(Lo),
+ Lo, LoOps[0], ISD::SETULT);
+ SDValue Carry1 = DAG.getNode(ISD::SELECT, NVT, Cmp1,
+ DAG.getConstant(1, NVT),
+ DAG.getConstant(0, NVT));
+ SDValue Cmp2 = DAG.getSetCC(TLI.getSetCCResultType(Lo),
+ Lo, LoOps[1], ISD::SETULT);
+ SDValue Carry2 = DAG.getNode(ISD::SELECT, NVT, Cmp2,
+ DAG.getConstant(1, NVT),
+ Carry1);
+ Hi = DAG.getNode(ISD::ADD, NVT, Hi, Carry2);
+ } else {
+ Lo = DAG.getNode(ISD::SUB, VTList, LoOps, 2);
+ Hi = DAG.getNode(ISD::SUB, VTList, HiOps, 2);
+ SDValue Cmp = DAG.getSetCC(NVT, LoOps[0], LoOps[1], ISD::SETULT);
+ SDValue Borrow = DAG.getNode(ISD::SELECT, NVT, Cmp,
+ DAG.getConstant(1, NVT),
+ DAG.getConstant(0, NVT));
+ Hi = DAG.getNode(ISD::SUB, NVT, Hi, Borrow);
+ }
+ break;
}
- break;
}
case ISD::ADDC: