46#define DEBUG_TYPE "hcp"
58 class ConstantProperties {
68 NumericProperties = (Zero|NonZero|Finite|Infinity|NaN|SignedZero),
71 SignProperties = (PosOrZero|NegOrZero),
72 Everything = (NumericProperties|SignProperties)
91 enum { Normal, Top, Bottom };
93 static const unsigned MaxCellSize = 4;
104 const Constant *Values[MaxCellSize];
107 LatticeCell() : Kind(Top), Size(0), IsSpecial(
false) {
111 bool meet(
const LatticeCell &L);
115 unsigned size()
const {
return Size; }
117 LatticeCell(
const LatticeCell &L) {
120 L.IsSpecial ?
sizeof L.Properties : L.Size *
sizeof(
const Constant *);
121 memcpy(Values, L.Values,
N);
124 IsSpecial = L.IsSpecial;
127 LatticeCell &operator=(
const LatticeCell &L) {
130 uint32_t N = L.IsSpecial ?
sizeof L.Properties
131 : L.Size *
sizeof(
const Constant *);
132 memcpy(Values, L.Values,
N);
135 IsSpecial = L.IsSpecial;
140 bool isSingle()
const {
return size() == 1; }
141 bool isProperty()
const {
return IsSpecial; }
142 bool isTop()
const {
return Kind == Top; }
143 bool isBottom()
const {
return Kind == Bottom; }
146 bool Changed = (Kind != Bottom);
162 bool convertToProperty();
172 class MachineConstEvaluator;
174 class MachineConstPropagator {
176 MachineConstPropagator(MachineConstEvaluator &E) : MCE(E) {
197 void clear() { Map.clear(); }
203 MapType::const_iterator
F = Map.find(R);
204 return F != Map.end();
210 MapType::const_iterator
F = Map.find(R);
217 void update(
Register R,
const LatticeCell &L) { Map[R] = L; }
222 using MapType = std::map<Register, LatticeCell>;
228 LatticeCell Top, Bottom;
243 void visitUsesOf(
unsigned R);
252 MachineConstEvaluator &MCE;
254 using CFGEdge = std::pair<unsigned, unsigned>;
255 using SetOfCFGEdge = std::set<CFGEdge>;
256 using SetOfInstr = std::set<const MachineInstr *>;
257 using QueueOfCFGEdge = std::queue<CFGEdge>;
261 SetOfCFGEdge EdgeExec;
262 SetOfInstr InstrExec;
263 QueueOfCFGEdge FlowQ;
269 class MachineConstEvaluator {
274 virtual ~MachineConstEvaluator() =
default;
291 using CellMap = MachineConstPropagator::CellMap;
293 CellMap &Outputs) = 0;
295 LatticeCell &Result) = 0;
298 bool &CanFallThru) = 0;
299 virtual bool rewrite(
MachineInstr &
MI,
const CellMap &Inputs) = 0;
347 const CellMap &Inputs,
bool &Result);
349 const CellMap &Inputs,
bool &Result);
357 bool evaluateCOPY(
const RegSubRegPair &R1,
const CellMap &Inputs,
358 LatticeCell &Result);
362 const CellMap &Inputs, LatticeCell &Result);
364 const CellMap &Inputs, LatticeCell &Result);
367 const CellMap &Inputs, LatticeCell &Result);
369 const CellMap &Inputs, LatticeCell &Result);
372 const CellMap &Inputs, LatticeCell &Result);
374 const CellMap &Inputs, LatticeCell &Result);
378 bool evaluateZEXTr(
const RegSubRegPair &R1,
unsigned Width,
unsigned Bits,
379 const CellMap &Inputs, LatticeCell &Result);
380 bool evaluateZEXTi(
const APInt &A1,
unsigned Width,
unsigned Bits,
382 bool evaluateSEXTr(
const RegSubRegPair &R1,
unsigned Width,
unsigned Bits,
383 const CellMap &Inputs, LatticeCell &Result);
384 bool evaluateSEXTi(
const APInt &A1,
unsigned Width,
unsigned Bits,
388 bool evaluateCLBr(
const RegSubRegPair &R1,
bool Zeros,
bool Ones,
389 const CellMap &Inputs, LatticeCell &Result);
390 bool evaluateCLBi(
const APInt &A1,
bool Zeros,
bool Ones,
APInt &Result);
391 bool evaluateCTBr(
const RegSubRegPair &R1,
bool Zeros,
bool Ones,
392 const CellMap &Inputs, LatticeCell &Result);
393 bool evaluateCTBi(
const APInt &A1,
bool Zeros,
bool Ones,
APInt &Result);
396 bool evaluateEXTRACTr(
const RegSubRegPair &R1,
unsigned Width,
398 const CellMap &Inputs, LatticeCell &Result);
399 bool evaluateEXTRACTi(
const APInt &A1,
unsigned Bits,
unsigned Offset,
402 bool evaluateSplatr(
const RegSubRegPair &R1,
unsigned Bits,
unsigned Count,
403 const CellMap &Inputs, LatticeCell &Result);
404 bool evaluateSplati(
const APInt &A1,
unsigned Bits,
unsigned Count,
411 if (isa<ConstantInt>(
C)) {
414 return Zero | PosOrZero | NegOrZero | Finite;
415 uint32_t Props = (NonZero | Finite);
417 return Props | NegOrZero;
418 return Props | PosOrZero;
421 if (isa<ConstantFP>(
C)) {
426 return (Props & ~NumericProperties) | (
Zero|Finite);
427 Props = (Props & ~NumericProperties) | NonZero;
429 return (Props & ~NumericProperties) | NaN;
432 return (Props & ~NumericProperties) | Infinity;
442bool LatticeCell::convertToProperty() {
447 uint32_t Everything = ConstantProperties::Everything;
448 uint32_t Ps = !isTop() ? properties()
450 if (Ps != ConstantProperties::Unknown) {
464 if (Ps & ConstantProperties::Zero)
466 if (Ps & ConstantProperties::NonZero)
468 if (Ps & ConstantProperties::Finite)
470 if (Ps & ConstantProperties::Infinity)
472 if (Ps & ConstantProperties::NaN)
474 if (Ps & ConstantProperties::PosOrZero)
476 if (Ps & ConstantProperties::NegOrZero)
485 }
else if (isTop()) {
488 for (
unsigned i = 0; i <
size(); ++i) {
501bool LatticeCell::meet(
const LatticeCell &L) {
502 bool Changed =
false;
504 Changed = setBottom();
505 if (isBottom() ||
L.isTop())
515 return add(
L.properties());
516 for (
unsigned i = 0; i <
L.size(); ++i) {
528bool LatticeCell::add(
const Constant *LC) {
537 while (Index <
Size) {
544 if (Index < MaxCellSize) {
552 bool Changed =
false;
556 Changed = convertToProperty();
558 uint32_t NewPs = Ps & ConstantProperties::deduce(LC);
559 if (NewPs == ConstantProperties::Unknown) {
572bool LatticeCell::add(
uint32_t Property) {
573 bool Changed = convertToProperty();
575 if (Ps == (Ps & Property))
577 Properties = Property & Ps;
583uint32_t LatticeCell::properties()
const {
586 assert(!isTop() &&
"Should not call this for a top cell");
588 return ConstantProperties::Unknown;
591 uint32_t Ps = ConstantProperties::deduce(Values[0]);
592 for (
unsigned i = 1; i <
size(); ++i) {
593 if (Ps == ConstantProperties::Unknown)
595 Ps &= ConstantProperties::deduce(Values[i]);
601void MachineConstPropagator::CellMap::print(
raw_ostream &os,
608void MachineConstPropagator::visitPHI(
const MachineInstr &PN) {
615 assert(DefR.Reg.isVirtual());
617 bool Changed =
false;
622 const LatticeCell &
T = Cells.get(DefR.Reg);
623 Changed = !
T.isBottom();
624 Cells.update(DefR.Reg, Bottom);
626 visitUsesOf(DefR.Reg);
630 LatticeCell DefC = Cells.get(DefR.Reg);
634 unsigned PBN =
PB->getNumber();
635 if (!EdgeExec.count(CFGEdge(PBN, MBN))) {
644 if (!UseR.Reg.isVirtual())
647 if (!Cells.has(UseR.Reg))
651 bool Eval = MCE.evaluate(UseR, Cells.get(UseR.Reg), SrcC);
653 <<
printReg(UseR.Reg, &MCE.TRI, UseR.SubReg) << SrcC
655 Changed |= Eval ? DefC.meet(SrcC)
657 Cells.update(DefR.Reg, DefC);
662 visitUsesOf(DefR.Reg);
665void MachineConstPropagator::visitNonBranch(
const MachineInstr &
MI) {
669 bool Eval = MCE.evaluate(
MI, Cells, Outputs);
672 dbgs() <<
" outputs:";
673 for (
auto &
I : Outputs)
674 dbgs() <<
' ' <<
I.second;
682 if (!MO.isReg() || !MO.isDef())
686 if (!DefR.Reg.isVirtual())
688 bool Changed =
false;
691 const LatticeCell &
T = Cells.get(DefR.Reg);
692 Changed = !
T.isBottom();
693 Cells.update(DefR.Reg, Bottom);
697 if (!Outputs.has(DefR.Reg))
699 LatticeCell RC = Cells.get(DefR.Reg);
700 Changed = RC.meet(Outputs.get(DefR.Reg));
701 Cells.update(DefR.Reg, RC);
704 visitUsesOf(DefR.Reg);
712void MachineConstPropagator::visitBranchesFrom(
const MachineInstr &BrI) {
714 unsigned MBN =
B.getNumber();
719 bool EvalOk =
true, FallsThru =
true;
722 InstrExec.insert(&
MI);
728 EvalOk = EvalOk && MCE.evaluate(
MI, Cells, Targets, FallsThru);
736 if (
B.mayHaveInlineAsmBr())
751 if (Next != MF.
end())
761 LLVM_DEBUG(
dbgs() <<
" failed to evaluate a branch...adding all CFG "
767 unsigned TBN =
TB->getNumber();
770 FlowQ.push(CFGEdge(MBN, TBN));
774void MachineConstPropagator::visitUsesOf(
unsigned Reg) {
776 << Cells.get(Reg) <<
'\n');
781 if (!InstrExec.count(&
MI))
785 else if (!
MI.isBranch())
788 visitBranchesFrom(
MI);
798 if (
MI.getOpcode() == TargetOpcode::INLINEASM_BR)
800 if (
MI.isDebugInstr())
803 FirstBr =
MI.getIterator();
814 if (
MI.isDebugInstr())
816 if (!InstrExec.count(&
MI))
818 bool Eval = MCE.evaluate(
MI, Cells, Targets, DoNext);
828 if (NextI != MB->getParent()->end())
843 From->removeSuccessor(To);
860 unsigned EntryNum =
Entry->getNumber();
863 FlowQ.push(CFGEdge(EntryNum, EntryNum));
865 while (!FlowQ.empty()) {
866 CFGEdge
Edge = FlowQ.front();
870 dbgs() <<
"Picked edge "
873 if (
Edge.first != EntryNum)
874 if (EdgeExec.count(Edge))
876 EdgeExec.insert(Edge);
886 while (It !=
End && It->isPHI()) {
887 InstrExec.insert(&*It);
895 while (It !=
End && It->isDebugInstr())
899 if (It !=
End && InstrExec.count(&*It))
903 while (It !=
End && !It->isBranch()) {
904 if (!It->isDebugInstr()) {
905 InstrExec.insert(&*It);
916 visitBranchesFrom(*It);
922 FlowQ.push(CFGEdge(SBN, SSB->getNumber()));
927 dbgs() <<
"Cells after propagation:\n";
928 Cells.print(
dbgs(), MCE.TRI);
929 dbgs() <<
"Dead CFG edges:\n";
931 unsigned BN =
B.getNumber();
934 if (!EdgeExec.count(CFGEdge(BN, SN)))
943 bool Changed =
false;
960 std::vector<MachineBasicBlock*> POT;
974 bool HaveTargets = computeBlockSuccessors(
B, Targets);
978 if (InstrExec.count(&
MI)) {
979 if (
MI.isBranch() && !HaveTargets)
981 Changed |= MCE.rewrite(
MI, Cells);
987 for (
auto I =
B->begin(), E =
B->end();
I != E; ++
I) {
1007 if (!Targets.
count(SB))
1012 removeCFGEdge(
B,
MBB);
1027 if (
MI.isBranch() && !InstrExec.count(&
MI))
1046 bool Changed = rewrite(MF);
1049 dbgs() <<
"End of MachineConstPropagator (Changed=" << Changed <<
")\n";
1060 const CellMap &Inputs, LatticeCell &RC) {
1061 if (!
R.Reg.isVirtual())
1063 const LatticeCell &
L = Inputs.get(
R.Reg);
1066 return !RC.isBottom();
1069 return Eval && !RC.isBottom();
1072bool MachineConstEvaluator::constToInt(
const Constant *
C,
1081const ConstantInt *MachineConstEvaluator::intToConst(
const APInt &Val)
const {
1082 return ConstantInt::get(CX, Val);
1087 const CellMap &Inputs,
bool &Result) {
1089 LatticeCell LS1, LS2;
1090 if (!getCell(R1, Inputs, LS1) || !getCell(
R2, Inputs, LS2))
1093 bool IsProp1 = LS1.isProperty();
1094 bool IsProp2 = LS2.isProperty();
1098 return evaluateCMPpp(Cmp, Prop1, LS2.properties(), Result);
1099 uint32_t NegCmp = Comparison::negate(Cmp);
1100 return evaluateCMPrp(NegCmp,
R2, Prop1, Inputs, Result);
1104 return evaluateCMPrp(Cmp, R1, Prop2, Inputs, Result);
1108 bool IsTrue =
true, IsFalse =
true;
1109 for (
unsigned i = 0; i < LS2.size(); ++i) {
1111 bool Computed = constToInt(LS2.Values[i],
A) &&
1112 evaluateCMPri(Cmp, R1,
A, Inputs, Res);
1118 assert(!IsTrue || !IsFalse);
1122 return IsTrue || IsFalse;
1127 const CellMap &Inputs,
bool &Result) {
1130 if (!getCell(R1, Inputs, LS))
1132 if (
LS.isProperty())
1133 return evaluateCMPpi(Cmp,
LS.properties(), A2, Result);
1136 bool IsTrue =
true, IsFalse =
true;
1137 for (
unsigned i = 0; i <
LS.size(); ++i) {
1139 bool Computed = constToInt(
LS.Values[i],
A) &&
1140 evaluateCMPii(Cmp,
A, A2, Res);
1146 assert(!IsTrue || !IsFalse);
1150 return IsTrue || IsFalse;
1155 const CellMap &Inputs,
bool &Result) {
1158 if (!getCell(R1, Inputs, LS))
1160 if (
LS.isProperty())
1161 return evaluateCMPpp(Cmp,
LS.properties(), Props2, Result);
1164 uint32_t NegCmp = Comparison::negate(Cmp);
1165 bool IsTrue =
true, IsFalse =
true;
1166 for (
unsigned i = 0; i <
LS.size(); ++i) {
1168 bool Computed = constToInt(
LS.Values[i],
A) &&
1169 evaluateCMPpi(NegCmp, Props2,
A, Res);
1175 assert(!IsTrue || !IsFalse);
1177 return IsTrue || IsFalse;
1180bool MachineConstEvaluator::evaluateCMPii(
uint32_t Cmp,
const APInt &A1,
1181 const APInt &A2,
bool &Result) {
1183 if (Cmp == Comparison::NE) {
1187 if (Cmp == Comparison::EQ) {
1191 if (Cmp & Comparison::EQ) {
1193 return (Result =
true);
1195 assert((Cmp & (Comparison::L | Comparison::G)) &&
"Malformed comparison");
1200 unsigned MaxW = (W1 >= W2) ? W1 : W2;
1201 if (Cmp & Comparison::U) {
1204 if (Cmp & Comparison::L)
1206 else if (Cmp & Comparison::G)
1214 if (Cmp & Comparison::L)
1216 else if (Cmp & Comparison::G)
1222 const APInt &A2,
bool &Result) {
1223 if (Props == ConstantProperties::Unknown)
1227 if (Props & ConstantProperties::NaN)
1232 if (!(Props & ConstantProperties::Finite))
1237 if (Cmp & Comparison::U) {
1241 if (Props & ConstantProperties::Zero)
1243 else if (Props & ConstantProperties::NonZero)
1244 Result = (
Cmp & Comparison::G) || (Cmp == Comparison::NE);
1250 if (Props & ConstantProperties::Zero) {
1251 Result = (
Cmp & Comparison::L) || (Cmp == Comparison::NE);
1258 if (Props & ConstantProperties::Zero) {
1263 ((Cmp & Comparison::L) && !A2.
isNegative()) ||
1267 if (Props & ConstantProperties::PosOrZero) {
1272 Result = (
Cmp & Comparison::G) || (Cmp == Comparison::NE);
1275 if (Props & ConstantProperties::NegOrZero) {
1280 Result = (
Cmp & Comparison::L) || (Cmp == Comparison::NE);
1289 using P = ConstantProperties;
1291 if ((Props1 & P::NaN) && (Props2 & P::NaN))
1293 if (!(Props1 & P::Finite) || !(Props2 & P::Finite))
1296 bool Zero1 = (Props1 & P::Zero), Zero2 = (Props2 & P::Zero);
1297 bool NonZero1 = (Props1 & P::NonZero), NonZero2 = (Props2 & P::NonZero);
1298 if (Zero1 && Zero2) {
1302 if (Cmp == Comparison::NE) {
1303 if ((Zero1 && NonZero2) || (NonZero1 && Zero2))
1304 return (Result =
true);
1308 if (Cmp & Comparison::U) {
1311 if (Zero1 && NonZero2) {
1315 if (NonZero1 && Zero2) {
1323 bool Poz1 = (Props1 & P::PosOrZero), Poz2 = (Props2 & P::PosOrZero);
1324 bool Nez1 = (Props1 & P::NegOrZero), Nez2 = (Props2 & P::NegOrZero);
1326 if (NonZero1 || NonZero2) {
1331 if ((Cmp & Comparison::EQ) && (
Cmp & Comparison::L))
1332 return (Result =
true);
1335 if (NonZero1 || NonZero2) {
1340 if ((Cmp & Comparison::EQ) && (
Cmp & Comparison::G))
1341 return (Result =
true);
1347bool MachineConstEvaluator::evaluateCOPY(
const RegSubRegPair &R1,
1348 const CellMap &Inputs,
1349 LatticeCell &Result) {
1350 return getCell(R1, Inputs, Result);
1353bool MachineConstEvaluator::evaluateANDrr(
const RegSubRegPair &R1,
1355 const CellMap &Inputs,
1356 LatticeCell &Result) {
1358 const LatticeCell &L1 = Inputs.get(
R2.Reg);
1359 const LatticeCell &L2 = Inputs.get(
R2.Reg);
1363 if (L2.isBottom()) {
1366 return evaluateANDrr(
R2, R1, Inputs, Result);
1371 if (LS2.isBottom() || LS2.isProperty())
1375 for (
unsigned i = 0; i < LS2.size(); ++i) {
1377 bool Eval = constToInt(LS2.Values[i],
A) &&
1378 evaluateANDri(R1,
A, Inputs, RC);
1383 return !
Result.isBottom();
1386bool MachineConstEvaluator::evaluateANDri(
const RegSubRegPair &R1,
1388 const CellMap &Inputs,
1389 LatticeCell &Result) {
1392 return getCell(R1, Inputs, Result);
1395 RC.add(intToConst(A2));
1401 if (!getCell(R1, Inputs, LS1))
1403 if (LS1.isBottom() || LS1.isProperty())
1407 for (
unsigned i = 0; i < LS1.size(); ++i) {
1408 bool Eval = constToInt(LS1.Values[i],
A) &&
1409 evaluateANDii(
A, A2, ResA);
1415 return !
Result.isBottom();
1418bool MachineConstEvaluator::evaluateANDii(
const APInt &A1,
1424bool MachineConstEvaluator::evaluateORrr(
const RegSubRegPair &R1,
1426 const CellMap &Inputs,
1427 LatticeCell &Result) {
1429 const LatticeCell &L1 = Inputs.get(
R2.Reg);
1430 const LatticeCell &L2 = Inputs.get(
R2.Reg);
1434 if (L2.isBottom()) {
1437 return evaluateORrr(
R2, R1, Inputs, Result);
1442 if (LS2.isBottom() || LS2.isProperty())
1446 for (
unsigned i = 0; i < LS2.size(); ++i) {
1448 bool Eval = constToInt(LS2.Values[i],
A) &&
1449 evaluateORri(R1,
A, Inputs, RC);
1454 return !
Result.isBottom();
1457bool MachineConstEvaluator::evaluateORri(
const RegSubRegPair &R1,
1458 const APInt &A2,
const CellMap &Inputs,
1459 LatticeCell &Result) {
1462 return getCell(R1, Inputs, Result);
1465 RC.add(intToConst(A2));
1471 if (!getCell(R1, Inputs, LS1))
1473 if (LS1.isBottom() || LS1.isProperty())
1477 for (
unsigned i = 0; i < LS1.size(); ++i) {
1478 bool Eval = constToInt(LS1.Values[i],
A) &&
1479 evaluateORii(
A, A2, ResA);
1485 return !
Result.isBottom();
1488bool MachineConstEvaluator::evaluateORii(
const APInt &A1,
1494bool MachineConstEvaluator::evaluateXORrr(
const RegSubRegPair &R1,
1496 const CellMap &Inputs,
1497 LatticeCell &Result) {
1499 LatticeCell LS1, LS2;
1500 if (!getCell(R1, Inputs, LS1) || !getCell(
R2, Inputs, LS2))
1502 if (LS1.isProperty()) {
1503 if (LS1.properties() & ConstantProperties::Zero)
1504 return !(
Result = LS2).isBottom();
1507 if (LS2.isProperty()) {
1508 if (LS2.properties() & ConstantProperties::Zero)
1509 return !(Result = LS1).isBottom();
1514 for (
unsigned i = 0; i < LS2.size(); ++i) {
1516 bool Eval = constToInt(LS2.Values[i],
A) &&
1517 evaluateXORri(R1,
A, Inputs, RC);
1522 return !
Result.isBottom();
1525bool MachineConstEvaluator::evaluateXORri(
const RegSubRegPair &R1,
1527 const CellMap &Inputs,
1528 LatticeCell &Result) {
1531 if (!getCell(R1, Inputs, LS1))
1533 if (LS1.isProperty()) {
1534 if (LS1.properties() & ConstantProperties::Zero) {
1537 return !
Result.isBottom();
1543 for (
unsigned i = 0; i < LS1.size(); ++i) {
1544 bool Eval = constToInt(LS1.Values[i],
A) &&
1545 evaluateXORii(
A, A2, XA);
1551 return !
Result.isBottom();
1554bool MachineConstEvaluator::evaluateXORii(
const APInt &A1,
1560bool MachineConstEvaluator::evaluateZEXTr(
const RegSubRegPair &R1,
1561 unsigned Width,
unsigned Bits,
1562 const CellMap &Inputs,
1563 LatticeCell &Result) {
1566 if (!getCell(R1, Inputs, LS1))
1568 if (LS1.isProperty())
1572 for (
unsigned i = 0; i < LS1.size(); ++i) {
1573 bool Eval = constToInt(LS1.Values[i],
A) &&
1574 evaluateZEXTi(
A, Width, Bits, XA);
1583bool MachineConstEvaluator::evaluateZEXTi(
const APInt &A1,
unsigned Width,
1584 unsigned Bits,
APInt &Result) {
1587 assert(Width >= Bits && BW >= Bits);
1593bool MachineConstEvaluator::evaluateSEXTr(
const RegSubRegPair &R1,
1594 unsigned Width,
unsigned Bits,
1595 const CellMap &Inputs,
1596 LatticeCell &Result) {
1599 if (!getCell(R1, Inputs, LS1))
1601 if (LS1.isBottom() || LS1.isProperty())
1605 for (
unsigned i = 0; i < LS1.size(); ++i) {
1606 bool Eval = constToInt(LS1.Values[i],
A) &&
1607 evaluateSEXTi(
A, Width, Bits, XA);
1616bool MachineConstEvaluator::evaluateSEXTi(
const APInt &A1,
unsigned Width,
1617 unsigned Bits,
APInt &Result) {
1619 assert(Width >= Bits && BW >= Bits);
1628 if (BW <= 64 && Bits != 0) {
1632 V =
static_cast<int8_t
>(
V);
1635 V =
static_cast<int16_t
>(
V);
1638 V =
static_cast<int32_t
>(
V);
1660bool MachineConstEvaluator::evaluateCLBr(
const RegSubRegPair &R1,
bool Zeros,
1661 bool Ones,
const CellMap &Inputs,
1662 LatticeCell &Result) {
1665 if (!getCell(R1, Inputs, LS1))
1667 if (LS1.isBottom() || LS1.isProperty())
1671 for (
unsigned i = 0; i < LS1.size(); ++i) {
1672 bool Eval = constToInt(LS1.Values[i],
A) &&
1673 evaluateCLBi(
A, Zeros, Ones, CA);
1682bool MachineConstEvaluator::evaluateCLBi(
const APInt &A1,
bool Zeros,
1683 bool Ones,
APInt &Result) {
1685 if (!Zeros && !Ones)
1688 if (Zeros && (Count == 0))
1690 if (Ones && (Count == 0))
1696bool MachineConstEvaluator::evaluateCTBr(
const RegSubRegPair &R1,
bool Zeros,
1697 bool Ones,
const CellMap &Inputs,
1698 LatticeCell &Result) {
1701 if (!getCell(R1, Inputs, LS1))
1703 if (LS1.isBottom() || LS1.isProperty())
1707 for (
unsigned i = 0; i < LS1.size(); ++i) {
1708 bool Eval = constToInt(LS1.Values[i],
A) &&
1709 evaluateCTBi(
A, Zeros, Ones, CA);
1718bool MachineConstEvaluator::evaluateCTBi(
const APInt &A1,
bool Zeros,
1719 bool Ones,
APInt &Result) {
1721 if (!Zeros && !Ones)
1724 if (Zeros && (Count == 0))
1726 if (Ones && (Count == 0))
1732bool MachineConstEvaluator::evaluateEXTRACTr(
const RegSubRegPair &R1,
1733 unsigned Width,
unsigned Bits,
1735 const CellMap &Inputs,
1736 LatticeCell &Result) {
1740 if (!getCell(R1, Inputs, LS1))
1744 if (LS1.isProperty()) {
1746 if (Ps & ConstantProperties::Zero) {
1755 for (
unsigned i = 0; i < LS1.size(); ++i) {
1756 bool Eval = constToInt(LS1.Values[i],
A) &&
1766bool MachineConstEvaluator::evaluateEXTRACTi(
const APInt &A1,
unsigned Bits,
1792bool MachineConstEvaluator::evaluateSplatr(
const RegSubRegPair &R1,
1793 unsigned Bits,
unsigned Count,
1794 const CellMap &Inputs,
1795 LatticeCell &Result) {
1798 if (!getCell(R1, Inputs, LS1))
1800 if (LS1.isBottom() || LS1.isProperty())
1804 for (
unsigned i = 0; i < LS1.size(); ++i) {
1805 bool Eval = constToInt(LS1.Values[i],
A) &&
1806 evaluateSplati(
A, Bits, Count, SA);
1815bool MachineConstEvaluator::evaluateSplati(
const APInt &A1,
unsigned Bits,
1816 unsigned Count,
APInt &Result) {
1821 LoBits = LoBits.
zext(SW);
1823 APInt Res(SW, 0,
false);
1824 for (
unsigned i = 0; i < Count; ++i) {
1837 class HexagonConstEvaluator :
public MachineConstEvaluator {
1842 CellMap &Outputs)
override;
1844 LatticeCell &Result)
override;
1854 static APInt getCmpImm(
unsigned Opc,
unsigned OpX,
1859 const CellMap &Inputs, LatticeCell &Result);
1860 bool evaluateHexCompare(
const MachineInstr &
MI,
const CellMap &Inputs,
1864 const MachineOperand &Src2,
const CellMap &Inputs,
bool &Result);
1865 bool evaluateHexLogical(
const MachineInstr &
MI,
const CellMap &Inputs,
1867 bool evaluateHexCondMove(
const MachineInstr &
MI,
const CellMap &Inputs,
1869 bool evaluateHexExt(
const MachineInstr &
MI,
const CellMap &Inputs,
1871 bool evaluateHexVector1(
const MachineInstr &
MI,
const CellMap &Inputs,
1873 bool evaluateHexVector2(
const MachineInstr &
MI,
const CellMap &Inputs,
1877 bool rewriteHexBranch(
MachineInstr &BrI,
const CellMap &Inputs);
1878 bool rewriteHexConstDefs(
MachineInstr &
MI,
const CellMap &Inputs,
1880 bool rewriteHexConstUses(
MachineInstr &
MI,
const CellMap &Inputs);
1894 return "Hexagon Constant Propagation";
1902 HexagonConstEvaluator HCE(MF);
1903 return MachineConstPropagator(HCE).run(MF);
1909char HexagonConstPropagation::ID = 0;
1912 "Hexagon Constant Propagation",
false,
false)
1915 : MachineConstEvaluator(Fn),
1918 MRI = &Fn.getRegInfo();
1922 const CellMap &Inputs, CellMap &Outputs) {
1925 if (
MI.getNumOperands() == 0 || !
MI.getOperand(0).isReg())
1931 unsigned Opc =
MI.getOpcode();
1934 if (!DefR.Reg.isVirtual())
1940 bool Eval = evaluateCOPY(SrcR, Inputs, RC);
1943 Outputs.update(DefR.Reg, RC);
1946 if (
MI.isRegSequence()) {
1947 unsigned Sub1 =
MI.getOperand(2).getImm();
1948 unsigned Sub2 =
MI.getOperand(4).getImm();
1952 if (Sub1 != SubLo && Sub1 != SubHi)
1954 if (Sub2 != SubLo && Sub2 != SubHi)
1957 bool LoIs1 = (Sub1 == SubLo);
1962 bool Eval = evaluateHexRSEQ32(SrcRL, SrcRH, Inputs, RC);
1965 Outputs.update(DefR.Reg, RC);
1968 if (
MI.isCompare()) {
1969 bool Eval = evaluateHexCompare(
MI, Inputs, Outputs);
1976 case Hexagon::A2_tfrsi:
1977 case Hexagon::A2_tfrpi:
1978 case Hexagon::CONST32:
1979 case Hexagon::CONST64:
1987 int64_t
V =
MI.getOperand(1).getImm();
1989 if (W != 32 && W != 64)
1993 const ConstantInt *CI = ConstantInt::get(Ty, V,
true);
1994 LatticeCell RC = Outputs.get(DefR.Reg);
1996 Outputs.update(DefR.Reg, RC);
2000 case Hexagon::PS_true:
2001 case Hexagon::PS_false:
2003 LatticeCell RC = Outputs.get(DefR.Reg);
2004 bool NonZero = (
Opc == Hexagon::PS_true);
2005 uint32_t P = NonZero ? ConstantProperties::NonZero
2006 : ConstantProperties::Zero;
2008 Outputs.update(DefR.Reg, RC);
2012 case Hexagon::A2_and:
2013 case Hexagon::A2_andir:
2014 case Hexagon::A2_andp:
2015 case Hexagon::A2_or:
2016 case Hexagon::A2_orir:
2017 case Hexagon::A2_orp:
2018 case Hexagon::A2_xor:
2019 case Hexagon::A2_xorp:
2021 bool Eval = evaluateHexLogical(
MI, Inputs, Outputs);
2027 case Hexagon::A2_combineii:
2028 case Hexagon::A4_combineii:
2030 if (!
MI.getOperand(1).isImm() || !
MI.getOperand(2).isImm())
2036 const ConstantInt *CI = ConstantInt::get(Ty, Res,
false);
2037 LatticeCell RC = Outputs.get(DefR.Reg);
2039 Outputs.update(DefR.Reg, RC);
2043 case Hexagon::S2_setbit_i:
2045 int64_t
B =
MI.getOperand(2).getImm();
2047 APInt A(32, (1ull <<
B),
false);
2049 LatticeCell RC = Outputs.get(DefR.Reg);
2050 bool Eval = evaluateORri(R,
A, Inputs, RC);
2053 Outputs.update(DefR.Reg, RC);
2057 case Hexagon::C2_mux:
2058 case Hexagon::C2_muxir:
2059 case Hexagon::C2_muxri:
2060 case Hexagon::C2_muxii:
2062 bool Eval = evaluateHexCondMove(
MI, Inputs, Outputs);
2068 case Hexagon::A2_sxtb:
2069 case Hexagon::A2_sxth:
2070 case Hexagon::A2_sxtw:
2071 case Hexagon::A2_zxtb:
2072 case Hexagon::A2_zxth:
2074 bool Eval = evaluateHexExt(
MI, Inputs, Outputs);
2080 case Hexagon::S2_ct0:
2081 case Hexagon::S2_ct0p:
2082 case Hexagon::S2_ct1:
2083 case Hexagon::S2_ct1p:
2085 using namespace Hexagon;
2087 bool Ones = (
Opc == S2_ct1) || (
Opc == S2_ct1p);
2091 bool Eval = evaluateCTBr(R1, !Ones, Ones, Inputs,
T);
2098 LatticeCell RC = Outputs.get(DefR.Reg);
2099 for (
unsigned i = 0; i <
T.size(); ++i) {
2101 if (constToInt(CI,
C) &&
C.getBitWidth() > 32)
2102 CI = intToConst(
C.trunc(32));
2105 Outputs.update(DefR.Reg, RC);
2109 case Hexagon::S2_cl0:
2110 case Hexagon::S2_cl0p:
2111 case Hexagon::S2_cl1:
2112 case Hexagon::S2_cl1p:
2113 case Hexagon::S2_clb:
2114 case Hexagon::S2_clbp:
2116 using namespace Hexagon;
2118 bool OnlyZeros = (
Opc == S2_cl0) || (
Opc == S2_cl0p);
2119 bool OnlyOnes = (
Opc == S2_cl1) || (
Opc == S2_cl1p);
2123 bool Eval = evaluateCLBr(R1, !OnlyOnes, !OnlyZeros, Inputs,
T);
2130 LatticeCell RC = Outputs.get(DefR.Reg);
2131 for (
unsigned i = 0; i <
T.size(); ++i) {
2133 if (constToInt(CI,
C) &&
C.getBitWidth() > 32)
2134 CI = intToConst(
C.trunc(32));
2137 Outputs.update(DefR.Reg, RC);
2141 case Hexagon::S4_extract:
2142 case Hexagon::S4_extractp:
2143 case Hexagon::S2_extractu:
2144 case Hexagon::S2_extractup:
2146 bool Signed = (
Opc == Hexagon::S4_extract) ||
2147 (
Opc == Hexagon::S4_extractp);
2150 unsigned Bits =
MI.getOperand(2).getImm();
2151 unsigned Offset =
MI.getOperand(3).getImm();
2152 LatticeCell RC = Outputs.get(DefR.Reg);
2155 RC.add(intToConst(Zero));
2165 bool Eval = evaluateEXTRACTr(R1, BW, Bits,
Offset,
Signed, Inputs, RC);
2168 Outputs.update(DefR.Reg, RC);
2172 case Hexagon::S2_vsplatrb:
2173 case Hexagon::S2_vsplatrh:
2183 bool Eval = evaluateHexVector1(
MI, Inputs, Outputs);
2200 const LatticeCell &Input,
2201 LatticeCell &Result) {
2207 if (RC != &Hexagon::DoubleRegsRegClass)
2209 if (
R.SubReg != Hexagon::isub_lo &&
R.SubReg != Hexagon::isub_hi)
2213 if (Input.isBottom())
2216 using P = ConstantProperties;
2218 if (Input.isProperty()) {
2220 if (Ps & (P::Zero|P::NaN)) {
2221 uint32_t Ns = (Ps & (P::Zero|P::NaN|P::SignProperties));
2225 if (
R.SubReg == Hexagon::isub_hi) {
2226 uint32_t Ns = (Ps & P::SignProperties);
2236 for (
unsigned i = 0; i < Input.size(); ++i) {
2238 if (!constToInt(
C,
A))
2243 if (
R.SubReg == Hexagon::isub_hi)
2248 memcpy(&V32, &U32,
sizeof V32);
2250 const ConstantInt *C32 = ConstantInt::get(Ty,
static_cast<int64_t
>(V32));
2256bool HexagonConstEvaluator::evaluate(
const MachineInstr &BrI,
2262 bool SimpleBranch =
false;
2263 bool Negated =
false;
2265 case Hexagon::J2_jumpf:
2266 case Hexagon::J2_jumpfnew:
2267 case Hexagon::J2_jumpfnewpt:
2270 case Hexagon::J2_jumpt:
2271 case Hexagon::J2_jumptnew:
2272 case Hexagon::J2_jumptnewpt:
2275 SimpleBranch =
true;
2277 case Hexagon::J2_jump:
2296 assert(Inputs.has(PR.Reg));
2297 const LatticeCell &PredC = Inputs.get(PR.Reg);
2298 if (PredC.isBottom())
2301 uint32_t Props = PredC.properties();
2302 bool CTrue =
false, CFalse =
false;
2303 if (Props & ConstantProperties::Zero)
2305 else if (Props & ConstantProperties::NonZero)
2308 if (!CTrue && !CFalse)
2314 if ((!Negated && CTrue) || (Negated && CFalse))
2315 Targets.
insert(BranchTarget);
2316 else if ((!Negated && CFalse) || (Negated && CTrue))
2325bool HexagonConstEvaluator::rewrite(
MachineInstr &
MI,
const CellMap &Inputs) {
2327 return rewriteHexBranch(
MI, Inputs);
2329 unsigned Opc =
MI.getOpcode();
2333 case Hexagon::A2_tfrsi:
2334 case Hexagon::A2_tfrpi:
2335 case Hexagon::CONST32:
2336 case Hexagon::CONST64:
2337 case Hexagon::PS_true:
2338 case Hexagon::PS_false:
2342 unsigned NumOp =
MI.getNumOperands();
2346 bool AllDefs, Changed;
2347 Changed = rewriteHexConstDefs(
MI, Inputs, AllDefs);
2352 Changed |= rewriteHexConstUses(
MI, Inputs);
2357unsigned HexagonConstEvaluator::getRegBitWidth(
unsigned Reg)
const {
2359 if (Hexagon::IntRegsRegClass.hasSubClassEq(RC))
2361 if (Hexagon::DoubleRegsRegClass.hasSubClassEq(RC))
2363 if (Hexagon::PredRegsRegClass.hasSubClassEq(RC))
2369uint32_t HexagonConstEvaluator::getCmp(
unsigned Opc) {
2371 case Hexagon::C2_cmpeq:
2372 case Hexagon::C2_cmpeqp:
2373 case Hexagon::A4_cmpbeq:
2374 case Hexagon::A4_cmpheq:
2375 case Hexagon::A4_cmpbeqi:
2376 case Hexagon::A4_cmpheqi:
2377 case Hexagon::C2_cmpeqi:
2378 case Hexagon::J4_cmpeqn1_t_jumpnv_nt:
2379 case Hexagon::J4_cmpeqn1_t_jumpnv_t:
2380 case Hexagon::J4_cmpeqi_t_jumpnv_nt:
2381 case Hexagon::J4_cmpeqi_t_jumpnv_t:
2382 case Hexagon::J4_cmpeq_t_jumpnv_nt:
2383 case Hexagon::J4_cmpeq_t_jumpnv_t:
2384 return Comparison::EQ;
2386 case Hexagon::C4_cmpneq:
2387 case Hexagon::C4_cmpneqi:
2388 case Hexagon::J4_cmpeqn1_f_jumpnv_nt:
2389 case Hexagon::J4_cmpeqn1_f_jumpnv_t:
2390 case Hexagon::J4_cmpeqi_f_jumpnv_nt:
2391 case Hexagon::J4_cmpeqi_f_jumpnv_t:
2392 case Hexagon::J4_cmpeq_f_jumpnv_nt:
2393 case Hexagon::J4_cmpeq_f_jumpnv_t:
2394 return Comparison::NE;
2396 case Hexagon::C2_cmpgt:
2397 case Hexagon::C2_cmpgtp:
2398 case Hexagon::A4_cmpbgt:
2399 case Hexagon::A4_cmphgt:
2400 case Hexagon::A4_cmpbgti:
2401 case Hexagon::A4_cmphgti:
2402 case Hexagon::C2_cmpgti:
2403 case Hexagon::J4_cmpgtn1_t_jumpnv_nt:
2404 case Hexagon::J4_cmpgtn1_t_jumpnv_t:
2405 case Hexagon::J4_cmpgti_t_jumpnv_nt:
2406 case Hexagon::J4_cmpgti_t_jumpnv_t:
2407 case Hexagon::J4_cmpgt_t_jumpnv_nt:
2408 case Hexagon::J4_cmpgt_t_jumpnv_t:
2409 return Comparison::GTs;
2411 case Hexagon::C4_cmplte:
2412 case Hexagon::C4_cmpltei:
2413 case Hexagon::J4_cmpgtn1_f_jumpnv_nt:
2414 case Hexagon::J4_cmpgtn1_f_jumpnv_t:
2415 case Hexagon::J4_cmpgti_f_jumpnv_nt:
2416 case Hexagon::J4_cmpgti_f_jumpnv_t:
2417 case Hexagon::J4_cmpgt_f_jumpnv_nt:
2418 case Hexagon::J4_cmpgt_f_jumpnv_t:
2419 return Comparison::LEs;
2421 case Hexagon::C2_cmpgtu:
2422 case Hexagon::C2_cmpgtup:
2423 case Hexagon::A4_cmpbgtu:
2424 case Hexagon::A4_cmpbgtui:
2425 case Hexagon::A4_cmphgtu:
2426 case Hexagon::A4_cmphgtui:
2427 case Hexagon::C2_cmpgtui:
2428 case Hexagon::J4_cmpgtui_t_jumpnv_nt:
2429 case Hexagon::J4_cmpgtui_t_jumpnv_t:
2430 case Hexagon::J4_cmpgtu_t_jumpnv_nt:
2431 case Hexagon::J4_cmpgtu_t_jumpnv_t:
2432 return Comparison::GTu;
2434 case Hexagon::J4_cmpltu_f_jumpnv_nt:
2435 case Hexagon::J4_cmpltu_f_jumpnv_t:
2436 return Comparison::GEu;
2438 case Hexagon::J4_cmpltu_t_jumpnv_nt:
2439 case Hexagon::J4_cmpltu_t_jumpnv_t:
2440 return Comparison::LTu;
2442 case Hexagon::J4_cmplt_f_jumpnv_nt:
2443 case Hexagon::J4_cmplt_f_jumpnv_t:
2444 return Comparison::GEs;
2446 case Hexagon::C4_cmplteu:
2447 case Hexagon::C4_cmplteui:
2448 case Hexagon::J4_cmpgtui_f_jumpnv_nt:
2449 case Hexagon::J4_cmpgtui_f_jumpnv_t:
2450 case Hexagon::J4_cmpgtu_f_jumpnv_nt:
2451 case Hexagon::J4_cmpgtu_f_jumpnv_t:
2452 return Comparison::LEu;
2454 case Hexagon::J4_cmplt_t_jumpnv_nt:
2455 case Hexagon::J4_cmplt_t_jumpnv_t:
2456 return Comparison::LTs;
2461 return Comparison::Unk;
2464APInt HexagonConstEvaluator::getCmpImm(
unsigned Opc,
unsigned OpX,
2468 case Hexagon::A4_cmpbgtui:
2469 case Hexagon::A4_cmphgtui:
2471 case Hexagon::A4_cmpheqi:
2472 case Hexagon::C4_cmpneqi:
2475 case Hexagon::A4_cmpbeqi:
2477 case Hexagon::C2_cmpgtui:
2478 case Hexagon::C4_cmplteui:
2480 case Hexagon::C2_cmpeqi:
2481 case Hexagon::C2_cmpgti:
2482 case Hexagon::C4_cmpltei:
2485 case Hexagon::J4_cmpeqi_f_jumpnv_nt:
2486 case Hexagon::J4_cmpeqi_f_jumpnv_t:
2487 case Hexagon::J4_cmpeqi_t_jumpnv_nt:
2488 case Hexagon::J4_cmpeqi_t_jumpnv_t:
2489 case Hexagon::J4_cmpgti_f_jumpnv_nt:
2490 case Hexagon::J4_cmpgti_f_jumpnv_t:
2491 case Hexagon::J4_cmpgti_t_jumpnv_nt:
2492 case Hexagon::J4_cmpgti_t_jumpnv_t:
2493 case Hexagon::J4_cmpgtui_f_jumpnv_nt:
2494 case Hexagon::J4_cmpgtui_f_jumpnv_t:
2495 case Hexagon::J4_cmpgtui_t_jumpnv_nt:
2496 case Hexagon::J4_cmpgtui_t_jumpnv_t:
2509 MI.setDesc(HII.get(Hexagon::A2_nop));
2510 while (
MI.getNumOperands() > 0)
2511 MI.removeOperand(0);
2514bool HexagonConstEvaluator::evaluateHexRSEQ32(
RegSubRegPair RL,
2516 const CellMap &Inputs,
2517 LatticeCell &Result) {
2519 LatticeCell
LSL, LSH;
2520 if (!getCell(RL, Inputs, LSL) || !getCell(RH, Inputs, LSH))
2522 if (
LSL.isProperty() || LSH.isProperty())
2525 unsigned LN =
LSL.size(), HN = LSH.size();
2527 for (
unsigned i = 0; i < LN; ++i) {
2528 bool Eval = constToInt(
LSL.Values[i], LoVs[i]);
2533 for (
unsigned i = 0; i < HN; ++i) {
2534 bool Eval = constToInt(LSH.Values[i], HiVs[i]);
2540 for (
unsigned i = 0; i < HiVs.size(); ++i) {
2542 for (
unsigned j = 0;
j < LoVs.size(); ++
j) {
2544 const Constant *
C = intToConst(HV | LV);
2550 return !
Result.isBottom();
2553bool HexagonConstEvaluator::evaluateHexCompare(
const MachineInstr &
MI,
2554 const CellMap &Inputs, CellMap &Outputs) {
2555 unsigned Opc =
MI.getOpcode();
2556 bool Classic =
false;
2558 case Hexagon::C2_cmpeq:
2559 case Hexagon::C2_cmpeqp:
2560 case Hexagon::C2_cmpgt:
2561 case Hexagon::C2_cmpgtp:
2562 case Hexagon::C2_cmpgtu:
2563 case Hexagon::C2_cmpgtup:
2564 case Hexagon::C2_cmpeqi:
2565 case Hexagon::C2_cmpgti:
2566 case Hexagon::C2_cmpgtui:
2580 unsigned Opc =
MI.getOpcode();
2581 bool Computed = evaluateHexCompare2(
Opc, Src1, Src2, Inputs, Result);
2586 LatticeCell
L = Outputs.get(DefR.Reg);
2588 : ConstantProperties::Zero;
2590 Outputs.update(DefR.Reg, L);
2598bool HexagonConstEvaluator::evaluateHexCompare2(
unsigned Opc,
2600 const CellMap &Inputs,
bool &Result) {
2602 bool Reg1 = Src1.
isReg(), Reg2 = Src2.
isReg();
2603 bool Imm1 = Src1.
isImm(), Imm2 = Src2.
isImm();
2608 return evaluateCMPrr(Cmp, R1,
R2, Inputs, Result);
2610 APInt A2 = getCmpImm(
Opc, 2, Src2);
2611 return evaluateCMPri(Cmp, R1, A2, Inputs, Result);
2614 APInt A1 = getCmpImm(
Opc, 1, Src1);
2617 uint32_t NegCmp = Comparison::negate(Cmp);
2618 return evaluateCMPri(NegCmp,
R2, A1, Inputs, Result);
2620 APInt A2 = getCmpImm(
Opc, 2, Src2);
2621 return evaluateCMPii(Cmp, A1, A2, Result);
2628bool HexagonConstEvaluator::evaluateHexLogical(
const MachineInstr &
MI,
2629 const CellMap &Inputs, CellMap &Outputs) {
2630 unsigned Opc =
MI.getOpcode();
2631 if (
MI.getNumOperands() != 3)
2641 case Hexagon::A2_and:
2642 case Hexagon::A2_andp:
2646 case Hexagon::A2_andir: {
2650 Eval = evaluateANDri(R1,
A, Inputs, RC);
2653 case Hexagon::A2_or:
2654 case Hexagon::A2_orp:
2658 case Hexagon::A2_orir: {
2662 Eval = evaluateORri(R1,
A, Inputs, RC);
2665 case Hexagon::A2_xor:
2666 case Hexagon::A2_xorp:
2673 Outputs.update(DefR.Reg, RC);
2678bool HexagonConstEvaluator::evaluateHexCondMove(
const MachineInstr &
MI,
2679 const CellMap &Inputs, CellMap &Outputs) {
2682 assert(Inputs.has(CR.Reg));
2684 if (!getCell(CR, Inputs, LS))
2688 if (Ps & ConstantProperties::Zero)
2690 else if (Ps & ConstantProperties::NonZero)
2697 LatticeCell RC = Outputs.get(DefR.Reg);
2699 if (ValOp.
isImm()) {
2705 Outputs.update(DefR.Reg, RC);
2708 if (ValOp.
isReg()) {
2710 const LatticeCell &LR = Inputs.get(
R.Reg);
2715 Outputs.update(DefR.Reg, RC);
2721bool HexagonConstEvaluator::evaluateHexExt(
const MachineInstr &
MI,
2722 const CellMap &Inputs, CellMap &Outputs) {
2727 unsigned Opc =
MI.getOpcode();
2730 case Hexagon::A2_sxtb:
2731 case Hexagon::A2_zxtb:
2734 case Hexagon::A2_sxth:
2735 case Hexagon::A2_zxth:
2738 case Hexagon::A2_sxtw:
2747 case Hexagon::A2_sxtb:
2748 case Hexagon::A2_sxth:
2749 case Hexagon::A2_sxtw:
2756 LatticeCell RC = Outputs.get(DefR.Reg);
2757 bool Eval =
Signed ? evaluateSEXTr(R1, BW, Bits, Inputs, RC)
2758 : evaluateZEXTr(R1, BW,
Bits, Inputs, RC);
2761 Outputs.update(DefR.Reg, RC);
2765bool HexagonConstEvaluator::evaluateHexVector1(
const MachineInstr &
MI,
2766 const CellMap &Inputs, CellMap &Outputs) {
2771 LatticeCell RC = Outputs.get(DefR.Reg);
2774 unsigned Opc =
MI.getOpcode();
2776 case Hexagon::S2_vsplatrb:
2778 Eval = evaluateSplatr(R1, 8, 4, Inputs, RC);
2780 case Hexagon::S2_vsplatrh:
2782 Eval = evaluateSplatr(R1, 16, 4, Inputs, RC);
2790 Outputs.update(DefR.Reg, RC);
2795 const CellMap &Inputs,
bool &AllDefs) {
2803 bool Const =
true, HasUse =
false;
2808 if (!
R.Reg.isVirtual())
2812 if (!
MI.isPHI() && !Inputs.has(
R.Reg)) {
2814 <<
" in MI: " <<
MI;
2817 const LatticeCell &
L = Inputs.get(
R.Reg);
2822 if (HasUse && Const) {
2824 dbgs() <<
"CONST: " <<
MI;
2854 DefRegs.push_back(R);
2859 unsigned ChangedNum = 0;
2867 for (
unsigned R : DefRegs) {
2868 const LatticeCell &
L = Inputs.get(R);
2874 if (!
L.isSingle()) {
2877 using P = ConstantProperties;
2880 if (!(Ps & (P::Zero|P::NonZero)))
2886 &HII.get(Hexagon::PS_false) :
2887 &HII.get(Hexagon::PS_true);
2888 Register NewR =
MRI->createVirtualRegister(PredRC);
2894 replaceAllRegUsesWith(R, NewR);
2898 if (!constToInt(
L.Value,
A) || !
A.isSignedIntN(64))
2904 int64_t
V =
A.getSExtValue();
2905 assert(W == 32 || W == 64);
2907 NewRC = &Hexagon::IntRegsRegClass;
2909 NewRC = &Hexagon::DoubleRegsRegClass;
2910 Register NewR =
MRI->createVirtualRegister(NewRC);
2914 NewD = &HII.get(Hexagon::A2_tfrsi);
2918 if (
A.isSignedIntN(8)) {
2919 NewD = &HII.get(Hexagon::A2_tfrpi);
2923 int32_t
Hi =
V >> 32;
2924 int32_t
Lo =
V & 0xFFFFFFFFLL;
2925 if (isInt<8>(
Hi) && isInt<8>(
Lo)) {
2926 NewD = &HII.get(Hexagon::A2_combineii);
2932 NewD = &HII.get(Hexagon::CONST64);
2943 replaceAllRegUsesWith(R, NewR);
2949 if (!NewInstrs.
empty()) {
2950 MachineFunction &MF = *MI.getParent()->getParent();
2951 dbgs() <<
"In function: " << MF.getName() <<
"\n";
2952 dbgs() <<
"Rewrite: for " << MI <<
" created " << *NewInstrs[0];
2953 for (unsigned i = 1; i < NewInstrs.size(); ++i)
2954 dbgs() <<
" " << *NewInstrs[i];
2958 AllDefs = (ChangedNum == DefRegs.size());
2959 return ChangedNum > 0;
2963 const CellMap &Inputs) {
2964 bool Changed =
false;
2965 unsigned Opc =
MI.getOpcode();
2972 case Hexagon::M2_maci:
2981 assert(Inputs.has(
R2.Reg) && Inputs.has(R3.Reg));
2982 LatticeCell LS2, LS3;
2985 bool HasC2 = getCell(
R2, Inputs, LS2), HasC3 = getCell(R3, Inputs, LS3);
2986 if (!HasC2 && !HasC3)
2988 bool Zero = ((HasC2 && (LS2.properties() & ConstantProperties::Zero)) ||
2989 (HasC3 && (LS3.properties() & ConstantProperties::Zero)));
2995 unsigned NewR = R1.
Reg;
2999 NewR =
MRI->createVirtualRegister(RC);
3000 NewMI =
BuildMI(
B, At,
DL, HII.get(TargetOpcode::COPY), NewR)
3003 replaceAllRegUsesWith(DefR.Reg, NewR);
3004 MRI->clearKillFlags(NewR);
3010 if (!LS3.isSingle()) {
3011 if (!LS2.isSingle())
3015 const LatticeCell &LI = Swap ? LS2 : LS3;
3020 if (!constToInt(LI.Value,
A) || !
A.isSignedIntN(8))
3022 int64_t
V =
A.getSExtValue();
3023 const MCInstrDesc &
D = (
V >= 0) ? HII.get(Hexagon::M2_macsip)
3024 : HII.get(Hexagon::M2_macsin);
3034 replaceAllRegUsesWith(DefR.Reg, NewR);
3039 case Hexagon::A2_and:
3044 LatticeCell LS1, LS2;
3045 unsigned CopyOf = 0;
3047 if (getCell(R1, Inputs, LS1) && LS1.isSingle()) {
3049 if (constToInt(LS1.Value,
M1) && !~
M1)
3052 else if (getCell(
R2, Inputs, LS2) && LS2.isSingle()) {
3054 if (constToInt(LS2.Value,
M1) && !~
M1)
3062 unsigned NewR = SR.Reg;
3065 NewR =
MRI->createVirtualRegister(RC);
3066 NewMI =
BuildMI(
B, At,
DL, HII.get(TargetOpcode::COPY), NewR)
3069 replaceAllRegUsesWith(DefR.Reg, NewR);
3070 MRI->clearKillFlags(NewR);
3075 case Hexagon::A2_or:
3080 LatticeCell LS1, LS2;
3081 unsigned CopyOf = 0;
3083 using P = ConstantProperties;
3085 if (getCell(R1, Inputs, LS1) && (LS1.properties() & P::Zero))
3087 else if (getCell(
R2, Inputs, LS2) && (LS2.properties() & P::Zero))
3094 unsigned NewR = SR.Reg;
3097 NewR =
MRI->createVirtualRegister(RC);
3098 NewMI =
BuildMI(
B, At,
DL, HII.get(TargetOpcode::COPY), NewR)
3101 replaceAllRegUsesWith(DefR.Reg, NewR);
3102 MRI->clearKillFlags(NewR);
3117 dbgs() <<
"Rewrite: for " <<
MI;
3119 dbgs() <<
" created " << *NewMI;
3121 dbgs() <<
" modified the instruction itself and created:" << *NewMI;
3128void HexagonConstEvaluator::replaceAllRegUsesWith(
Register FromReg,
3137bool HexagonConstEvaluator::rewriteHexBranch(
MachineInstr &BrI,
3138 const CellMap &Inputs) {
3146 bool Eval =
evaluate(BrI, Inputs, Targets, FallsThru);
3147 unsigned NumTargets = Targets.
size();
3148 if (!Eval || NumTargets > 1 || (NumTargets == 1 && FallsThru))
3150 if (BrI.
getOpcode() == Hexagon::J2_jump)
3154 bool Rewritten =
false;
3155 if (NumTargets > 0) {
3156 assert(!FallsThru &&
"This should have been checked before");
3159 bool Moot =
B.isLayoutSuccessor(TargetB);
3165 const MCInstrDesc &JD = HII.get(Hexagon::J2_jump);
3173 for (
auto &
Op : NI->operands())
3175 NI->eraseFromParent();
3184 replaceWithNop(BrI);
3189 return new HexagonConstPropagation();
unsigned const MachineRegisterInfo * MRI
static bool evaluate(const MCSpecifierExpr &Expr, MCValue &Res, const MCAssembler *Asm)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file implements a class to represent arbitrary precision integral constant values and operations...
ReachingDefAnalysis InstSet & ToRemove
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
TargetInstrInfo::RegSubRegPair RegSubRegPair
Register const TargetRegisterInfo * TRI
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
std::pair< BasicBlock *, BasicBlock * > Edge
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
static Comparison getCmp(SelectionDAG &DAG, SDValue CmpOp0, SDValue CmpOp1, ISD::CondCode Cond, const SDLoc &DL, SDValue Chain=SDValue(), bool IsSignaling=false)
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
support::ulittle16_t & Lo
support::ulittle16_t & Hi
Class for arbitrary precision integers.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
uint64_t getZExtValue() const
Get zero extended value.
LLVM_ABI APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
unsigned getBitWidth() const
Return the number of bits in the APInt.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
bool isNegative() const
Determine sign of this APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned countl_zero() const
The APInt version of std::countl_zero.
unsigned countl_one() const
Count the number of leading one bits.
APInt ashr(unsigned ShiftAmt) const
Arithmetic right-shift function.
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
APInt shl(unsigned shiftAmt) const
Left-shift function.
static bool isSameValue(const APInt &I1, const APInt &I2)
Determine if two APInts have the same value, after zero-extending one of them (if needed!...
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
bool slt(const APInt &RHS) const
Signed less than comparison.
int64_t getSExtValue() const
Get sign extended value.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
unsigned countr_one() const
Count the number of trailing one bits.
ConstantFP - Floating Point Values [float, double].
const APFloat & getValueAPF() const
bool isNegative() const
Return true if the sign bit is set.
bool isNaN() const
Return true if the value is a NaN.
bool isZero() const
Return true if the value is positive or negative zero.
This is the shared class of boolean and integer constants.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
const APInt & getValue() const
Return the constant as an APInt value reference.
This is an important base class in LLVM.
This class represents an Operation in the Expression.
FunctionPass class - This class is used to implement most global optimizations.
bool skipFunction(const Function &F) const
Optional passes call this function to check whether the pass should be skipped.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Class to represent integer types.
This is an important class for using LLVM in a threaded context.
Describe properties that are true of each instruction in the target description file.
iterator_range< iterator > phis()
Returns a range that iterates over the phis in the basic block.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
iterator_range< succ_iterator > successors()
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
MachineBasicBlock * getBlockNumbered(unsigned N) const
getBlockNumbered - MachineBasicBlocks are automatically numbered when they are inserted into the mach...
Function & getFunction()
Return the LLVM function that this machine code represents.
void print(raw_ostream &OS, const SlotIndexes *=nullptr) const
print - Print out the MachineFunction in a format suitable for debugging to the specified stream.
BasicBlockListType::const_iterator const_iterator
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
bool isUnconditionalBranch(QueryType Type=AnyInBundle) const
Return true if this is a branch which always transfers control flow to some other block.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
void setIsKill(bool Val=true)
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
A vector that has set insertion semantics.
bool remove(const value_type &X)
Remove an item from the set vector.
size_type size() const
Determine the number of elements in the SetVector.
void insert_range(Range &&R)
void clear()
Completely clear the SetVector.
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
bool insert(const value_type &X)
Insert a new element into the SetVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
LLVM Value Representation.
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned getRegBitWidth(const TargetRegisterClass &RC)
Get the size in bits of a register from the register class RC.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ TB
TB - TwoByte - Set if this instruction has a two byte opcode, which starts with a 0x0F byte before th...
This is an optimization pass for GlobalISel generic memory operations.
TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O)
Create RegSubRegPair from a register MachineOperand.
void fill(R &&Range, T &&Value)
Provide wrappers to std::fill which take ranges instead of having to pass begin/end explicitly.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI bool isCurrentDebugType(const char *Type, int Level=0)
isCurrentDebugType - Return true if the specified string is the debug type specified on the command l...
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
iterator_range< po_iterator< T > > post_order(const T &G)
FunctionPass * createHexagonConstPropagationPass()
unsigned M1(unsigned Val)
LLVM_ABI bool DebugFlag
This boolean is set to true if the '-debug' command line option is specified.
auto reverse(ContainerTy &&C)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
unsigned getRegState(const MachineOperand &RegOp)
Get all register state flags from machine operand RegOp.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
A pair composed of a register and a sub-register index.