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 SoftPromoteHalfResult(
N, i);
302 unsigned NumOperands =
N->getNumOperands();
303 bool NeedsReanalyzing =
false;
305 for (i = 0; i != NumOperands; ++i) {
306 if (IgnoreNodeResults(
N->getOperand(i).getNode()))
309 const auto &
Op =
N->getOperand(i);
311 EVT OpVT =
Op.getValueType();
312 switch (getTypeAction(OpVT)) {
318 "Scalarization of scalable vectors is not supported.");
323 NeedsReanalyzing = PromoteIntegerOperand(
N, i);
327 NeedsReanalyzing = ExpandIntegerOperand(
N, i);
331 NeedsReanalyzing = SoftenFloatOperand(
N, i);
335 NeedsReanalyzing = ExpandFloatOperand(
N, i);
339 NeedsReanalyzing = ScalarizeVectorOperand(
N, i);
343 NeedsReanalyzing = SplitVectorOperand(
N, i);
347 NeedsReanalyzing = WidenVectorOperand(
N, i);
351 NeedsReanalyzing = SoftPromoteHalfOperand(
N, i);
361 if (NeedsReanalyzing) {
374 assert(
N->getNumValues() == M->getNumValues() &&
375 "Node morphing changed the number of results!");
376 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i)
386 if (i == NumOperands) {
398 int NodeId =
User->getNodeId();
403 User->setNodeId(NodeId-1);
407 Worklist.push_back(
User);
425 Worklist.push_back(
User);
429#ifndef EXPENSIVE_CHECKS
432 PerformExpensiveChecks();
441 DAG.RemoveDeadNodes();
450 if (!IgnoreNodeResults(&
Node))
451 for (
unsigned i = 0, NumVals =
Node.getNumValues(); i < NumVals; ++i)
452 if (!isTypeLegal(
Node.getValueType(i))) {
453 dbgs() <<
"Result type " << i <<
" illegal: ";
460 if (!IgnoreNodeResults(
Node.getOperand(i).getNode()) &&
461 !isTypeLegal(
Node.getOperand(i).getValueType())) {
462 dbgs() <<
"Operand type " << i <<
" illegal: ";
469 dbgs() <<
"New node not analyzed?\n";
471 dbgs() <<
"Unanalyzed node not noticed?\n";
472 else if (
Node.getNodeId() > 0)
473 dbgs() <<
"Operand not processed?\n";
475 dbgs() <<
"Not added to worklist?\n";
509 std::vector<SDValue> NewOps;
510 unsigned NumProcessed = 0;
511 for (
unsigned i = 0, e =
N->getNumOperands(); i != e; ++i) {
520 if (!NewOps.empty()) {
522 NewOps.push_back(
Op);
523 }
else if (
Op != OrigOp) {
526 NewOps.push_back(
Op);
531 if (!NewOps.empty()) {
532 SDNode *
M = DAG.UpdateNodeOperands(
N, NewOps);
553 N->setNodeId(
N->getNumOperands() - NumProcessed);
555 Worklist.push_back(
N);
562void DAGTypeLegalizer::AnalyzeNewValue(
SDValue &Val) {
571void DAGTypeLegalizer::RemapValue(
SDValue &V) {
572 auto Id = getTableId(V);
576void DAGTypeLegalizer::RemapId(TableId &Id) {
577 auto I = ReplacedValues.find(Id);
578 if (
I != ReplacedValues.end()) {
579 assert(Id !=
I->second &&
"Id is mapped to itself.");
595 DAGTypeLegalizer &DTL;
596 SmallSetVector<SDNode*, 16> &NodesToAnalyze;
598 explicit NodeUpdateListener(DAGTypeLegalizer &dtl,
599 SmallSetVector<SDNode*, 16> &nta)
600 : SelectionDAG::DAGUpdateListener(dtl.getDAG()),
601 DTL(dtl), NodesToAnalyze(nta) {}
603 void NodeDeleted(SDNode *
N, SDNode *
E)
override {
606 "Invalid node ID for RAUW deletion!");
609 assert(
E &&
"Node not replaced?");
624 void NodeUpdated(SDNode *
N)
override {
630 "Invalid node ID for RAUW deletion!");
640void DAGTypeLegalizer::ReplaceValueWith(
SDValue From,
SDValue To) {
648 SmallSetVector<SDNode*, 16> NodesToAnalyze;
649 NodeUpdateListener NUL(*
this, NodesToAnalyze);
654 auto FromId = getTableId(From);
655 auto ToId = getTableId(To);
658 ReplacedValues[FromId] = ToId;
659 DAG.ReplaceAllUsesOfValueWith(From, To);
662 while (!NodesToAnalyze.
empty()) {
671 SDNode *
M = AnalyzeNewNode(
N);
675 assert(
M->getNodeId() !=
NewNode &&
"Analysis resulted in NewNode!");
676 assert(
N->getNumValues() ==
M->getNumValues() &&
677 "Node morphing changed the number of results!");
678 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i) {
687 auto OldValId = getTableId(OldVal);
688 auto NewValId = getTableId(NewVal);
689 DAG.ReplaceAllUsesOfValueWith(OldVal, NewVal);
696 if (OldValId != NewValId)
697 ReplacedValues[OldValId] = NewValId;
710 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
711 "Invalid type for promoted integer");
712 AnalyzeNewValue(Result);
714 auto &OpIdEntry = PromotedIntegers[getTableId(
Op)];
715 assert((OpIdEntry == 0) &&
"Node is already promoted!");
716 OpIdEntry = getTableId(Result);
718 DAG.transferDbgValues(
Op, Result);
723 EVT VT =
Result.getValueType();
724 LLVMContext &Ctx = *DAG.getContext();
726 VT == TLI.getTypeToTransformTo(Ctx,
Op.getValueType())) &&
727 "Invalid type for softened float");
729 AnalyzeNewValue(Result);
731 auto &OpIdEntry = SoftenedFloats[getTableId(
Op)];
732 assert((OpIdEntry == 0) &&
"Node is already converted to integer!");
733 OpIdEntry = getTableId(Result);
738 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
739 "Invalid type for promoted float");
740 AnalyzeNewValue(Result);
742 auto &OpIdEntry = PromotedFloats[getTableId(
Op)];
743 assert((OpIdEntry == 0) &&
"Node is already promoted!");
744 OpIdEntry = getTableId(Result);
749 "Invalid type for soft-promoted half");
750 AnalyzeNewValue(Result);
752 auto &OpIdEntry = SoftPromotedHalfs[getTableId(
Op)];
753 assert((OpIdEntry == 0) &&
"Node is already promoted!");
754 OpIdEntry = getTableId(Result);
764 Op.getScalarValueSizeInBits() &&
765 "Invalid type for scalarized vector");
766 AnalyzeNewValue(Result);
768 auto &OpIdEntry = ScalarizedVectors[getTableId(
Op)];
769 assert((OpIdEntry == 0) &&
"Node is already scalarized!");
770 OpIdEntry = getTableId(Result);
775 std::pair<TableId, TableId> &
Entry = ExpandedIntegers[getTableId(
Op)];
776 assert((
Entry.first != 0) &&
"Operand isn't expanded");
784 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
785 Hi.getValueType() ==
Lo.getValueType() &&
786 "Invalid type for expanded integer");
793 if (DAG.getDataLayout().isBigEndian()) {
794 DAG.transferDbgValues(
Op,
Hi, 0,
Hi.getValueSizeInBits(),
false);
795 DAG.transferDbgValues(
Op,
Lo,
Hi.getValueSizeInBits(),
796 Lo.getValueSizeInBits());
798 DAG.transferDbgValues(
Op,
Lo, 0,
Lo.getValueSizeInBits(),
false);
799 DAG.transferDbgValues(
Op,
Hi,
Lo.getValueSizeInBits(),
800 Hi.getValueSizeInBits());
804 std::pair<TableId, TableId> &
Entry = ExpandedIntegers[getTableId(
Op)];
805 assert((
Entry.first == 0) &&
"Node already expanded");
812 std::pair<TableId, TableId> &
Entry = ExpandedFloats[getTableId(
Op)];
813 assert((
Entry.first != 0) &&
"Operand isn't expanded");
821 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
822 Hi.getValueType() ==
Lo.getValueType() &&
823 "Invalid type for expanded float");
828 std::pair<TableId, TableId> &
Entry = ExpandedFloats[getTableId(
Op)];
829 assert((
Entry.first == 0) &&
"Node already expanded");
836 std::pair<TableId, TableId> &
Entry = SplitVectors[getTableId(
Op)];
839 assert(
Lo.getNode() &&
"Operand isn't split");
845 assert(
Lo.getValueType().getVectorElementType() ==
846 Op.getValueType().getVectorElementType() &&
847 Lo.getValueType().getVectorElementCount() * 2 ==
848 Op.getValueType().getVectorElementCount() &&
849 Hi.getValueType() ==
Lo.getValueType() &&
850 "Invalid type for split vector");
856 std::pair<TableId, TableId> &
Entry = SplitVectors[getTableId(
Op)];
857 assert((
Entry.first == 0) &&
"Node already split");
864 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
865 "Invalid type for widened vector");
866 AnalyzeNewValue(Result);
868 auto &OpIdEntry = WidenedVectors[getTableId(
Op)];
869 assert((OpIdEntry == 0) &&
"Node already widened!");
870 OpIdEntry = getTableId(Result);
887 assert(
Op.getValueType().isVector() &&
"Only applies to vectors!");
888 unsigned EltWidth =
Op.getScalarValueSizeInBits();
890 auto EltCnt =
Op.getValueType().getVectorElementCount();
903 Align DestAlign = DAG.getReducedAlign(DestVT,
false);
904 Align OpAlign = DAG.getReducedAlign(
Op.getValueType(),
false);
907 DAG.CreateStackTemporary(
Op.getValueType().getStoreSize(), Align);
909 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl,
Op, StackPtr,
910 MachinePointerInfo(), Align);
912 return DAG.getLoad(DestVT, dl, Store, StackPtr, MachinePointerInfo(), Align);
923bool DAGTypeLegalizer::CustomLowerNode(
SDNode *
N,
EVT VT,
bool LegalizeResult) {
930 TLI.ReplaceNodeResults(
N,
Results, DAG);
932 TLI.LowerOperationWrapper(
N,
Results, DAG);
940 "Custom lowering returned the wrong number of results!");
941 for (
unsigned i = 0, e =
Results.
size(); i != e; ++i) {
950bool DAGTypeLegalizer::CustomWidenLowerNode(
SDNode *
N,
EVT VT) {
956 TLI.ReplaceNodeResults(
N,
Results, DAG);
964 "Custom lowering returned the wrong number of results!");
965 for (
unsigned i = 0, e =
Results.
size(); i != e; ++i) {
976SDValue DAGTypeLegalizer::DisintegrateMERGE_VALUES(
SDNode *
N,
unsigned ResNo) {
977 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i)
980 return SDValue(
N->getOperand(ResNo));
985void DAGTypeLegalizer::GetPairElements(
SDValue Pair,
988 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Pair.
getValueType());
989 std::tie(
Lo,
Hi) = DAG.SplitScalar(Pair, dl, NVT, NVT);
997 EVT LVT =
Lo.getValueType();
998 EVT HVT =
Hi.getValueType();
1005 DAG.getShiftAmountConstant(LVT.
getSizeInBits(), NVT, dlHi));
1015 return TLI.promoteTargetBoolean(DAG, Bool, ValVT);
1019void DAGTypeLegalizer::SplitInteger(
SDValue Op,
1024 Op.getValueSizeInBits() &&
"Invalid integer splitting!");
1028 DAG.getShiftAmountConstant(LoVT.
getSizeInBits(),
Op.getValueType(), dl));
1034void DAGTypeLegalizer::SplitInteger(
SDValue Op,
1038 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.
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.