27 #define DEBUG_TYPE "hexagon-isel" 32 cl::desc(
"Rebalance address calculation trees to improve " 33 "instruction selection"));
40 cl::desc(
"Rebalance address tree only if this allows optimizations"));
45 cl::init(
false),
cl::desc(
"Rebalance address tree only if it is imbalanced"));
54 #define GET_DAGISEL_BODY HexagonDAGToDAGISel 55 #include "HexagonGenDAGISel.inc" 71 int32_t Inc = cast<ConstantSDNode>(Offset.
getNode())->getSExtValue();
85 Opcode = IsValidInc ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrub_io;
87 Opcode = IsValidInc ? Hexagon::L2_loadrb_pi : Hexagon::L2_loadrb_io;
91 Opcode = IsValidInc ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadruh_io;
93 Opcode = IsValidInc ? Hexagon::L2_loadrh_pi : Hexagon::L2_loadrh_io;
99 Opcode = IsValidInc ? Hexagon::L2_loadri_pi : Hexagon::L2_loadri_io;
106 Opcode = IsValidInc ? Hexagon::L2_loadrd_pi : Hexagon::L2_loadrd_io;
116 if (isAlignedMemNode(LD)) {
118 Opcode = IsValidInc ? Hexagon::V6_vL32b_nt_pi : Hexagon::V6_vL32b_nt_ai;
120 Opcode = IsValidInc ? Hexagon::V6_vL32b_pi : Hexagon::V6_vL32b_ai;
122 Opcode = IsValidInc ? Hexagon::V6_vL32Ub_pi : Hexagon::V6_vL32Ub_ai;
191 unsigned IntNo = cast<ConstantSDNode>(IntN->
getOperand(1))->getZExtValue();
193 static std::map<unsigned,unsigned> LoadPciMap = {
201 auto FLC = LoadPciMap.find(IntNo);
202 if (FLC != LoadPciMap.end()) {
206 auto Inc = cast<ConstantSDNode>(IntN->
getOperand(5));
209 { IntN->getOperand(2), I, IntN->getOperand(4),
210 IntN->getOperand(0) });
225 unsigned Size = 1U << (SizeBits-1);
283 switch (cast<ConstantSDNode>(C->
getOperand(1))->getZExtValue()) {
323 const SDLoc &dl(IntN);
324 unsigned IntNo = cast<ConstantSDNode>(IntN->
getOperand(1))->getZExtValue();
326 static const std::map<unsigned, unsigned> LoadBrevMap = {
334 auto FLI = LoadBrevMap.find(IntNo);
335 if (FLI != LoadBrevMap.end()) {
343 FLI->second, dl, RTys,
344 {IntN->getOperand(2), IntN->getOperand(3), IntN->getOperand(0)});
365 unsigned IntNo = cast<ConstantSDNode>(IntN->
getOperand(1))->getZExtValue();
368 static std::map<unsigned,unsigned> LoadNPcMap = {
382 auto FLI = LoadNPcMap.find (IntNo);
383 if (FLI != LoadNPcMap.end()) {
391 auto Inc = cast<ConstantSDNode>(IntN->
getOperand(3));
409 static std::map<unsigned,unsigned> StoreNPcMap = {
421 auto FSI = StoreNPcMap.find (IntNo);
422 if (FSI != StoreNPcMap.end()) {
426 auto Inc = cast<ConstantSDNode>(IntN->
getOperand(3));
470 int32_t Inc = cast<ConstantSDNode>(Offset.
getNode())->getSExtValue();
480 Opcode = IsValidInc ? Hexagon::S2_storerb_pi : Hexagon::S2_storerb_io;
483 Opcode = IsValidInc ? Hexagon::S2_storerh_pi : Hexagon::S2_storerh_io;
489 Opcode = IsValidInc ? Hexagon::S2_storeri_pi : Hexagon::S2_storeri_io;
496 Opcode = IsValidInc ? Hexagon::S2_storerd_pi : Hexagon::S2_storerd_io;
506 if (isAlignedMemNode(ST)) {
508 Opcode = IsValidInc ? Hexagon::V6_vS32b_nt_pi : Hexagon::V6_vS32b_nt_ai;
510 Opcode = IsValidInc ? Hexagon::V6_vS32b_pi : Hexagon::V6_vS32b_ai;
512 Opcode = IsValidInc ? Hexagon::V6_vS32Ub_pi : Hexagon::V6_vS32Ub_ai;
534 SDValue Ops[] = { Base, IncV, Value, Chain };
542 SDValue Ops[] = { Base, Zero, Value, Chain };
574 auto Default = [
this,
N] () ->
void { SelectCode(N); };
580 int32_t ShlConst = cast<ConstantSDNode>(Shl_1)->getSExtValue();
587 int32_t ValConst =
C->getSExtValue() << ShlConst;
588 if (isInt<9>(ValConst)) {
608 int32_t ValConst = 1 << (ShlConst + C2->getSExtValue());
609 if (isInt<9>(-ValConst)) {
640 unsigned IntNo = cast<ConstantSDNode>(N->
getOperand(1))->getZExtValue();
664 unsigned IID = cast<ConstantSDNode>(N->
getOperand(0))->getZExtValue();
686 if (keepsLowBits(V, Bits, U)) {
722 assert(!(cast<ConstantSDNode>(N)->getZExtValue() >> 1));
723 unsigned Opc = (cast<ConstantSDNode>(
N)->getSExtValue() != 0)
736 int FX = cast<FrameIndexSDNode>(
N)->getIndex();
764 : Hexagon::A4_subp_c;
774 return SelectHvxVAlign(N);
813 int Mask = -cast<ConstantSDNode>(A.
getNode())->getSExtValue();
908 std::vector<SDValue> &OutOps) {
911 switch (ConstraintID) {
919 OutOps.push_back(Res);
921 OutOps.push_back(Inp);
962 SDValue LDBasePtr = cast<MemSDNode>(SYNode)->getBasePtr();
963 SDValue STBasePtr = cast<MemSDNode>(UUse)->getBasePtr();
964 if (LDBasePtr == STBasePtr)
973 void HexagonDAGToDAGISel::ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes) {
976 for (
auto I : Nodes) {
980 auto IsZero = [] (
const SDValue &V) ->
bool {
982 return SC->isNullValue();
985 auto IsSelect0 = [IsZero] (
const SDValue &
Op) ->
bool {
988 return IsZero(
Op.getOperand(1)) || IsZero(
Op.getOperand(2));
991 SDValue N0 =
I->getOperand(0), N1 =
I->getOperand(1);
992 EVT VT =
I->getValueType(0);
993 bool SelN0 = IsSelect0(N0);
1006 }
else if (IsZero(SX)) {
1021 void HexagonDAGToDAGISel::ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes) {
1024 for (
auto I : Nodes) {
1056 if (EV % (1 << CV) != 0)
1058 unsigned DV = EV / (1 << CV);
1085 void HexagonDAGToDAGISel::ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes) {
1089 unsigned Opc =
N->getOpcode();
1126 if (TZ + M1 + LZ != 32)
1150 void HexagonDAGToDAGISel::ppHoistZextI1(std::vector<SDNode*> &&Nodes) {
1154 unsigned Opc =
N->getOpcode();
1161 for (
auto I =
N->use_begin(),
E =
N->use_end();
I !=
E; ++
I) {
1172 unsigned I1N =
I.getOperandNo();
1176 EVT BVT = Ops[I1N].getValueType();
1183 if (isa<MachineSDNode>(U)) {
1192 If0 = DAG.
getNode(UseOpc, dl, UVT, Ops);
1194 If1 = DAG.
getNode(UseOpc, dl, UVT, Ops);
1205 auto getNodes = [
this] () -> std::vector<SDNode*> {
1206 std::vector<SDNode*>
T;
1215 ppSimplifyOrSelect0(getNodes());
1223 ppAddrReorderAddShl(getNodes());
1238 ppAddrRewriteAndSrl(getNodes());
1242 ppHoistZextI1(getNodes());
1245 dbgs() <<
"Preprocessed (Hexagon) selection DAG:";
1250 rebalanceAddressTrees();
1253 dbgs() <<
"Address tree balanced selection DAG:";
1262 if (!HFI.needsAligna(*
MF))
1280 int FX = cast<FrameIndexSDNode>(
N)->getIndex();
1322 auto IsAligned = [LogAlign] (uint64_t V) ->
bool {
1323 return alignTo(V, (uint64_t)1 << LogAlign) == V;
1330 int32_t V = cast<const ConstantSDNode>(
N)->getZExtValue();
1351 if (LogAlign > 2 || !IsAligned(cast<BlockAddressSDNode>(N)->
getOffset()))
1366 auto IsAligned = [LogAlign] (uint64_t V) ->
bool {
1367 return alignTo(V, (uint64_t)1 << LogAlign) == V;
1382 if (!IsAligned(Const->getZExtValue()))
1386 uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue();
1465 if (!S || S->getZExtValue() != 32)
1491 bool HexagonDAGToDAGISel::keepsLowBits(
const SDValue &Val,
unsigned NumBits,
1519 uint64_t
Mask = (1 << NumBits) - 1;
1521 if (
C->getZExtValue() ==
Mask) {
1527 if (
C->getZExtValue() ==
Mask) {
1537 uint64_t
Mask = (1 << NumBits) - 1;
1539 if ((
C->getZExtValue() &
Mask) == 0) {
1545 if ((
C->getZExtValue() &
Mask) == 0) {
1558 bool HexagonDAGToDAGISel::isAlignedMemNode(
const MemSDNode *
N)
const {
1562 bool HexagonDAGToDAGISel::isSmallStackStore(
const StoreSDNode *N)
const {
1566 return StackSize <= 56;
1568 return StackSize <= 120;
1570 return StackSize <= 248;
1577 bool HexagonDAGToDAGISel::isPositiveHalfWord(
const SDNode *N)
const {
1578 if (
const ConstantSDNode *CN = dyn_cast<const ConstantSDNode>(N)) {
1579 int64_t V = CN->getSExtValue();
1589 bool HexagonDAGToDAGISel::hasOneUse(
const SDNode *N)
const {
1611 int HexagonDAGToDAGISel::getWeight(
SDNode *N) {
1614 assert(RootWeights.count(N) &&
"Cannot get weight of unseen root!");
1615 assert(RootWeights[N] != -1 &&
"Cannot get weight of unvisited root!");
1616 assert(RootWeights[N] != -2 &&
"Cannot get weight of RAWU'd root!");
1617 return RootWeights[
N];
1620 int HexagonDAGToDAGISel::getHeight(
SDNode *N) {
1623 assert(RootWeights.count(N) && RootWeights[
N] >= 0 &&
1624 "Cannot query height of unvisited/RAUW'd node!");
1625 return RootHeights[
N];
1629 struct WeightedLeaf {
1634 WeightedLeaf() : Value(
SDValue()) { }
1636 WeightedLeaf(
SDValue Value,
int Weight,
int InsertionOrder) :
1637 Value(Value), Weight(Weight), InsertionOrder(InsertionOrder) {
1638 assert(Weight >= 0 &&
"Weight must be >= 0");
1641 static bool Compare(
const WeightedLeaf &A,
const WeightedLeaf &
B) {
1642 assert(A.Value.getNode() && B.Value.getNode());
1643 return A.Weight == B.Weight ?
1644 (A.InsertionOrder > B.InsertionOrder) :
1645 (A.Weight > B.Weight);
1652 class LeafPrioQueue {
1655 WeightedLeaf ConstElt;
1660 return (!HaveConst && Q.
empty());
1664 return Q.
size() + HaveConst;
1671 const WeightedLeaf &top() {
1677 WeightedLeaf pop() {
1686 void push(WeightedLeaf L,
bool SeparateConst=
true) {
1687 if (!HaveConst && SeparateConst && isa<ConstantSDNode>(L.Value)) {
1689 cast<ConstantSDNode>(L.Value)->getSExtValue() == 1)
1692 cast<ConstantSDNode>(L.Value)->getSExtValue() == 0)
1705 void pushToBottom(WeightedLeaf L) {
1712 WeightedLeaf findSHL(uint64_t MaxAmount);
1714 WeightedLeaf findMULbyConst();
1716 LeafPrioQueue(
unsigned Opcode) :
1717 HaveConst(
false), Opcode(Opcode) { }
1721 WeightedLeaf LeafPrioQueue::findSHL(uint64_t MaxAmount) {
1723 WeightedLeaf Result;
1725 for (
int Pos = 0, End = Q.size(); Pos != End; ++Pos) {
1726 const WeightedLeaf &L = Q[Pos];
1732 if (!Result.Value.getNode() || Result.Weight > L.Weight ||
1733 (Result.Weight == L.Weight && Result.InsertionOrder > L.InsertionOrder))
1740 if (Result.Value.getNode()) {
1741 Q.erase(&Q[ResultPos]);
1748 WeightedLeaf LeafPrioQueue::findMULbyConst() {
1750 WeightedLeaf Result;
1752 for (
int Pos = 0, End = Q.size(); Pos != End; ++Pos) {
1753 const WeightedLeaf &L = Q[Pos];
1759 if (!Result.Value.getNode() || Result.Weight > L.Weight ||
1760 (Result.Weight == L.Weight && Result.InsertionOrder > L.InsertionOrder))
1767 if (Result.Value.getNode()) {
1768 Q.erase(&Q[ResultPos]);
1775 SDValue HexagonDAGToDAGISel::getMultiplierForSHL(
SDNode *N) {
1784 unsigned MaxFactor = 0;
1785 for (
int i = 0; i < 2; ++i) {
1808 for (
int i = 0; i < 2; ++i)
1809 if (isa<ConstantSDNode>(Ops[i].getNode()) &&
1812 return (NewConst == 1);
1821 SDValue HexagonDAGToDAGISel::factorOutPowerOf2(
SDValue V,
unsigned Power) {
1824 for (
int i=0; i < 2; ++i) {
1825 if (isa<ConstantSDNode>(Ops[i].getNode()) &&
1837 if (ShiftAmount == Power)
1851 unsigned HexagonDAGToDAGISel::getUsesInFunction(
const Value *V) {
1852 if (GAUsesInFunction.count(V))
1853 return GAUsesInFunction[V];
1855 unsigned Result = 0;
1858 if (isa<Instruction>(U) &&
1863 GAUsesInFunction[V] = Result;
1873 SDValue HexagonDAGToDAGISel::balanceSubTree(
SDNode *N,
bool TopLevel) {
1874 assert(RootWeights.count(N) &&
"Cannot balance non-root node.");
1875 assert(RootWeights[N] != -2 &&
"This node was RAUW'd!");
1879 if (RootWeights[N] != -1)
1893 Weight = getWeight(balanceSubTree(Op0N).getNode());
1896 Weight = getWeight(Op0N);
1900 Weight += getWeight(balanceSubTree(Op1N).getNode());
1903 Weight += getWeight(Op1N);
1905 RootWeights[
N] = Weight;
1909 LLVM_DEBUG(
dbgs() <<
"--> No need to balance root (Weight=" << Weight
1910 <<
" Height=" << RootHeights[N] <<
"): ");
1921 LeafPrioQueue Leaves(NOpcode);
1929 bool CanFactorize =
false;
1930 WeightedLeaf Mul1, Mul2;
1931 unsigned MaxPowerOf2 = 0;
1936 bool HaveTopLevelShift =
false;
1942 HaveTopLevelShift =
true;
1946 int InsertionOrder = 0;
1948 bool Imbalanced =
false;
1949 int CurrentWeight = 0;
1950 while (!Worklist.
empty()) {
1953 if (Child.
getNode() != N && RootWeights.count(Child.
getNode())) {
1956 int Weight = RootWeights[Child.
getNode()];
1958 Child = balanceSubTree(Child.
getNode());
1960 Weight = getWeight(Child.
getNode());
1961 }
else if (Weight == -2) {
1966 return balanceSubTree(N, TopLevel);
1969 NodeHeights[Child] = 1;
1970 CurrentWeight += Weight;
1973 if (TopLevel && !CanFactorize && !HaveTopLevelShift &&
1979 if (!Mul1.Value.getNode()) {
1980 Mul1 = WeightedLeaf(Child, Weight, InsertionOrder++);
1981 MaxPowerOf2 = PowerOf2;
1983 Mul2 = WeightedLeaf(Child, Weight, InsertionOrder++);
1984 MaxPowerOf2 = std::min(MaxPowerOf2, PowerOf2);
1987 if (MaxPowerOf2 > 3)
1990 CanFactorize =
true;
1993 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
1996 int Weight = getWeight(Child.
getNode());
1998 NodeHeights[Child] = getHeight(Child.
getNode());
1999 CurrentWeight += Weight;
2002 GA = WeightedLeaf(Child, Weight, InsertionOrder++);
2004 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2008 unsigned ChildOpcode = Child.
getOpcode();
2009 assert(ChildOpcode == NOpcode ||
2015 Op1 = getMultiplierForSHL(Child.
getNode());
2020 assert(!NodeHeights.
count(Child) &&
"Parent visited before children?");
2030 NodeHeights[Child] =
std::max(NodeHeights[Op1],
2037 <<
" weight=" << CurrentWeight
2038 <<
" imbalanced=" << Imbalanced <<
"\n");
2044 LLVM_DEBUG(
dbgs() <<
"--> Found common factor for two MUL children!\n");
2045 int Weight = Mul1.Weight + Mul2.Weight;
2046 int Height =
std::max(NodeHeights[Mul1.Value], NodeHeights[Mul2.Value]) + 1;
2047 SDValue Mul1Factored = factorOutPowerOf2(Mul1.Value, MaxPowerOf2);
2048 SDValue Mul2Factored = factorOutPowerOf2(Mul2.Value, MaxPowerOf2);
2050 Mul1Factored, Mul2Factored);
2052 Mul1.Value.getValueType());
2055 NodeHeights[New] = Height;
2056 Leaves.push(WeightedLeaf(New, Weight, Mul1.InsertionOrder));
2057 }
else if (Mul1.Value.getNode()) {
2061 if (Mul2.Value.getNode())
2063 CanFactorize =
false;
2069 bool CombinedGA =
false;
2070 if (NOpcode ==
ISD::ADD && GA.Value.getNode() && Leaves.hasConst() &&
2071 GA.Value.hasOneUse() && N->
use_size() < 3) {
2073 cast<GlobalAddressSDNode>(GA.Value.getOperand(0));
2076 if (getUsesInFunction(GANode->
getGlobal()) == 1 && Offset->hasOneUse() &&
2079 << Offset->getSExtValue() <<
"): ");
2085 GANode->
getOffset() + (uint64_t)Offset->getSExtValue());
2087 GA.Value.getValueType(), NewTGA);
2088 GA.Weight += Leaves.top().Weight;
2090 NodeHeights[GA.Value] = getHeight(GA.Value.getNode());
2099 RootWeights[
N] = CurrentWeight;
2100 RootHeights[
N] = NodeHeights[
SDValue(N, 0)];
2106 if (NOpcode ==
ISD::ADD && GA.Value.getNode()) {
2107 WeightedLeaf
SHL = Leaves.findSHL(31);
2108 if (SHL.Value.getNode()) {
2109 int Height =
std::max(NodeHeights[GA.Value], NodeHeights[SHL.Value]) + 1;
2111 GA.Value.getValueType(),
2112 GA.Value, SHL.Value);
2113 GA.Weight = SHL.Weight;
2114 NodeHeights[GA.Value] = Height;
2118 if (GA.Value.getNode())
2123 if (TopLevel && !CanFactorize && Leaves.hasConst()) {
2125 Leaves.pushToBottom(Leaves.pop());
2132 while (Leaves.size() > 1) {
2133 WeightedLeaf L0 = Leaves.pop();
2137 WeightedLeaf L1 = Leaves.findMULbyConst();
2138 if (!L1.Value.getNode())
2141 assert(L0.Weight <= L1.Weight &&
"Priority queue is broken!");
2144 int V0Weight = L0.Weight;
2146 int V1Weight = L1.Weight;
2149 if ((RootWeights.count(V0.
getNode()) && RootWeights[V0.
getNode()] == -2) ||
2150 (RootWeights.count(V1.
getNode()) && RootWeights[V1.
getNode()] == -2)) {
2152 return balanceSubTree(N, TopLevel);
2167 "Children must have been visited before re-combining them!");
2168 int Height =
std::max(NodeHeights[V0], NodeHeights[V1]) + 1;
2171 if (V1C && NOpcode ==
ISD::MUL && V1C->getAPIntValue().isPowerOf2())
2175 V1C->getAPIntValue().logBase2(),
SDLoc(N),
2180 NodeHeights[NewNode] = Height;
2182 int Weight = V0Weight + V1Weight;
2183 Leaves.push(WeightedLeaf(NewNode, Weight, L0.InsertionOrder));
2186 <<
",Height=" << Height <<
"):\n");
2190 assert(Leaves.size() == 1);
2191 SDValue NewRoot = Leaves.top().Value;
2194 int Height = NodeHeights[NewRoot];
2197 if (NewRoot.getOpcode() ==
ISD::MUL) {
2200 EVT VT = NewRoot.getValueType();
2210 if (N != NewRoot.getNode()) {
2217 RootWeights[
N] = -2;
2222 RootWeights[NewRoot.getNode()] = Leaves.top().Weight;
2223 RootHeights[NewRoot.getNode()] = Height;
2228 void HexagonDAGToDAGISel::rebalanceAddressTrees() {
2234 SDValue BasePtr = cast<MemSDNode>(
N)->getBasePtr();
2239 if (RootWeights.count(BasePtr.
getNode()))
2242 LLVM_DEBUG(
dbgs() <<
"** Rebalancing address calculation in node: ");
2251 while (!Worklist.empty()) {
2252 SDNode *N = Worklist.pop_back_val();
2266 if (RootWeights.count(N))
2269 RootWeights[
N] = -1;
2273 RootWeights[BasePtr.
getNode()] = -1;
2288 GAUsesInFunction.clear();
2289 RootHeights.clear();
2290 RootWeights.clear();
SDValue getStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, unsigned Alignment=0, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
Helper function to build ISD::STORE nodes.
SDNode * MorphNodeTo(SDNode *N, unsigned Opc, SDVTList VTs, ArrayRef< SDValue > Ops)
This mutates the specified node to have the specified return type, opcode, and operands.
static MVT getIntegerVT(unsigned BitWidth)
A parsed version of the target data layout string in and methods for querying it. ...
void SelectV2Q(SDNode *N)
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOffset() const
const GlobalValue * getGlobal() const
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
static cl::opt< bool > CheckSingleUse("hexagon-isel-su", cl::Hidden, cl::init(true), cl::desc("Enable checking of SDNode's single-use status"))
This class represents lattice values for constants.
static bool isMemOPCandidate(SDNode *I, SDNode *U)
void EmitFunctionEntryCode() override
static bool willShiftRightEliminate(SDValue V, unsigned Amount)
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
void ReplaceUses(SDValue F, SDValue T)
ReplaceUses - replace all uses of the old node F with the use of the new node T.
const SDValue & getBasePtr() const
void SelectIntrinsicWOChain(SDNode *N)
void push_back(const T &Elt)
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
bool DetectUseSxtw(SDValue &N, SDValue &R)
const SDValue & getValue() const
SDVTList getVTList() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool SelectAddrFI(SDValue &N, SDValue &R)
const SDValue & getChain() const
static unsigned getPowerOf2Factor(SDValue Val)
ISD::MemIndexedMode getAddressingMode() const
Return the addressing mode for this load or store: unindexed, pre-inc, pre-dec, post-inc, or post-dec.
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
unsigned getAlignment() const
void SelectFrameIndex(SDNode *N)
Hexagon target-specific information for each MachineFunction.
constexpr bool isInt< 16 >(int64_t x)
bool isInteger() const
Return true if this is an integer or a vector integer type.
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
const HexagonFrameLowering * getFrameLowering() const override
void SelectP2D(SDNode *N)
void setNodeId(int Id)
Set unique node id.
SDNode * getNode() const
get the SDNode which holds the desired result
SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
void SelectVAlignAddr(SDNode *N)
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
std::size_t countLeadingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the most significant bit to the least stopping at the first 1...
unsigned getStackAlignBaseVReg() const
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
unsigned getBitWidth() const
Return the number of bits in the APInt.
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
bool isTruncatingStore() const
Return true if the op does a truncation before store.
#define DEBUG_WITH_TYPE(TYPE, X)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
unsigned countTrailingZeros() const
Count the number of trailing zero bits.
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
bool hasOneUse() const
Return true if there is exactly one use of this node.
void SelectVAlign(SDNode *N)
A description of a memory reference used in the backend.
static ManagedStatic< DebugCounter > DC
static cl::opt< bool > RebalanceOnlyForOptimizations("rebalance-only-opt", cl::Hidden, cl::init(false), cl::desc("Rebalance address tree only if this allows optimizations"))
Shift and rotation operations.
std::size_t countTrailingOnes(T Value, ZeroBehavior ZB=ZB_Width)
Count the number of ones from the least significant bit to the first zero bit.
SDValue getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT, SDValue Operand)
A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes.
MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s), MachineInstr opcode, and operands.
const TargetLowering * TLI
static bool isTargetConstant(const SDValue &V)
uint64_t getConstantOperandVal(unsigned i) const
ISD::LoadExtType getExtensionType() const
Return whether this is a plain node, or one of the varieties of value-extending loads.
unsigned getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
void SelectTypecast(SDNode *N)
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
void SelectIndexedLoad(LoadSDNode *LD, const SDLoc &dl)
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
SDValue getEntryNode() const
Return the token chain corresponding to the entry of the function.
const DataLayout & getDataLayout() const
SDVTList getVTList(EVT VT)
Return an SDVTList that represents the list of values specified.
This class is used to represent EVT's, which are used to parameterize some operations.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
iterator_range< allnodes_iterator > allnodes()
unsigned getSizeInBits() const
unsigned getSizeInBits() const
Return the size of the specified value type in bits.
bool getBoolValue() const
Convert APInt to a boolean value.
MachineFunction & getMachineFunction() const
SDValue getTargetFrameIndex(int FI, EVT VT)
Simple integer binary arithmetic operators.
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
SDValue getTargetConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isOpaque=false)
bool SelectNewCircIntrinsic(SDNode *IntN)
Generate a machine instruction node for the new circlar buffer intrinsics.
static cl::opt< bool > EnableAddressRebalancing("isel-rebalance-addr", cl::Hidden, cl::init(true), cl::desc("Rebalance address calculation trees to improve " "instruction selection"))
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
bool SelectBrevLdIntrinsic(SDNode *IntN)
SDNode * StoreInstrForLoadIntrinsic(MachineSDNode *LoadN, SDNode *IntN)
This class is used to represent ISD::STORE nodes.
void SelectConstantFP(SDNode *N)
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
const SDValue & getBasePtr() const
initializer< Ty > init(const Ty &Val)
int64_t getOffset() const
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
std::size_t countTrailingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the least significant bit to the most stopping at the first 1...
use_iterator use_begin() const
Provide iteration support to walk over all uses of an SDNode.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
bool SelectAnyImm0(SDValue &N, SDValue &R)
bool SelectAnyInt(SDValue &N, SDValue &R)
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
const SDValue & getOperand(unsigned Num) const
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector< SDValue > &OutOps) override
SelectInlineAsmMemoryOperand - Implement addressing mode selection for inline asm expressions...
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
const SDValue & getOffset() const
void RemoveDeadNodes()
This method deletes all unreachable nodes in the SelectionDAG.
void SelectLoad(SDNode *N)
unsigned getMaxAlignment() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
bool isValidAutoIncImm(const EVT VT, const int Offset) const
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
const APInt & getAPIntValue() const
bool SelectAnyImm2(SDValue &N, SDValue &R)
FunctionPass class - This class is used to implement most global optimizations.
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
void RemoveDeadNode(SDNode *N)
Remove the specified node from the system.
void SelectQ2V(SDNode *N)
void SelectIndexedStore(StoreSDNode *ST, const SDLoc &dl)
const MachineBasicBlock & front() const
This class contains a discriminated union of information about pointers in memory operands...
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode...
unsigned getNumOperands() const
Return the number of values used by this operation.
unsigned getStackAlignment() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
static bool isOpcodeHandled(const SDNode *N)
void dump() const
Dump this node, for debugging.
bool isHVXVectorType(MVT VecTy, bool IncludeBool=false) const
bool SelectAddrGA(SDValue &N, SDValue &R)
void SelectSHL(SDNode *N)
auto size(R &&Range, typename std::enable_if< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void >::type *=nullptr) -> decltype(std::distance(Range.begin(), Range.end()))
Get the size of a range.
BlockVerifier::State From
ilist< SDNode >::size_type allnodes_size() const
SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP, uint32_t LogAlign)
unsigned estimateStackSize(const MachineFunction &MF) const
Estimate and return the size of the stack frame.
void SelectIntrinsicWChain(SDNode *N)
constexpr size_t array_lengthof(T(&)[N])
Find the length of an array.
void SelectD2P(SDNode *N)
virtual MVT getScalarShiftAmountTy(const DataLayout &, EVT) const
EVT is not used in-tree, but is used by out-of-tree target.
An SDNode that represents everything that will be needed to construct a MachineInstr.
LLVM_NODISCARD T pop_back_val()
CHAIN = SC CHAIN, Imm128 - System call.
This is an abstract virtual class for memory operations.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
void SelectConstant(SDNode *N)
Represents one node in the SelectionDAG.
allnodes_const_iterator allnodes_begin() const
const Function & getFunction() const
Return the LLVM function that this machine code represents.
bool SelectAnyImmediate(SDValue &N, SDValue &R, uint32_t LogAlign)
unsigned logBase2() const
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
size_t use_size() const
Return the number of uses of this node.
EVT getMemoryVT() const
Return the type of the in-memory value.
Class for arbitrary precision integers.
Select(COND, TRUEVAL, FALSEVAL).
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
iterator_range< user_iterator > users()
ZERO_EXTEND - Used for integer types, zeroing the new bits.
ANY_EXTEND - Used for integer types. The high bits are undefined.
static cl::opt< bool > RebalanceOnlyImbalancedTrees("rebalance-only-imbal", cl::Hidden, cl::init(false), cl::desc("Rebalance address tree only if it is imbalanced"))
void SelectStore(SDNode *N)
void SelectAddSubCarry(SDNode *N)
bool SelectAnyImm3(SDValue &N, SDValue &R)
bool SelectAnyImm1(SDValue &N, SDValue &R)
allnodes_const_iterator allnodes_end() const
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
const SDValue & getValue() const
Bitwise operators - logical and, logical or, logical xor.
SDValue getCopyFromReg(SDValue Chain, const SDLoc &dl, unsigned Reg, EVT VT)
LLVM_NODISCARD bool empty() const
bool SelectAddrGP(SDValue &N, SDValue &R)
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
APFloat abs(APFloat X)
Returns the absolute value of the argument.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
bool tryLoadOfLoadIntrinsic(LoadSDNode *N)
void SelectV65Gather(SDNode *N)
FunctionPass * createHexagonISelDag(HexagonTargetMachine &TM, CodeGenOpt::Level OptLevel)
unsigned getOpcode() const
unsigned CreateReg(MVT VT)
CreateReg - Allocate a single virtual register for the given type.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
const TargetLowering * getTargetLowering() const
bool SelectAnyImm(SDValue &N, SDValue &R)
This class is used to form a handle around another node that is persistent and is updated across invo...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SDValue getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT SVT, unsigned Alignment=0, MachineMemOperand::Flags MMOFlags=MachineMemOperand::MONone, const AAMDNodes &AAInfo=AAMDNodes())
void PreprocessISelDAG() override
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
static const Function * getParent(const Value *V)
bool isNonTemporal() const
const APFloat & getValueAPF() const
void ReplaceNode(SDNode *F, SDNode *T)
Replace all uses of F with T, then remove F from the DAG.
void SelectHVXDualOutput(SDNode *N)
virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const
Return true if folding a constant offset with the given GlobalAddress is legal.
APInt bitcastToAPInt() const
const SDValue & getOperand(unsigned i) const
uint64_t getZExtValue() const
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
MachineSDNode * LoadInstrForLoadIntrinsic(SDNode *IntN)
void Select(SDNode *N) override
Main hook for targets to transform nodes into machine nodes.
void setNodeMemRefs(MachineSDNode *N, ArrayRef< MachineMemOperand *> NewMemRefs)
Mutate the specified machine node's memory references to the provided list.
void SelectV65GatherPred(SDNode *N)
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
FunctionLoweringInfo * FuncInfo
SDValue getTargetGlobalAddress(const GlobalValue *GV, const SDLoc &DL, EVT VT, int64_t offset=0, unsigned char TargetFlags=0)
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
This class is used to represent ISD::LOAD nodes.