#include "LegalizeTypes.h"
#include "llvm/CallingConv.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetData.h"
using namespace llvm;
static cl::opt<bool>
EnableExpensiveChecks("enable-legalize-types-checking", cl::Hidden);
void DAGTypeLegalizer::PerformExpensiveChecks() {
SmallVector<SDNode*, 16> NewNodes;
for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
E = DAG.allnodes_end(); I != E; ++I) {
if (I->getNodeId() == NewNode)
NewNodes.push_back(I);
for (unsigned i = 0, e = I->getNumValues(); i != e; ++i) {
SDValue Res(I, i);
bool Failed = false;
unsigned Mapped = 0;
if (ReplacedValues.find(Res) != ReplacedValues.end()) {
Mapped |= 1;
for (SDNode::use_iterator UI = I->use_begin(), UE = I->use_end();
UI != UE; ++UI)
if (UI.getUse().getResNo() == i)
assert(UI->getNodeId() == NewNode &&
"Remapped value has non-trivial use!");
SDValue NewVal = ReplacedValues[Res];
DenseMap<SDValue, SDValue>::iterator I = ReplacedValues.find(NewVal);
while (I != ReplacedValues.end()) {
NewVal = I->second;
I = ReplacedValues.find(NewVal);
}
assert(NewVal.getNode()->getNodeId() != NewNode &&
"ReplacedValues maps to a new node!");
}
if (PromotedIntegers.find(Res) != PromotedIntegers.end())
Mapped |= 2;
if (SoftenedFloats.find(Res) != SoftenedFloats.end())
Mapped |= 4;
if (ScalarizedVectors.find(Res) != ScalarizedVectors.end())
Mapped |= 8;
if (ExpandedIntegers.find(Res) != ExpandedIntegers.end())
Mapped |= 16;
if (ExpandedFloats.find(Res) != ExpandedFloats.end())
Mapped |= 32;
if (SplitVectors.find(Res) != SplitVectors.end())
Mapped |= 64;
if (WidenedVectors.find(Res) != WidenedVectors.end())
Mapped |= 128;
if (I->getNodeId() != Processed) {
if (Mapped != 0) {
cerr << "Unprocessed value in a map!";
Failed = true;
}
} else if (isTypeLegal(Res.getValueType()) || IgnoreNodeResults(I)) {
if (Mapped > 1 && Res.getOpcode() != ISD::BUILD_VECTOR) {
cerr << "Value with legal type was transformed!";
Failed = true;
}
} else {
if (Mapped == 0) {
cerr << "Processed value not in any map!";
Failed = true;
} else if (Mapped & (Mapped - 1)) {
cerr << "Value in multiple maps!";
Failed = true;
}
}
if (Failed) {
if (Mapped & 1)
cerr << " ReplacedValues";
if (Mapped & 2)
cerr << " PromotedIntegers";
if (Mapped & 4)
cerr << " SoftenedFloats";
if (Mapped & 8)
cerr << " ScalarizedVectors";
if (Mapped & 16)
cerr << " ExpandedIntegers";
if (Mapped & 32)
cerr << " ExpandedFloats";
if (Mapped & 64)
cerr << " SplitVectors";
if (Mapped & 128)
cerr << " WidenedVectors";
cerr << "\n";
abort();
}
}
}
for (unsigned i = 0, e = NewNodes.size(); i != e; ++i) {
SDNode *N = NewNodes[i];
for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
UI != UE; ++UI)
assert(UI->getNodeId() == NewNode && "NewNode used by non-NewNode!");
}
}
bool DAGTypeLegalizer::run() {
bool Changed = false;
HandleSDNode Dummy(DAG.getRoot());
Dummy.setNodeId(Unanalyzed);
DAG.setRoot(SDValue());
for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
E = DAG.allnodes_end(); I != E; ++I) {
if (I->getNumOperands() == 0) {
I->setNodeId(ReadyToProcess);
Worklist.push_back(I);
} else {
I->setNodeId(Unanalyzed);
}
}
while (!Worklist.empty()) {
#ifndef XDEBUG
if (EnableExpensiveChecks)
#endif
PerformExpensiveChecks();
SDNode *N = Worklist.back();
Worklist.pop_back();
assert(N->getNodeId() == ReadyToProcess &&
"Node should be ready if on worklist!");
if (IgnoreNodeResults(N))
goto ScanOperands;
for (unsigned i = 0, NumResults = N->getNumValues(); i < NumResults; ++i) {
MVT ResultVT = N->getValueType(i);
switch (getTypeAction(ResultVT)) {
default:
assert(false && "Unknown action!");
case Legal:
break;
case PromoteInteger:
PromoteIntegerResult(N, i);
Changed = true;
goto NodeDone;
case ExpandInteger:
ExpandIntegerResult(N, i);
Changed = true;
goto NodeDone;
case SoftenFloat:
SoftenFloatResult(N, i);
Changed = true;
goto NodeDone;
case ExpandFloat:
ExpandFloatResult(N, i);
Changed = true;
goto NodeDone;
case ScalarizeVector:
ScalarizeVectorResult(N, i);
Changed = true;
goto NodeDone;
case SplitVector:
SplitVectorResult(N, i);
Changed = true;
goto NodeDone;
case WidenVector:
WidenVectorResult(N, i);
Changed = true;
goto NodeDone;
}
}
ScanOperands:
{
unsigned NumOperands = N->getNumOperands();
bool NeedsReanalyzing = false;
unsigned i;
for (i = 0; i != NumOperands; ++i) {
if (IgnoreNodeResults(N->getOperand(i).getNode()))
continue;
if (N->getOpcode() == ISD::VECTOR_SHUFFLE && i == 2) {
SetIgnoredNodeResult(N->getOperand(2).getNode());
continue;
}
MVT OpVT = N->getOperand(i).getValueType();
switch (getTypeAction(OpVT)) {
default:
assert(false && "Unknown action!");
case Legal:
continue;
case PromoteInteger:
NeedsReanalyzing = PromoteIntegerOperand(N, i);
Changed = true;
break;
case ExpandInteger:
NeedsReanalyzing = ExpandIntegerOperand(N, i);
Changed = true;
break;
case SoftenFloat:
NeedsReanalyzing = SoftenFloatOperand(N, i);
Changed = true;
break;
case ExpandFloat:
NeedsReanalyzing = ExpandFloatOperand(N, i);
Changed = true;
break;
case ScalarizeVector:
NeedsReanalyzing = ScalarizeVectorOperand(N, i);
Changed = true;
break;
case SplitVector:
NeedsReanalyzing = SplitVectorOperand(N, i);
Changed = true;
break;
case WidenVector:
NeedsReanalyzing = WidenVectorOperand(N, i);
Changed = true;
break;
}
break;
}
if (NeedsReanalyzing) {
assert(N->getNodeId() == ReadyToProcess && "Node ID recalculated?");
N->setNodeId(NewNode);
SDNode *M = AnalyzeNewNode(N);
if (M == N)
continue;
assert(N->getNumValues() == M->getNumValues() &&
"Node morphing changed the number of results!");
for (unsigned i = 0, e = N->getNumValues(); i != e; ++i)
ReplaceValueWithHelper(SDValue(N, i), SDValue(M, i));
assert(N->getNodeId() == NewNode && "Unexpected node state!");
continue;
}
if (i == NumOperands) {
DEBUG(cerr << "Legally typed node: "; N->dump(&DAG); cerr << "\n");
}
}
NodeDone:
assert(N->getNodeId() == ReadyToProcess && "Node ID recalculated?");
N->setNodeId(Processed);
for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end();
UI != E; ++UI) {
SDNode *User = *UI;
int NodeId = User->getNodeId();
if (NodeId > 0) {
User->setNodeId(NodeId-1);
if (NodeId-1 == ReadyToProcess)
Worklist.push_back(User);
continue;
}
if (NodeId == NewNode)
continue;
assert(NodeId == Unanalyzed && "Unknown node ID!");
User->setNodeId(User->getNumOperands() - 1);
if (User->getNumOperands() == 1)
Worklist.push_back(User);
}
}
#ifndef XDEBUG
if (EnableExpensiveChecks)
#endif
PerformExpensiveChecks();
DAG.setRoot(Dummy.getValue());
DAG.RemoveDeadNodes();
#ifndef NDEBUG
for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
E = DAG.allnodes_end(); I != E; ++I) {
bool Failed = false;
if (!IgnoreNodeResults(I))
for (unsigned i = 0, NumVals = I->getNumValues(); i < NumVals; ++i)
if (!isTypeLegal(I->getValueType(i))) {
cerr << "Result type " << i << " illegal!\n";
Failed = true;
}
for (unsigned i = 0, NumOps = I->getNumOperands(); i < NumOps; ++i)
if (!IgnoreNodeResults(I->getOperand(i).getNode()) &&
!isTypeLegal(I->getOperand(i).getValueType())) {
cerr << "Operand type " << i << " illegal!\n";
Failed = true;
}
if (I->getNodeId() != Processed) {
if (I->getNodeId() == NewNode)
cerr << "New node not analyzed?\n";
else if (I->getNodeId() == Unanalyzed)
cerr << "Unanalyzed node not noticed?\n";
else if (I->getNodeId() > 0)
cerr << "Operand not processed?\n";
else if (I->getNodeId() == ReadyToProcess)
cerr << "Not added to worklist?\n";
Failed = true;
}
if (Failed) {
I->dump(&DAG); cerr << "\n";
abort();
}
}
#endif
return Changed;
}
SDNode *DAGTypeLegalizer::AnalyzeNewNode(SDNode *N) {
if (N->getNodeId() != NewNode && N->getNodeId() != Unanalyzed)
return N;
ExpungeNode(N);
SmallVector<SDValue, 8> NewOps;
unsigned NumProcessed = 0;
for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
SDValue OrigOp = N->getOperand(i);
SDValue Op = OrigOp;
AnalyzeNewValue(Op);
if (Op.getNode()->getNodeId() == Processed)
++NumProcessed;
if (!NewOps.empty()) {
NewOps.push_back(Op);
} else if (Op != OrigOp) {
for (unsigned j = 0; j < i; ++j)
NewOps.push_back(N->getOperand(j));
NewOps.push_back(Op);
}
}
if (!NewOps.empty()) {
SDNode *M = DAG.UpdateNodeOperands(SDValue(N, 0), &NewOps[0],
NewOps.size()).getNode();
if (M != N) {
N->setNodeId(NewNode);
if (M->getNodeId() != NewNode && M->getNodeId() != Unanalyzed)
return M;
N = M;
ExpungeNode(N);
}
}
N->setNodeId(N->getNumOperands() - NumProcessed);
if (N->getNodeId() == ReadyToProcess)
Worklist.push_back(N);
return N;
}
void DAGTypeLegalizer::AnalyzeNewValue(SDValue &Val) {
Val.setNode(AnalyzeNewNode(Val.getNode()));
if (Val.getNode()->getNodeId() == Processed)
RemapValue(Val);
}
void DAGTypeLegalizer::ExpungeNode(SDNode *N) {
if (N->getNodeId() != NewNode)
return;
unsigned i, e;
for (i = 0, e = N->getNumValues(); i != e; ++i)
if (ReplacedValues.find(SDValue(N, i)) != ReplacedValues.end())
break;
if (i == e)
return;
for (DenseMap<SDValue, SDValue>::iterator I = PromotedIntegers.begin(),
E = PromotedIntegers.end(); I != E; ++I) {
assert(I->first.getNode() != N);
RemapValue(I->second);
}
for (DenseMap<SDValue, SDValue>::iterator I = SoftenedFloats.begin(),
E = SoftenedFloats.end(); I != E; ++I) {
assert(I->first.getNode() != N);
RemapValue(I->second);
}
for (DenseMap<SDValue, SDValue>::iterator I = ScalarizedVectors.begin(),
E = ScalarizedVectors.end(); I != E; ++I) {
assert(I->first.getNode() != N);
RemapValue(I->second);
}
for (DenseMap<SDValue, SDValue>::iterator I = WidenedVectors.begin(),
E = WidenedVectors.end(); I != E; ++I) {
assert(I->first.getNode() != N);
RemapValue(I->second);
}
for (DenseMap<SDValue, std::pair<SDValue, SDValue> >::iterator
I = ExpandedIntegers.begin(), E = ExpandedIntegers.end(); I != E; ++I){
assert(I->first.getNode() != N);
RemapValue(I->second.first);
RemapValue(I->second.second);
}
for (DenseMap<SDValue, std::pair<SDValue, SDValue> >::iterator
I = ExpandedFloats.begin(), E = ExpandedFloats.end(); I != E; ++I) {
assert(I->first.getNode() != N);
RemapValue(I->second.first);
RemapValue(I->second.second);
}
for (DenseMap<SDValue, std::pair<SDValue, SDValue> >::iterator
I = SplitVectors.begin(), E = SplitVectors.end(); I != E; ++I) {
assert(I->first.getNode() != N);
RemapValue(I->second.first);
RemapValue(I->second.second);
}
for (DenseMap<SDValue, SDValue>::iterator I = ReplacedValues.begin(),
E = ReplacedValues.end(); I != E; ++I)
RemapValue(I->second);
for (unsigned i = 0, e = N->getNumValues(); i != e; ++i)
ReplacedValues.erase(SDValue(N, i));
}
void DAGTypeLegalizer::RemapValue(SDValue &N) {
DenseMap<SDValue, SDValue>::iterator I = ReplacedValues.find(N);
if (I != ReplacedValues.end()) {
RemapValue(I->second);
N = I->second;
assert(N.getNode()->getNodeId() != NewNode && "Mapped to new node!");
}
}
namespace {
class VISIBILITY_HIDDEN NodeUpdateListener :
public SelectionDAG::DAGUpdateListener {
DAGTypeLegalizer &DTL;
SmallSetVector<SDNode*, 16> &NodesToAnalyze;
public:
explicit NodeUpdateListener(DAGTypeLegalizer &dtl,
SmallSetVector<SDNode*, 16> &nta)
: DTL(dtl), NodesToAnalyze(nta) {}
virtual void NodeDeleted(SDNode *N, SDNode *E) {
assert(N->getNodeId() != DAGTypeLegalizer::ReadyToProcess &&
N->getNodeId() != DAGTypeLegalizer::Processed &&
"Invalid node ID for RAUW deletion!");
assert(E && "Node not replaced?");
DTL.NoteDeletion(N, E);
NodesToAnalyze.remove(N);
if (E->getNodeId() == DAGTypeLegalizer::NewNode)
NodesToAnalyze.insert(E);
}
virtual void NodeUpdated(SDNode *N) {
assert(N->getNodeId() != DAGTypeLegalizer::ReadyToProcess &&
N->getNodeId() != DAGTypeLegalizer::Processed &&
"Invalid node ID for RAUW deletion!");
N->setNodeId(DAGTypeLegalizer::NewNode);
NodesToAnalyze.insert(N);
}
};
}
void DAGTypeLegalizer::ReplaceValueWithHelper(SDValue From, SDValue To) {
assert(From.getNode() != To.getNode() && "Potential legalization loop!");
AnalyzeNewValue(To);
SmallSetVector<SDNode*, 16> NodesToAnalyze;
NodeUpdateListener NUL(*this, NodesToAnalyze);
DAG.ReplaceAllUsesOfValueWith(From, To, &NUL);
while (!NodesToAnalyze.empty()) {
SDNode *N = NodesToAnalyze.back();
NodesToAnalyze.pop_back();
if (N->getNodeId() != DAGTypeLegalizer::NewNode)
continue;
SDNode *M = AnalyzeNewNode(N);
if (M != N) {
assert(M->getNodeId() != NewNode && "Analysis resulted in NewNode!");
assert(N->getNumValues() == M->getNumValues() &&
"Node morphing changed the number of results!");
for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) {
SDValue OldVal(N, i);
SDValue NewVal(M, i);
if (M->getNodeId() == Processed)
RemapValue(NewVal);
DAG.ReplaceAllUsesOfValueWith(OldVal, NewVal, &NUL);
}
}
}
}
void DAGTypeLegalizer::ReplaceValueWith(SDValue From, SDValue To) {
assert(From.getNode()->getNodeId() == ReadyToProcess &&
"Only the node being processed may be remapped!");
ExpungeNode(From.getNode());
AnalyzeNewValue(To);
ReplacedValues[From] = To;
ReplaceValueWithHelper(From, To);
}
void DAGTypeLegalizer::SetPromotedInteger(SDValue Op, SDValue Result) {
AnalyzeNewValue(Result);
SDValue &OpEntry = PromotedIntegers[Op];
assert(OpEntry.getNode() == 0 && "Node is already promoted!");
OpEntry = Result;
}
void DAGTypeLegalizer::SetSoftenedFloat(SDValue Op, SDValue Result) {
AnalyzeNewValue(Result);
SDValue &OpEntry = SoftenedFloats[Op];
assert(OpEntry.getNode() == 0 && "Node is already converted to integer!");
OpEntry = Result;
}
void DAGTypeLegalizer::SetScalarizedVector(SDValue Op, SDValue Result) {
AnalyzeNewValue(Result);
SDValue &OpEntry = ScalarizedVectors[Op];
assert(OpEntry.getNode() == 0 && "Node is already scalarized!");
OpEntry = Result;
}
void DAGTypeLegalizer::GetExpandedInteger(SDValue Op, SDValue &Lo,
SDValue &Hi) {
std::pair<SDValue, SDValue> &Entry = ExpandedIntegers[Op];
RemapValue(Entry.first);
RemapValue(Entry.second);
assert(Entry.first.getNode() && "Operand isn't expanded");
Lo = Entry.first;
Hi = Entry.second;
}
void DAGTypeLegalizer::SetExpandedInteger(SDValue Op, SDValue Lo,
SDValue Hi) {
AnalyzeNewValue(Lo);
AnalyzeNewValue(Hi);
std::pair<SDValue, SDValue> &Entry = ExpandedIntegers[Op];
assert(Entry.first.getNode() == 0 && "Node already expanded");
Entry.first = Lo;
Entry.second = Hi;
}
void DAGTypeLegalizer::GetExpandedFloat(SDValue Op, SDValue &Lo,
SDValue &Hi) {
std::pair<SDValue, SDValue> &Entry = ExpandedFloats[Op];
RemapValue(Entry.first);
RemapValue(Entry.second);
assert(Entry.first.getNode() && "Operand isn't expanded");
Lo = Entry.first;
Hi = Entry.second;
}
void DAGTypeLegalizer::SetExpandedFloat(SDValue Op, SDValue Lo,
SDValue Hi) {
AnalyzeNewValue(Lo);
AnalyzeNewValue(Hi);
std::pair<SDValue, SDValue> &Entry = ExpandedFloats[Op];
assert(Entry.first.getNode() == 0 && "Node already expanded");
Entry.first = Lo;
Entry.second = Hi;
}
void DAGTypeLegalizer::GetSplitVector(SDValue Op, SDValue &Lo,
SDValue &Hi) {
std::pair<SDValue, SDValue> &Entry = SplitVectors[Op];
RemapValue(Entry.first);
RemapValue(Entry.second);
assert(Entry.first.getNode() && "Operand isn't split");
Lo = Entry.first;
Hi = Entry.second;
}
void DAGTypeLegalizer::SetSplitVector(SDValue Op, SDValue Lo,
SDValue Hi) {
AnalyzeNewValue(Lo);
AnalyzeNewValue(Hi);
std::pair<SDValue, SDValue> &Entry = SplitVectors[Op];
assert(Entry.first.getNode() == 0 && "Node already split");
Entry.first = Lo;
Entry.second = Hi;
}
void DAGTypeLegalizer::SetWidenedVector(SDValue Op, SDValue Result) {
AnalyzeNewValue(Result);
SDValue &OpEntry = WidenedVectors[Op];
assert(OpEntry.getNode() == 0 && "Node already widened!");
OpEntry = Result;
}
void DAGTypeLegalizer::SetIgnoredNodeResult(SDNode* N) {
IgnoredNodesResultsSet.insert(N);
}
SDValue DAGTypeLegalizer::BitConvertToInteger(SDValue Op) {
unsigned BitWidth = Op.getValueType().getSizeInBits();
return DAG.getNode(ISD::BIT_CONVERT, Op.getDebugLoc(),
MVT::getIntegerVT(BitWidth), Op);
}
SDValue DAGTypeLegalizer::BitConvertVectorToIntegerVector(SDValue Op) {
assert(Op.getValueType().isVector() && "Only applies to vectors!");
unsigned EltWidth = Op.getValueType().getVectorElementType().getSizeInBits();
MVT EltNVT = MVT::getIntegerVT(EltWidth);
unsigned NumElts = Op.getValueType().getVectorNumElements();
return DAG.getNode(ISD::BIT_CONVERT, Op.getDebugLoc(),
MVT::getVectorVT(EltNVT, NumElts), Op);
}
SDValue DAGTypeLegalizer::CreateStackStoreLoad(SDValue Op,
MVT DestVT) {
DebugLoc dl = Op.getDebugLoc();
SDValue StackPtr = DAG.CreateStackTemporary(Op.getValueType(), DestVT);
SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Op, StackPtr, NULL, 0);
return DAG.getLoad(DestVT, dl, Store, StackPtr, NULL, 0);
}
bool DAGTypeLegalizer::CustomLowerResults(SDNode *N, MVT VT,
bool LegalizeResult) {
if (TLI.getOperationAction(N->getOpcode(), VT) != TargetLowering::Custom)
return false;
SmallVector<SDValue, 8> Results;
if (LegalizeResult)
TLI.ReplaceNodeResults(N, Results, DAG);
else
TLI.LowerOperationWrapper(N, Results, DAG);
if (Results.empty())
return false;
assert(Results.size() == N->getNumValues() &&
"Custom lowering returned the wrong number of results!");
for (unsigned i = 0, e = Results.size(); i != e; ++i)
ReplaceValueWith(SDValue(N, i), Results[i]);
return true;
}
void DAGTypeLegalizer::GetSplitDestVTs(MVT InVT, MVT &LoVT, MVT &HiVT) {
if (!InVT.isVector()) {
LoVT = HiVT = TLI.getTypeToTransformTo(InVT);
} else {
MVT NewEltVT = InVT.getVectorElementType();
unsigned NumElements = InVT.getVectorNumElements();
if ((NumElements & (NumElements-1)) == 0) { NumElements >>= 1;
LoVT = HiVT = MVT::getVectorVT(NewEltVT, NumElements);
} else { unsigned NewNumElts_Lo = 1 << Log2_32(NumElements);
unsigned NewNumElts_Hi = NumElements - NewNumElts_Lo;
LoVT = MVT::getVectorVT(NewEltVT, NewNumElts_Lo);
HiVT = MVT::getVectorVT(NewEltVT, NewNumElts_Hi);
}
}
}
SDValue DAGTypeLegalizer::GetVectorElementPointer(SDValue VecPtr, MVT EltVT,
SDValue Index) {
DebugLoc dl = Index.getDebugLoc();
if (Index.getValueType().bitsGT(TLI.getPointerTy()))
Index = DAG.getNode(ISD::TRUNCATE, dl, TLI.getPointerTy(), Index);
else
Index = DAG.getNode(ISD::ZERO_EXTEND, dl, TLI.getPointerTy(), Index);
unsigned EltSize = EltVT.getSizeInBits() / 8;
Index = DAG.getNode(ISD::MUL, dl, Index.getValueType(), Index,
DAG.getConstant(EltSize, Index.getValueType()));
return DAG.getNode(ISD::ADD, dl, Index.getValueType(), Index, VecPtr);
}
SDValue DAGTypeLegalizer::JoinIntegers(SDValue Lo, SDValue Hi) {
DebugLoc dlHi = Hi.getDebugLoc();
DebugLoc dlLo = Lo.getDebugLoc();
MVT LVT = Lo.getValueType();
MVT HVT = Hi.getValueType();
MVT NVT = MVT::getIntegerVT(LVT.getSizeInBits() + HVT.getSizeInBits());
Lo = DAG.getNode(ISD::ZERO_EXTEND, dlLo, NVT, Lo);
Hi = DAG.getNode(ISD::ANY_EXTEND, dlHi, NVT, Hi);
Hi = DAG.getNode(ISD::SHL, dlHi, NVT, Hi,
DAG.getConstant(LVT.getSizeInBits(), TLI.getPointerTy()));
return DAG.getNode(ISD::OR, dlHi, NVT, Lo, Hi);
}
SDValue DAGTypeLegalizer::LibCallify(RTLIB::Libcall LC, SDNode *N,
bool isSigned) {
unsigned NumOps = N->getNumOperands();
DebugLoc dl = N->getDebugLoc();
if (NumOps == 0) {
return MakeLibCall(LC, N->getValueType(0), 0, 0, isSigned, dl);
} else if (NumOps == 1) {
SDValue Op = N->getOperand(0);
return MakeLibCall(LC, N->getValueType(0), &Op, 1, isSigned, dl);
} else if (NumOps == 2) {
SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) };
return MakeLibCall(LC, N->getValueType(0), Ops, 2, isSigned, dl);
}
SmallVector<SDValue, 8> Ops(NumOps);
for (unsigned i = 0; i < NumOps; ++i)
Ops[i] = N->getOperand(i);
return MakeLibCall(LC, N->getValueType(0), &Ops[0], NumOps, isSigned, dl);
}
SDValue DAGTypeLegalizer::MakeLibCall(RTLIB::Libcall LC, MVT RetVT,
const SDValue *Ops, unsigned NumOps,
bool isSigned, DebugLoc dl) {
TargetLowering::ArgListTy Args;
Args.reserve(NumOps);
TargetLowering::ArgListEntry Entry;
for (unsigned i = 0; i != NumOps; ++i) {
Entry.Node = Ops[i];
Entry.Ty = Entry.Node.getValueType().getTypeForMVT();
Entry.isSExt = isSigned;
Entry.isZExt = !isSigned;
Args.push_back(Entry);
}
SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(LC),
TLI.getPointerTy());
const Type *RetTy = RetVT.getTypeForMVT();
std::pair<SDValue,SDValue> CallInfo =
TLI.LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false,
false, CallingConv::C, false, Callee, Args, DAG, dl);
return CallInfo.first;
}
SDValue DAGTypeLegalizer::PromoteTargetBoolean(SDValue Bool, MVT VT) {
DebugLoc dl = Bool.getDebugLoc();
ISD::NodeType ExtendCode;
switch (TLI.getBooleanContents()) {
default:
assert(false && "Unknown BooleanContent!");
case TargetLowering::UndefinedBooleanContent:
ExtendCode = ISD::ANY_EXTEND;
break;
case TargetLowering::ZeroOrOneBooleanContent:
ExtendCode = ISD::ZERO_EXTEND;
break;
case TargetLowering::ZeroOrNegativeOneBooleanContent: {
ExtendCode = ISD::SIGN_EXTEND;
break;
}
}
return DAG.getNode(ExtendCode, dl, VT, Bool);
}
void DAGTypeLegalizer::SplitInteger(SDValue Op,
MVT LoVT, MVT HiVT,
SDValue &Lo, SDValue &Hi) {
DebugLoc dl = Op.getDebugLoc();
assert(LoVT.getSizeInBits() + HiVT.getSizeInBits() ==
Op.getValueType().getSizeInBits() && "Invalid integer splitting!");
Lo = DAG.getNode(ISD::TRUNCATE, dl, LoVT, Op);
Hi = DAG.getNode(ISD::SRL, dl, Op.getValueType(), Op,
DAG.getConstant(LoVT.getSizeInBits(), TLI.getPointerTy()));
Hi = DAG.getNode(ISD::TRUNCATE, dl, HiVT, Hi);
}
void DAGTypeLegalizer::SplitInteger(SDValue Op,
SDValue &Lo, SDValue &Hi) {
MVT HalfVT = MVT::getIntegerVT(Op.getValueType().getSizeInBits()/2);
SplitInteger(Op, HalfVT, HalfVT, Lo, Hi);
}
bool SelectionDAG::LegalizeTypes() {
return DAGTypeLegalizer(*this).run();
}