23#define DEBUG_TYPE "legalize-types"
29void DAGTypeLegalizer::PerformExpensiveChecks() {
79 for (
unsigned i = 0, e =
Node.getNumValues(); i != e; ++i) {
83 auto ResId = ValueToIdMap.lookup(Res);
87 auto I = ReplacedValues.find(ResId);
88 if (
I != ReplacedValues.end()) {
92 if (U.getResNo() == i)
94 "Remapped value has non-trivial use!");
98 auto NewValId =
I->second;
99 I = ReplacedValues.find(NewValId);
100 while (
I != ReplacedValues.end()) {
101 NewValId =
I->second;
102 I = ReplacedValues.find(NewValId);
104 SDValue NewVal = getSDValue(NewValId);
107 "ReplacedValues maps to a new node!");
109 if (PromotedIntegers.count(ResId))
111 if (SoftenedFloats.count(ResId))
113 if (ScalarizedVectors.count(ResId))
115 if (ExpandedIntegers.count(ResId))
117 if (ExpandedFloats.count(ResId))
119 if (SplitVectors.count(ResId))
121 if (WidenedVectors.count(ResId))
123 if (SoftPromotedHalfs.count(ResId))
133 dbgs() <<
"Unprocessed value in a map!";
136 }
else if (isTypeLegal(Res.getValueType()) || IgnoreNodeResults(&Node)) {
138 dbgs() <<
"Value with legal type was transformed!";
143 SDValue NodeById = IdToValueMap.lookup(ResId);
150 dbgs() <<
"Processed value not in any map!";
153 }
else if (Mapped & (Mapped - 1)) {
154 dbgs() <<
"Value in multiple maps!";
161 dbgs() <<
" ReplacedValues";
163 dbgs() <<
" PromotedIntegers";
165 dbgs() <<
" SoftenedFloats";
167 dbgs() <<
" ScalarizedVectors";
169 dbgs() <<
" ExpandedIntegers";
171 dbgs() <<
" ExpandedFloats";
173 dbgs() <<
" SplitVectors";
175 dbgs() <<
" WidenedVectors";
177 dbgs() <<
" SoftPromoteHalfs";
186 for (SDNode *
N : NewNodes) {
187 for (SDNode *U :
N->users())
188 assert(
U->getNodeId() ==
NewNode &&
"NewNode used by non-NewNode!");
213 if (
Node.getNumOperands() == 0) {
215 Worklist.push_back(&
Node);
222 while (!Worklist.empty()) {
223#ifndef EXPENSIVE_CHECKS
226 PerformExpensiveChecks();
228 SDNode *
N = Worklist.pop_back_val();
230 "Node should be ready if on worklist!");
237 if (IgnoreNodeResults(
N)) {
244 for (
unsigned i = 0, NumResults =
N->getNumValues(); i < NumResults; ++i) {
245 EVT ResultVT =
N->getValueType(i);
246 LLVM_DEBUG(
dbgs() <<
"Analyzing result type: " << ResultVT <<
"\n");
247 switch (getTypeAction(ResultVT)) {
253 "Scalarization of scalable vectors is not supported.");
260 PromoteIntegerResult(
N, i);
264 ExpandIntegerResult(
N, i);
268 SoftenFloatResult(
N, i);
272 ExpandFloatResult(
N, i);
276 ScalarizeVectorResult(
N, i);
280 SplitVectorResult(
N, i);
284 WidenVectorResult(
N, i);
288 SoftPromoteHalfResult(
N, i);
298 unsigned NumOperands =
N->getNumOperands();
299 bool NeedsReanalyzing =
false;
301 for (i = 0; i != NumOperands; ++i) {
302 if (IgnoreNodeResults(
N->getOperand(i).getNode()))
305 const auto &
Op =
N->getOperand(i);
307 EVT OpVT =
Op.getValueType();
308 switch (getTypeAction(OpVT)) {
314 "Scalarization of scalable vectors is not supported.");
319 NeedsReanalyzing = PromoteIntegerOperand(
N, i);
323 NeedsReanalyzing = ExpandIntegerOperand(
N, i);
327 NeedsReanalyzing = SoftenFloatOperand(
N, i);
331 NeedsReanalyzing = ExpandFloatOperand(
N, i);
335 NeedsReanalyzing = ScalarizeVectorOperand(
N, i);
339 NeedsReanalyzing = SplitVectorOperand(
N, i);
343 NeedsReanalyzing = WidenVectorOperand(
N, i);
347 NeedsReanalyzing = SoftPromoteHalfOperand(
N, i);
357 if (NeedsReanalyzing) {
370 assert(
N->getNumValues() == M->getNumValues() &&
371 "Node morphing changed the number of results!");
372 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i)
382 if (i == NumOperands) {
394 int NodeId =
User->getNodeId();
399 User->setNodeId(NodeId-1);
403 Worklist.push_back(
User);
421 Worklist.push_back(
User);
425#ifndef EXPENSIVE_CHECKS
428 PerformExpensiveChecks();
437 DAG.RemoveDeadNodes();
446 if (!IgnoreNodeResults(&
Node))
447 for (
unsigned i = 0, NumVals =
Node.getNumValues(); i < NumVals; ++i)
448 if (!isTypeLegal(
Node.getValueType(i))) {
449 dbgs() <<
"Result type " << i <<
" illegal: ";
456 if (!IgnoreNodeResults(
Node.getOperand(i).getNode()) &&
457 !isTypeLegal(
Node.getOperand(i).getValueType())) {
458 dbgs() <<
"Operand type " << i <<
" illegal: ";
465 dbgs() <<
"New node not analyzed?\n";
467 dbgs() <<
"Unanalyzed node not noticed?\n";
468 else if (
Node.getNodeId() > 0)
469 dbgs() <<
"Operand not processed?\n";
471 dbgs() <<
"Not added to worklist?\n";
505 std::vector<SDValue> NewOps;
506 unsigned NumProcessed = 0;
507 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
516 if (!NewOps.empty()) {
518 NewOps.push_back(
Op);
519 }
else if (
Op != OrigOp) {
522 NewOps.push_back(
Op);
527 if (!NewOps.empty()) {
528 SDNode *
M = DAG.UpdateNodeOperands(
N, NewOps);
549 N->setNodeId(
N->getNumOperands() - NumProcessed);
551 Worklist.push_back(
N);
558void DAGTypeLegalizer::AnalyzeNewValue(
SDValue &Val) {
567void DAGTypeLegalizer::RemapValue(
SDValue &V) {
568 auto Id = getTableId(V);
572void DAGTypeLegalizer::RemapId(TableId &Id) {
573 auto I = ReplacedValues.find(Id);
574 if (
I != ReplacedValues.end()) {
575 assert(Id !=
I->second &&
"Id is mapped to itself.");
591 DAGTypeLegalizer &DTL;
592 SmallSetVector<SDNode*, 16> &NodesToAnalyze;
594 explicit NodeUpdateListener(DAGTypeLegalizer &dtl,
595 SmallSetVector<SDNode*, 16> &nta)
596 : SelectionDAG::DAGUpdateListener(dtl.getDAG()),
597 DTL(dtl), NodesToAnalyze(nta) {}
599 void NodeDeleted(SDNode *
N, SDNode *
E)
override {
602 "Invalid node ID for RAUW deletion!");
605 assert(
E &&
"Node not replaced?");
620 void NodeUpdated(SDNode *
N)
override {
626 "Invalid node ID for RAUW deletion!");
636void DAGTypeLegalizer::ReplaceValueWith(
SDValue From,
SDValue To) {
644 SmallSetVector<SDNode*, 16> NodesToAnalyze;
645 NodeUpdateListener NUL(*
this, NodesToAnalyze);
650 auto FromId = getTableId(From);
651 auto ToId = getTableId(To);
654 ReplacedValues[FromId] = ToId;
655 DAG.ReplaceAllUsesOfValueWith(From, To);
658 while (!NodesToAnalyze.
empty()) {
667 SDNode *
M = AnalyzeNewNode(
N);
671 assert(
M->getNodeId() !=
NewNode &&
"Analysis resulted in NewNode!");
672 assert(
N->getNumValues() ==
M->getNumValues() &&
673 "Node morphing changed the number of results!");
674 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i) {
675 SDValue OldVal(
N, i);
676 SDValue NewVal(M, i);
683 auto OldValId = getTableId(OldVal);
684 auto NewValId = getTableId(NewVal);
685 DAG.ReplaceAllUsesOfValueWith(OldVal, NewVal);
692 if (OldValId != NewValId)
693 ReplacedValues[OldValId] = NewValId;
706 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
707 "Invalid type for promoted integer");
708 AnalyzeNewValue(Result);
710 auto &OpIdEntry = PromotedIntegers[getTableId(
Op)];
711 assert((OpIdEntry == 0) &&
"Node is already promoted!");
712 OpIdEntry = getTableId(Result);
714 DAG.transferDbgValues(
Op, Result);
719 EVT VT =
Result.getValueType();
720 LLVMContext &Ctx = *DAG.getContext();
722 VT == TLI.getTypeToTransformTo(Ctx,
Op.getValueType())) &&
723 "Invalid type for softened float");
725 AnalyzeNewValue(Result);
727 auto &OpIdEntry = SoftenedFloats[getTableId(
Op)];
728 assert((OpIdEntry == 0) &&
"Node is already converted to integer!");
729 OpIdEntry = getTableId(Result);
734 "Invalid type for soft-promoted half");
735 AnalyzeNewValue(Result);
737 auto &OpIdEntry = SoftPromotedHalfs[getTableId(
Op)];
738 assert((OpIdEntry == 0) &&
"Node is already promoted!");
739 OpIdEntry = getTableId(Result);
749 Op.getScalarValueSizeInBits() &&
750 "Invalid type for scalarized vector");
751 AnalyzeNewValue(Result);
753 auto &OpIdEntry = ScalarizedVectors[getTableId(
Op)];
754 assert((OpIdEntry == 0) &&
"Node is already scalarized!");
755 OpIdEntry = getTableId(Result);
760 std::pair<TableId, TableId> &
Entry = ExpandedIntegers[getTableId(
Op)];
761 assert((
Entry.first != 0) &&
"Operand isn't expanded");
769 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
770 Hi.getValueType() ==
Lo.getValueType() &&
771 "Invalid type for expanded integer");
778 if (DAG.getDataLayout().isBigEndian()) {
779 DAG.transferDbgValues(
Op,
Hi, 0,
Hi.getValueSizeInBits(),
false);
780 DAG.transferDbgValues(
Op,
Lo,
Hi.getValueSizeInBits(),
781 Lo.getValueSizeInBits());
783 DAG.transferDbgValues(
Op,
Lo, 0,
Lo.getValueSizeInBits(),
false);
784 DAG.transferDbgValues(
Op,
Hi,
Lo.getValueSizeInBits(),
785 Hi.getValueSizeInBits());
789 std::pair<TableId, TableId> &
Entry = ExpandedIntegers[getTableId(
Op)];
790 assert((
Entry.first == 0) &&
"Node already expanded");
797 std::pair<TableId, TableId> &
Entry = ExpandedFloats[getTableId(
Op)];
798 assert((
Entry.first != 0) &&
"Operand isn't expanded");
806 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
807 Hi.getValueType() ==
Lo.getValueType() &&
808 "Invalid type for expanded float");
813 std::pair<TableId, TableId> &
Entry = ExpandedFloats[getTableId(
Op)];
814 assert((
Entry.first == 0) &&
"Node already expanded");
821 std::pair<TableId, TableId> &
Entry = SplitVectors[getTableId(
Op)];
824 assert(
Lo.getNode() &&
"Operand isn't split");
830 assert(
Lo.getValueType().getVectorElementType() ==
831 Op.getValueType().getVectorElementType() &&
832 Lo.getValueType().getVectorElementCount() * 2 ==
833 Op.getValueType().getVectorElementCount() &&
834 Hi.getValueType() ==
Lo.getValueType() &&
835 "Invalid type for split vector");
841 std::pair<TableId, TableId> &
Entry = SplitVectors[getTableId(
Op)];
842 assert((
Entry.first == 0) &&
"Node already split");
849 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
850 "Invalid type for widened vector");
851 AnalyzeNewValue(Result);
853 auto &OpIdEntry = WidenedVectors[getTableId(
Op)];
854 assert((OpIdEntry == 0) &&
"Node already widened!");
855 OpIdEntry = getTableId(Result);
872 assert(
Op.getValueType().isVector() &&
"Only applies to vectors!");
873 unsigned EltWidth =
Op.getScalarValueSizeInBits();
875 auto EltCnt =
Op.getValueType().getVectorElementCount();
888 Align DestAlign = DAG.getReducedAlign(DestVT,
false);
889 Align OpAlign = DAG.getReducedAlign(
Op.getValueType(),
false);
892 DAG.CreateStackTemporary(
Op.getValueType().getStoreSize(), Align);
894 SDValue
Store = DAG.getStore(DAG.getEntryNode(), dl,
Op, StackPtr,
895 MachinePointerInfo(), Align);
897 return DAG.getLoad(DestVT, dl,
Store, StackPtr, MachinePointerInfo(), Align);
908bool DAGTypeLegalizer::CustomLowerNode(
SDNode *
N,
EVT VT,
bool LegalizeResult) {
915 TLI.ReplaceNodeResults(
N,
Results, DAG);
917 TLI.LowerOperationWrapper(
N,
Results, DAG);
925 "Custom lowering returned the wrong number of results!");
926 for (
unsigned i = 0, e =
Results.
size(); i != e; ++i) {
927 ReplaceValueWith(SDValue(
N, i),
Results[i]);
935bool DAGTypeLegalizer::CustomWidenLowerNode(
SDNode *
N,
EVT VT) {
941 TLI.ReplaceNodeResults(
N,
Results, DAG);
949 "Custom lowering returned the wrong number of results!");
950 for (
unsigned i = 0, e =
Results.
size(); i != e; ++i) {
954 SetWidenedVector(SDValue(
N, i),
Results[i]);
956 ReplaceValueWith(SDValue(
N, i),
Results[i]);
961SDValue DAGTypeLegalizer::DisintegrateMERGE_VALUES(
SDNode *
N,
unsigned ResNo) {
962 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i)
964 ReplaceValueWith(SDValue(
N, i), SDValue(
N->getOperand(i)));
965 return SDValue(
N->getOperand(ResNo));
970void DAGTypeLegalizer::GetPairElements(
SDValue Pair,
973 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Pair.
getValueType());
974 std::tie(
Lo,
Hi) = DAG.SplitScalar(Pair, dl, NVT, NVT);
982 EVT LVT =
Lo.getValueType();
983 EVT HVT =
Hi.getValueType();
1000 return TLI.promoteTargetBoolean(DAG, Bool, ValVT);
1004void DAGTypeLegalizer::SplitInteger(
SDValue Op,
1009 Op.getValueSizeInBits() &&
"Invalid integer splitting!");
1013 DAG.getShiftAmountConstant(LoVT.
getSizeInBits(),
Op.getValueType(), dl));
1019void DAGTypeLegalizer::SplitInteger(
SDValue Op,
1023 SplitInteger(
Op, HalfVT, HalfVT,
Lo,
Hi);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Function Alias Analysis Results
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
static cl::opt< bool > EnableExpensiveChecks("enable-legalize-types-checking", cl::Hidden)
This file implements a set that has insertion order iteration characteristics.
DEMANGLE_DUMP_METHOD void dump() const
This takes an arbitrary SelectionDAG as input and hacks on it until only value types the target machi...
bool run()
This is the main entry point for the type legalizer.
void NoteDeletion(SDNode *Old, SDNode *New)
@ ReadyToProcess
All operands have been processed, so this node is ready to be handled.
@ NewNode
This is a new node, not before seen, that was created in the process of legalizing some other node.
@ Unanalyzed
This node's ID needs to be set to the number of its unprocessed operands.
@ Processed
This is a node that has already been processed.
Convenience struct for specifying and reasoning about fast-math flags.
Type * getValueType() const
This class is used to form a handle around another node that is persistent and is updated across invo...
const SDValue & getValue() const
Represents one node in the SelectionDAG.
int getNodeId() const
Return the unique node id.
void setNodeId(int Id)
Set unique node id.
Represents a use of a SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
EVT getValueType() const
Return the ValueType of the referenced return value.
bool use_empty() const
Return true if there are no nodes using value ResNo of Node.
void setNode(SDNode *N)
set the SDNode
Help to insert SDNodeFlags automatically in transforming.
iterator_range< allnodes_iterator > allnodes()
LLVM_ABI bool LegalizeTypes()
This transforms the SelectionDAG into a SelectionDAG that only uses types natively supported by the t...
bool remove(const value_type &X)
Remove an item from the set vector.
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
value_type pop_back_val()
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
@ TypeScalarizeScalableVector
unsigned getNumOperands() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ SHL
Shift and rotation operations.
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
@ Store
The extracted value is stored (ExtractElement only).
testing::Matcher< const detail::ErrorHolder & > Failed()
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
DWARFExpression::Operation Op
constexpr unsigned BitWidth
static EVT getVectorVT(LLVMContext &Context, EVT VT, unsigned NumElements, bool IsScalable=false)
Returns the EVT that represents a vector NumElements in length, where each element is of type VT.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
static EVT getIntegerVT(LLVMContext &Context, unsigned BitWidth)
Returns the EVT that represents an integer with the given number of bits.
These are IR-level optimization flags that may be propagated to SDNodes.
Clients of various APIs that cause global effects on the DAG can optionally implement this interface.