mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-15 05:24:01 +00:00
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:
@ -164,6 +164,10 @@ private:
|
|||||||
SDValue EmitStackConvert(SDValue SrcOp, MVT SlotVT, MVT DestVT, DebugLoc dl);
|
SDValue EmitStackConvert(SDValue SrcOp, MVT SlotVT, MVT DestVT, DebugLoc dl);
|
||||||
SDValue ExpandBUILD_VECTOR(SDNode *Node);
|
SDValue ExpandBUILD_VECTOR(SDNode *Node);
|
||||||
SDValue ExpandSCALAR_TO_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,
|
SDValue ExpandLegalINT_TO_FP(bool isSigned, SDValue LegalOp, MVT DestVT,
|
||||||
DebugLoc dl);
|
DebugLoc dl);
|
||||||
SDValue PromoteLegalINT_TO_FP(SDValue LegalOp, MVT DestVT, bool isSigned,
|
SDValue PromoteLegalINT_TO_FP(SDValue LegalOp, MVT DestVT, bool isSigned,
|
||||||
@ -789,9 +793,11 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
|
|||||||
case ISD::TRAMPOLINE:
|
case ISD::TRAMPOLINE:
|
||||||
case ISD::FRAMEADDR:
|
case ISD::FRAMEADDR:
|
||||||
case ISD::RETURNADDR:
|
case ISD::RETURNADDR:
|
||||||
// These operations lie about being legal: they must always be
|
// These operations lie about being legal: when they claim to be legal,
|
||||||
// custom-lowered.
|
// they should actually be custom-lowered.
|
||||||
Action = TargetLowering::Custom;
|
Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
|
||||||
|
if (Action == TargetLowering::Legal)
|
||||||
|
Action = TargetLowering::Custom;
|
||||||
break;
|
break;
|
||||||
case ISD::BUILD_VECTOR:
|
case ISD::BUILD_VECTOR:
|
||||||
// A weird case: when a BUILD_VECTOR is custom-lowered, it doesn't legalize
|
// A weird case: when a BUILD_VECTOR is custom-lowered, it doesn't legalize
|
||||||
@ -883,66 +889,6 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
|
|||||||
#endif
|
#endif
|
||||||
assert(0 && "Do not know how to legalize this operator!");
|
assert(0 && "Do not know how to legalize this operator!");
|
||||||
abort();
|
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::FORMAL_ARGUMENTS:
|
||||||
case ISD::CALL:
|
case ISD::CALL:
|
||||||
// The only option for this is to custom lower it.
|
// The only option for this is to custom lower it.
|
||||||
@ -1081,106 +1027,6 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
|
|||||||
if (Node->getNumValues() == 2)
|
if (Node->getNumValues() == 2)
|
||||||
AddLegalizedOperand(SDValue(Node, 1), Result.getValue(1));
|
AddLegalizedOperand(SDValue(Node, 1), Result.getValue(1));
|
||||||
return Result.getValue(Op.getResNo());
|
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:
|
case ISD::BR_CC:
|
||||||
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
|
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
|
||||||
// Ensure that libcalls are emitted before a branch.
|
// Ensure that libcalls are emitted before a branch.
|
||||||
@ -1753,151 +1599,6 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
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() &&
|
assert(Result.getValueType() == Op.getValueType() &&
|
||||||
@ -1937,6 +1638,113 @@ SDValue SelectionDAGLegalize::ExpandExtractFromVectorThroughStack(SDValue Op) {
|
|||||||
return DAG.getLoad(Op.getValueType(), dl, Ch, StackPtr, NULL, 0);
|
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
|
/// LegalizeSetCCOperands - Attempts to create a legal LHS and RHS for a SETCC
|
||||||
/// with condition CC on the current target. This usually involves legalizing
|
/// 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,
|
/// 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:
|
case ISD::VAEND:
|
||||||
Results.push_back(Node->getOperand(0));
|
Results.push_back(Node->getOperand(0));
|
||||||
break;
|
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:
|
case ISD::MERGE_VALUES:
|
||||||
for (unsigned i = 0; i < Node->getNumValues(); i++)
|
for (unsigned i = 0; i < Node->getNumValues(); i++)
|
||||||
Results.push_back(Node->getOperand(i));
|
Results.push_back(Node->getOperand(i));
|
||||||
@ -2897,6 +2711,9 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
|
|||||||
Results.push_back(Node->getOperand(0));
|
Results.push_back(Node->getOperand(0));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ISD::FCOPYSIGN:
|
||||||
|
Results.push_back(ExpandFCOPYSIGN(Node));
|
||||||
|
break;
|
||||||
case ISD::FNEG:
|
case ISD::FNEG:
|
||||||
// Expand Y = FNEG(X) -> Y = SUB -0.0, X
|
// Expand Y = FNEG(X) -> Y = SUB -0.0, X
|
||||||
Tmp1 = DAG.getConstantFP(-0.0, Node->getValueType(0));
|
Tmp1 = DAG.getConstantFP(-0.0, Node->getValueType(0));
|
||||||
@ -3120,6 +2937,53 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
|
|||||||
Results.push_back(Tmp1);
|
Results.push_back(Tmp1);
|
||||||
break;
|
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: {
|
case ISD::BUILD_PAIR: {
|
||||||
MVT PairTy = Node->getValueType(0);
|
MVT PairTy = Node->getValueType(0);
|
||||||
Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, dl, PairTy, Node->getOperand(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);
|
Results.push_back(Tmp1);
|
||||||
break;
|
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:
|
case ISD::BRCOND:
|
||||||
// Expand brcond's setcc into its constituent parts and create a BR_CC
|
// Expand brcond's setcc into its constituent parts and create a BR_CC
|
||||||
// Node.
|
// Node.
|
||||||
@ -3245,10 +3136,10 @@ void SelectionDAGLegalize::PromoteNode(SDNode *Node,
|
|||||||
break;
|
break;
|
||||||
case ISD::SELECT:
|
case ISD::SELECT:
|
||||||
unsigned ExtOp, TruncOp;
|
unsigned ExtOp, TruncOp;
|
||||||
if (Tmp2.getValueType().isVector()) {
|
if (Node->getValueType(0).isVector()) {
|
||||||
ExtOp = ISD::BIT_CONVERT;
|
ExtOp = ISD::BIT_CONVERT;
|
||||||
TruncOp = ISD::BIT_CONVERT;
|
TruncOp = ISD::BIT_CONVERT;
|
||||||
} else if (Tmp2.getValueType().isInteger()) {
|
} else if (Node->getValueType(0).isInteger()) {
|
||||||
ExtOp = ISD::ANY_EXTEND;
|
ExtOp = ISD::ANY_EXTEND;
|
||||||
TruncOp = ISD::TRUNCATE;
|
TruncOp = ISD::TRUNCATE;
|
||||||
} else {
|
} else {
|
||||||
|
Reference in New Issue
Block a user