10 #define DEBUG_TYPE "hcp"
56 class ConstantProperties {
66 NumericProperties = (
Zero|NonZero|Finite|Infinity|NaN|SignedZero),
69 SignProperties = (PosOrZero|NegOrZero),
70 Everything = (NumericProperties|SignProperties)
92 return (
Reg == R.Reg) && (
SubReg == R.SubReg);
105 enum { Normal, Top, Bottom };
107 static const unsigned MaxCellSize = 4;
111 unsigned IsSpecial:1;
118 const Constant *Values[MaxCellSize];
121 LatticeCell() :
Kind(Top), Size(0), IsSpecial(
false) {
122 for (
unsigned i = 0;
i < MaxCellSize; ++
i)
126 bool meet(
const LatticeCell &
L);
130 unsigned size()
const {
return Size; }
132 LatticeCell &operator= (
const LatticeCell &L) {
135 uint32_t N = L.IsSpecial ?
sizeof L.Properties
137 memcpy(Values, L.Values, N);
140 IsSpecial = L.IsSpecial;
145 bool isSingle()
const {
return size() == 1; }
146 bool isProperty()
const {
return IsSpecial; }
147 bool isTop()
const {
return Kind == Top; }
148 bool isBottom()
const {
return Kind == Bottom; }
151 bool Changed = (
Kind != Bottom);
167 bool convertToProperty();
175 class MachineConstEvaluator;
177 class MachineConstPropagator {
179 MachineConstPropagator(MachineConstEvaluator &
E) : MCE(E) {
200 void clear() { Map.clear(); }
202 bool has(
unsigned R)
const {
206 MapType::const_iterator
F = Map.find(R);
207 return F != Map.end();
210 const LatticeCell &
get(
unsigned R)
const {
213 MapType::const_iterator
F = Map.find(R);
220 void update(
unsigned R,
const LatticeCell &L) {
227 typedef std::map<unsigned,LatticeCell> MapType;
232 LatticeCell Top, Bottom;
235 typedef MapType::const_iterator const_iterator;
236 const_iterator
begin()
const {
return Map.
begin(); }
237 const_iterator
end()
const {
return Map.
end(); }
246 void visitUsesOf(
unsigned R);
255 MachineConstEvaluator &MCE;
257 typedef std::pair<unsigned,unsigned> CFGEdge;
258 typedef std::set<CFGEdge> SetOfCFGEdge;
259 typedef std::set<const MachineInstr*> SetOfInstr;
260 typedef std::queue<CFGEdge> QueueOfCFGEdge;
264 SetOfCFGEdge EdgeExec;
265 SetOfInstr InstrExec;
266 QueueOfCFGEdge FlowQ;
272 class MachineConstEvaluator {
277 virtual ~MachineConstEvaluator() =
default;
294 typedef MachineConstPropagator::CellMap CellMap;
295 virtual bool evaluate(
const MachineInstr &
MI,
const CellMap &Inputs,
296 CellMap &Outputs) = 0;
297 virtual bool evaluate(
const Register &R,
const LatticeCell &SrcC,
298 LatticeCell &Result) = 0;
299 virtual bool evaluate(
const MachineInstr &BrI,
const CellMap &Inputs,
301 bool &CanFallThru) = 0;
302 virtual bool rewrite(
MachineInstr &MI,
const CellMap &Inputs) = 0;
340 bool getCell(
const Register &R,
const CellMap &Inputs, LatticeCell &RC);
347 const CellMap &Inputs,
bool &Result);
349 const CellMap &Inputs,
bool &Result);
351 const CellMap &Inputs,
bool &Result);
359 bool evaluateCOPY(
const Register &R1,
const CellMap &Inputs,
360 LatticeCell &Result);
364 const CellMap &Inputs, LatticeCell &Result);
366 const CellMap &Inputs, LatticeCell &Result);
369 const CellMap &Inputs, LatticeCell &Result);
371 const CellMap &Inputs, LatticeCell &Result);
374 const CellMap &Inputs, LatticeCell &Result);
376 const CellMap &Inputs, LatticeCell &Result);
380 bool evaluateZEXTr(
const Register &R1,
unsigned Width,
unsigned Bits,
381 const CellMap &Inputs, LatticeCell &Result);
382 bool evaluateZEXTi(
const APInt &A1,
unsigned Width,
unsigned Bits,
384 bool evaluateSEXTr(
const Register &R1,
unsigned Width,
unsigned Bits,
385 const CellMap &Inputs, LatticeCell &Result);
386 bool evaluateSEXTi(
const APInt &A1,
unsigned Width,
unsigned Bits,
390 bool evaluateCLBr(
const Register &R1,
bool Zeros,
bool Ones,
391 const CellMap &Inputs, LatticeCell &Result);
392 bool evaluateCLBi(
const APInt &A1,
bool Zeros,
bool Ones,
APInt &Result);
393 bool evaluateCTBr(
const Register &R1,
bool Zeros,
bool Ones,
394 const CellMap &Inputs, LatticeCell &Result);
395 bool evaluateCTBi(
const APInt &A1,
bool Zeros,
bool Ones,
APInt &Result);
398 bool evaluateEXTRACTr(
const Register &R1,
unsigned Width,
unsigned Bits,
400 LatticeCell &Result);
401 bool evaluateEXTRACTi(
const APInt &A1,
unsigned Bits,
unsigned Offset,
402 bool Signed,
APInt &Result);
404 bool evaluateSplatr(
const Register &R1,
unsigned Bits,
unsigned Count,
405 const CellMap &Inputs, LatticeCell &Result);
406 bool evaluateSplati(
const APInt &A1,
unsigned Bits,
unsigned Count,
413 if (isa<ConstantInt>(C)) {
416 return Zero | PosOrZero | NegOrZero | Finite;
417 uint32_t Props = (NonZero | Finite);
419 return Props | NegOrZero;
420 return Props | PosOrZero;
423 if (isa<ConstantFP>(C)) {
428 return (Props & ~NumericProperties) | (
Zero|Finite);
429 Props = (Props & ~NumericProperties) | NonZero;
431 return (Props & ~NumericProperties) | NaN;
434 return (Props & ~NumericProperties) | Infinity;
444 bool LatticeCell::convertToProperty() {
449 uint32_t Everything = ConstantProperties::Everything;
450 uint32_t Ps = !isTop() ? properties()
467 if (Ps & ConstantProperties::NonZero)
469 if (Ps & ConstantProperties::Finite)
471 if (Ps & ConstantProperties::Infinity)
473 if (Ps & ConstantProperties::NaN)
475 if (Ps & ConstantProperties::PosOrZero)
477 if (Ps & ConstantProperties::NegOrZero)
486 }
else if (isTop()) {
489 for (
unsigned i = 0;
i < size(); ++
i) {
501 bool 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) {
537 while (Index < Size) {
544 if (Index < MaxCellSize) {
552 bool Changed =
false;
556 Changed = convertToProperty();
558 uint32_t NewPs = Ps & ConstantProperties::deduce(LC);
573 bool Changed = convertToProperty();
575 if (Ps == (Ps & Property))
577 Properties = Property & Ps;
583 uint32_t LatticeCell::properties()
const {
586 assert(!isTop() &&
"Should not call this for a top cell");
590 assert(size() > 0 &&
"Empty cell");
591 uint32_t Ps = ConstantProperties::deduce(Values[0]);
592 for (
unsigned i = 1;
i < size(); ++
i) {
595 Ps &= ConstantProperties::deduce(Values[
i]);
600 void MachineConstPropagator::CellMap::print(
raw_ostream &os,
603 dbgs() <<
" " <<
PrintReg(
I.first, &TRI) <<
" -> " <<
I.second <<
'\n';
606 void MachineConstPropagator::visitPHI(
const MachineInstr &PN) {
609 DEBUG(
dbgs() <<
"Visiting FI(BB#" << MBN <<
"): " << PN);
615 bool Changed =
false;
620 const LatticeCell &
T = Cells.get(DefR.Reg);
621 Changed = !T.isBottom();
622 Cells.update(DefR.Reg, Bottom);
624 visitUsesOf(DefR.Reg);
628 LatticeCell DefC = Cells.get(DefR.Reg);
633 if (!EdgeExec.count(CFGEdge(PBN, MBN))) {
634 DEBUG(
dbgs() <<
" edge BB#" << PBN <<
"->BB#" << MBN
635 <<
" not executable\n");
645 if (!Cells.has(UseR.Reg))
649 bool Eval = MCE.evaluate(UseR, Cells.get(UseR.Reg), SrcC);
650 DEBUG(
dbgs() <<
" edge from BB#" << PBN <<
": "
651 <<
PrintReg(UseR.Reg, &MCE.TRI, UseR.SubReg)
653 Changed |= Eval ? DefC.meet(SrcC)
655 Cells.update(DefR.Reg, DefC);
660 visitUsesOf(DefR.Reg);
663 void MachineConstPropagator::visitNonBranch(
const MachineInstr &
MI) {
667 bool Eval = MCE.evaluate(MI, Cells, Outputs);
670 dbgs() <<
" outputs:";
671 for (
auto &
I : Outputs)
672 dbgs() <<
' ' <<
I.second;
680 if (!MO.isReg() || !MO.isDef())
686 bool Changed =
false;
689 const LatticeCell &
T = Cells.get(DefR.Reg);
690 Changed = !T.isBottom();
691 Cells.update(DefR.Reg, Bottom);
695 if (!Outputs.has(DefR.Reg))
697 LatticeCell RC = Cells.get(DefR.Reg);
698 Changed = RC.meet(Outputs.get(DefR.Reg));
699 Cells.update(DefR.Reg, RC);
702 visitUsesOf(DefR.Reg);
710 void MachineConstPropagator::visitBranchesFrom(
const MachineInstr &BrI) {
717 bool EvalOk =
true, FallsThru =
true;
720 InstrExec.insert(&MI);
721 DEBUG(
dbgs() <<
"Visiting " << (EvalOk ?
"BR" :
"br") <<
"(BB#"
722 << MBN <<
"): " << MI);
726 EvalOk = EvalOk && MCE.evaluate(MI, Cells, Targets, FallsThru);
746 if (Next != MF.
end())
756 DEBUG(
dbgs() <<
" failed to evaluate a branch...adding all CFG "
763 unsigned TBN =
TB->getNumber();
764 DEBUG(
dbgs() <<
" pushing edge BB#" << MBN <<
" -> BB#" << TBN <<
"\n");
765 FlowQ.push(CFGEdge(MBN, TBN));
769 void MachineConstPropagator::visitUsesOf(
unsigned Reg) {
771 << Cells.get(Reg) <<
'\n');
776 if (!InstrExec.count(&MI))
783 visitBranchesFrom(MI);
808 if (!InstrExec.count(&MI))
810 bool Eval = MCE.evaluate(MI, Cells, Targets, DoNext);
820 if (NextI != MB->getParent()->end())
856 FlowQ.push(CFGEdge(EntryNum, EntryNum));
858 while (!FlowQ.empty()) {
859 CFGEdge Edge = FlowQ.front();
862 DEBUG(
dbgs() <<
"Picked edge BB#" << Edge.first <<
"->BB#"
863 << Edge.second <<
'\n');
864 if (Edge.first != EntryNum)
865 if (EdgeExec.count(Edge))
867 EdgeExec.insert(Edge);
877 while (It !=
End && It->isPHI()) {
878 InstrExec.insert(&*It);
886 while (It !=
End && It->isDebugValue())
890 if (It !=
End && InstrExec.count(&*It))
894 while (It !=
End && !It->isBranch()) {
895 if (!It->isDebugValue()) {
896 InstrExec.insert(&*It);
907 visitBranchesFrom(*It);
913 FlowQ.push(CFGEdge(SBN, SSB->getNumber()));
918 dbgs() <<
"Cells after propagation:\n";
919 Cells.print(
dbgs(), MCE.TRI);
920 dbgs() <<
"Dead CFG edges:\n";
922 unsigned BN =
B.getNumber();
924 unsigned SN =
SB->getNumber();
925 if (!EdgeExec.count(CFGEdge(BN, SN)))
926 dbgs() <<
" BB#" << BN <<
" -> BB#" << SN <<
'\n';
933 bool Changed =
false;
950 std::vector<MachineBasicBlock*> POT;
964 bool HaveTargets = computeBlockSuccessors(
B, Targets);
967 for (
auto I =
B->rbegin(),
E =
B->rend();
I !=
E; ++
I) {
969 if (InstrExec.count(&MI)) {
972 Changed |= MCE.rewrite(MI, Cells);
978 for (
auto I =
B->begin(),
E =
B->end();
I !=
E; ++
I) {
999 ToRemove.
push_back(const_cast<MachineBasicBlock*>(
SB));
1002 for (
unsigned i = 0, n = ToRemove.
size();
i < n; ++
i)
1003 removeCFGEdge(
B, ToRemove[
i]);
1019 auto Next = std::next(I);
1020 if (I->isBranch() && !InstrExec.count(&*I))
1031 DEBUG(MF.
print(
dbgs() <<
"Starting MachineConstPropagator\n", 0));
1041 bool Changed = rewrite(MF);
1044 dbgs() <<
"End of MachineConstPropagator (Changed=" << Changed <<
")\n";
1054 bool MachineConstEvaluator::getCell(
const Register &R,
const CellMap &Inputs,
1058 const LatticeCell &L = Inputs.get(R.Reg);
1061 return !RC.isBottom();
1063 bool Eval = evaluate(R, L, RC);
1064 return Eval && !RC.isBottom();
1067 bool MachineConstEvaluator::constToInt(
const Constant *C,
1076 const ConstantInt *MachineConstEvaluator::intToConst(
const APInt &Val)
const {
1080 bool MachineConstEvaluator::evaluateCMPrr(
uint32_t Cmp,
const Register &R1,
1081 const Register &
R2,
const CellMap &Inputs,
bool &Result) {
1082 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
1083 LatticeCell LS1, LS2;
1084 if (!getCell(R1, Inputs, LS1) || !getCell(R2, Inputs, LS2))
1087 bool IsProp1 = LS1.isProperty();
1088 bool IsProp2 = LS2.isProperty();
1092 return evaluateCMPpp(Cmp, Prop1, LS2.properties(), Result);
1093 uint32_t NegCmp = Comparison::negate(Cmp);
1094 return evaluateCMPrp(NegCmp, R2, Prop1, Inputs, Result);
1098 return evaluateCMPrp(Cmp, R1, Prop2, Inputs, Result);
1102 bool IsTrue =
true, IsFalse =
true;
1103 for (
unsigned i = 0;
i < LS2.size(); ++
i) {
1105 bool Computed = constToInt(LS2.Values[
i], A) &&
1106 evaluateCMPri(Cmp, R1, A, Inputs, Res);
1112 assert(!IsTrue || !IsFalse);
1116 return IsTrue || IsFalse;
1119 bool MachineConstEvaluator::evaluateCMPri(
uint32_t Cmp,
const Register &R1,
1120 const APInt &A2,
const CellMap &Inputs,
bool &Result) {
1121 assert(Inputs.has(R1.Reg));
1123 if (!getCell(R1, Inputs, LS))
1125 if (LS.isProperty())
1126 return evaluateCMPpi(Cmp, LS.properties(), A2, Result);
1129 bool IsTrue =
true, IsFalse =
true;
1130 for (
unsigned i = 0;
i < LS.size(); ++
i) {
1132 bool Computed = constToInt(LS.Values[
i], A) &&
1133 evaluateCMPii(Cmp, A, A2, Res);
1139 assert(!IsTrue || !IsFalse);
1143 return IsTrue || IsFalse;
1146 bool MachineConstEvaluator::evaluateCMPrp(
uint32_t Cmp,
const Register &R1,
1147 uint64_t Props2,
const CellMap &Inputs,
bool &Result) {
1148 assert(Inputs.has(R1.Reg));
1150 if (!getCell(R1, Inputs, LS))
1152 if (LS.isProperty())
1153 return evaluateCMPpp(Cmp, LS.properties(), Props2, Result);
1156 uint32_t NegCmp = Comparison::negate(Cmp);
1157 bool IsTrue =
true, IsFalse =
true;
1158 for (
unsigned i = 0;
i < LS.size(); ++
i) {
1160 bool Computed = constToInt(LS.Values[
i], A) &&
1161 evaluateCMPpi(NegCmp, Props2, A, Res);
1167 assert(!IsTrue || !IsFalse);
1169 return IsTrue || IsFalse;
1172 bool MachineConstEvaluator::evaluateCMPii(
uint32_t Cmp,
const APInt &A1,
1173 const APInt &A2,
bool &Result) {
1185 return (Result =
true);
1192 unsigned MaxW = (W1 >= W2) ? W1 : W2;
1193 if (Cmp & Comparison::U) {
1197 Result = Zx1.
ult(Zx2);
1199 Result = Zx2.
ult(Zx1);
1207 Result = Sx1.
slt(Sx2);
1209 Result = Sx2.
slt(Sx1);
1214 const APInt &A2,
bool &Result) {
1219 if (Props & ConstantProperties::NaN)
1224 if (!(Props & ConstantProperties::Finite))
1229 if (Cmp & Comparison::U) {
1235 else if (Props & ConstantProperties::NonZero)
1259 if (Props & ConstantProperties::PosOrZero) {
1267 if (Props & ConstantProperties::NegOrZero) {
1281 typedef ConstantProperties
P;
1282 if ((Props1 & P::NaN) && (Props2 & P::NaN))
1284 if (!(Props1 & P::Finite) || !(Props2 & P::Finite))
1288 bool NonZero1 = (Props1 & P::NonZero), NonZero2 = (Props2 & P::NonZero);
1289 if (Zero1 && Zero2) {
1294 if ((Zero1 && NonZero2) || (NonZero1 && Zero2))
1295 return (Result =
true);
1299 if (Cmp & Comparison::U) {
1302 if (Zero1 && NonZero2) {
1306 if (NonZero1 && Zero2) {
1314 bool Poz1 = (Props1 & P::PosOrZero), Poz2 = (Props2 & P::PosOrZero);
1315 bool Nez1 = (Props1 & P::NegOrZero), Nez2 = (Props2 & P::NegOrZero);
1317 if (NonZero1 || NonZero2) {
1323 return (Result =
true);
1326 if (NonZero1 || NonZero2) {
1332 return (Result =
true);
1338 bool MachineConstEvaluator::evaluateCOPY(
const Register &R1,
1339 const CellMap &Inputs, LatticeCell &Result) {
1340 return getCell(R1, Inputs, Result);
1343 bool MachineConstEvaluator::evaluateANDrr(
const Register &R1,
1344 const Register &R2,
const CellMap &Inputs, LatticeCell &Result) {
1345 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
1346 const LatticeCell &L1 = Inputs.get(R2.Reg);
1347 const LatticeCell &L2 = Inputs.get(R2.Reg);
1351 if (L2.isBottom()) {
1354 return evaluateANDrr(R2, R1, Inputs, Result);
1357 if (!evaluate(R2, L2, LS2))
1359 if (LS2.isBottom() || LS2.isProperty())
1363 for (
unsigned i = 0;
i < LS2.size(); ++
i) {
1365 bool Eval = constToInt(LS2.Values[
i], A) &&
1366 evaluateANDri(R1, A, Inputs, RC);
1371 return !Result.isBottom();
1374 bool MachineConstEvaluator::evaluateANDri(
const Register &R1,
1375 const APInt &A2,
const CellMap &Inputs, LatticeCell &Result) {
1376 assert(Inputs.has(R1.Reg));
1378 return getCell(R1, Inputs, Result);
1381 RC.add(intToConst(A2));
1387 if (!getCell(R1, Inputs, LS1))
1389 if (LS1.isBottom() || LS1.isProperty())
1393 for (
unsigned i = 0;
i < LS1.size(); ++
i) {
1394 bool Eval = constToInt(LS1.Values[
i], A) &&
1395 evaluateANDii(A, A2, ResA);
1398 const Constant *C = intToConst(ResA);
1401 return !Result.isBottom();
1404 bool MachineConstEvaluator::evaluateANDii(
const APInt &A1,
1410 bool MachineConstEvaluator::evaluateORrr(
const Register &R1,
1411 const Register &R2,
const CellMap &Inputs, LatticeCell &Result) {
1412 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
1413 const LatticeCell &L1 = Inputs.get(R2.Reg);
1414 const LatticeCell &L2 = Inputs.get(R2.Reg);
1418 if (L2.isBottom()) {
1421 return evaluateORrr(R2, R1, Inputs, Result);
1424 if (!evaluate(R2, L2, LS2))
1426 if (LS2.isBottom() || LS2.isProperty())
1430 for (
unsigned i = 0;
i < LS2.size(); ++
i) {
1432 bool Eval = constToInt(LS2.Values[
i], A) &&
1433 evaluateORri(R1, A, Inputs, RC);
1438 return !Result.isBottom();
1441 bool MachineConstEvaluator::evaluateORri(
const Register &R1,
1442 const APInt &A2,
const CellMap &Inputs, LatticeCell &Result) {
1443 assert(Inputs.has(R1.Reg));
1445 return getCell(R1, Inputs, Result);
1448 RC.add(intToConst(A2));
1454 if (!getCell(R1, Inputs, LS1))
1456 if (LS1.isBottom() || LS1.isProperty())
1460 for (
unsigned i = 0;
i < LS1.size(); ++
i) {
1461 bool Eval = constToInt(LS1.Values[
i], A) &&
1462 evaluateORii(A, A2, ResA);
1465 const Constant *C = intToConst(ResA);
1468 return !Result.isBottom();
1471 bool MachineConstEvaluator::evaluateORii(
const APInt &A1,
1477 bool MachineConstEvaluator::evaluateXORrr(
const Register &R1,
1478 const Register &R2,
const CellMap &Inputs, LatticeCell &Result) {
1479 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
1480 LatticeCell LS1, LS2;
1481 if (!getCell(R1, Inputs, LS1) || !getCell(R2, Inputs, LS2))
1483 if (LS1.isProperty()) {
1485 return !(Result = LS2).isBottom();
1488 if (LS2.isProperty()) {
1490 return !(Result = LS1).isBottom();
1495 for (
unsigned i = 0;
i < LS2.size(); ++
i) {
1497 bool Eval = constToInt(LS2.Values[
i], A) &&
1498 evaluateXORri(R1, A, Inputs, RC);
1503 return !Result.isBottom();
1506 bool MachineConstEvaluator::evaluateXORri(
const Register &R1,
1507 const APInt &A2,
const CellMap &Inputs, LatticeCell &Result) {
1508 assert(Inputs.has(R1.Reg));
1510 if (!getCell(R1, Inputs, LS1))
1512 if (LS1.isProperty()) {
1514 const Constant *C = intToConst(A2);
1516 return !Result.isBottom();
1522 for (
unsigned i = 0;
i < LS1.size(); ++
i) {
1523 bool Eval = constToInt(LS1.Values[
i], A) &&
1524 evaluateXORii(A, A2, XA);
1527 const Constant *C = intToConst(XA);
1530 return !Result.isBottom();
1533 bool MachineConstEvaluator::evaluateXORii(
const APInt &A1,
1539 bool MachineConstEvaluator::evaluateZEXTr(
const Register &R1,
unsigned Width,
1540 unsigned Bits,
const CellMap &Inputs, LatticeCell &Result) {
1541 assert(Inputs.has(R1.Reg));
1543 if (!getCell(R1, Inputs, LS1))
1545 if (LS1.isProperty())
1549 for (
unsigned i = 0;
i < LS1.size(); ++
i) {
1550 bool Eval = constToInt(LS1.Values[
i], A) &&
1551 evaluateZEXTi(A, Width, Bits, XA);
1554 const Constant *C = intToConst(XA);
1560 bool MachineConstEvaluator::evaluateZEXTi(
const APInt &A1,
unsigned Width,
1561 unsigned Bits,
APInt &Result) {
1564 assert(Width >= Bits && BW >= Bits);
1570 bool MachineConstEvaluator::evaluateSEXTr(
const Register &R1,
unsigned Width,
1571 unsigned Bits,
const CellMap &Inputs, LatticeCell &Result) {
1572 assert(Inputs.has(R1.Reg));
1574 if (!getCell(R1, Inputs, LS1))
1576 if (LS1.isBottom() || LS1.isProperty())
1580 for (
unsigned i = 0;
i < LS1.size(); ++
i) {
1581 bool Eval = constToInt(LS1.Values[
i], A) &&
1582 evaluateSEXTi(A, Width, Bits, XA);
1585 const Constant *C = intToConst(XA);
1591 bool MachineConstEvaluator::evaluateSEXTi(
const APInt &A1,
unsigned Width,
1592 unsigned Bits,
APInt &Result) {
1594 assert(Width >= Bits && BW >= Bits);
1599 Result =
APInt(Width, 0);
1603 if (BW <= 64 && Bits != 0) {
1607 V =
static_cast<int8_t
>(V);
1610 V =
static_cast<int16_t
>(V);
1613 V =
static_cast<int32_t
>(V);
1624 Result =
APInt(Width, V,
true);
1631 Result = A1.
sext(Width);
1635 bool MachineConstEvaluator::evaluateCLBr(
const Register &R1,
bool Zeros,
1636 bool Ones,
const CellMap &Inputs, LatticeCell &Result) {
1637 assert(Inputs.has(R1.Reg));
1639 if (!getCell(R1, Inputs, LS1))
1641 if (LS1.isBottom() || LS1.isProperty())
1645 for (
unsigned i = 0;
i < LS1.size(); ++
i) {
1646 bool Eval = constToInt(LS1.Values[
i], A) &&
1647 evaluateCLBi(A, Zeros, Ones, CA);
1650 const Constant *C = intToConst(CA);
1656 bool MachineConstEvaluator::evaluateCLBi(
const APInt &A1,
bool Zeros,
1657 bool Ones,
APInt &Result) {
1659 if (!Zeros && !Ones)
1662 if (Zeros && (Count == 0))
1664 if (Ones && (Count == 0))
1666 Result =
APInt(BW, static_cast<uint64_t>(Count),
false);
1670 bool MachineConstEvaluator::evaluateCTBr(
const Register &R1,
bool Zeros,
1671 bool Ones,
const CellMap &Inputs, LatticeCell &Result) {
1672 assert(Inputs.has(R1.Reg));
1674 if (!getCell(R1, Inputs, LS1))
1676 if (LS1.isBottom() || LS1.isProperty())
1680 for (
unsigned i = 0;
i < LS1.size(); ++
i) {
1681 bool Eval = constToInt(LS1.Values[
i], A) &&
1682 evaluateCTBi(A, Zeros, Ones, CA);
1685 const Constant *C = intToConst(CA);
1691 bool MachineConstEvaluator::evaluateCTBi(
const APInt &A1,
bool Zeros,
1692 bool Ones,
APInt &Result) {
1694 if (!Zeros && !Ones)
1697 if (Zeros && (Count == 0))
1699 if (Ones && (Count == 0))
1701 Result =
APInt(BW, static_cast<uint64_t>(Count),
false);
1705 bool MachineConstEvaluator::evaluateEXTRACTr(
const Register &R1,
1706 unsigned Width,
unsigned Bits,
unsigned Offset,
bool Signed,
1707 const CellMap &Inputs, LatticeCell &Result) {
1708 assert(Inputs.has(R1.Reg));
1709 assert(Bits+Offset <= Width);
1711 if (!getCell(R1, Inputs, LS1))
1715 if (LS1.isProperty()) {
1726 for (
unsigned i = 0;
i < LS1.size(); ++
i) {
1727 bool Eval = constToInt(LS1.Values[
i], A) &&
1728 evaluateEXTRACTi(A, Bits, Offset, Signed, CA);
1731 const Constant *C = intToConst(CA);
1737 bool MachineConstEvaluator::evaluateEXTRACTi(
const APInt &A1,
unsigned Bits,
1738 unsigned Offset,
bool Signed,
APInt &Result) {
1740 assert(Bits+Offset <= BW);
1743 Result =
APInt(BW, 0);
1752 V =
static_cast<uint64_t
>(V) >> (64-Bits);
1753 Result =
APInt(BW, V, Signed);
1757 Result = A1.
shl(BW-Bits-Offset).
ashr(BW-Bits);
1759 Result = A1.
shl(BW-Bits-Offset).
lshr(BW-Bits);
1763 bool MachineConstEvaluator::evaluateSplatr(
const Register &R1,
1764 unsigned Bits,
unsigned Count,
const CellMap &Inputs,
1765 LatticeCell &Result) {
1766 assert(Inputs.has(R1.Reg));
1768 if (!getCell(R1, Inputs, LS1))
1770 if (LS1.isBottom() || LS1.isProperty())
1774 for (
unsigned i = 0;
i < LS1.size(); ++
i) {
1775 bool Eval = constToInt(LS1.Values[
i], A) &&
1776 evaluateSplati(A, Bits, Count, SA);
1779 const Constant *C = intToConst(SA);
1785 bool MachineConstEvaluator::evaluateSplati(
const APInt &A1,
unsigned Bits,
1786 unsigned Count,
APInt &Result) {
1791 LoBits = LoBits.
zext(SW);
1793 APInt Res(SW, 0,
false);
1794 for (
unsigned i = 0;
i < Count; ++
i) {
1814 class HexagonConstEvaluator :
public MachineConstEvaluator {
1818 bool evaluate(
const MachineInstr &MI,
const CellMap &Inputs,
1819 CellMap &Outputs)
override;
1820 bool evaluate(
const Register &R,
const LatticeCell &SrcC,
1821 LatticeCell &Result)
override;
1822 bool evaluate(
const MachineInstr &BrI,
const CellMap &Inputs,
1825 bool rewrite(
MachineInstr &MI,
const CellMap &Inputs)
override;
1831 static APInt getCmpImm(
unsigned Opc,
unsigned OpX,
1836 LatticeCell &Result);
1837 bool evaluateHexCompare(
const MachineInstr &MI,
const CellMap &Inputs,
1841 const MachineOperand &Src2,
const CellMap &Inputs,
bool &Result);
1842 bool evaluateHexLogical(
const MachineInstr &MI,
const CellMap &Inputs,
1844 bool evaluateHexCondMove(
const MachineInstr &MI,
const CellMap &Inputs,
1846 bool evaluateHexExt(
const MachineInstr &MI,
const CellMap &Inputs,
1848 bool evaluateHexVector1(
const MachineInstr &MI,
const CellMap &Inputs,
1850 bool evaluateHexVector2(
const MachineInstr &MI,
const CellMap &Inputs,
1853 void replaceAllRegUsesWith(
unsigned FromReg,
unsigned ToReg);
1854 bool rewriteHexBranch(
MachineInstr &BrI,
const CellMap &Inputs);
1855 bool rewriteHexConstDefs(
MachineInstr &MI,
const CellMap &Inputs,
1857 bool rewriteHexConstUses(
MachineInstr &MI,
const CellMap &Inputs);
1873 StringRef getPassName()
const override {
1874 return "Hexagon Constant Propagation";
1881 if (skipFunction(*F))
1884 HexagonConstEvaluator HCE(MF);
1885 return MachineConstPropagator(HCE).run(MF);
1897 : MachineConstEvaluator(Fn),
1900 MRI = &Fn.getRegInfo();
1903 bool HexagonConstEvaluator::evaluate(
const MachineInstr &MI,
1904 const CellMap &Inputs, CellMap &Outputs) {
1922 bool Eval = evaluateCOPY(SrcR, Inputs, RC);
1925 Outputs.update(DefR.Reg, RC);
1934 if (Sub1 != SubLo && Sub1 != SubHi)
1936 if (Sub2 != SubLo && Sub2 != SubHi)
1939 bool LoIs1 = (Sub1 == SubLo);
1944 bool Eval = evaluateHexRSEQ32(SrcRL, SrcRH, Inputs, RC);
1947 Outputs.update(DefR.Reg, RC);
1951 bool Eval = evaluateHexCompare(MI, Inputs, Outputs);
1958 case Hexagon::A2_tfrsi:
1959 case Hexagon::A2_tfrpi:
1961 case Hexagon::CONST64:
1971 if (W != 32 && W != 64)
1976 LatticeCell RC = Outputs.get(DefR.Reg);
1978 Outputs.update(DefR.Reg, RC);
1982 case Hexagon::PS_true:
1983 case Hexagon::PS_false:
1985 LatticeCell RC = Outputs.get(DefR.Reg);
1986 bool NonZero = (Opc == Hexagon::PS_true);
1987 uint32_t P = NonZero ? ConstantProperties::NonZero
1990 Outputs.update(DefR.Reg, RC);
1994 case Hexagon::A2_and:
1995 case Hexagon::A2_andir:
1996 case Hexagon::A2_andp:
1997 case Hexagon::A2_or:
1998 case Hexagon::A2_orir:
1999 case Hexagon::A2_orp:
2000 case Hexagon::A2_xor:
2001 case Hexagon::A2_xorp:
2003 bool Eval = evaluateHexLogical(MI, Inputs, Outputs);
2009 case Hexagon::A2_combineii:
2010 case Hexagon::A4_combineii:
2014 uint64_t Res = (Hi << 32) | (Lo & 0xFFFFFFFF);
2017 LatticeCell RC = Outputs.get(DefR.Reg);
2019 Outputs.update(DefR.Reg, RC);
2023 case Hexagon::S2_setbit_i:
2027 APInt A(32, (1ull << B),
false);
2029 LatticeCell RC = Outputs.get(DefR.Reg);
2030 bool Eval = evaluateORri(R,
A, Inputs, RC);
2033 Outputs.update(DefR.Reg, RC);
2037 case Hexagon::C2_mux:
2038 case Hexagon::C2_muxir:
2039 case Hexagon::C2_muxri:
2040 case Hexagon::C2_muxii:
2042 bool Eval = evaluateHexCondMove(MI, Inputs, Outputs);
2048 case Hexagon::A2_sxtb:
2049 case Hexagon::A2_sxth:
2050 case Hexagon::A2_sxtw:
2051 case Hexagon::A2_zxtb:
2052 case Hexagon::A2_zxth:
2054 bool Eval = evaluateHexExt(MI, Inputs, Outputs);
2060 case Hexagon::S2_ct0:
2061 case Hexagon::S2_ct0p:
2062 case Hexagon::S2_ct1:
2063 case Hexagon::S2_ct1p:
2065 using namespace Hexagon;
2067 bool Ones = (Opc == S2_ct1) || (Opc == S2_ct1p);
2069 assert(Inputs.has(R1.Reg));
2071 bool Eval = evaluateCTBr(R1, !Ones, Ones, Inputs,
T);
2078 LatticeCell RC = Outputs.get(DefR.Reg);
2079 for (
unsigned i = 0;
i <
T.size(); ++
i) {
2081 if (constToInt(CI, C) && C.getBitWidth() > 32)
2082 CI = intToConst(C.trunc(32));
2085 Outputs.update(DefR.Reg, RC);
2089 case Hexagon::S2_cl0:
2090 case Hexagon::S2_cl0p:
2091 case Hexagon::S2_cl1:
2092 case Hexagon::S2_cl1p:
2093 case Hexagon::S2_clb:
2094 case Hexagon::S2_clbp:
2096 using namespace Hexagon;
2098 bool OnlyZeros = (Opc == S2_cl0) || (Opc == S2_cl0p);
2099 bool OnlyOnes = (Opc == S2_cl1) || (Opc == S2_cl1p);
2101 assert(Inputs.has(R1.Reg));
2103 bool Eval = evaluateCLBr(R1, !OnlyOnes, !OnlyZeros, Inputs,
T);
2110 LatticeCell RC = Outputs.get(DefR.Reg);
2111 for (
unsigned i = 0;
i <
T.size(); ++
i) {
2113 if (constToInt(CI, C) && C.getBitWidth() > 32)
2114 CI = intToConst(C.trunc(32));
2117 Outputs.update(DefR.Reg, RC);
2121 case Hexagon::S4_extract:
2122 case Hexagon::S4_extractp:
2123 case Hexagon::S2_extractu:
2124 case Hexagon::S2_extractup:
2126 bool Signed = (Opc == Hexagon::S4_extract) ||
2127 (Opc == Hexagon::S4_extractp);
2132 LatticeCell RC = Outputs.get(DefR.Reg);
2135 RC.add(intToConst(
Zero));
2138 if (Offset+Bits > BW) {
2145 bool Eval = evaluateEXTRACTr(R1, BW, Bits, Offset, Signed, Inputs, RC);
2148 Outputs.update(DefR.Reg, RC);
2152 case Hexagon::S2_vsplatrb:
2153 case Hexagon::S2_vsplatrh:
2163 bool Eval = evaluateHexVector1(MI, Inputs, Outputs);
2179 bool HexagonConstEvaluator::evaluate(
const Register &R,
2180 const LatticeCell &Input, LatticeCell &Result) {
2186 if (RC != &Hexagon::DoubleRegsRegClass)
2188 if (R.SubReg != Hexagon::isub_lo && R.SubReg != Hexagon::isub_hi)
2192 if (Input.isBottom())
2195 typedef ConstantProperties
P;
2196 if (Input.isProperty()) {
2203 if (R.SubReg == Hexagon::isub_hi) {
2204 uint32_t Ns = (Ps & P::SignProperties);
2214 for (
unsigned i = 0;
i < Input.size(); ++
i) {
2216 if (!constToInt(C, A))
2221 if (R.SubReg == Hexagon::isub_hi)
2226 memcpy(&V32, &U32,
sizeof V32);
2234 bool HexagonConstEvaluator::evaluate(
const MachineInstr &BrI,
2240 bool SimpleBranch =
false;
2241 bool Negated =
false;
2243 case Hexagon::J2_jumpf:
2244 case Hexagon::J2_jumpfnew:
2245 case Hexagon::J2_jumpfnewpt:
2247 case Hexagon::J2_jumpt:
2248 case Hexagon::J2_jumptnew:
2249 case Hexagon::J2_jumptnewpt:
2252 SimpleBranch =
true;
2254 case Hexagon::J2_jump:
2273 assert(Inputs.has(PR.Reg));
2274 const LatticeCell &PredC = Inputs.get(PR.Reg);
2275 if (PredC.isBottom())
2278 uint32_t Props = PredC.properties();
2279 bool CTrue =
false, CFalse =
false;;
2282 else if (Props & ConstantProperties::NonZero)
2285 if (!CTrue && !CFalse)
2291 if ((!Negated && CTrue) || (Negated && CFalse))
2292 Targets.
insert(BranchTarget);
2293 else if ((!Negated && CFalse) || (Negated && CTrue))
2302 bool HexagonConstEvaluator::rewrite(
MachineInstr &MI,
const CellMap &Inputs) {
2304 return rewriteHexBranch(MI, Inputs);
2310 case Hexagon::A2_tfrsi:
2311 case Hexagon::A2_tfrpi:
2313 case Hexagon::CONST64:
2314 case Hexagon::PS_true:
2315 case Hexagon::PS_false:
2323 bool AllDefs, Changed;
2324 Changed = rewriteHexConstDefs(MI, Inputs, AllDefs);
2329 Changed |= rewriteHexConstUses(MI, Inputs);
2336 if (Hexagon::IntRegsRegClass.hasSubClassEq(RC))
2338 if (Hexagon::DoubleRegsRegClass.hasSubClassEq(RC))
2340 if (Hexagon::PredRegsRegClass.hasSubClassEq(RC))
2348 case Hexagon::C2_cmpeq:
2349 case Hexagon::C2_cmpeqp:
2350 case Hexagon::A4_cmpbeq:
2351 case Hexagon::A4_cmpheq:
2352 case Hexagon::A4_cmpbeqi:
2353 case Hexagon::A4_cmpheqi:
2354 case Hexagon::C2_cmpeqi:
2355 case Hexagon::J4_cmpeqn1_t_jumpnv_nt:
2356 case Hexagon::J4_cmpeqn1_t_jumpnv_t:
2357 case Hexagon::J4_cmpeqi_t_jumpnv_nt:
2358 case Hexagon::J4_cmpeqi_t_jumpnv_t:
2359 case Hexagon::J4_cmpeq_t_jumpnv_nt:
2360 case Hexagon::J4_cmpeq_t_jumpnv_t:
2363 case Hexagon::C4_cmpneq:
2364 case Hexagon::C4_cmpneqi:
2365 case Hexagon::J4_cmpeqn1_f_jumpnv_nt:
2366 case Hexagon::J4_cmpeqn1_f_jumpnv_t:
2367 case Hexagon::J4_cmpeqi_f_jumpnv_nt:
2368 case Hexagon::J4_cmpeqi_f_jumpnv_t:
2369 case Hexagon::J4_cmpeq_f_jumpnv_nt:
2370 case Hexagon::J4_cmpeq_f_jumpnv_t:
2373 case Hexagon::C2_cmpgt:
2374 case Hexagon::C2_cmpgtp:
2375 case Hexagon::A4_cmpbgt:
2376 case Hexagon::A4_cmphgt:
2377 case Hexagon::A4_cmpbgti:
2378 case Hexagon::A4_cmphgti:
2379 case Hexagon::C2_cmpgti:
2380 case Hexagon::J4_cmpgtn1_t_jumpnv_nt:
2381 case Hexagon::J4_cmpgtn1_t_jumpnv_t:
2382 case Hexagon::J4_cmpgti_t_jumpnv_nt:
2383 case Hexagon::J4_cmpgti_t_jumpnv_t:
2384 case Hexagon::J4_cmpgt_t_jumpnv_nt:
2385 case Hexagon::J4_cmpgt_t_jumpnv_t:
2386 return Comparison::GTs;
2388 case Hexagon::C4_cmplte:
2389 case Hexagon::C4_cmpltei:
2390 case Hexagon::J4_cmpgtn1_f_jumpnv_nt:
2391 case Hexagon::J4_cmpgtn1_f_jumpnv_t:
2392 case Hexagon::J4_cmpgti_f_jumpnv_nt:
2393 case Hexagon::J4_cmpgti_f_jumpnv_t:
2394 case Hexagon::J4_cmpgt_f_jumpnv_nt:
2395 case Hexagon::J4_cmpgt_f_jumpnv_t:
2396 return Comparison::LEs;
2398 case Hexagon::C2_cmpgtu:
2399 case Hexagon::C2_cmpgtup:
2400 case Hexagon::A4_cmpbgtu:
2401 case Hexagon::A4_cmpbgtui:
2402 case Hexagon::A4_cmphgtu:
2403 case Hexagon::A4_cmphgtui:
2404 case Hexagon::C2_cmpgtui:
2405 case Hexagon::J4_cmpgtui_t_jumpnv_nt:
2406 case Hexagon::J4_cmpgtui_t_jumpnv_t:
2407 case Hexagon::J4_cmpgtu_t_jumpnv_nt:
2408 case Hexagon::J4_cmpgtu_t_jumpnv_t:
2409 return Comparison::GTu;
2411 case Hexagon::J4_cmpltu_f_jumpnv_nt:
2412 case Hexagon::J4_cmpltu_f_jumpnv_t:
2413 return Comparison::GEu;
2415 case Hexagon::J4_cmpltu_t_jumpnv_nt:
2416 case Hexagon::J4_cmpltu_t_jumpnv_t:
2417 return Comparison::LTu;
2419 case Hexagon::J4_cmplt_f_jumpnv_nt:
2420 case Hexagon::J4_cmplt_f_jumpnv_t:
2421 return Comparison::GEs;
2423 case Hexagon::C4_cmplteu:
2424 case Hexagon::C4_cmplteui:
2425 case Hexagon::J4_cmpgtui_f_jumpnv_nt:
2426 case Hexagon::J4_cmpgtui_f_jumpnv_t:
2427 case Hexagon::J4_cmpgtu_f_jumpnv_nt:
2428 case Hexagon::J4_cmpgtu_f_jumpnv_t:
2429 return Comparison::LEu;
2431 case Hexagon::J4_cmplt_t_jumpnv_nt:
2432 case Hexagon::J4_cmplt_t_jumpnv_t:
2433 return Comparison::LTs;
2438 return Comparison::Unk;
2441 APInt HexagonConstEvaluator::getCmpImm(
unsigned Opc,
unsigned OpX,
2443 bool Signed =
false;
2445 case Hexagon::A4_cmpbgtui:
2446 case Hexagon::A4_cmphgtui:
2448 case Hexagon::A4_cmpheqi:
2449 case Hexagon::C4_cmpneqi:
2451 case Hexagon::A4_cmpbeqi:
2453 case Hexagon::C2_cmpgtui:
2454 case Hexagon::C4_cmplteui:
2456 case Hexagon::C2_cmpeqi:
2457 case Hexagon::C2_cmpgti:
2458 case Hexagon::C4_cmpltei:
2461 case Hexagon::J4_cmpeqi_f_jumpnv_nt:
2462 case Hexagon::J4_cmpeqi_f_jumpnv_t:
2463 case Hexagon::J4_cmpeqi_t_jumpnv_nt:
2464 case Hexagon::J4_cmpeqi_t_jumpnv_t:
2465 case Hexagon::J4_cmpgti_f_jumpnv_nt:
2466 case Hexagon::J4_cmpgti_f_jumpnv_t:
2467 case Hexagon::J4_cmpgti_t_jumpnv_nt:
2468 case Hexagon::J4_cmpgti_t_jumpnv_t:
2469 case Hexagon::J4_cmpgtui_f_jumpnv_nt:
2470 case Hexagon::J4_cmpgtui_f_jumpnv_t:
2471 case Hexagon::J4_cmpgtui_t_jumpnv_nt:
2472 case Hexagon::J4_cmpgtui_t_jumpnv_t:
2479 uint64_t Val = MO.
getImm();
2480 return APInt(32, Val, Signed);
2483 void HexagonConstEvaluator::replaceWithNop(
MachineInstr &MI) {
2484 MI.
setDesc(HII.get(Hexagon::A2_nop));
2490 const CellMap &Inputs, LatticeCell &Result) {
2491 assert(Inputs.has(RL.Reg) && Inputs.has(RH.Reg));
2492 LatticeCell
LSL, LSH;
2493 if (!getCell(RL, Inputs, LSL) || !getCell(RH, Inputs, LSH))
2495 if (LSL.isProperty() || LSH.isProperty())
2498 unsigned LN = LSL.size(), HN = LSH.size();
2500 for (
unsigned i = 0;
i < LN; ++
i) {
2501 bool Eval = constToInt(LSL.Values[
i], LoVs[
i]);
2506 for (
unsigned i = 0;
i < HN; ++
i) {
2507 bool Eval = constToInt(LSH.Values[
i], HiVs[
i]);
2513 for (
unsigned i = 0;
i < HiVs.size(); ++
i) {
2515 for (
unsigned j = 0; j < LoVs.size(); ++j) {
2517 const Constant *C = intToConst(HV | LV);
2519 if (Result.isBottom())
2523 return !Result.isBottom();
2526 bool HexagonConstEvaluator::evaluateHexCompare(
const MachineInstr &MI,
2527 const CellMap &Inputs, CellMap &Outputs) {
2529 bool Classic =
false;
2531 case Hexagon::C2_cmpeq:
2532 case Hexagon::C2_cmpeqp:
2533 case Hexagon::C2_cmpgt:
2534 case Hexagon::C2_cmpgtp:
2535 case Hexagon::C2_cmpgtu:
2536 case Hexagon::C2_cmpgtup:
2537 case Hexagon::C2_cmpeqi:
2538 case Hexagon::C2_cmpgti:
2539 case Hexagon::C2_cmpgtui:
2554 bool Computed = evaluateHexCompare2(Opc, Src1, Src2, Inputs, Result);
2559 LatticeCell L = Outputs.get(DefR.Reg);
2560 uint32_t P = Result ? ConstantProperties::NonZero
2563 Outputs.update(DefR.Reg, L);
2571 bool HexagonConstEvaluator::evaluateHexCompare2(
unsigned Opc,
2573 const CellMap &Inputs,
bool &Result) {
2575 bool Reg1 = Src1.
isReg(), Reg2 = Src2.
isReg();
2576 bool Imm1 = Src1.
isImm(), Imm2 = Src2.
isImm();
2581 return evaluateCMPrr(Cmp, R1, R2, Inputs, Result);
2583 APInt A2 = getCmpImm(Opc, 2, Src2);
2584 return evaluateCMPri(Cmp, R1, A2, Inputs, Result);
2587 APInt A1 = getCmpImm(Opc, 1, Src1);
2590 uint32_t NegCmp = Comparison::negate(Cmp);
2591 return evaluateCMPri(NegCmp, R2, A1, Inputs, Result);
2593 APInt A2 = getCmpImm(Opc, 2, Src2);
2594 return evaluateCMPii(Cmp, A1, A2, Result);
2601 bool HexagonConstEvaluator::evaluateHexLogical(
const MachineInstr &MI,
2602 const CellMap &Inputs, CellMap &Outputs) {
2614 case Hexagon::A2_and:
2615 case Hexagon::A2_andp:
2616 Eval = evaluateANDrr(R1,
Register(Src2), Inputs, RC);
2618 case Hexagon::A2_andir: {
2620 Eval = evaluateANDri(R1, A, Inputs, RC);
2623 case Hexagon::A2_or:
2624 case Hexagon::A2_orp:
2625 Eval = evaluateORrr(R1,
Register(Src2), Inputs, RC);
2627 case Hexagon::A2_orir: {
2629 Eval = evaluateORri(R1, A, Inputs, RC);
2632 case Hexagon::A2_xor:
2633 case Hexagon::A2_xorp:
2634 Eval = evaluateXORrr(R1,
Register(Src2), Inputs, RC);
2639 Outputs.update(DefR.Reg, RC);
2644 bool HexagonConstEvaluator::evaluateHexCondMove(
const MachineInstr &MI,
2645 const CellMap &Inputs, CellMap &Outputs) {
2648 assert(Inputs.has(CR.Reg));
2650 if (!getCell(CR, Inputs, LS))
2654 if (Ps & ConstantProperties::Zero)
2656 else if (Ps & ConstantProperties::NonZero)
2663 LatticeCell RC = Outputs.get(DefR.Reg);
2665 if (ValOp.
isImm()) {
2666 int64_t V = ValOp.
getImm();
2671 Outputs.update(DefR.Reg, RC);
2674 if (ValOp.
isReg()) {
2676 const LatticeCell &LR = Inputs.get(R.Reg);
2678 if (!evaluate(R, LR, LSR))
2681 Outputs.update(DefR.Reg, RC);
2687 bool HexagonConstEvaluator::evaluateHexExt(
const MachineInstr &MI,
2688 const CellMap &Inputs, CellMap &Outputs) {
2691 assert(Inputs.has(R1.Reg));
2696 case Hexagon::A2_sxtb:
2697 case Hexagon::A2_zxtb:
2700 case Hexagon::A2_sxth:
2701 case Hexagon::A2_zxth:
2704 case Hexagon::A2_sxtw:
2709 bool Signed =
false;
2711 case Hexagon::A2_sxtb:
2712 case Hexagon::A2_sxth:
2713 case Hexagon::A2_sxtw:
2720 LatticeCell RC = Outputs.get(DefR.Reg);
2721 bool Eval = Signed ? evaluateSEXTr(R1, BW, Bits, Inputs, RC)
2722 : evaluateZEXTr(R1, BW, Bits, Inputs, RC);
2725 Outputs.update(DefR.Reg, RC);
2729 bool HexagonConstEvaluator::evaluateHexVector1(
const MachineInstr &MI,
2730 const CellMap &Inputs, CellMap &Outputs) {
2734 assert(Inputs.has(R1.Reg));
2735 LatticeCell RC = Outputs.get(DefR.Reg);
2740 case Hexagon::S2_vsplatrb:
2742 Eval = evaluateSplatr(R1, 8, 4, Inputs, RC);
2744 case Hexagon::S2_vsplatrh:
2746 Eval = evaluateSplatr(R1, 16, 4, Inputs, RC);
2754 Outputs.update(DefR.Reg, RC);
2758 bool HexagonConstEvaluator::rewriteHexConstDefs(
MachineInstr &MI,
2759 const CellMap &Inputs,
bool &AllDefs) {
2767 bool Const =
true, HasUse =
false;
2776 if (!MI.
isPHI() && !Inputs.has(R.Reg)) {
2778 <<
" in MI: " <<
MI;
2781 const LatticeCell &L = Inputs.get(R.Reg);
2782 Const &= L.isSingle();
2786 if (HasUse && Const) {
2788 dbgs() <<
"CONST: " <<
MI;
2792 unsigned R = MO.
getReg();
2793 dbgs() <<
PrintReg(R, &TRI) <<
": " << Inputs.get(R) <<
"\n";
2810 unsigned R = MO.
getReg();
2820 unsigned ChangedNum = 0;
2828 for (
unsigned i = 0, n = DefRegs.
size();
i < n; ++
i) {
2829 unsigned R = DefRegs[
i];
2830 const LatticeCell &L = Inputs.get(R);
2836 if (!L.isSingle()) {
2839 typedef ConstantProperties
P;
2840 uint64_t Ps = L.properties();
2841 if (!(Ps & (
P::Zero|P::NonZero)))
2847 &HII.get(Hexagon::PS_false) :
2848 &HII.get(Hexagon::PS_true);
2849 unsigned NewR =
MRI->createVirtualRegister(PredRC);
2855 replaceAllRegUsesWith(R, NewR);
2866 assert(W == 32 || W == 64);
2868 NewRC = &Hexagon::IntRegsRegClass;
2870 NewRC = &Hexagon::DoubleRegsRegClass;
2871 unsigned NewR =
MRI->createVirtualRegister(NewRC);
2875 NewD = &HII.get(Hexagon::A2_tfrsi);
2876 NewMI =
BuildMI(B, At, DL, *NewD, NewR)
2880 NewD = &HII.get(Hexagon::A2_tfrpi);
2881 NewMI =
BuildMI(B, At, DL, *NewD, NewR)
2884 int32_t Hi = V >> 32;
2885 int32_t Lo = V & 0xFFFFFFFFLL;
2887 NewD = &HII.get(Hexagon::A2_combineii);
2888 NewMI =
BuildMI(B, At, DL, *NewD, NewR)
2892 NewD = &HII.get(Hexagon::CONST64);
2893 NewMI =
BuildMI(B, At, DL, *NewD, NewR)
2902 replaceAllRegUsesWith(R, NewR);
2908 if (!NewInstrs.
empty()) {
2911 dbgs() <<
"Rewrite: for " << MI <<
" created " << *NewInstrs[0];
2912 for (
unsigned i = 1;
i < NewInstrs.size(); ++
i)
2913 dbgs() <<
" " << *NewInstrs[
i];
2917 AllDefs = (ChangedNum == DefRegs.
size());
2918 return ChangedNum > 0;
2921 bool HexagonConstEvaluator::rewriteHexConstUses(
MachineInstr &MI,
2922 const CellMap &Inputs) {
2923 bool Changed =
false;
2931 case Hexagon::M2_maci:
2940 assert(Inputs.has(R2.Reg) && Inputs.has(R3.Reg));
2941 LatticeCell LS2, LS3;
2944 bool HasC2 = getCell(R2, Inputs, LS2), HasC3 = getCell(R3, Inputs, LS3);
2945 if (!HasC2 && !HasC3)
2954 unsigned NewR = R1.Reg;
2958 NewR =
MRI->createVirtualRegister(RC);
2959 NewMI =
BuildMI(B, At, DL, HII.
get(TargetOpcode::COPY), NewR)
2962 replaceAllRegUsesWith(DefR.Reg, NewR);
2963 MRI->clearKillFlags(NewR);
2969 if (!LS3.isSingle()) {
2970 if (!LS2.isSingle())
2974 const LatticeCell &LI = Swap ? LS2 : LS3;
2982 const MCInstrDesc &
D = (V >= 0) ? HII.get(Hexagon::M2_macsip)
2983 : HII.get(Hexagon::M2_macsin);
2987 unsigned NewR =
MRI->createVirtualRegister(RC);
2989 NewMI =
BuildMI(B, At, DL, D, NewR)
2993 replaceAllRegUsesWith(DefR.Reg, NewR);
2998 case Hexagon::A2_and:
3002 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
3003 LatticeCell LS1, LS2;
3004 unsigned CopyOf = 0;
3006 if (getCell(R1, Inputs, LS1) && LS1.isSingle()) {
3008 if (constToInt(LS1.Value, M1) && !~M1)
3011 else if (getCell(R2, Inputs, LS2) && LS2.isSingle()) {
3013 if (constToInt(LS2.Value, M1) && !~M1)
3021 unsigned NewR = SR.Reg;
3024 NewR =
MRI->createVirtualRegister(RC);
3025 NewMI =
BuildMI(B, At, DL, HII.
get(TargetOpcode::COPY), NewR)
3028 replaceAllRegUsesWith(DefR.Reg, NewR);
3029 MRI->clearKillFlags(NewR);
3034 case Hexagon::A2_or:
3038 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
3039 LatticeCell LS1, LS2;
3040 unsigned CopyOf = 0;
3041 typedef ConstantProperties
P;
3042 if (getCell(R1, Inputs, LS1) && (LS1.properties() &
P::Zero))
3044 else if (getCell(R2, Inputs, LS2) && (LS2.properties() &
P::Zero))
3051 unsigned NewR = SR.Reg;
3054 NewR =
MRI->createVirtualRegister(RC);
3055 NewMI =
BuildMI(B, At, DL, HII.
get(TargetOpcode::COPY), NewR)
3058 replaceAllRegUsesWith(DefR.Reg, NewR);
3059 MRI->clearKillFlags(NewR);
3074 dbgs() <<
"Rewrite: for " <<
MI;
3076 dbgs() <<
" created " << *NewMI;
3078 dbgs() <<
" modified the instruction itself and created:" << *NewMI;
3085 void HexagonConstEvaluator::replaceAllRegUsesWith(
unsigned FromReg,
3089 for (
auto I =
MRI->use_begin(FromReg),
E =
MRI->use_end();
I !=
E;) {
3096 bool HexagonConstEvaluator::rewriteHexBranch(
MachineInstr &BrI,
3097 const CellMap &Inputs) {
3105 bool Eval = evaluate(BrI, Inputs, Targets, FallsThru);
3106 unsigned NumTargets = Targets.
size();
3107 if (!Eval || NumTargets > 1 || (NumTargets == 1 && FallsThru))
3109 if (BrI.
getOpcode() == Hexagon::J2_jump)
3113 bool Rewritten =
false;
3114 if (NumTargets > 0) {
3115 assert(!FallsThru &&
"This should have been checked before");
3124 const MCInstrDesc &JD = HII.get(Hexagon::J2_jump);
3132 for (
auto &
Op : NI->operands())
3134 NI->eraseFromParent();
3143 replaceWithNop(BrI);
3148 return new HexagonConstPropagation();
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type (if unknown returns 0).
APInt ashr(unsigned shiftAmt) const
Arithmetic right-shift function.
void push_back(const T &Elt)
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const_iterator end(StringRef path)
Get end iterator over path.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
uint64_t getZExtValue() const
Get zero extended value.
bool isBranch(QueryType Type=AnyInBundle) const
Returns true if this is a conditional, unconditional, or indirect branch.
unsigned getRegState(const MachineOperand &RegOp)
Get all register state flags from machine operand RegOp.
MachineBasicBlock * getMBB() const
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
constexpr uint32_t Lo_32(uint64_t Value)
Lo_32 - This function returns the low 32 bits of a 64 bit value.
Describe properties that are true of each instruction in the target description file.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
A global registry used in conjunction with static constructors to make pluggable components (like tar...
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Get a value with low bits set.
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
constexpr bool isInt< 8 >(int64_t x)
const_iterator begin(StringRef path)
Get begin iterator over path.
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
static IntegerType * getInt64Ty(LLVMContext &C)
iterator_range< mop_iterator > operands()
APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
size_type size() const
Determine the number of elements in the SetVector.
iterator_range< succ_iterator > successors()
StringRef getName() const
Return a constant reference to the value's name.
bool isNegative() const
Determine sign of this APInt.
void initializeHexagonConstPropagationPass(PassRegistry &Registry)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
DILocation * get() const
Get the underlying DILocation.
const APInt & getValue() const
Return the constant as an APInt value reference.
void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static GCRegistry::Add< StatepointGC > D("statepoint-example","an example strategy for statepoint")
Reg
All possible values of the reg field in the ModR/M byte.
bool isIntN(unsigned N) const
Check if this APInt has an N-bits unsigned integer value.
bool remove(const value_type &X)
Remove an item from the set vector.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
This file implements a class to represent arbitrary precision integral constant values and operations...
LLVM_NODISCARD bool empty() const
unsigned getNumOperands() const
Access to explicit operands of the instruction.
APInt shl(unsigned shiftAmt) const
Left-shift function.
void RemoveOperand(unsigned i)
Erase an operand from an instruction, leaving it with one fewer operand than it started with...
bool insert(const value_type &X)
Insert a new element into the SetVector.
APInt zextOrSelf(unsigned width) const
Zero extend or truncate to width.
GraphT::NodeRef Eval(DominatorTreeBaseByGraphTraits< GraphT > &DT, typename GraphT::NodeRef VIn, unsigned LastLinked)
static bool add(uint64_t *dest, const uint64_t *x, const uint64_t *y, unsigned len)
This function adds the integer array x to the integer array Y and places the result in dest...
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
bool isZero() const
Return true if the value is positive or negative zero.
Printable PrintReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubRegIdx=0)
Prints virtual and physical registers with or without a TRI instance.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
INITIALIZE_PASS(HexagonConstPropagation,"hcp","Hexagon Constant Propagation", false, false) HexagonConstEvaluator
const MachineBasicBlock * getParent() const
FunctionPass * createHexagonConstPropagationPass()
bool isDebugValue() const
INITIALIZE_PASS(HexagonEarlyIfConversion,"hexagon-eif","Hexagon early if conversion", false, false) bool HexagonEarlyIfConversion MachineBasicBlock * SB
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool isNaN() const
Return true if the value is a NaN.
friend const_iterator end(StringRef path)
Get end iterator over path.
unsigned const MachineRegisterInfo * MRI
APInt trunc(unsigned width) const
Truncate to new width.
APInt sextOrSelf(unsigned width) const
Sign extend or truncate to width.
This is an important class for using LLVM in a threaded context.
This is an important base class in LLVM.
int64_t getSExtValue() const
Get sign extended value.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const MachineOperand & getOperand(unsigned i) const
ConstantFP - Floating Point Values [float, double].
APInt sext(unsigned width) const
Sign extend to a new width.
This file declares a class to represent arbitrary precision floating point values and provide a varie...
unsigned getBitWidth() const
Return the number of bits in the APInt.
static const unsigned End
FunctionPass class - This class is used to implement most global optimizations.
iterator_range< po_iterator< T > > post_order(const T &G)
self_iterator getIterator()
Class to represent integer types.
static Comparison getCmp(SelectionDAG &DAG, SDValue CmpOp0, SDValue CmpOp1, ISD::CondCode Cond, const SDLoc &DL)
unsigned getSubReg() const
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!) to ensure ...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void setIsKill(bool Val=true)
unsigned countTrailingZeros() const
Count the number of trailing zero bits.
Iterator for intrusive lists based on ilist_node.
void setDesc(const MCInstrDesc &tid)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one...
This is the shared class of boolean and integer constants.
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
bool slt(const APInt &RHS) const
Signed less than comparison.
friend const_iterator begin(StringRef path)
Get begin iterator over path.
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...
MachineBasicBlock * getBlockNumbered(unsigned N) const
getBlockNumbered - MachineBasicBlocks are automatically numbered when they are inserted into the mach...
Promote Memory to Register
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
bool isCompare(QueryType Type=IgnoreBundle) const
Return true if this instruction is a comparison.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void clear()
Completely clear the SetVector.
Class for arbitrary precision integers.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
static void clear(coro::Shape &Shape)
static void propagate(InstantiatedValue From, InstantiatedValue To, MatchState State, ReachabilitySet &ReachSet, std::vector< WorkListItem > &WorkList)
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
bool isNegative() const
Return true if the sign bit is set.
unsigned countLeadingOnes() const
Count the number of leading one bits.
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
static IntegerType * getInt32Ty(LLVMContext &C)
void setReg(unsigned Reg)
Change the register this operand corresponds to.
bool isCall(QueryType Type=AnyInBundle) const
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
unsigned countTrailingOnes() const
Count the number of trailing one bits.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
void print(raw_ostream &OS, const SlotIndexes *=nullptr) const
print - Print out the MachineFunction in a format suitable for debugging to the specified stream...
iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
raw_ostream & operator<<(raw_ostream &OS, const APInt &I)
void removeSuccessor(MachineBasicBlock *Succ, bool NormalizeSuccProbs=false)
Remove successor from the successors list of this MachineBasicBlock.
const APFloat & getValueAPF() const
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
A vector that has set insertion semantics.
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.
This class implements an extremely fast bulk output stream that can only output to a stream...
unsigned countLeadingZeros() const
The APInt version of the countLeadingZeros functions in MathExtras.h.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
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 zext(unsigned width) const
Zero extend to a new width.
bool operator==(uint64_t V1, const APInt &V2)
bool isRegSequence() const
bool isLayoutSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB will be emitted immediately after this block, such that if this bloc...
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
bool DebugFlag
DebugFlag - This boolean is set to true if the '-debug' command line option is specified.
bool isCurrentDebugType(const char *Type)
isCurrentDebugType - Return true if the specified string is the debug type specified on the command l...
bool isUnconditionalBranch(QueryType Type=AnyInBundle) const
Return true if this is a branch which always transfers control flow to some other block...