26 #define DEBUG_TYPE "hexagon-cext-opt" 32 cl::desc(
"Minimum number of extenders to trigger replacement"));
42 static int32_t
adjustUp(int32_t V, uint8_t A, uint8_t
O) {
44 int32_t U = (V & -A) + O;
45 return U >= V ? U : U+A;
50 int32_t U = (V & -A) + O;
51 return U <= V ? U : U-A;
59 int32_t Min = INT_MIN, Max = INT_MAX;
63 OffsetRange() =
default;
64 OffsetRange(int32_t L, int32_t
H, uint8_t A, uint8_t
O = 0)
71 if (Offset >= A.Offset && (Offset - A.Offset) % A.Align == 0) {
73 Max =
adjustDown(std::min(Max, A.Max), Align, Offset);
81 std::tie(Min, Max, Align) = std::make_tuple(0, -1, 1);
84 OffsetRange &shift(int32_t S) {
87 Offset = (Offset+S) % Align;
90 OffsetRange &extendBy(int32_t
D) {
94 Min = (INT_MIN-D < Min) ? Min+D : INT_MIN;
96 Max = (INT_MAX-D > Max) ? Max+D : INT_MAX;
103 return Min <= V && V <= Max && (V-
Offset) % Align == 0;
106 return Min == R.Min && Max == R.Max && Align == R.Align;
111 bool operator<(
const OffsetRange &R)
const {
116 return Align < R.Align;
118 static OffsetRange zero() {
return {0, 0, 1}; }
123 Node(
const OffsetRange &R) : MaxEnd(R.Max), Range(R) {}
127 const OffsetRange &Range;
131 Node *Root =
nullptr;
133 void add(
const OffsetRange &R) {
136 void erase(
const Node *
N) {
137 Root =
remove(Root,
N);
145 nodesWith(Root, P, CheckAlign, Nodes);
152 for (Node *N : Nodes)
157 void dump(
const Node *N)
const;
159 void nodesWith(Node *N, int32_t P,
bool CheckA,
162 Node *
add(Node *N,
const OffsetRange &R);
163 Node *
remove(Node *
N,
const Node *
D);
165 Node *rotateRight(Node *Lower, Node *Higher);
166 unsigned height(Node *N) {
167 return N !=
nullptr ? N->Height : 0;
169 Node *update(Node *N) {
171 N->Height = 1 +
std::max(height(N->Left), height(N->Right));
173 N->MaxEnd =
std::max(N->MaxEnd, N->Left->MaxEnd);
175 N->MaxEnd =
std::max(N->MaxEnd, N->Right->MaxEnd);
178 Node *rebalance(Node *N) {
180 int32_t Balance = height(N->Right) - height(N->Left);
182 return rotateRight(N->Left, N);
184 return rotateLeft(N->Right, N);
195 if (B->
end() == It) {
199 Pos = std::distance(B->
begin(), It);
203 if (Block != A.Block)
204 return Block->
getNumber() < A.Block->getNumber();
207 return Pos != -1 && Pos < A.Pos;
224 return "Hexagon constant-extender optimization";
231 Register(
unsigned R,
unsigned S) :
Reg(R), Sub(S) {}
238 }
else if (Op.
isFI()) {
243 bool isVReg()
const {
247 bool isSlot()
const {
265 return Reg < R.Reg || (
Reg == R.Reg && Sub < R.Sub);
267 unsigned Reg = 0, Sub = 0;
297 ExtExpr(
Register RS,
bool NG,
unsigned SH) : Rs(RS), S(SH), Neg(NG) {}
299 bool trivial()
const {
303 return Rs == Ex.Rs && S == Ex.S && Neg == Ex.Neg;
308 bool operator<(
const ExtExpr &Ex)
const {
313 return !Neg && Ex.Neg;
319 unsigned OpNum = -1u;
352 return Kind == ER.Kind && V.ImmVal == ER.V.ImmVal;
360 struct ExtValue :
public ExtRoot {
364 ExtValue(
const ExtDesc &ED) : ExtValue(ED.getOp()) {}
365 ExtValue(
const ExtRoot &ER, int32_t Off) : ExtRoot(ER),
Offset(Off) {}
366 bool operator<(
const ExtValue &EV)
const;
368 return ExtRoot(*
this) == ExtRoot(EV) && Offset == EV.Offset;
377 using ExtenderInit = std::pair<ExtValue, ExtExpr>;
378 using AssignmentMap = std::map<ExtenderInit, IndexList>;
379 using LocDefList = std::vector<std::pair<Loc, IndexList>>;
385 std::vector<ExtDesc> Extenders;
386 std::vector<unsigned> NewRegs;
388 bool isStoreImmediate(
unsigned Opc)
const;
389 bool isRegOffOpcode(
unsigned ExtOpc)
const ;
390 unsigned getRegOffOpcode(
unsigned ExtOpc)
const;
391 unsigned getDirectRegReplacement(
unsigned ExtOpc)
const;
393 OffsetRange getOffsetRange(
const ExtDesc &ED)
const;
394 OffsetRange getOffsetRange(
Register Rd)
const;
399 void assignInits(
const ExtRoot &ER,
unsigned Begin,
unsigned End,
400 AssignmentMap &IMap);
401 void calculatePlacement(
const ExtenderInit &ExtI,
const IndexList &Refs,
403 Register insertInitializer(Loc DefL,
const ExtenderInit &ExtI);
404 bool replaceInstrExact(
const ExtDesc &ED,
Register ExtR);
405 bool replaceInstrExpr(
const ExtDesc &ED,
const ExtenderInit &ExtI,
407 bool replaceInstr(
unsigned Idx,
Register ExtR,
const ExtenderInit &ExtI);
408 bool replaceExtenders(
const AssignmentMap &IMap);
416 friend struct PrintRegister;
417 friend struct PrintExpr;
418 friend struct PrintInit;
419 friend struct PrintIMap;
421 const struct PrintRegister &
P);
431 using HCE = HexagonConstExtenders;
437 OS <<
'[' << OR.Min <<
',' << OR.Max <<
"]a" <<
unsigned(OR.Align)
442 struct PrintRegister {
452 OS <<
printReg(P.Rs.Reg, &P.HRI, P.Rs.Sub);
461 const HCE::ExtExpr &Ex;
467 OS <<
"## " << (P.Ex.Neg ?
"- " :
"+ ");
468 if (P.Ex.Rs.Reg != 0)
469 OS <<
printReg(P.Ex.Rs.Reg, &P.HRI, P.Ex.Rs.Sub);
472 OS <<
" << " << P.Ex.S;
478 : ExtI(EI), HRI(I) {}
479 const HCE::ExtenderInit &ExtI;
485 OS <<
'[' << P.ExtI.first <<
", " 486 << PrintExpr(P.ExtI.second, P.HRI) <<
']';
498 OS <<
printReg(ED.Rd.Reg, &HRI, ED.Rd.Sub);
501 OS <<
" = " << PrintExpr(ED.Expr, HRI);
511 OS <<
"imm:" << ER.V.ImmVal;
514 OS <<
"fpi:" << *ER.V.CFP;
517 OS <<
"sym:" << *ER.V.SymbolName;
520 OS <<
"gad:" << ER.V.GV->getName();
523 OS <<
"blk:" << *ER.V.BA;
526 OS <<
"tgi:" << ER.V.ImmVal;
529 OS <<
"cpi:" << ER.V.ImmVal;
532 OS <<
"jti:" << ER.V.ImmVal;
535 OS <<
"???:" << ER.V.ImmVal;
543 OS << HCE::ExtRoot(EV) <<
" off:" << EV.Offset;
550 const HCE::AssignmentMap &IMap;
557 for (
const std::pair<HCE::ExtenderInit,HCE::IndexList> &Q : P.IMap) {
558 OS <<
" " << PrintInit(Q.first, P.HRI) <<
" -> {";
559 for (
unsigned I : Q.second)
569 "Hexagon constant-extender optimization",
false,
false)
580 dbgs() <<
"Root: " << Root <<
'\n';
586 dbgs() <<
"Node: " << N <<
'\n';
587 dbgs() <<
" Height: " << N->Height <<
'\n';
588 dbgs() <<
" Count: " << N->Count <<
'\n';
589 dbgs() <<
" MaxEnd: " << N->MaxEnd <<
'\n';
590 dbgs() <<
" Range: " << N->Range <<
'\n';
591 dbgs() <<
" Left: " << N->Left <<
'\n';
592 dbgs() <<
" Right: " << N->Right <<
"\n\n";
606 order(N->Right, Seq);
609 void RangeTree::nodesWith(Node *N, int32_t
P,
bool CheckA,
611 if (N ==
nullptr || N->MaxEnd < P)
613 nodesWith(N->Left, P, CheckA, Seq);
614 if (N->Range.Min <= P) {
615 if ((CheckA && N->Range.contains(P)) || (!CheckA && P <= N->Range.Max))
617 nodesWith(N->Right, P, CheckA, Seq);
631 N->Left =
add(N->Left, R);
633 N->Right =
add(N->Right, R);
634 return rebalance(update(N));
641 assert(N->Range != D->Range &&
"N and D should not be equal");
642 if (D->Range < N->Range)
643 N->Left =
remove(N->Left,
D);
645 N->Right =
remove(N->Right,
D);
646 return rebalance(update(N));
651 if (N->Left ==
nullptr || N->Right ==
nullptr)
652 return (N->Left ==
nullptr) ? N->Right : N->Left;
659 M->Left =
remove(N->Left, M);
661 return rebalance(update(M));
664 RangeTree::Node *RangeTree::rotateLeft(Node *
Lower, Node *
Higher) {
665 assert(Higher->Right == Lower);
669 if (height(Lower->Left) > height(Lower->Right))
670 Lower = rotateRight(Lower->Left, Lower);
671 assert(height(Lower->Left) <= height(Lower->Right));
672 Higher->Right = Lower->Left;
679 RangeTree::Node *RangeTree::rotateRight(Node *Lower, Node *Higher) {
680 assert(Higher->Left == Lower);
684 if (height(Lower->Left) < height(Lower->Right))
685 Lower = rotateLeft(Lower->Right, Lower);
686 assert(height(Lower->Left) >= height(Lower->Right));
687 Higher->Left = Lower->Right;
719 return Kind < ER.Kind;
725 return V.ImmVal < ER.V.ImmVal;
727 const APFloat &ThisF = V.CFP->getValueAPF();
728 const APFloat &OtherF = ER.V.CFP->getValueAPF();
738 assert(!V.GV->getName().empty() && !ER.V.GV->getName().empty());
739 return V.GV->getName() < ER.V.GV->getName();
741 const BasicBlock *ThisB = V.BA->getBasicBlock();
742 const BasicBlock *OtherB = ER.V.BA->getBasicBlock();
745 return std::distance(F.begin(), ThisB->
getIterator()) <
749 return V.ImmVal < ER.V.ImmVal;
765 const ExtRoot &ER = *
this;
766 if (!(ER == ExtRoot(EV)))
768 return Offset < EV.Offset;
797 bool HCE::isStoreImmediate(
unsigned Opc)
const {
799 case Hexagon::S4_storeirbt_io:
800 case Hexagon::S4_storeirbf_io:
801 case Hexagon::S4_storeirht_io:
802 case Hexagon::S4_storeirhf_io:
803 case Hexagon::S4_storeirit_io:
804 case Hexagon::S4_storeirif_io:
805 case Hexagon::S4_storeirb_io:
806 case Hexagon::S4_storeirh_io:
807 case Hexagon::S4_storeiri_io:
815 bool HCE::isRegOffOpcode(
unsigned Opc)
const {
817 case Hexagon::L2_loadrub_io:
818 case Hexagon::L2_loadrb_io:
819 case Hexagon::L2_loadruh_io:
820 case Hexagon::L2_loadrh_io:
821 case Hexagon::L2_loadri_io:
822 case Hexagon::L2_loadrd_io:
823 case Hexagon::L2_loadbzw2_io:
824 case Hexagon::L2_loadbzw4_io:
825 case Hexagon::L2_loadbsw2_io:
826 case Hexagon::L2_loadbsw4_io:
827 case Hexagon::L2_loadalignh_io:
828 case Hexagon::L2_loadalignb_io:
829 case Hexagon::L2_ploadrubt_io:
830 case Hexagon::L2_ploadrubf_io:
831 case Hexagon::L2_ploadrbt_io:
832 case Hexagon::L2_ploadrbf_io:
833 case Hexagon::L2_ploadruht_io:
834 case Hexagon::L2_ploadruhf_io:
835 case Hexagon::L2_ploadrht_io:
836 case Hexagon::L2_ploadrhf_io:
837 case Hexagon::L2_ploadrit_io:
838 case Hexagon::L2_ploadrif_io:
839 case Hexagon::L2_ploadrdt_io:
840 case Hexagon::L2_ploadrdf_io:
841 case Hexagon::S2_storerb_io:
842 case Hexagon::S2_storerh_io:
843 case Hexagon::S2_storerf_io:
844 case Hexagon::S2_storeri_io:
845 case Hexagon::S2_storerd_io:
846 case Hexagon::S2_pstorerbt_io:
847 case Hexagon::S2_pstorerbf_io:
848 case Hexagon::S2_pstorerht_io:
849 case Hexagon::S2_pstorerhf_io:
850 case Hexagon::S2_pstorerft_io:
851 case Hexagon::S2_pstorerff_io:
852 case Hexagon::S2_pstorerit_io:
853 case Hexagon::S2_pstorerif_io:
854 case Hexagon::S2_pstorerdt_io:
855 case Hexagon::S2_pstorerdf_io:
856 case Hexagon::A2_addi:
864 unsigned HCE::getRegOffOpcode(
unsigned ExtOpc)
const {
867 using namespace Hexagon;
869 case A2_tfrsi:
return A2_addi;
884 case L4_loadrub_ur:
return L2_loadrub_io;
887 case L4_loadrb_ur:
return L2_loadrb_io;
890 case L4_loadruh_ur:
return L2_loadruh_io;
893 case L4_loadrh_ur:
return L2_loadrh_io;
896 case L4_loadri_ur:
return L2_loadri_io;
899 case L4_loadrd_ur:
return L2_loadrd_io;
901 case L4_loadbzw2_ur:
return L2_loadbzw2_io;
903 case L4_loadbzw4_ur:
return L2_loadbzw4_io;
905 case L4_loadbsw2_ur:
return L2_loadbsw2_io;
907 case L4_loadbsw4_ur:
return L2_loadbsw4_io;
908 case L4_loadalignh_ap:
909 case L4_loadalignh_ur:
return L2_loadalignh_io;
910 case L4_loadalignb_ap:
911 case L4_loadalignb_ur:
return L2_loadalignb_io;
912 case L4_ploadrubt_abs:
return L2_ploadrubt_io;
913 case L4_ploadrubf_abs:
return L2_ploadrubf_io;
914 case L4_ploadrbt_abs:
return L2_ploadrbt_io;
915 case L4_ploadrbf_abs:
return L2_ploadrbf_io;
916 case L4_ploadruht_abs:
return L2_ploadruht_io;
917 case L4_ploadruhf_abs:
return L2_ploadruhf_io;
918 case L4_ploadrht_abs:
return L2_ploadrht_io;
919 case L4_ploadrhf_abs:
return L2_ploadrhf_io;
920 case L4_ploadrit_abs:
return L2_ploadrit_io;
921 case L4_ploadrif_abs:
return L2_ploadrif_io;
922 case L4_ploadrdt_abs:
return L2_ploadrdt_io;
923 case L4_ploadrdf_abs:
return L2_ploadrdf_io;
926 case S4_storerb_ur:
return S2_storerb_io;
929 case S4_storerh_ur:
return S2_storerh_io;
932 case S4_storerf_ur:
return S2_storerf_io;
935 case S4_storeri_ur:
return S2_storeri_io;
938 case S4_storerd_ur:
return S2_storerd_io;
939 case S4_pstorerbt_abs:
return S2_pstorerbt_io;
940 case S4_pstorerbf_abs:
return S2_pstorerbf_io;
941 case S4_pstorerht_abs:
return S2_pstorerht_io;
942 case S4_pstorerhf_abs:
return S2_pstorerhf_io;
943 case S4_pstorerft_abs:
return S2_pstorerft_io;
944 case S4_pstorerff_abs:
return S2_pstorerff_io;
945 case S4_pstorerit_abs:
return S2_pstorerit_io;
946 case S4_pstorerif_abs:
return S2_pstorerif_io;
947 case S4_pstorerdt_abs:
return S2_pstorerdt_io;
948 case S4_pstorerdf_abs:
return S2_pstorerdf_io;
954 if (!isStoreImmediate(ExtOpc))
964 unsigned HCE::getDirectRegReplacement(
unsigned ExtOpc)
const {
966 case Hexagon::A2_addi:
return Hexagon::A2_add;
967 case Hexagon::A2_andir:
return Hexagon::A2_and;
968 case Hexagon::A2_combineii:
return Hexagon::A4_combineri;
969 case Hexagon::A2_orir:
return Hexagon::A2_or;
970 case Hexagon::A2_paddif:
return Hexagon::A2_paddf;
971 case Hexagon::A2_paddit:
return Hexagon::A2_paddt;
972 case Hexagon::A2_subri:
return Hexagon::A2_sub;
973 case Hexagon::A2_tfrsi:
return TargetOpcode::COPY;
974 case Hexagon::A4_cmpbeqi:
return Hexagon::A4_cmpbeq;
975 case Hexagon::A4_cmpbgti:
return Hexagon::A4_cmpbgt;
976 case Hexagon::A4_cmpbgtui:
return Hexagon::A4_cmpbgtu;
977 case Hexagon::A4_cmpheqi:
return Hexagon::A4_cmpheq;
978 case Hexagon::A4_cmphgti:
return Hexagon::A4_cmphgt;
979 case Hexagon::A4_cmphgtui:
return Hexagon::A4_cmphgtu;
980 case Hexagon::A4_combineii:
return Hexagon::A4_combineir;
981 case Hexagon::A4_combineir:
return TargetOpcode::REG_SEQUENCE;
982 case Hexagon::A4_combineri:
return TargetOpcode::REG_SEQUENCE;
983 case Hexagon::A4_rcmpeqi:
return Hexagon::A4_rcmpeq;
984 case Hexagon::A4_rcmpneqi:
return Hexagon::A4_rcmpneq;
985 case Hexagon::C2_cmoveif:
return Hexagon::A2_tfrpf;
986 case Hexagon::C2_cmoveit:
return Hexagon::A2_tfrpt;
987 case Hexagon::C2_cmpeqi:
return Hexagon::C2_cmpeq;
988 case Hexagon::C2_cmpgti:
return Hexagon::C2_cmpgt;
989 case Hexagon::C2_cmpgtui:
return Hexagon::C2_cmpgtu;
990 case Hexagon::C2_muxii:
return Hexagon::C2_muxir;
991 case Hexagon::C2_muxir:
return Hexagon::C2_mux;
992 case Hexagon::C2_muxri:
return Hexagon::C2_mux;
993 case Hexagon::C4_cmpltei:
return Hexagon::C4_cmplte;
994 case Hexagon::C4_cmplteui:
return Hexagon::C4_cmplteu;
995 case Hexagon::C4_cmpneqi:
return Hexagon::C4_cmpneq;
996 case Hexagon::M2_accii:
return Hexagon::M2_acci;
998 case Hexagon::M2_macsip:
return Hexagon::M2_maci;
999 case Hexagon::M2_mpysin:
return Hexagon::M2_mpyi;
1000 case Hexagon::M2_mpysip:
return Hexagon::M2_mpyi;
1001 case Hexagon::M2_mpysmi:
return Hexagon::M2_mpyi;
1002 case Hexagon::M2_naccii:
return Hexagon::M2_nacci;
1003 case Hexagon::M4_mpyri_addi:
return Hexagon::M4_mpyri_addr;
1004 case Hexagon::M4_mpyri_addr:
return Hexagon::M4_mpyrr_addr;
1005 case Hexagon::M4_mpyrr_addi:
return Hexagon::M4_mpyrr_addr;
1006 case Hexagon::S4_addaddi:
return Hexagon::M2_acci;
1007 case Hexagon::S4_addi_asl_ri:
return Hexagon::S2_asl_i_r_acc;
1008 case Hexagon::S4_addi_lsr_ri:
return Hexagon::S2_lsr_i_r_acc;
1009 case Hexagon::S4_andi_asl_ri:
return Hexagon::S2_asl_i_r_and;
1010 case Hexagon::S4_andi_lsr_ri:
return Hexagon::S2_lsr_i_r_and;
1011 case Hexagon::S4_ori_asl_ri:
return Hexagon::S2_asl_i_r_or;
1012 case Hexagon::S4_ori_lsr_ri:
return Hexagon::S2_lsr_i_r_or;
1013 case Hexagon::S4_subaddi:
return Hexagon::M2_subacc;
1014 case Hexagon::S4_subi_asl_ri:
return Hexagon::S2_asl_i_r_nac;
1015 case Hexagon::S4_subi_lsr_ri:
return Hexagon::S2_lsr_i_r_nac;
1018 case Hexagon::S4_storeirbf_io:
return Hexagon::S2_pstorerbf_io;
1019 case Hexagon::S4_storeirb_io:
return Hexagon::S2_storerb_io;
1020 case Hexagon::S4_storeirbt_io:
return Hexagon::S2_pstorerbt_io;
1021 case Hexagon::S4_storeirhf_io:
return Hexagon::S2_pstorerhf_io;
1022 case Hexagon::S4_storeirh_io:
return Hexagon::S2_storerh_io;
1023 case Hexagon::S4_storeirht_io:
return Hexagon::S2_pstorerht_io;
1024 case Hexagon::S4_storeirif_io:
return Hexagon::S2_pstorerif_io;
1025 case Hexagon::S4_storeiri_io:
return Hexagon::S2_storeri_io;
1026 case Hexagon::S4_storeirit_io:
return Hexagon::S2_pstorerit_io;
1051 if (!isRegOffOpcode(Opc) || HII->isConstExtended(MI))
1052 return OffsetRange::zero();
1054 if (Opc == Hexagon::A2_addi) {
1056 if (Rb !=
Register(Op1) || !Op2.isImm())
1057 return OffsetRange::zero();
1058 OffsetRange R = { -(1<<15)+1, (1<<15)-1, 1 };
1059 return R.shift(Op2.getImm());
1063 if (HII->isPostIncrement(MI))
1064 return OffsetRange::zero();
1069 unsigned BaseP, OffP;
1070 if (!HII->getBaseAndOffsetPosition(MI, BaseP, OffP) ||
1073 return OffsetRange::zero();
1085 int32_t Max = Off >= 0 ? 0 : -Off;
1087 OffsetRange R = { Min, Max, A };
1088 return R.shift(Off);
1098 OffsetRange HCE::getOffsetRange(
const ExtDesc &ED)
const {
1102 unsigned IdxOpc = getRegOffOpcode(ED.UseMI->getOpcode());
1105 return OffsetRange::zero();
1106 case Hexagon::A2_addi:
1107 return { -32767, 32767, 1 };
1108 case Hexagon::A2_subri:
1109 return { -511, 511, 1 };
1112 if (!ED.UseMI->mayLoad() && !ED.UseMI->mayStore())
1113 return OffsetRange::zero();
1122 return { Min, Max, A };
1127 OffsetRange HCE::getOffsetRange(
Register Rd)
const {
1134 return OffsetRange::zero();
1135 Range.intersect(getOffsetRange(Rd, *Op.
getParent()));
1140 void HCE::recordExtender(
MachineInstr &MI,
unsigned OpNum) {
1155 if (IsLoad || IsStore) {
1156 unsigned AM = HII->getAddrMode(MI);
1169 if (!isStoreImmediate(Opc))
1181 case Hexagon::A2_tfrsi:
1185 case Hexagon::A2_combineii:
1186 case Hexagon::A4_combineir:
1190 case Hexagon::A4_combineri:
1194 case Hexagon::A2_addi:
1198 case Hexagon::M2_accii:
1199 case Hexagon::M2_naccii:
1200 case Hexagon::S4_addaddi:
1203 case Hexagon::A2_subri:
1208 case Hexagon::S4_subaddi:
1220 ExtRoot ER(ED.getOp());
1222 if (ER.V.GV->getName().empty())
1224 Extenders.push_back(ED);
1228 if (!HII->isConstExtended(MI))
1234 case Hexagon::M2_macsin:
1235 case Hexagon::C4_addipc:
1236 case Hexagon::S4_or_andi:
1237 case Hexagon::S4_or_andix:
1238 case Hexagon::S4_or_ori:
1241 recordExtender(MI, HII->getCExtOpNum(MI));
1248 if (MBB.getNumber() == -1)
1255 void HCE::assignInits(
const ExtRoot &ER,
unsigned Begin,
unsigned End,
1256 AssignmentMap &IMap) {
1259 for (
unsigned I = Begin;
I != End; ++
I)
1260 assert(ER == ExtRoot(Extenders[
I].getOp()));
1266 std::vector<OffsetRange> Ranges(End-Begin);
1272 for (
unsigned I = Begin;
I != End; ++
I) {
1273 const ExtDesc &ED = Extenders[
I];
1279 Ranges[
I-Begin] = getOffsetRange(ED.Rd).shift(EV.Offset);
1284 if (ED.UseMI->getOpcode() == Hexagon::A2_tfrsi) {
1286 Ranges[
I-Begin].extendBy(-D).extendBy(D);
1292 for (
unsigned I = Begin;
I != End; ++
I) {
1293 const ExtDesc &ED = Extenders[
I];
1298 OffsetRange Dev = getOffsetRange(ED);
1299 Ranges[
I-Begin].intersect(Dev.shift(EV.Offset));
1305 std::map<OffsetRange, IndexList> RangeMap;
1306 for (
unsigned I = Begin;
I != End; ++
I)
1307 RangeMap[Ranges[
I-Begin]].insert(
I);
1310 dbgs() <<
"Ranges\n";
1311 for (
unsigned I = Begin;
I != End; ++
I)
1312 dbgs() <<
" " <<
I <<
". " << Ranges[
I-Begin] <<
'\n';
1313 dbgs() <<
"RangeMap\n";
1314 for (
auto &P : RangeMap) {
1315 dbgs() <<
" " << P.first <<
" ->";
1316 for (
unsigned I : P.second)
1328 using CandData = std::pair<unsigned, SmallVector<RangeTree::Node*,8>>;
1329 std::map<int32_t, CandData> CandMap;
1332 for (
const OffsetRange &R : Ranges)
1339 for (RangeTree::Node *N : Nodes) {
1340 if (N->Range.Align <= Align || N->Range.Offset <
Offset)
1342 if ((N->Range.Offset -
Offset) % Align != 0)
1344 Align = N->Range.Align;
1345 Offset = N->Range.Offset;
1347 return std::make_pair(Align,
Offset);
1354 std::set<int32_t> CandSet;
1355 for (RangeTree::Node *N : Nodes) {
1356 const OffsetRange &R = N->Range;
1357 auto P0 = MaxAlign(Tree.nodesWith(R.Min,
false), R.Align, R.Offset);
1358 CandSet.insert(R.Min);
1359 if (R.Align < P0.first)
1360 CandSet.insert(
adjustUp(R.Min, P0.first, P0.second));
1361 auto P1 = MaxAlign(Tree.nodesWith(R.Max,
false), R.Align, R.Offset);
1362 CandSet.insert(R.Max);
1363 if (R.Align < P1.first)
1364 CandSet.insert(
adjustDown(R.Max, P1.first, P1.second));
1373 using CMap = std::map<int32_t,unsigned>;
1375 for (
auto It = CandSet.begin(), Et = CandSet.end(); It != Et; ) {
1376 auto &&V = Tree.nodesWith(*It);
1377 unsigned N = std::accumulate(V.begin(), V.end(), 0u,
1378 [](
unsigned Acc,
const RangeTree::Node *
N) {
1379 return Acc + N->Count;
1382 Counts.insert({*It, N});
1383 It = (N != 0) ? std::next(It) : CandSet.erase(It);
1389 auto BestIt = std::max_element(Counts.begin(), Counts.end(),
1390 [](
const CMap::value_type &A,
const CMap::value_type &
B) {
1391 return A.second <
B.second ||
1392 (A.second ==
B.second && A <
B);
1394 int32_t Best = BestIt->first;
1395 ExtValue BestV(ER, Best);
1396 for (RangeTree::Node *N : Tree.nodesWith(Best)) {
1397 for (
unsigned I : RangeMap[N->Range])
1398 IMap[{BestV,Extenders[
I].Expr}].insert(
I);
1403 LLVM_DEBUG(
dbgs() <<
"IMap (before fixup) = " << PrintIMap(IMap, *HRI));
1412 for (std::pair<const ExtenderInit,IndexList> &P : IMap) {
1414 if (P.first.second.trivial())
1418 const ExtValue &EV = P.first.first;
1419 AssignmentMap::iterator
F = IMap.find({EV, ExtExpr()});
1420 if (F == IMap.end())
1459 bool IsStack =
any_of(F->second, [
this](
unsigned I) {
1460 return Extenders[I].Expr.Rs.isSlot();
1462 auto SameValue = [&EV,
this,IsStack](
unsigned I) {
1463 const ExtDesc &ED = Extenders[
I];
1464 return ED.Expr.Rs.isSlot() == IsStack &&
1465 ExtValue(ED).Offset == EV.Offset;
1467 if (
all_of(P.second, SameValue)) {
1468 F->second.insert(P.second.begin(), P.second.end());
1473 LLVM_DEBUG(
dbgs() <<
"IMap (after fixup) = " << PrintIMap(IMap, *HRI));
1476 void HCE::calculatePlacement(
const ExtenderInit &ExtI,
const IndexList &Refs,
1488 const ExtDesc &ED0 = Extenders[Refs[0]];
1490 RefMIs.
insert(ED0.UseMI);
1492 for (
unsigned i = 1, e = Refs.size(); i != e; ++i) {
1493 const ExtDesc &ED = Extenders[Refs[i]];
1496 DomB = MDT->findNearestCommonDominator(DomB, MBB);
1504 const MachineInstr *DefI = Rs.isVReg() ?
MRI->getVRegDef(Rs.Reg) :
nullptr;
1512 if (Blocks.
count(DomB)) {
1515 for (It = DomB->
begin(); It != End; ++It)
1516 if (RefMIs.
count(&*It))
1518 assert(It != End &&
"Should have found a ref in DomB");
1523 Loc DefLoc(DomB, It);
1524 Defs.emplace_back(DefLoc, Refs);
1527 HCE::Register HCE::insertInitializer(Loc DefL,
const ExtenderInit &ExtI) {
1528 unsigned DefR =
MRI->createVirtualRegister(&Hexagon::IntRegsRegClass);
1531 DebugLoc dl = DefL.Block->findDebugLoc(DefL.At);
1532 const ExtValue &EV = ExtI.first;
1535 const ExtExpr &Ex = ExtI.second;
1538 if (Ex.Rs.isSlot()) {
1539 assert(Ex.S == 0 &&
"Cannot have a shift of a stack slot");
1540 assert(!Ex.Neg &&
"Cannot subtract a stack slot");
1542 InitI =
BuildMI(MBB, At, dl, HII->
get(Hexagon::PS_fi), DefR)
1546 assert((Ex.Rs.Reg == 0 || Ex.Rs.isVReg()) &&
"Expecting virtual register");
1549 InitI =
BuildMI(MBB, At, dl, HII->
get(Hexagon::A2_tfrsi), DefR)
1551 }
else if (Ex.S == 0) {
1554 InitI =
BuildMI(MBB, At, dl, HII->
get(Hexagon::A2_subri), DefR)
1559 InitI =
BuildMI(MBB, At, dl, HII->
get(Hexagon::A2_addi), DefR)
1564 unsigned NewOpc = Ex.Neg ? Hexagon::S4_subi_asl_ri
1565 : Hexagon::S4_addi_asl_ri;
1567 InitI =
BuildMI(MBB, At, dl, HII->
get(NewOpc), DefR)
1577 <<
" for initializer: " << PrintInit(ExtI, *HRI) <<
"\n " 1583 bool HCE::replaceInstrExact(
const ExtDesc &ED,
Register ExtR) {
1593 unsigned RegOpc = getDirectRegReplacement(ExtOpc);
1595 if (RegOpc == TargetOpcode::REG_SEQUENCE) {
1596 if (ExtOpc == Hexagon::A4_combineri)
1600 .addImm(Hexagon::isub_hi)
1602 .addImm(Hexagon::isub_lo);
1603 else if (ExtOpc == Hexagon::A4_combineir)
1607 .addImm(Hexagon::isub_hi)
1609 .addImm(Hexagon::isub_lo);
1615 if (ExtOpc == Hexagon::C2_cmpgei || ExtOpc == Hexagon::C2_cmpgeui) {
1616 unsigned NewOpc = ExtOpc == Hexagon::C2_cmpgei ? Hexagon::C2_cmplt
1617 : Hexagon::C2_cmpltu;
1628 unsigned RegN = ED.OpNum;
1649 unsigned RegOpc, Shift;
1650 unsigned AM = HII->getAddrMode(MI);
1652 RegOpc = HII->changeAddrMode_io_rr(ExtOpc);
1657 RegOpc = HII->changeAddrMode_ur_rr(ExtOpc);
1663 if (RegOpc == -1u) {
1664 dbgs() <<
"\nExtOpc: " << HII->getName(ExtOpc) <<
" has no rr version\n";
1669 unsigned BaseP, OffP;
1670 HII->getBaseAndOffsetPosition(MI, BaseP, OffP);
1676 MIB.
add(getLoadResultOp(MI));
1678 if (HII->isPredicated(MI))
1679 MIB.
add(getPredicateOp(MI));
1686 MIB.
add(getStoredValueOp(MI));
1700 bool HCE::replaceInstrExpr(
const ExtDesc &ED,
const ExtenderInit &ExtI,
1708 if (ExtOpc == Hexagon::A2_tfrsi) {
1717 unsigned IdxOpc = getRegOffOpcode(ExtOpc);
1718 assert(IdxOpc == Hexagon::A2_addi);
1721 int32_t D =
isInt<16>(Diff) ? Diff : (Diff > 0 ? 32767 : -32768);
1727 OffsetRange R = getOffsetRange(MI.
getOperand(0));
1740 OffsetRange Uses = getOffsetRange(MI.
getOperand(0));
1741 if (!Uses.contains(-Diff))
1742 dbgs() <<
"Diff: " << -Diff <<
" out of range " << Uses
1744 assert(Uses.contains(-Diff));
1750 const ExtValue &EV = ExtI.first; (void)EV;
1751 const ExtExpr &Ex = ExtI.second; (void)Ex;
1753 if (ExtOpc == Hexagon::A2_addi || ExtOpc == Hexagon::A2_subri) {
1758 bool IsAddi = ExtOpc == Hexagon::A2_addi;
1761 assert(Ex.Rs == RegOp && EV == ImmOp && Ex.Neg != IsAddi &&
1762 "Initializer mismatch");
1764 BuildMI(MBB, At, dl, HII->
get(TargetOpcode::COPY))
1771 if (ExtOpc == Hexagon::M2_accii || ExtOpc == Hexagon::M2_naccii ||
1772 ExtOpc == Hexagon::S4_addaddi || ExtOpc == Hexagon::S4_subaddi) {
1781 bool IsSub = ExtOpc == Hexagon::S4_subaddi;
1784 assert(EV == V && Rs == Ex.Rs && IsSub == Ex.Neg &&
"Initializer mismatch");
1786 unsigned NewOpc = ExtOpc == Hexagon::M2_naccii ? Hexagon::A2_sub
1797 unsigned IdxOpc = getRegOffOpcode(ExtOpc);
1798 assert(IdxOpc &&
"Expecting indexed opcode");
1803 MIB.
add(getLoadResultOp(MI));
1805 if (HII->isPredicated(MI))
1806 MIB.
add(getPredicateOp(MI));
1812 MIB.
add(getStoredValueOp(MI));
1819 dbgs() <<
'\n' << PrintInit(ExtI, *HRI) <<
" " <<
MI;
1825 bool HCE::replaceInstr(
unsigned Idx,
Register ExtR,
const ExtenderInit &ExtI) {
1831 const ExtDesc &ED = Extenders[Idx];
1832 assert((!ED.IsDef || ED.Rd.Reg != 0) &&
"Missing Rd for def");
1833 const ExtValue &DefV = ExtI.first;
1834 assert(ExtRoot(ExtValue(ED)) == ExtRoot(DefV) &&
"Extender root mismatch");
1835 const ExtExpr &DefEx = ExtI.second;
1838 int32_t Diff = EV.Offset - DefV.Offset;
1841 << PrintRegister(ExtR, *HRI) <<
" Diff:" << Diff <<
'\n');
1845 bool IsAbs =
false, IsAbsSet =
false;
1847 unsigned AM = HII->getAddrMode(MI);
1856 std::vector<std::pair<MachineInstr*,unsigned>> RegOps;
1857 if (ED.IsDef && Diff != 0) {
1860 RegOps.push_back({&UI, getOperandIndex(UI, Op)});
1865 bool Replaced =
false;
1866 if (Diff == 0 && DefEx.trivial() && !IsAbs && !IsAbsSet)
1867 Replaced = replaceInstrExact(ED, ExtR);
1869 Replaced = replaceInstrExpr(ED, ExtI, ExtR, Diff);
1871 if (Diff != 0 && Replaced && ED.IsDef) {
1873 for (std::pair<MachineInstr*,unsigned> P : RegOps) {
1874 unsigned J = P.second;
1875 assert(P.first->getNumOperands() > J+1 &&
1876 P.first->getOperand(J+1).isImm());
1878 ImmOp.
setImm(ImmOp.getImm() + Diff);
1885 assert(ED.Rd.Sub == 0 && ExtR.Sub == 0);
1886 MRI->replaceRegWith(ED.Rd.Reg, ExtR.Reg);
1893 bool HCE::replaceExtenders(
const AssignmentMap &IMap) {
1895 bool Changed =
false;
1897 for (
const std::pair<ExtenderInit,IndexList> &P : IMap) {
1898 const IndexList &Idxs = P.second;
1903 calculatePlacement(P.first, Idxs, Defs);
1904 for (
const std::pair<Loc,IndexList> &Q : Defs) {
1905 Register DefR = insertInitializer(Q.first, P.first);
1906 NewRegs.push_back(DefR.Reg);
1907 for (
unsigned I : Q.second)
1908 Changed |= replaceInstr(I, DefR, P.first);
1923 assert(HII->isPredicated(MI));
1926 MRI->getRegClass(Op.
getReg()) != &Hexagon::PredRegsRegClass)
1928 assert(Op.
getSubReg() == 0 &&
"Predicate register with a subregister");
1949 <<
" due to exception handling\n");
1956 MDT = &getAnalysis<MachineDominatorTree>();
1961 llvm::sort(Extenders, [
this](
const ExtDesc &A,
const ExtDesc &
B) {
1962 ExtValue VA(A),
VB(B);
1969 return A.OpNum < B.OpNum;
1977 return MDT->dominates(MA, MB);
1980 bool Changed =
false;
1981 LLVM_DEBUG(
dbgs() <<
"Collected " << Extenders.size() <<
" extenders\n");
1982 for (
unsigned I = 0,
E = Extenders.size();
I !=
E; ) {
1984 const ExtRoot &
T = Extenders[
B].getOp();
1985 while (
I !=
E && ExtRoot(Extenders[
I].getOp()) == T)
1989 assignInits(T, B,
I, IMap);
1990 Changed |= replaceExtenders(IMap);
1995 MF.
print(
dbgs() <<
"After " << getPassName() <<
'\n',
nullptr);
1997 dbgs() <<
"No changes\n";
2003 return new HexagonConstExtenders();
unsigned getTargetFlags() const
const MachineInstrBuilder & add(const MachineOperand &MO) const
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
This class represents lattice values for constants.
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
bool isTargetIndex() const
isTargetIndex - Tests if this is a MO_TargetIndex operand.
Implements a dense probed hash-table based set.
void push_back(const T &Elt)
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
static MachineOperand CreateJTI(unsigned Idx, unsigned char TargetFlags=0)
Describe properties that are true of each instruction in the target description file.
unsigned getReg() const
getReg - Returns the register number.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
Address of indexed Jump Table for switch.
unsigned getSubReg() const
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly...
static void dump(StringRef Title, SpillInfo const &Spills)
constexpr bool isInt< 16 >(int64_t x)
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
bool mayLoad() const
Return true if this instruction could possibly read memory.
iterator_range< mop_iterator > operands()
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
return AArch64::GPR64RegClass contains(Reg)
static MachineOperand CreateReg(unsigned Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
static int stackSlot2Index(unsigned Reg)
Compute the frame index from a register value representing a stack slot.
The address of a basic block.
uint64_t alignDown(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the largest uint64_t less than or equal to Value and is Skew mod Align.
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const ConstantFP * getFPImm() const
unsigned getNumOperands() const
Retuns the total number of operands.
Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
Target-dependent index+offset operand.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Name of external global symbol.
static int32_t adjustUp(int32_t V, uint8_t A, uint8_t O)
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const char * getSymbolName() const
void initializeHexagonConstExtendersPass(PassRegistry &)
static cl::opt< unsigned > CountThreshold("hexagon-cext-threshold", cl::init(3), cl::Hidden, cl::ZeroOrMore, cl::desc("Minimum number of extenders to trigger replacement"))
FunctionPass * createHexagonConstExtenders()
bool isFPImm() const
isFPImm - Tests if this is a MO_FPImmediate operand.
bool hasPersonalityFn() const
Check whether this function has a personality function.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata *> MDs)
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
Address of a global value.
initializer< Ty > init(const Ty &Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
unsigned const MachineRegisterInfo * MRI
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...
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
static MachineOperand CreateCPI(unsigned Idx, int Offset, unsigned char TargetFlags=0)
LLVM Basic Block Representation.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
static MachineOperand CreateFPImm(const ConstantFP *CFP)
bool ult(const APInt &RHS) const
Unsigned less than comparison.
MachineInstrBuilder & UseMI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const GlobalValue * getGlobal() const
std::pair< iterator, bool > insert(const ValueT &V)
static ManagedStatic< OptionRegistry > OR
ConstantFP - Floating Point Values [float, double].
static MachineOperand CreateBA(const BlockAddress *BA, int64_t Offset, unsigned char TargetFlags=0)
Represent the analysis usage information of a pass.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly...
Address of a basic block.
void setImm(int64_t immVal)
static MachineOperand CreateGA(const GlobalValue *GV, int64_t Offset, unsigned char TargetFlags=0)
static MachineOperand CreateTargetIndex(unsigned Idx, int64_t Offset, unsigned char TargetFlags=0)
FunctionPass class - This class is used to implement most global optimizations.
self_iterator getIterator()
void print(raw_ostream &OS, const SlotIndexes *=nullptr) const
print - Print out the MachineFunction in a format suitable for debugging to the specified stream...
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
void sort(IteratorTy Start, IteratorTy End)
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
static bool isStackSlot(unsigned Reg)
isStackSlot - Sometimes it is useful the be able to store a non-negative frame index in a variable th...
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
hexagon cext Hexagon constant extender optimization
Promote Memory to Register
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
bool isBlockAddress() const
isBlockAddress - Tests if this is a MO_BlockAddress operand.
const Function & getFunction() const
Return the LLVM function that this machine code represents.
static int32_t adjustDown(int32_t V, uint8_t A, uint8_t O)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static MachineOperand CreateES(const char *SymName, unsigned char TargetFlags=0)
static LLVM_ATTRIBUTE_UNUSED unsigned getMemAccessSizeInBytes(MemAccessSize S)
bool mayStore() const
Return true if this instruction could possibly modify memory.
const MachineBasicBlock * getParent() const
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
bool operator!=(uint64_t V1, const APInt &V2)
Representation of each machine instruction.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
static ValueLatticeElement intersect(const ValueLatticeElement &A, const ValueLatticeElement &B)
Combine two sets of facts about the same value into a single set of facts.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
int64_t getOffset() const
Return the offset from the symbol in this operand.
const Function * getParent() const
Return the enclosing method, or null if none.
const BlockAddress * getBlockAddress() const
static MachineOperand CreateImm(int64_t Val)
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
hexagon cext Hexagon constant extender static false unsigned ReplaceCounter
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
static cl::opt< unsigned > ReplaceLimit("hexagon-cext-limit", cl::init(0), cl::Hidden, cl::ZeroOrMore, cl::desc("Maximum number of replacements"))
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
raw_ostream & operator<<(raw_ostream &OS, const APInt &I)
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool operator<(int64_t V1, const APSInt &V2)
INITIALIZE_PASS_BEGIN(HexagonConstExtenders, "hexagon-cext-opt", "Hexagon constant-extender optimization", false, false) INITIALIZE_PASS_END(HexagonConstExtenders
Floating-point immediate operand.
A vector that has set insertion semantics.
This class implements an extremely fast bulk output stream that can only output to a stream...
StringRef - Represent a constant reference to a string, i.e.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
APInt bitcastToAPInt() const
Address of indexed Constant in Constant Pool.
#define LLVM_ATTRIBUTE_UNUSED
bool operator==(uint64_t V1, const APInt &V2)
const MachineOperand & getOperand(unsigned i) const
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
static MachineOperand CreateFI(int Idx)
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
static unsigned index2StackSlot(int FI)
Convert a non-negative frame index to a stack slot register value.