Remove more special cases for opcodes.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72468 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eli Friedman 2009-05-27 12:20:41 +00:00
parent 509150f973
commit 4bc8c71821

View File

@ -164,6 +164,10 @@ private:
SDValue EmitStackConvert(SDValue SrcOp, MVT SlotVT, MVT DestVT, DebugLoc dl);
SDValue ExpandBUILD_VECTOR(SDNode *Node);
SDValue ExpandSCALAR_TO_VECTOR(SDNode *Node);
SDValue ExpandDBG_STOPPOINT(SDNode *Node);
void ExpandDYNAMIC_STACKALLOC(SDNode *Node,
SmallVectorImpl<SDValue> &Results);
SDValue ExpandFCOPYSIGN(SDNode *Node);
SDValue ExpandLegalINT_TO_FP(bool isSigned, SDValue LegalOp, MVT DestVT,
DebugLoc dl);
SDValue PromoteLegalINT_TO_FP(SDValue LegalOp, MVT DestVT, bool isSigned,
@ -789,9 +793,11 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
case ISD::TRAMPOLINE:
case ISD::FRAMEADDR:
case ISD::RETURNADDR:
// These operations lie about being legal: they must always be
// custom-lowered.
Action = TargetLowering::Custom;
// These operations lie about being legal: when they claim to be legal,
// they should actually be custom-lowered.
Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
if (Action == TargetLowering::Legal)
Action = TargetLowering::Custom;
break;
case ISD::BUILD_VECTOR:
// A weird case: when a BUILD_VECTOR is custom-lowered, it doesn't legalize
@ -883,66 +889,6 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
#endif
assert(0 && "Do not know how to legalize this operator!");
abort();
case ISD::DBG_STOPPOINT:
assert(Node->getNumOperands() == 1 && "Invalid DBG_STOPPOINT node!");
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the input chain.
switch (TLI.getOperationAction(ISD::DBG_STOPPOINT, MVT::Other)) {
case TargetLowering::Promote:
default: assert(0 && "This action is not supported yet!");
case TargetLowering::Expand: {
DwarfWriter *DW = DAG.getDwarfWriter();
bool useDEBUG_LOC = TLI.isOperationLegalOrCustom(ISD::DEBUG_LOC,
MVT::Other);
bool useLABEL = TLI.isOperationLegalOrCustom(ISD::DBG_LABEL, MVT::Other);
const DbgStopPointSDNode *DSP = cast<DbgStopPointSDNode>(Node);
GlobalVariable *CU_GV = cast<GlobalVariable>(DSP->getCompileUnit());
if (DW && (useDEBUG_LOC || useLABEL) && !CU_GV->isDeclaration()) {
DICompileUnit CU(cast<GlobalVariable>(DSP->getCompileUnit()));
unsigned Line = DSP->getLine();
unsigned Col = DSP->getColumn();
if (OptLevel == CodeGenOpt::None) {
// A bit self-referential to have DebugLoc on Debug_Loc nodes, but it
// won't hurt anything.
if (useDEBUG_LOC) {
SDValue Ops[] = { Tmp1, DAG.getConstant(Line, MVT::i32),
DAG.getConstant(Col, MVT::i32),
DAG.getSrcValue(CU.getGV()) };
Result = DAG.getNode(ISD::DEBUG_LOC, dl, MVT::Other, Ops, 4);
} else {
unsigned ID = DW->RecordSourceLine(Line, Col, CU);
Result = DAG.getLabel(ISD::DBG_LABEL, dl, Tmp1, ID);
}
} else {
Result = Tmp1; // chain
}
} else {
Result = Tmp1; // chain
}
break;
}
case TargetLowering::Custom:
Result = TLI.LowerOperation(Op, DAG);
if (Result.getNode())
break;
case TargetLowering::Legal: {
if (Tmp1 == Node->getOperand(0))
break;
SmallVector<SDValue, 8> Ops;
Ops.push_back(Tmp1);
Ops.push_back(Node->getOperand(1)); // line # must be legal.
Ops.push_back(Node->getOperand(2)); // col # must be legal.
Ops.push_back(Node->getOperand(3)); // filename must be legal.
Ops.push_back(Node->getOperand(4)); // working dir # must be legal.
Result = DAG.UpdateNodeOperands(Result, &Ops[0], Ops.size());
break;
}
}
break;
case ISD::FORMAL_ARGUMENTS:
case ISD::CALL:
// The only option for this is to custom lower it.
@ -1081,106 +1027,6 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
if (Node->getNumValues() == 2)
AddLegalizedOperand(SDValue(Node, 1), Result.getValue(1));
return Result.getValue(Op.getResNo());
case ISD::DYNAMIC_STACKALLOC: {
MVT VT = Node->getValueType(0);
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the size.
Tmp3 = LegalizeOp(Node->getOperand(2)); // Legalize the alignment.
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3);
Tmp1 = Result.getValue(0);
Tmp2 = Result.getValue(1);
switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
default: assert(0 && "This action is not supported yet!");
case TargetLowering::Expand: {
unsigned SPReg = TLI.getStackPointerRegisterToSaveRestore();
assert(SPReg && "Target cannot require DYNAMIC_STACKALLOC expansion and"
" not tell us which reg is the stack pointer!");
SDValue Chain = Tmp1.getOperand(0);
// 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.getIntPtrConstant(0, true));
SDValue Size = Tmp2.getOperand(1);
SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, VT);
Chain = SP.getValue(1);
unsigned Align = cast<ConstantSDNode>(Tmp3)->getZExtValue();
unsigned StackAlign =
TLI.getTargetMachine().getFrameInfo()->getStackAlignment();
if (Align > StackAlign)
SP = DAG.getNode(ISD::AND, dl, VT, SP,
DAG.getConstant(-(uint64_t)Align, VT));
Tmp1 = DAG.getNode(ISD::SUB, dl, VT, SP, Size); // Value
Chain = DAG.getCopyToReg(Chain, dl, SPReg, Tmp1); // Output chain
Tmp2 = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(0, true),
DAG.getIntPtrConstant(0, true), SDValue());
Tmp1 = LegalizeOp(Tmp1);
Tmp2 = LegalizeOp(Tmp2);
break;
}
case TargetLowering::Custom:
Tmp3 = TLI.LowerOperation(Tmp1, DAG);
if (Tmp3.getNode()) {
Tmp1 = LegalizeOp(Tmp3);
Tmp2 = LegalizeOp(Tmp3.getValue(1));
}
break;
case TargetLowering::Legal:
break;
}
// Since this op produce two values, make sure to remember that we
// legalized both of them.
AddLegalizedOperand(SDValue(Node, 0), Tmp1);
AddLegalizedOperand(SDValue(Node, 1), Tmp2);
return Op.getResNo() ? Tmp2 : Tmp1;
}
case ISD::BR_JT:
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
// Ensure that libcalls are emitted before a branch.
Tmp1 = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Tmp1, LastCALLSEQ_END);
Tmp1 = LegalizeOp(Tmp1);
LastCALLSEQ_END = DAG.getEntryNode();
Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the jumptable node.
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Node->getOperand(2));
switch (TLI.getOperationAction(ISD::BR_JT, MVT::Other)) {
default: assert(0 && "This action is not supported yet!");
case TargetLowering::Legal: break;
case TargetLowering::Custom:
Tmp1 = TLI.LowerOperation(Result, DAG);
if (Tmp1.getNode()) Result = Tmp1;
break;
case TargetLowering::Expand: {
SDValue Chain = Result.getOperand(0);
SDValue Table = Result.getOperand(1);
SDValue Index = Result.getOperand(2);
MVT PTy = TLI.getPointerTy();
MachineFunction &MF = DAG.getMachineFunction();
unsigned EntrySize = MF.getJumpTableInfo()->getEntrySize();
Index= DAG.getNode(ISD::MUL, dl, PTy,
Index, DAG.getConstant(EntrySize, PTy));
SDValue Addr = DAG.getNode(ISD::ADD, dl, PTy, Index, Table);
MVT MemVT = MVT::getIntegerVT(EntrySize * 8);
SDValue LD = DAG.getExtLoad(ISD::SEXTLOAD, dl, PTy, Chain, Addr,
PseudoSourceValue::getJumpTable(), 0, MemVT);
Addr = LD;
if (TLI.getTargetMachine().getRelocationModel() == Reloc::PIC_) {
// For PIC, the sequence is:
// BRIND(load(Jumptable + index) + RelocBase)
// RelocBase can be JumpTable, GOT or some sort of global base.
Addr = DAG.getNode(ISD::ADD, dl, PTy, Addr,
TLI.getPICJumpTableRelocBase(Table, DAG));
}
Result = DAG.getNode(ISD::BRIND, dl, MVT::Other, LD.getValue(1), Addr);
}
}
break;
case ISD::BR_CC:
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
// Ensure that libcalls are emitted before a branch.
@ -1753,151 +1599,6 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
break;
}
break;
// Binary operators
case ISD::FCOPYSIGN: // FCOPYSIGN does not require LHS/RHS to match type!
Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS
Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the RHS.
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
default: assert(0 && "Operation not supported");
case TargetLowering::Custom:
Tmp1 = TLI.LowerOperation(Result, DAG);
if (Tmp1.getNode()) Result = Tmp1;
break;
case TargetLowering::Legal: break;
case TargetLowering::Expand: {
assert((Tmp2.getValueType() == MVT::f32 ||
Tmp2.getValueType() == MVT::f64) &&
"Ugly special-cased code!");
// Get the sign bit of the RHS.
SDValue SignBit;
MVT IVT = Tmp2.getValueType() == MVT::f64 ? MVT::i64 : MVT::i32;
if (isTypeLegal(IVT)) {
SignBit = DAG.getNode(ISD::BIT_CONVERT, dl, IVT, Tmp2);
} else {
assert(isTypeLegal(TLI.getPointerTy()) &&
(TLI.getPointerTy() == MVT::i32 ||
TLI.getPointerTy() == MVT::i64) &&
"Legal type for load?!");
SDValue StackPtr = DAG.CreateStackTemporary(Tmp2.getValueType());
SDValue StorePtr = StackPtr, LoadPtr = StackPtr;
SDValue Ch =
DAG.getStore(DAG.getEntryNode(), dl, Tmp2, StorePtr, NULL, 0);
if (Tmp2.getValueType() == MVT::f64 && TLI.isLittleEndian())
LoadPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(),
LoadPtr, DAG.getIntPtrConstant(4));
SignBit = DAG.getExtLoad(ISD::SEXTLOAD, dl, TLI.getPointerTy(),
Ch, LoadPtr, NULL, 0, MVT::i32);
}
SignBit =
DAG.getSetCC(dl, TLI.getSetCCResultType(SignBit.getValueType()),
SignBit, DAG.getConstant(0, SignBit.getValueType()),
ISD::SETLT);
// Get the absolute value of the result.
SDValue AbsVal = DAG.getNode(ISD::FABS, dl, Tmp1.getValueType(), Tmp1);
// Select between the nabs and abs value based on the sign bit of
// the input.
Result = DAG.getNode(ISD::SELECT, dl, AbsVal.getValueType(), SignBit,
DAG.getNode(ISD::FNEG, dl, AbsVal.getValueType(),
AbsVal),
AbsVal);
Result = LegalizeOp(Result);
break;
}
}
break;
case ISD::SADDO:
case ISD::SSUBO: {
MVT VT = Node->getValueType(0);
switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
default: assert(0 && "This action not supported for this op yet!");
case TargetLowering::Custom:
Result = TLI.LowerOperation(Op, DAG);
if (Result.getNode()) break;
// FALLTHROUGH
case TargetLowering::Legal: {
SDValue LHS = LegalizeOp(Node->getOperand(0));
SDValue RHS = LegalizeOp(Node->getOperand(1));
SDValue Sum = DAG.getNode(Node->getOpcode() == ISD::SADDO ?
ISD::ADD : ISD::SUB, dl, LHS.getValueType(),
LHS, RHS);
MVT OType = Node->getValueType(1);
SDValue Zero = DAG.getConstant(0, LHS.getValueType());
// LHSSign -> LHS >= 0
// RHSSign -> RHS >= 0
// SumSign -> Sum >= 0
//
// Add:
// Overflow -> (LHSSign == RHSSign) && (LHSSign != SumSign)
// Sub:
// Overflow -> (LHSSign != RHSSign) && (LHSSign != SumSign)
//
SDValue LHSSign = DAG.getSetCC(dl, OType, LHS, Zero, ISD::SETGE);
SDValue RHSSign = DAG.getSetCC(dl, OType, RHS, Zero, ISD::SETGE);
SDValue SignsMatch = DAG.getSetCC(dl, OType, LHSSign, RHSSign,
Node->getOpcode() == ISD::SADDO ?
ISD::SETEQ : ISD::SETNE);
SDValue SumSign = DAG.getSetCC(dl, OType, Sum, Zero, ISD::SETGE);
SDValue SumSignNE = DAG.getSetCC(dl, OType, LHSSign, SumSign, ISD::SETNE);
SDValue Cmp = DAG.getNode(ISD::AND, dl, OType, SignsMatch, SumSignNE);
MVT ValueVTs[] = { LHS.getValueType(), OType };
SDValue Ops[] = { Sum, Cmp };
Result = DAG.getNode(ISD::MERGE_VALUES, dl,
DAG.getVTList(&ValueVTs[0], 2),
&Ops[0], 2);
SDNode *RNode = Result.getNode();
DAG.ReplaceAllUsesWith(Node, RNode);
break;
}
}
break;
}
case ISD::UADDO:
case ISD::USUBO: {
MVT VT = Node->getValueType(0);
switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
default: assert(0 && "This action not supported for this op yet!");
case TargetLowering::Custom:
Result = TLI.LowerOperation(Op, DAG);
if (Result.getNode()) break;
// FALLTHROUGH
case TargetLowering::Legal: {
SDValue LHS = LegalizeOp(Node->getOperand(0));
SDValue RHS = LegalizeOp(Node->getOperand(1));
SDValue Sum = DAG.getNode(Node->getOpcode() == ISD::UADDO ?
ISD::ADD : ISD::SUB, dl, LHS.getValueType(),
LHS, RHS);
MVT OType = Node->getValueType(1);
SDValue Cmp = DAG.getSetCC(dl, OType, Sum, LHS,
Node->getOpcode () == ISD::UADDO ?
ISD::SETULT : ISD::SETUGT);
MVT ValueVTs[] = { LHS.getValueType(), OType };
SDValue Ops[] = { Sum, Cmp };
Result = DAG.getNode(ISD::MERGE_VALUES, dl,
DAG.getVTList(&ValueVTs[0], 2),
&Ops[0], 2);
SDNode *RNode = Result.getNode();
DAG.ReplaceAllUsesWith(Node, RNode);
break;
}
}
break;
}
}
assert(Result.getValueType() == Op.getValueType() &&
@ -1937,6 +1638,113 @@ SDValue SelectionDAGLegalize::ExpandExtractFromVectorThroughStack(SDValue Op) {
return DAG.getLoad(Op.getValueType(), dl, Ch, StackPtr, NULL, 0);
}
SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode* Node) {
DebugLoc dl = Node->getDebugLoc();
SDValue Tmp1 = Node->getOperand(0);
SDValue Tmp2 = Node->getOperand(1);
assert((Tmp2.getValueType() == MVT::f32 ||
Tmp2.getValueType() == MVT::f64) &&
"Ugly special-cased code!");
// Get the sign bit of the RHS.
SDValue SignBit;
MVT IVT = Tmp2.getValueType() == MVT::f64 ? MVT::i64 : MVT::i32;
if (isTypeLegal(IVT)) {
SignBit = DAG.getNode(ISD::BIT_CONVERT, dl, IVT, Tmp2);
} else {
assert(isTypeLegal(TLI.getPointerTy()) &&
(TLI.getPointerTy() == MVT::i32 ||
TLI.getPointerTy() == MVT::i64) &&
"Legal type for load?!");
SDValue StackPtr = DAG.CreateStackTemporary(Tmp2.getValueType());
SDValue StorePtr = StackPtr, LoadPtr = StackPtr;
SDValue Ch =
DAG.getStore(DAG.getEntryNode(), dl, Tmp2, StorePtr, NULL, 0);
if (Tmp2.getValueType() == MVT::f64 && TLI.isLittleEndian())
LoadPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(),
LoadPtr, DAG.getIntPtrConstant(4));
SignBit = DAG.getExtLoad(ISD::SEXTLOAD, dl, TLI.getPointerTy(),
Ch, LoadPtr, NULL, 0, MVT::i32);
}
SignBit =
DAG.getSetCC(dl, TLI.getSetCCResultType(SignBit.getValueType()),
SignBit, DAG.getConstant(0, SignBit.getValueType()),
ISD::SETLT);
// Get the absolute value of the result.
SDValue AbsVal = DAG.getNode(ISD::FABS, dl, Tmp1.getValueType(), Tmp1);
// Select between the nabs and abs value based on the sign bit of
// the input.
return DAG.getNode(ISD::SELECT, dl, AbsVal.getValueType(), SignBit,
DAG.getNode(ISD::FNEG, dl, AbsVal.getValueType(), AbsVal),
AbsVal);
}
SDValue SelectionDAGLegalize::ExpandDBG_STOPPOINT(SDNode* Node) {
DebugLoc dl = Node->getDebugLoc();
DwarfWriter *DW = DAG.getDwarfWriter();
bool useDEBUG_LOC = TLI.isOperationLegalOrCustom(ISD::DEBUG_LOC,
MVT::Other);
bool useLABEL = TLI.isOperationLegalOrCustom(ISD::DBG_LABEL, MVT::Other);
const DbgStopPointSDNode *DSP = cast<DbgStopPointSDNode>(Node);
GlobalVariable *CU_GV = cast<GlobalVariable>(DSP->getCompileUnit());
if (DW && (useDEBUG_LOC || useLABEL) && !CU_GV->isDeclaration()) {
DICompileUnit CU(cast<GlobalVariable>(DSP->getCompileUnit()));
unsigned Line = DSP->getLine();
unsigned Col = DSP->getColumn();
if (OptLevel == CodeGenOpt::None) {
// A bit self-referential to have DebugLoc on Debug_Loc nodes, but it
// won't hurt anything.
if (useDEBUG_LOC) {
return DAG.getNode(ISD::DEBUG_LOC, dl, MVT::Other, Node->getOperand(0),
DAG.getConstant(Line, MVT::i32),
DAG.getConstant(Col, MVT::i32),
DAG.getSrcValue(CU.getGV()));
} else {
unsigned ID = DW->RecordSourceLine(Line, Col, CU);
return DAG.getLabel(ISD::DBG_LABEL, dl, Node->getOperand(0), ID);
}
}
}
return Node->getOperand(0);
}
void SelectionDAGLegalize::ExpandDYNAMIC_STACKALLOC(SDNode* Node,
SmallVectorImpl<SDValue> &Results) {
unsigned SPReg = TLI.getStackPointerRegisterToSaveRestore();
assert(SPReg && "Target cannot require DYNAMIC_STACKALLOC expansion and"
" not tell us which reg is the stack pointer!");
DebugLoc dl = Node->getDebugLoc();
MVT VT = Node->getValueType(0);
SDValue Tmp1 = SDValue(Node, 0);
SDValue Tmp2 = SDValue(Node, 1);
SDValue Tmp3 = Node->getOperand(2);
SDValue Chain = Tmp1.getOperand(0);
// 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.getIntPtrConstant(0, true));
SDValue Size = Tmp2.getOperand(1);
SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, VT);
Chain = SP.getValue(1);
unsigned Align = cast<ConstantSDNode>(Tmp3)->getZExtValue();
unsigned StackAlign =
TLI.getTargetMachine().getFrameInfo()->getStackAlignment();
if (Align > StackAlign)
SP = DAG.getNode(ISD::AND, dl, VT, SP,
DAG.getConstant(-(uint64_t)Align, VT));
Tmp1 = DAG.getNode(ISD::SUB, dl, VT, SP, Size); // Value
Chain = DAG.getCopyToReg(Chain, dl, SPReg, Tmp1); // Output chain
Tmp2 = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(0, true),
DAG.getIntPtrConstant(0, true), SDValue());
Results.push_back(Tmp1);
Results.push_back(Tmp2);
}
/// LegalizeSetCCOperands - Attempts to create a legal LHS and RHS for a SETCC
/// with condition CC on the current target. This usually involves legalizing
/// or promoting the arguments. In the case where LHS and RHS must be expanded,
@ -2672,6 +2480,12 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
case ISD::VAEND:
Results.push_back(Node->getOperand(0));
break;
case ISD::DBG_STOPPOINT:
Results.push_back(ExpandDBG_STOPPOINT(Node));
break;
case ISD::DYNAMIC_STACKALLOC:
ExpandDYNAMIC_STACKALLOC(Node, Results);
break;
case ISD::MERGE_VALUES:
for (unsigned i = 0; i < Node->getNumValues(); i++)
Results.push_back(Node->getOperand(i));
@ -2897,6 +2711,9 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
Results.push_back(Node->getOperand(0));
}
break;
case ISD::FCOPYSIGN:
Results.push_back(ExpandFCOPYSIGN(Node));
break;
case ISD::FNEG:
// Expand Y = FNEG(X) -> Y = SUB -0.0, X
Tmp1 = DAG.getConstantFP(-0.0, Node->getValueType(0));
@ -3120,6 +2937,53 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
Results.push_back(Tmp1);
break;
}
case ISD::SADDO:
case ISD::SSUBO: {
SDValue LHS = Node->getOperand(0);
SDValue RHS = Node->getOperand(1);
SDValue Sum = DAG.getNode(Node->getOpcode() == ISD::SADDO ?
ISD::ADD : ISD::SUB, dl, LHS.getValueType(),
LHS, RHS);
Results.push_back(Sum);
MVT OType = Node->getValueType(1);
SDValue Zero = DAG.getConstant(0, LHS.getValueType());
// LHSSign -> LHS >= 0
// RHSSign -> RHS >= 0
// SumSign -> Sum >= 0
//
// Add:
// Overflow -> (LHSSign == RHSSign) && (LHSSign != SumSign)
// Sub:
// Overflow -> (LHSSign != RHSSign) && (LHSSign != SumSign)
//
SDValue LHSSign = DAG.getSetCC(dl, OType, LHS, Zero, ISD::SETGE);
SDValue RHSSign = DAG.getSetCC(dl, OType, RHS, Zero, ISD::SETGE);
SDValue SignsMatch = DAG.getSetCC(dl, OType, LHSSign, RHSSign,
Node->getOpcode() == ISD::SADDO ?
ISD::SETEQ : ISD::SETNE);
SDValue SumSign = DAG.getSetCC(dl, OType, Sum, Zero, ISD::SETGE);
SDValue SumSignNE = DAG.getSetCC(dl, OType, LHSSign, SumSign, ISD::SETNE);
SDValue Cmp = DAG.getNode(ISD::AND, dl, OType, SignsMatch, SumSignNE);
Results.push_back(Cmp);
break;
}
case ISD::UADDO:
case ISD::USUBO: {
SDValue LHS = Node->getOperand(0);
SDValue RHS = Node->getOperand(1);
SDValue Sum = DAG.getNode(Node->getOpcode() == ISD::UADDO ?
ISD::ADD : ISD::SUB, dl, LHS.getValueType(),
LHS, RHS);
Results.push_back(Sum);
Results.push_back(DAG.getSetCC(dl, Node->getValueType(1), Sum, LHS,
Node->getOpcode () == ISD::UADDO ?
ISD::SETULT : ISD::SETUGT));
break;
}
case ISD::BUILD_PAIR: {
MVT PairTy = Node->getValueType(0);
Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, dl, PairTy, Node->getOperand(0));
@ -3145,6 +3009,33 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
}
Results.push_back(Tmp1);
break;
case ISD::BR_JT: {
SDValue Chain = Node->getOperand(0);
SDValue Table = Node->getOperand(1);
SDValue Index = Node->getOperand(2);
MVT PTy = TLI.getPointerTy();
MachineFunction &MF = DAG.getMachineFunction();
unsigned EntrySize = MF.getJumpTableInfo()->getEntrySize();
Index= DAG.getNode(ISD::MUL, dl, PTy,
Index, DAG.getConstant(EntrySize, PTy));
SDValue Addr = DAG.getNode(ISD::ADD, dl, PTy, Index, Table);
MVT MemVT = MVT::getIntegerVT(EntrySize * 8);
SDValue LD = DAG.getExtLoad(ISD::SEXTLOAD, dl, PTy, Chain, Addr,
PseudoSourceValue::getJumpTable(), 0, MemVT);
Addr = LD;
if (TLI.getTargetMachine().getRelocationModel() == Reloc::PIC_) {
// For PIC, the sequence is:
// BRIND(load(Jumptable + index) + RelocBase)
// RelocBase can be JumpTable, GOT or some sort of global base.
Addr = DAG.getNode(ISD::ADD, dl, PTy, Addr,
TLI.getPICJumpTableRelocBase(Table, DAG));
}
Tmp1 = DAG.getNode(ISD::BRIND, dl, MVT::Other, LD.getValue(1), Addr);
Results.push_back(Tmp1);
break;
}
case ISD::BRCOND:
// Expand brcond's setcc into its constituent parts and create a BR_CC
// Node.
@ -3245,10 +3136,10 @@ void SelectionDAGLegalize::PromoteNode(SDNode *Node,
break;
case ISD::SELECT:
unsigned ExtOp, TruncOp;
if (Tmp2.getValueType().isVector()) {
if (Node->getValueType(0).isVector()) {
ExtOp = ISD::BIT_CONVERT;
TruncOp = ISD::BIT_CONVERT;
} else if (Tmp2.getValueType().isInteger()) {
} else if (Node->getValueType(0).isInteger()) {
ExtOp = ISD::ANY_EXTEND;
TruncOp = ISD::TRUNCATE;
} else {