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 (PromotedFloats.count(ResId))
125 if (SoftPromotedHalfs.count(ResId))
135 dbgs() <<
"Unprocessed value in a map!";
138 }
else if (isTypeLegal(Res.getValueType()) || IgnoreNodeResults(&Node)) {
140 dbgs() <<
"Value with legal type was transformed!";
145 SDValue NodeById = IdToValueMap.lookup(ResId);
152 dbgs() <<
"Processed value not in any map!";
155 }
else if (Mapped & (Mapped - 1)) {
156 dbgs() <<
"Value in multiple maps!";
163 dbgs() <<
" ReplacedValues";
165 dbgs() <<
" PromotedIntegers";
167 dbgs() <<
" SoftenedFloats";
169 dbgs() <<
" ScalarizedVectors";
171 dbgs() <<
" ExpandedIntegers";
173 dbgs() <<
" ExpandedFloats";
175 dbgs() <<
" SplitVectors";
177 dbgs() <<
" WidenedVectors";
179 dbgs() <<
" PromotedFloats";
181 dbgs() <<
" SoftPromoteHalfs";
190 for (SDNode *
N : NewNodes) {
191 for (SDNode *U :
N->users())
192 assert(
U->getNodeId() ==
NewNode &&
"NewNode used by non-NewNode!");
217 if (
Node.getNumOperands() == 0) {
219 Worklist.push_back(&
Node);
226 while (!Worklist.empty()) {
227#ifndef EXPENSIVE_CHECKS
230 PerformExpensiveChecks();
232 SDNode *
N = Worklist.pop_back_val();
234 "Node should be ready if on worklist!");
241 if (IgnoreNodeResults(
N)) {
248 for (
unsigned i = 0, NumResults =
N->getNumValues(); i < NumResults; ++i) {
249 EVT ResultVT =
N->getValueType(i);
250 LLVM_DEBUG(
dbgs() <<
"Analyzing result type: " << ResultVT <<
"\n");
251 switch (getTypeAction(ResultVT)) {
257 "Scalarization of scalable vectors is not supported.");
264 PromoteIntegerResult(
N, i);
268 ExpandIntegerResult(
N, i);
272 SoftenFloatResult(
N, i);
276 ExpandFloatResult(
N, i);
280 ScalarizeVectorResult(
N, i);
284 SplitVectorResult(
N, i);
288 WidenVectorResult(
N, i);
292 PromoteFloatResult(
N, i);
296 SoftPromoteHalfResult(
N, i);
306 unsigned NumOperands =
N->getNumOperands();
307 bool NeedsReanalyzing =
false;
309 for (i = 0; i != NumOperands; ++i) {
310 if (IgnoreNodeResults(
N->getOperand(i).getNode()))
313 const auto &
Op =
N->getOperand(i);
315 EVT OpVT =
Op.getValueType();
316 switch (getTypeAction(OpVT)) {
322 "Scalarization of scalable vectors is not supported.");
327 NeedsReanalyzing = PromoteIntegerOperand(
N, i);
331 NeedsReanalyzing = ExpandIntegerOperand(
N, i);
335 NeedsReanalyzing = SoftenFloatOperand(
N, i);
339 NeedsReanalyzing = ExpandFloatOperand(
N, i);
343 NeedsReanalyzing = ScalarizeVectorOperand(
N, i);
347 NeedsReanalyzing = SplitVectorOperand(
N, i);
351 NeedsReanalyzing = WidenVectorOperand(
N, i);
355 NeedsReanalyzing = PromoteFloatOperand(
N, i);
359 NeedsReanalyzing = SoftPromoteHalfOperand(
N, i);
369 if (NeedsReanalyzing) {
382 assert(
N->getNumValues() == M->getNumValues() &&
383 "Node morphing changed the number of results!");
384 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i)
394 if (i == NumOperands) {
406 int NodeId =
User->getNodeId();
411 User->setNodeId(NodeId-1);
415 Worklist.push_back(
User);
433 Worklist.push_back(
User);
437#ifndef EXPENSIVE_CHECKS
440 PerformExpensiveChecks();
449 DAG.RemoveDeadNodes();
458 if (!IgnoreNodeResults(&
Node))
459 for (
unsigned i = 0, NumVals =
Node.getNumValues(); i < NumVals; ++i)
460 if (!isTypeLegal(
Node.getValueType(i))) {
461 dbgs() <<
"Result type " << i <<
" illegal: ";
468 if (!IgnoreNodeResults(
Node.getOperand(i).getNode()) &&
469 !isTypeLegal(
Node.getOperand(i).getValueType())) {
470 dbgs() <<
"Operand type " << i <<
" illegal: ";
477 dbgs() <<
"New node not analyzed?\n";
479 dbgs() <<
"Unanalyzed node not noticed?\n";
480 else if (
Node.getNodeId() > 0)
481 dbgs() <<
"Operand not processed?\n";
483 dbgs() <<
"Not added to worklist?\n";
517 std::vector<SDValue> NewOps;
518 unsigned NumProcessed = 0;
519 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
528 if (!NewOps.empty()) {
530 NewOps.push_back(
Op);
531 }
else if (
Op != OrigOp) {
534 NewOps.push_back(
Op);
539 if (!NewOps.empty()) {
540 SDNode *
M = DAG.UpdateNodeOperands(
N, NewOps);
561 N->setNodeId(
N->getNumOperands() - NumProcessed);
563 Worklist.push_back(
N);
570void DAGTypeLegalizer::AnalyzeNewValue(
SDValue &Val) {
579void DAGTypeLegalizer::RemapValue(
SDValue &V) {
580 auto Id = getTableId(V);
584void DAGTypeLegalizer::RemapId(TableId &Id) {
585 auto I = ReplacedValues.find(Id);
586 if (
I != ReplacedValues.end()) {
587 assert(Id !=
I->second &&
"Id is mapped to itself.");
603 DAGTypeLegalizer &DTL;
604 SmallSetVector<SDNode*, 16> &NodesToAnalyze;
606 explicit NodeUpdateListener(DAGTypeLegalizer &dtl,
607 SmallSetVector<SDNode*, 16> &nta)
608 : SelectionDAG::DAGUpdateListener(dtl.getDAG()),
609 DTL(dtl), NodesToAnalyze(nta) {}
611 void NodeDeleted(SDNode *
N, SDNode *
E)
override {
614 "Invalid node ID for RAUW deletion!");
617 assert(
E &&
"Node not replaced?");
632 void NodeUpdated(SDNode *
N)
override {
638 "Invalid node ID for RAUW deletion!");
648void DAGTypeLegalizer::ReplaceValueWith(
SDValue From,
SDValue To) {
656 SmallSetVector<SDNode*, 16> NodesToAnalyze;
657 NodeUpdateListener NUL(*
this, NodesToAnalyze);
662 auto FromId = getTableId(From);
663 auto ToId = getTableId(To);
666 ReplacedValues[FromId] = ToId;
667 DAG.ReplaceAllUsesOfValueWith(From, To);
670 while (!NodesToAnalyze.
empty()) {
679 SDNode *
M = AnalyzeNewNode(
N);
683 assert(
M->getNodeId() !=
NewNode &&
"Analysis resulted in NewNode!");
684 assert(
N->getNumValues() ==
M->getNumValues() &&
685 "Node morphing changed the number of results!");
686 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i) {
695 auto OldValId = getTableId(OldVal);
696 auto NewValId = getTableId(NewVal);
697 DAG.ReplaceAllUsesOfValueWith(OldVal, NewVal);
698 if (OldValId != NewValId)
699 ReplacedValues[OldValId] = NewValId;
712 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
713 "Invalid type for promoted integer");
714 AnalyzeNewValue(Result);
716 auto &OpIdEntry = PromotedIntegers[getTableId(
Op)];
717 assert((OpIdEntry == 0) &&
"Node is already promoted!");
718 OpIdEntry = getTableId(Result);
720 DAG.transferDbgValues(
Op, Result);
725 EVT VT =
Result.getValueType();
726 LLVMContext &Ctx = *DAG.getContext();
728 VT == TLI.getTypeToTransformTo(Ctx,
Op.getValueType())) &&
729 "Invalid type for softened float");
731 AnalyzeNewValue(Result);
733 auto &OpIdEntry = SoftenedFloats[getTableId(
Op)];
734 assert((OpIdEntry == 0) &&
"Node is already converted to integer!");
735 OpIdEntry = getTableId(Result);
740 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
741 "Invalid type for promoted float");
742 AnalyzeNewValue(Result);
744 auto &OpIdEntry = PromotedFloats[getTableId(
Op)];
745 assert((OpIdEntry == 0) &&
"Node is already promoted!");
746 OpIdEntry = getTableId(Result);
751 "Invalid type for soft-promoted half");
752 AnalyzeNewValue(Result);
754 auto &OpIdEntry = SoftPromotedHalfs[getTableId(
Op)];
755 assert((OpIdEntry == 0) &&
"Node is already promoted!");
756 OpIdEntry = getTableId(Result);
766 Op.getScalarValueSizeInBits() &&
767 "Invalid type for scalarized vector");
768 AnalyzeNewValue(Result);
770 auto &OpIdEntry = ScalarizedVectors[getTableId(
Op)];
771 assert((OpIdEntry == 0) &&
"Node is already scalarized!");
772 OpIdEntry = getTableId(Result);
777 std::pair<TableId, TableId> &
Entry = ExpandedIntegers[getTableId(
Op)];
778 assert((
Entry.first != 0) &&
"Operand isn't expanded");
786 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
787 Hi.getValueType() ==
Lo.getValueType() &&
788 "Invalid type for expanded integer");
795 if (DAG.getDataLayout().isBigEndian()) {
796 DAG.transferDbgValues(
Op,
Hi, 0,
Hi.getValueSizeInBits(),
false);
797 DAG.transferDbgValues(
Op,
Lo,
Hi.getValueSizeInBits(),
798 Lo.getValueSizeInBits());
800 DAG.transferDbgValues(
Op,
Lo, 0,
Lo.getValueSizeInBits(),
false);
801 DAG.transferDbgValues(
Op,
Hi,
Lo.getValueSizeInBits(),
802 Hi.getValueSizeInBits());
806 std::pair<TableId, TableId> &
Entry = ExpandedIntegers[getTableId(
Op)];
807 assert((
Entry.first == 0) &&
"Node already expanded");
814 std::pair<TableId, TableId> &
Entry = ExpandedFloats[getTableId(
Op)];
815 assert((
Entry.first != 0) &&
"Operand isn't expanded");
823 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
824 Hi.getValueType() ==
Lo.getValueType() &&
825 "Invalid type for expanded float");
830 std::pair<TableId, TableId> &
Entry = ExpandedFloats[getTableId(
Op)];
831 assert((
Entry.first == 0) &&
"Node already expanded");
838 std::pair<TableId, TableId> &
Entry = SplitVectors[getTableId(
Op)];
841 assert(
Lo.getNode() &&
"Operand isn't split");
847 assert(
Lo.getValueType().getVectorElementType() ==
848 Op.getValueType().getVectorElementType() &&
849 Lo.getValueType().getVectorElementCount() * 2 ==
850 Op.getValueType().getVectorElementCount() &&
851 Hi.getValueType() ==
Lo.getValueType() &&
852 "Invalid type for split vector");
858 std::pair<TableId, TableId> &
Entry = SplitVectors[getTableId(
Op)];
859 assert((
Entry.first == 0) &&
"Node already split");
866 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
867 "Invalid type for widened vector");
868 AnalyzeNewValue(Result);
870 auto &OpIdEntry = WidenedVectors[getTableId(
Op)];
871 assert((OpIdEntry == 0) &&
"Node already widened!");
872 OpIdEntry = getTableId(Result);
883 return DAG.getNode(ISD::BITCAST, SDLoc(
Op),
889 assert(
Op.getValueType().isVector() &&
"Only applies to vectors!");
890 unsigned EltWidth =
Op.getScalarValueSizeInBits();
892 auto EltCnt =
Op.getValueType().getVectorElementCount();
893 return DAG.getNode(ISD::BITCAST, SDLoc(
Op),
905 Align DestAlign = DAG.getReducedAlign(DestVT,
false);
906 Align OpAlign = DAG.getReducedAlign(
Op.getValueType(),
false);
909 DAG.CreateStackTemporary(
Op.getValueType().getStoreSize(), Align);
911 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl,
Op, StackPtr,
912 MachinePointerInfo(), Align);
914 return DAG.getLoad(DestVT, dl, Store, StackPtr, MachinePointerInfo(), Align);
925bool DAGTypeLegalizer::CustomLowerNode(
SDNode *
N,
EVT VT,
bool LegalizeResult) {
932 TLI.ReplaceNodeResults(
N,
Results, DAG);
934 TLI.LowerOperationWrapper(
N,
Results, DAG);
942 "Custom lowering returned the wrong number of results!");
943 for (
unsigned i = 0, e =
Results.
size(); i != e; ++i) {
952bool DAGTypeLegalizer::CustomWidenLowerNode(
SDNode *
N,
EVT VT) {
958 TLI.ReplaceNodeResults(
N,
Results, DAG);
966 "Custom lowering returned the wrong number of results!");
967 for (
unsigned i = 0, e =
Results.
size(); i != e; ++i) {
978SDValue DAGTypeLegalizer::DisintegrateMERGE_VALUES(
SDNode *
N,
unsigned ResNo) {
979 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i)
982 return SDValue(
N->getOperand(ResNo));
987void DAGTypeLegalizer::GetPairElements(
SDValue Pair,
990 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Pair.
getValueType());
991 std::tie(
Lo,
Hi) = DAG.SplitScalar(Pair, dl, NVT, NVT);
999 EVT LVT =
Lo.getValueType();
1000 EVT HVT =
Hi.getValueType();
1004 EVT ShiftAmtVT = TLI.getShiftAmountTy(NVT, DAG.getDataLayout());
1018 return TLI.promoteTargetBoolean(DAG,
Bool, ValVT);
1022void DAGTypeLegalizer::SplitInteger(
SDValue Op,
1027 Op.getValueSizeInBits() &&
"Invalid integer splitting!");
1029 unsigned ReqShiftAmountInBits =
1032 TLI.getScalarShiftAmountTy(DAG.getDataLayout(),
Op.getValueType());
1042void DAGTypeLegalizer::SplitInteger(
SDValue Op,
1046 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
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
static MVT getIntegerVT(unsigned BitWidth)
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.
@ 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.
unsigned Log2_32_Ceil(uint32_t Value)
Return the ceil log base 2 of the specified value, 32 if the value is zero.
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
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
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.