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);
690 if (OldValId != NewValId)
691 ReplacedValues[OldValId] = NewValId;
704 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
705 "Invalid type for promoted integer");
706 AnalyzeNewValue(Result);
708 auto &OpIdEntry = PromotedIntegers[getTableId(
Op)];
709 assert((OpIdEntry == 0) &&
"Node is already promoted!");
710 OpIdEntry = getTableId(Result);
712 DAG.transferDbgValues(
Op, Result);
717 EVT VT =
Result.getValueType();
718 LLVMContext &Ctx = *DAG.getContext();
720 VT == TLI.getTypeToTransformTo(Ctx,
Op.getValueType())) &&
721 "Invalid type for softened float");
723 AnalyzeNewValue(Result);
725 auto &OpIdEntry = SoftenedFloats[getTableId(
Op)];
726 assert((OpIdEntry == 0) &&
"Node is already converted to integer!");
727 OpIdEntry = getTableId(Result);
732 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
733 "Invalid type for promoted float");
734 AnalyzeNewValue(Result);
736 auto &OpIdEntry = PromotedFloats[getTableId(
Op)];
737 assert((OpIdEntry == 0) &&
"Node is already promoted!");
738 OpIdEntry = getTableId(Result);
743 "Invalid type for soft-promoted half");
744 AnalyzeNewValue(Result);
746 auto &OpIdEntry = SoftPromotedHalfs[getTableId(
Op)];
747 assert((OpIdEntry == 0) &&
"Node is already promoted!");
748 OpIdEntry = getTableId(Result);
758 Op.getScalarValueSizeInBits() &&
759 "Invalid type for scalarized vector");
760 AnalyzeNewValue(Result);
762 auto &OpIdEntry = ScalarizedVectors[getTableId(
Op)];
763 assert((OpIdEntry == 0) &&
"Node is already scalarized!");
764 OpIdEntry = getTableId(Result);
769 std::pair<TableId, TableId> &
Entry = ExpandedIntegers[getTableId(
Op)];
770 assert((
Entry.first != 0) &&
"Operand isn't expanded");
778 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
779 Hi.getValueType() ==
Lo.getValueType() &&
780 "Invalid type for expanded integer");
787 if (DAG.getDataLayout().isBigEndian()) {
788 DAG.transferDbgValues(
Op,
Hi, 0,
Hi.getValueSizeInBits(),
false);
789 DAG.transferDbgValues(
Op,
Lo,
Hi.getValueSizeInBits(),
790 Lo.getValueSizeInBits());
792 DAG.transferDbgValues(
Op,
Lo, 0,
Lo.getValueSizeInBits(),
false);
793 DAG.transferDbgValues(
Op,
Hi,
Lo.getValueSizeInBits(),
794 Hi.getValueSizeInBits());
798 std::pair<TableId, TableId> &
Entry = ExpandedIntegers[getTableId(
Op)];
799 assert((
Entry.first == 0) &&
"Node already expanded");
806 std::pair<TableId, TableId> &
Entry = ExpandedFloats[getTableId(
Op)];
807 assert((
Entry.first != 0) &&
"Operand isn't expanded");
815 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
816 Hi.getValueType() ==
Lo.getValueType() &&
817 "Invalid type for expanded float");
822 std::pair<TableId, TableId> &
Entry = ExpandedFloats[getTableId(
Op)];
823 assert((
Entry.first == 0) &&
"Node already expanded");
830 std::pair<TableId, TableId> &
Entry = SplitVectors[getTableId(
Op)];
833 assert(
Lo.getNode() &&
"Operand isn't split");
839 assert(
Lo.getValueType().getVectorElementType() ==
840 Op.getValueType().getVectorElementType() &&
841 Lo.getValueType().getVectorElementCount() * 2 ==
842 Op.getValueType().getVectorElementCount() &&
843 Hi.getValueType() ==
Lo.getValueType() &&
844 "Invalid type for split vector");
850 std::pair<TableId, TableId> &
Entry = SplitVectors[getTableId(
Op)];
851 assert((
Entry.first == 0) &&
"Node already split");
858 TLI.getTypeToTransformTo(*DAG.getContext(),
Op.getValueType()) &&
859 "Invalid type for widened vector");
860 AnalyzeNewValue(Result);
862 auto &OpIdEntry = WidenedVectors[getTableId(
Op)];
863 assert((OpIdEntry == 0) &&
"Node already widened!");
864 OpIdEntry = getTableId(Result);
881 assert(
Op.getValueType().isVector() &&
"Only applies to vectors!");
882 unsigned EltWidth =
Op.getScalarValueSizeInBits();
884 auto EltCnt =
Op.getValueType().getVectorElementCount();
897 Align DestAlign = DAG.getReducedAlign(DestVT,
false);
898 Align OpAlign = DAG.getReducedAlign(
Op.getValueType(),
false);
901 DAG.CreateStackTemporary(
Op.getValueType().getStoreSize(), Align);
903 SDValue Store = DAG.getStore(DAG.getEntryNode(), dl,
Op, StackPtr,
904 MachinePointerInfo(), Align);
906 return DAG.getLoad(DestVT, dl, Store, StackPtr, MachinePointerInfo(), Align);
917bool DAGTypeLegalizer::CustomLowerNode(
SDNode *
N,
EVT VT,
bool LegalizeResult) {
924 TLI.ReplaceNodeResults(
N,
Results, DAG);
926 TLI.LowerOperationWrapper(
N,
Results, DAG);
934 "Custom lowering returned the wrong number of results!");
935 for (
unsigned i = 0, e =
Results.
size(); i != e; ++i) {
944bool DAGTypeLegalizer::CustomWidenLowerNode(
SDNode *
N,
EVT VT) {
950 TLI.ReplaceNodeResults(
N,
Results, DAG);
958 "Custom lowering returned the wrong number of results!");
959 for (
unsigned i = 0, e =
Results.
size(); i != e; ++i) {
970SDValue DAGTypeLegalizer::DisintegrateMERGE_VALUES(
SDNode *
N,
unsigned ResNo) {
971 for (
unsigned i = 0, e =
N->getNumValues(); i != e; ++i)
974 return SDValue(
N->getOperand(ResNo));
979void DAGTypeLegalizer::GetPairElements(
SDValue Pair,
982 EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), Pair.
getValueType());
983 std::tie(
Lo,
Hi) = DAG.SplitScalar(Pair, dl, NVT, NVT);
991 EVT LVT =
Lo.getValueType();
992 EVT HVT =
Hi.getValueType();
1009 return TLI.promoteTargetBoolean(DAG, Bool, ValVT);
1013void DAGTypeLegalizer::SplitInteger(
SDValue Op,
1018 Op.getValueSizeInBits() &&
"Invalid integer splitting!");
1022 DAG.getShiftAmountConstant(LoVT.
getSizeInBits(),
Op.getValueType(), dl));
1028void DAGTypeLegalizer::SplitInteger(
SDValue Op,
1032 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.