10 #define DEBUG_TYPE "hcp" 59 class ConstantProperties {
69 NumericProperties = (Zero|NonZero|Finite|Infinity|NaN|SignedZero),
72 SignProperties = (PosOrZero|NegOrZero),
73 Everything = (NumericProperties|SignProperties)
95 return (Reg == R.Reg) && (SubReg == R.SubReg);
108 enum { Normal, Top, Bottom };
110 static const unsigned MaxCellSize = 4;
114 unsigned IsSpecial:1;
121 const Constant *Values[MaxCellSize];
124 LatticeCell() :
Kind(Top),
Size(0), IsSpecial(
false) {
125 for (
unsigned i = 0; i < MaxCellSize; ++i)
129 bool meet(
const LatticeCell &L);
133 unsigned size()
const {
return Size; }
135 LatticeCell &operator= (
const LatticeCell &L) {
138 uint32_t N = L.IsSpecial ?
sizeof L.Properties
140 memcpy(Values, L.Values, N);
143 IsSpecial = L.IsSpecial;
148 bool isSingle()
const {
return size() == 1; }
149 bool isProperty()
const {
return IsSpecial; }
150 bool isTop()
const {
return Kind == Top; }
151 bool isBottom()
const {
return Kind == Bottom; }
154 bool Changed = (
Kind != Bottom);
170 bool convertToProperty();
180 class MachineConstEvaluator;
182 class MachineConstPropagator {
184 MachineConstPropagator(MachineConstEvaluator &
E) : MCE(E) {
205 void clear() { Map.clear(); }
207 bool has(
unsigned R)
const {
211 MapType::const_iterator
F = Map.find(R);
212 return F != Map.end();
215 const LatticeCell &
get(
unsigned R)
const {
218 MapType::const_iterator
F = Map.find(R);
225 void update(
unsigned R,
const LatticeCell &L) {
232 using MapType = std::map<unsigned, LatticeCell>;
238 LatticeCell Top, Bottom;
241 using const_iterator = MapType::const_iterator;
243 const_iterator
begin()
const {
return Map.
begin(); }
244 const_iterator
end()
const {
return Map.
end(); }
253 void visitUsesOf(
unsigned R);
262 MachineConstEvaluator &MCE;
264 using CFGEdge = std::pair<unsigned, unsigned>;
265 using SetOfCFGEdge = std::set<CFGEdge>;
266 using SetOfInstr = std::set<const MachineInstr *>;
267 using QueueOfCFGEdge = std::queue<CFGEdge>;
271 SetOfCFGEdge EdgeExec;
272 SetOfInstr InstrExec;
273 QueueOfCFGEdge FlowQ;
279 class MachineConstEvaluator {
284 virtual ~MachineConstEvaluator() =
default;
301 using CellMap = MachineConstPropagator::CellMap;
302 virtual bool evaluate(
const MachineInstr &
MI,
const CellMap &Inputs,
303 CellMap &Outputs) = 0;
304 virtual bool evaluate(
const Register &R,
const LatticeCell &SrcC,
305 LatticeCell &Result) = 0;
306 virtual bool evaluate(
const MachineInstr &BrI,
const CellMap &Inputs,
308 bool &CanFallThru) = 0;
309 virtual bool rewrite(
MachineInstr &MI,
const CellMap &Inputs) = 0;
347 bool getCell(
const Register &R,
const CellMap &Inputs, LatticeCell &RC);
354 const CellMap &Inputs,
bool &Result);
356 const CellMap &Inputs,
bool &Result);
358 const CellMap &Inputs,
bool &Result);
366 bool evaluateCOPY(
const Register &R1,
const CellMap &Inputs,
367 LatticeCell &Result);
371 const CellMap &Inputs, LatticeCell &Result);
373 const CellMap &Inputs, LatticeCell &Result);
376 const CellMap &Inputs, LatticeCell &Result);
378 const CellMap &Inputs, LatticeCell &Result);
381 const CellMap &Inputs, LatticeCell &Result);
383 const CellMap &Inputs, LatticeCell &Result);
387 bool evaluateZEXTr(
const Register &R1,
unsigned Width,
unsigned Bits,
388 const CellMap &Inputs, LatticeCell &Result);
389 bool evaluateZEXTi(
const APInt &A1,
unsigned Width,
unsigned Bits,
391 bool evaluateSEXTr(
const Register &R1,
unsigned Width,
unsigned Bits,
392 const CellMap &Inputs, LatticeCell &Result);
393 bool evaluateSEXTi(
const APInt &A1,
unsigned Width,
unsigned Bits,
397 bool evaluateCLBr(
const Register &R1,
bool Zeros,
bool Ones,
398 const CellMap &Inputs, LatticeCell &Result);
399 bool evaluateCLBi(
const APInt &A1,
bool Zeros,
bool Ones,
APInt &Result);
400 bool evaluateCTBr(
const Register &R1,
bool Zeros,
bool Ones,
401 const CellMap &Inputs, LatticeCell &Result);
402 bool evaluateCTBi(
const APInt &A1,
bool Zeros,
bool Ones,
APInt &Result);
405 bool evaluateEXTRACTr(
const Register &R1,
unsigned Width,
unsigned Bits,
407 LatticeCell &Result);
408 bool evaluateEXTRACTi(
const APInt &A1,
unsigned Bits,
unsigned Offset,
409 bool Signed,
APInt &Result);
411 bool evaluateSplatr(
const Register &R1,
unsigned Bits,
unsigned Count,
412 const CellMap &Inputs, LatticeCell &Result);
413 bool evaluateSplati(
const APInt &A1,
unsigned Bits,
unsigned Count,
420 if (isa<ConstantInt>(C)) {
423 return Zero | PosOrZero | NegOrZero | Finite;
424 uint32_t Props = (NonZero | Finite);
426 return Props | NegOrZero;
427 return Props | PosOrZero;
430 if (isa<ConstantFP>(C)) {
435 return (Props & ~NumericProperties) | (Zero|Finite);
436 Props = (Props & ~NumericProperties) | NonZero;
438 return (Props & ~NumericProperties) | NaN;
441 return (Props & ~NumericProperties) | Infinity;
451 bool LatticeCell::convertToProperty() {
456 uint32_t Everything = ConstantProperties::Everything;
457 uint32_t Ps = !isTop() ? properties()
473 if (Ps & ConstantProperties::Zero)
475 if (Ps & ConstantProperties::NonZero)
477 if (Ps & ConstantProperties::Finite)
479 if (Ps & ConstantProperties::Infinity)
481 if (Ps & ConstantProperties::NaN)
483 if (Ps & ConstantProperties::PosOrZero)
485 if (Ps & ConstantProperties::NegOrZero)
494 }
else if (isTop()) {
497 for (
unsigned i = 0; i <
size(); ++i) {
510 bool LatticeCell::meet(
const LatticeCell &L) {
511 bool Changed =
false;
513 Changed = setBottom();
514 if (isBottom() || L.isTop())
524 return add(L.properties());
525 for (
unsigned i = 0; i < L.size(); ++i) {
546 while (Index <
Size) {
553 if (Index < MaxCellSize) {
561 bool Changed =
false;
565 Changed = convertToProperty();
567 uint32_t NewPs = Ps & ConstantProperties::deduce(LC);
582 bool Changed = convertToProperty();
584 if (Ps == (Ps & Property))
586 Properties = Property & Ps;
592 uint32_t LatticeCell::properties()
const {
595 assert(!isTop() &&
"Should not call this for a top cell");
600 uint32_t Ps = ConstantProperties::deduce(Values[0]);
601 for (
unsigned i = 1; i <
size(); ++i) {
604 Ps &= ConstantProperties::deduce(Values[i]);
613 dbgs() <<
" " <<
printReg(
I.first, &TRI) <<
" -> " <<
I.second <<
'\n';
617 void MachineConstPropagator::visitPHI(
const MachineInstr &PN) {
626 bool Changed =
false;
631 const LatticeCell &
T = Cells.get(DefR.Reg);
632 Changed = !T.isBottom();
633 Cells.update(DefR.Reg, Bottom);
635 visitUsesOf(DefR.Reg);
639 LatticeCell DefC = Cells.get(DefR.Reg);
644 if (!EdgeExec.count(CFGEdge(PBN, MBN))) {
656 if (!Cells.has(UseR.Reg))
660 bool Eval = MCE.evaluate(UseR, Cells.get(UseR.Reg), SrcC);
662 <<
printReg(UseR.Reg, &MCE.TRI, UseR.SubReg) << SrcC
664 Changed |= Eval ? DefC.meet(SrcC)
666 Cells.update(DefR.Reg, DefC);
671 visitUsesOf(DefR.Reg);
674 void MachineConstPropagator::visitNonBranch(
const MachineInstr &
MI) {
678 bool Eval = MCE.evaluate(MI, Cells, Outputs);
681 dbgs() <<
" outputs:";
682 for (
auto &
I : Outputs)
683 dbgs() <<
' ' <<
I.second;
691 if (!MO.isReg() || !MO.isDef())
697 bool Changed =
false;
700 const LatticeCell &
T = Cells.get(DefR.Reg);
701 Changed = !T.isBottom();
702 Cells.update(DefR.Reg, Bottom);
706 if (!Outputs.has(DefR.Reg))
708 LatticeCell RC = Cells.get(DefR.Reg);
709 Changed = RC.meet(Outputs.get(DefR.Reg));
710 Cells.update(DefR.Reg, RC);
713 visitUsesOf(DefR.Reg);
721 void MachineConstPropagator::visitBranchesFrom(
const MachineInstr &BrI) {
728 bool EvalOk =
true, FallsThru =
true;
731 InstrExec.insert(&MI);
737 EvalOk = EvalOk && MCE.evaluate(MI, Cells, Targets, FallsThru);
757 if (Next != MF.
end())
767 LLVM_DEBUG(
dbgs() <<
" failed to evaluate a branch...adding all CFG " 774 unsigned TBN =
TB->getNumber();
777 FlowQ.push(CFGEdge(MBN, TBN));
781 void MachineConstPropagator::visitUsesOf(
unsigned Reg) {
783 << Cells.get(Reg) <<
'\n');
788 if (!InstrExec.count(&MI))
795 visitBranchesFrom(MI);
820 if (!InstrExec.count(&MI))
822 bool Eval = MCE.evaluate(MI, Cells, Targets, DoNext);
832 if (NextI != MB->getParent()->end())
868 FlowQ.push(CFGEdge(EntryNum, EntryNum));
870 while (!FlowQ.empty()) {
871 CFGEdge Edge = FlowQ.front();
875 dbgs() <<
"Picked edge " 878 if (Edge.first != EntryNum)
879 if (EdgeExec.count(Edge))
881 EdgeExec.insert(Edge);
891 while (It != End && It->isPHI()) {
892 InstrExec.insert(&*It);
900 while (It != End && It->isDebugInstr())
902 assert(It == End || !It->isPHI());
904 if (It != End && InstrExec.count(&*It))
908 while (It != End && !It->isBranch()) {
909 if (!It->isDebugInstr()) {
910 InstrExec.insert(&*It);
921 visitBranchesFrom(*It);
927 FlowQ.push(CFGEdge(SBN, SSB->getNumber()));
932 dbgs() <<
"Cells after propagation:\n";
933 Cells.print(
dbgs(), MCE.TRI);
934 dbgs() <<
"Dead CFG edges:\n";
936 unsigned BN =
B.getNumber();
938 unsigned SN = SB->getNumber();
939 if (!EdgeExec.count(CFGEdge(BN, SN)))
948 bool Changed =
false;
965 std::vector<MachineBasicBlock*> POT;
979 bool HaveTargets = computeBlockSuccessors(
B, Targets);
982 for (
auto I =
B->rbegin(),
E =
B->rend();
I !=
E; ++
I) {
984 if (InstrExec.count(&MI)) {
987 Changed |= MCE.rewrite(MI, Cells);
993 for (
auto I =
B->begin(),
E =
B->end();
I !=
E; ++
I) {
1013 if (!Targets.
count(SB))
1014 ToRemove.
push_back(const_cast<MachineBasicBlock*>(SB));
1017 for (
unsigned i = 0, n = ToRemove.
size(); i < n; ++i)
1018 removeCFGEdge(
B, ToRemove[i]);
1034 auto Next = std::next(I);
1035 if (I->isBranch() && !InstrExec.count(&*I))
1056 bool Changed = rewrite(MF);
1059 dbgs() <<
"End of MachineConstPropagator (Changed=" << Changed <<
")\n";
1069 bool MachineConstEvaluator::getCell(
const Register &R,
const CellMap &Inputs,
1073 const LatticeCell &L = Inputs.get(R.Reg);
1076 return !RC.isBottom();
1078 bool Eval = evaluate(R, L, RC);
1079 return Eval && !RC.isBottom();
1082 bool MachineConstEvaluator::constToInt(
const Constant *C,
1091 const ConstantInt *MachineConstEvaluator::intToConst(
const APInt &Val)
const {
1095 bool MachineConstEvaluator::evaluateCMPrr(
uint32_t Cmp,
const Register &R1,
1096 const Register &
R2,
const CellMap &Inputs,
bool &Result) {
1097 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
1098 LatticeCell LS1, LS2;
1099 if (!getCell(R1, Inputs, LS1) || !getCell(R2, Inputs, LS2))
1102 bool IsProp1 = LS1.isProperty();
1103 bool IsProp2 = LS2.isProperty();
1107 return evaluateCMPpp(Cmp, Prop1, LS2.properties(), Result);
1108 uint32_t NegCmp = Comparison::negate(Cmp);
1109 return evaluateCMPrp(NegCmp, R2, Prop1, Inputs, Result);
1113 return evaluateCMPrp(Cmp, R1, Prop2, Inputs, Result);
1117 bool IsTrue =
true, IsFalse =
true;
1118 for (
unsigned i = 0; i < LS2.size(); ++i) {
1120 bool Computed = constToInt(LS2.Values[i], A) &&
1121 evaluateCMPri(Cmp, R1, A, Inputs, Res);
1127 assert(!IsTrue || !IsFalse);
1131 return IsTrue || IsFalse;
1134 bool MachineConstEvaluator::evaluateCMPri(
uint32_t Cmp,
const Register &R1,
1135 const APInt &A2,
const CellMap &Inputs,
bool &Result) {
1136 assert(Inputs.has(R1.Reg));
1138 if (!getCell(R1, Inputs, LS))
1140 if (LS.isProperty())
1141 return evaluateCMPpi(Cmp, LS.properties(), A2, Result);
1144 bool IsTrue =
true, IsFalse =
true;
1145 for (
unsigned i = 0; i < LS.size(); ++i) {
1147 bool Computed = constToInt(LS.Values[i], A) &&
1148 evaluateCMPii(Cmp, A, A2, Res);
1154 assert(!IsTrue || !IsFalse);
1158 return IsTrue || IsFalse;
1161 bool MachineConstEvaluator::evaluateCMPrp(
uint32_t Cmp,
const Register &R1,
1162 uint64_t Props2,
const CellMap &Inputs,
bool &Result) {
1163 assert(Inputs.has(R1.Reg));
1165 if (!getCell(R1, Inputs, LS))
1167 if (LS.isProperty())
1168 return evaluateCMPpp(Cmp, LS.properties(), Props2, Result);
1171 uint32_t NegCmp = Comparison::negate(Cmp);
1172 bool IsTrue =
true, IsFalse =
true;
1173 for (
unsigned i = 0; i < LS.size(); ++i) {
1175 bool Computed = constToInt(LS.Values[i], A) &&
1176 evaluateCMPpi(NegCmp, Props2, A, Res);
1182 assert(!IsTrue || !IsFalse);
1184 return IsTrue || IsFalse;
1187 bool MachineConstEvaluator::evaluateCMPii(
uint32_t Cmp,
const APInt &A1,
1188 const APInt &A2,
bool &Result) {
1200 return (Result =
true);
1207 unsigned MaxW = (W1 >= W2) ? W1 : W2;
1208 if (Cmp & Comparison::U) {
1211 if (Cmp & Comparison::L)
1212 Result = Zx1.
ult(Zx2);
1214 Result = Zx2.
ult(Zx1);
1221 if (Cmp & Comparison::L)
1222 Result = Sx1.
slt(Sx2);
1224 Result = Sx2.
slt(Sx1);
1229 const APInt &A2,
bool &Result) {
1234 if (Props & ConstantProperties::NaN)
1239 if (!(Props & ConstantProperties::Finite))
1244 if (Cmp & Comparison::U) {
1248 if (Props & ConstantProperties::Zero)
1250 else if (Props & ConstantProperties::NonZero)
1257 if (Props & ConstantProperties::Zero) {
1265 if (Props & ConstantProperties::Zero) {
1270 ((Cmp & Comparison::L) && !A2.
isNegative()) ||
1274 if (Props & ConstantProperties::PosOrZero) {
1282 if (Props & ConstantProperties::NegOrZero) {
1296 using P = ConstantProperties;
1298 if ((Props1 & P::NaN) && (Props2 & P::NaN))
1300 if (!(Props1 & P::Finite) || !(Props2 & P::Finite))
1303 bool Zero1 = (Props1 & P::Zero), Zero2 = (Props2 & P::Zero);
1304 bool NonZero1 = (Props1 & P::NonZero), NonZero2 = (Props2 & P::NonZero);
1305 if (Zero1 && Zero2) {
1310 if ((Zero1 && NonZero2) || (NonZero1 && Zero2))
1311 return (Result =
true);
1315 if (Cmp & Comparison::U) {
1318 if (Zero1 && NonZero2) {
1319 Result = (Cmp & Comparison::L);
1322 if (NonZero1 && Zero2) {
1330 bool Poz1 = (Props1 & P::PosOrZero), Poz2 = (Props2 & P::PosOrZero);
1331 bool Nez1 = (Props1 & P::NegOrZero), Nez2 = (Props2 & P::NegOrZero);
1333 if (NonZero1 || NonZero2) {
1334 Result = (Cmp & Comparison::L);
1339 return (Result =
true);
1342 if (NonZero1 || NonZero2) {
1348 return (Result =
true);
1354 bool MachineConstEvaluator::evaluateCOPY(
const Register &R1,
1355 const CellMap &Inputs, LatticeCell &Result) {
1356 return getCell(R1, Inputs, Result);
1359 bool MachineConstEvaluator::evaluateANDrr(
const Register &R1,
1360 const Register &R2,
const CellMap &Inputs, LatticeCell &Result) {
1361 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
1362 const LatticeCell &L1 = Inputs.get(R2.Reg);
1363 const LatticeCell &L2 = Inputs.get(R2.Reg);
1367 if (L2.isBottom()) {
1370 return evaluateANDrr(R2, R1, Inputs, Result);
1373 if (!evaluate(R2, L2, LS2))
1375 if (LS2.isBottom() || LS2.isProperty())
1379 for (
unsigned i = 0; i < LS2.size(); ++i) {
1381 bool Eval = constToInt(LS2.Values[i], A) &&
1382 evaluateANDri(R1, A, Inputs, RC);
1387 return !Result.isBottom();
1390 bool MachineConstEvaluator::evaluateANDri(
const Register &R1,
1391 const APInt &A2,
const CellMap &Inputs, LatticeCell &Result) {
1392 assert(Inputs.has(R1.Reg));
1394 return getCell(R1, Inputs, Result);
1397 RC.add(intToConst(A2));
1403 if (!getCell(R1, Inputs, LS1))
1405 if (LS1.isBottom() || LS1.isProperty())
1409 for (
unsigned i = 0; i < LS1.size(); ++i) {
1410 bool Eval = constToInt(LS1.Values[i], A) &&
1411 evaluateANDii(A, A2, ResA);
1414 const Constant *C = intToConst(ResA);
1417 return !Result.isBottom();
1420 bool MachineConstEvaluator::evaluateANDii(
const APInt &A1,
1426 bool MachineConstEvaluator::evaluateORrr(
const Register &R1,
1427 const Register &R2,
const CellMap &Inputs, LatticeCell &Result) {
1428 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
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);
1440 if (!evaluate(R2, L2, LS2))
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();
1457 bool MachineConstEvaluator::evaluateORri(
const Register &R1,
1458 const APInt &A2,
const CellMap &Inputs, LatticeCell &Result) {
1459 assert(Inputs.has(R1.Reg));
1461 return getCell(R1, Inputs, Result);
1464 RC.add(intToConst(A2));
1470 if (!getCell(R1, Inputs, LS1))
1472 if (LS1.isBottom() || LS1.isProperty())
1476 for (
unsigned i = 0; i < LS1.size(); ++i) {
1477 bool Eval = constToInt(LS1.Values[i], A) &&
1478 evaluateORii(A, A2, ResA);
1481 const Constant *C = intToConst(ResA);
1484 return !Result.isBottom();
1487 bool MachineConstEvaluator::evaluateORii(
const APInt &A1,
1493 bool MachineConstEvaluator::evaluateXORrr(
const Register &R1,
1494 const Register &R2,
const CellMap &Inputs, LatticeCell &Result) {
1495 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
1496 LatticeCell LS1, LS2;
1497 if (!getCell(R1, Inputs, LS1) || !getCell(R2, Inputs, LS2))
1499 if (LS1.isProperty()) {
1500 if (LS1.properties() & ConstantProperties::Zero)
1501 return !(Result = LS2).isBottom();
1504 if (LS2.isProperty()) {
1505 if (LS2.properties() & ConstantProperties::Zero)
1506 return !(Result = LS1).isBottom();
1511 for (
unsigned i = 0; i < LS2.size(); ++i) {
1513 bool Eval = constToInt(LS2.Values[i], A) &&
1514 evaluateXORri(R1, A, Inputs, RC);
1519 return !Result.isBottom();
1522 bool MachineConstEvaluator::evaluateXORri(
const Register &R1,
1523 const APInt &A2,
const CellMap &Inputs, LatticeCell &Result) {
1524 assert(Inputs.has(R1.Reg));
1526 if (!getCell(R1, Inputs, LS1))
1528 if (LS1.isProperty()) {
1529 if (LS1.properties() & ConstantProperties::Zero) {
1530 const Constant *C = intToConst(A2);
1532 return !Result.isBottom();
1538 for (
unsigned i = 0; i < LS1.size(); ++i) {
1539 bool Eval = constToInt(LS1.Values[i], A) &&
1540 evaluateXORii(A, A2, XA);
1543 const Constant *C = intToConst(XA);
1546 return !Result.isBottom();
1549 bool MachineConstEvaluator::evaluateXORii(
const APInt &A1,
1555 bool MachineConstEvaluator::evaluateZEXTr(
const Register &R1,
unsigned Width,
1556 unsigned Bits,
const CellMap &Inputs, LatticeCell &Result) {
1557 assert(Inputs.has(R1.Reg));
1559 if (!getCell(R1, Inputs, LS1))
1561 if (LS1.isProperty())
1565 for (
unsigned i = 0; i < LS1.size(); ++i) {
1566 bool Eval = constToInt(LS1.Values[i], A) &&
1567 evaluateZEXTi(A, Width, Bits, XA);
1570 const Constant *C = intToConst(XA);
1576 bool MachineConstEvaluator::evaluateZEXTi(
const APInt &A1,
unsigned Width,
1577 unsigned Bits,
APInt &Result) {
1580 assert(Width >= Bits && BW >= Bits);
1586 bool MachineConstEvaluator::evaluateSEXTr(
const Register &R1,
unsigned Width,
1587 unsigned Bits,
const CellMap &Inputs, LatticeCell &Result) {
1588 assert(Inputs.has(R1.Reg));
1590 if (!getCell(R1, Inputs, LS1))
1592 if (LS1.isBottom() || LS1.isProperty())
1596 for (
unsigned i = 0; i < LS1.size(); ++i) {
1597 bool Eval = constToInt(LS1.Values[i], A) &&
1598 evaluateSEXTi(A, Width, Bits, XA);
1601 const Constant *C = intToConst(XA);
1607 bool MachineConstEvaluator::evaluateSEXTi(
const APInt &A1,
unsigned Width,
1608 unsigned Bits,
APInt &Result) {
1610 assert(Width >= Bits && BW >= Bits);
1615 Result =
APInt(Width, 0);
1619 if (BW <= 64 && Bits != 0) {
1623 V =
static_cast<int8_t
>(V);
1626 V =
static_cast<int16_t
>(V);
1629 V =
static_cast<int32_t
>(V);
1640 Result =
APInt(Width, V,
true);
1647 Result = A1.
sext(Width);
1651 bool MachineConstEvaluator::evaluateCLBr(
const Register &R1,
bool Zeros,
1652 bool Ones,
const CellMap &Inputs, LatticeCell &Result) {
1653 assert(Inputs.has(R1.Reg));
1655 if (!getCell(R1, Inputs, LS1))
1657 if (LS1.isBottom() || LS1.isProperty())
1661 for (
unsigned i = 0; i < LS1.size(); ++i) {
1662 bool Eval = constToInt(LS1.Values[i], A) &&
1663 evaluateCLBi(A, Zeros, Ones, CA);
1666 const Constant *C = intToConst(CA);
1672 bool MachineConstEvaluator::evaluateCLBi(
const APInt &A1,
bool Zeros,
1673 bool Ones,
APInt &Result) {
1675 if (!Zeros && !Ones)
1678 if (Zeros && (Count == 0))
1680 if (Ones && (Count == 0))
1682 Result =
APInt(BW, static_cast<uint64_t>(Count),
false);
1686 bool MachineConstEvaluator::evaluateCTBr(
const Register &R1,
bool Zeros,
1687 bool Ones,
const CellMap &Inputs, LatticeCell &Result) {
1688 assert(Inputs.has(R1.Reg));
1690 if (!getCell(R1, Inputs, LS1))
1692 if (LS1.isBottom() || LS1.isProperty())
1696 for (
unsigned i = 0; i < LS1.size(); ++i) {
1697 bool Eval = constToInt(LS1.Values[i], A) &&
1698 evaluateCTBi(A, Zeros, Ones, CA);
1701 const Constant *C = intToConst(CA);
1707 bool MachineConstEvaluator::evaluateCTBi(
const APInt &A1,
bool Zeros,
1708 bool Ones,
APInt &Result) {
1710 if (!Zeros && !Ones)
1713 if (Zeros && (Count == 0))
1715 if (Ones && (Count == 0))
1717 Result =
APInt(BW, static_cast<uint64_t>(Count),
false);
1721 bool MachineConstEvaluator::evaluateEXTRACTr(
const Register &R1,
1722 unsigned Width,
unsigned Bits,
unsigned Offset,
bool Signed,
1723 const CellMap &Inputs, LatticeCell &Result) {
1724 assert(Inputs.has(R1.Reg));
1725 assert(Bits+Offset <= Width);
1727 if (!getCell(R1, Inputs, LS1))
1731 if (LS1.isProperty()) {
1733 if (Ps & ConstantProperties::Zero) {
1742 for (
unsigned i = 0; i < LS1.size(); ++i) {
1743 bool Eval = constToInt(LS1.Values[i], A) &&
1744 evaluateEXTRACTi(A, Bits, Offset, Signed, CA);
1747 const Constant *C = intToConst(CA);
1753 bool MachineConstEvaluator::evaluateEXTRACTi(
const APInt &A1,
unsigned Bits,
1754 unsigned Offset,
bool Signed,
APInt &Result) {
1756 assert(Bits+Offset <= BW);
1759 Result =
APInt(BW, 0);
1768 V =
static_cast<uint64_t
>(V) >> (64-Bits);
1769 Result =
APInt(BW, V, Signed);
1773 Result = A1.
shl(BW-Bits-Offset).
ashr(BW-Bits);
1775 Result = A1.
shl(BW-Bits-Offset).
lshr(BW-Bits);
1779 bool MachineConstEvaluator::evaluateSplatr(
const Register &R1,
1780 unsigned Bits,
unsigned Count,
const CellMap &Inputs,
1781 LatticeCell &Result) {
1782 assert(Inputs.has(R1.Reg));
1784 if (!getCell(R1, Inputs, LS1))
1786 if (LS1.isBottom() || LS1.isProperty())
1790 for (
unsigned i = 0; i < LS1.size(); ++i) {
1791 bool Eval = constToInt(LS1.Values[i], A) &&
1792 evaluateSplati(A, Bits, Count, SA);
1795 const Constant *C = intToConst(SA);
1801 bool MachineConstEvaluator::evaluateSplati(
const APInt &A1,
unsigned Bits,
1802 unsigned Count,
APInt &Result) {
1807 LoBits = LoBits.
zext(SW);
1809 APInt Res(SW, 0,
false);
1810 for (
unsigned i = 0; i < Count; ++i) {
1830 class HexagonConstEvaluator :
public MachineConstEvaluator {
1834 bool evaluate(
const MachineInstr &MI,
const CellMap &Inputs,
1835 CellMap &Outputs)
override;
1836 bool evaluate(
const Register &R,
const LatticeCell &SrcC,
1837 LatticeCell &Result)
override;
1838 bool evaluate(
const MachineInstr &BrI,
const CellMap &Inputs,
1841 bool rewrite(
MachineInstr &MI,
const CellMap &Inputs)
override;
1847 static APInt getCmpImm(
unsigned Opc,
unsigned OpX,
1852 LatticeCell &Result);
1853 bool evaluateHexCompare(
const MachineInstr &MI,
const CellMap &Inputs,
1857 const MachineOperand &Src2,
const CellMap &Inputs,
bool &Result);
1858 bool evaluateHexLogical(
const MachineInstr &MI,
const CellMap &Inputs,
1860 bool evaluateHexCondMove(
const MachineInstr &MI,
const CellMap &Inputs,
1862 bool evaluateHexExt(
const MachineInstr &MI,
const CellMap &Inputs,
1864 bool evaluateHexVector1(
const MachineInstr &MI,
const CellMap &Inputs,
1866 bool evaluateHexVector2(
const MachineInstr &MI,
const CellMap &Inputs,
1869 void replaceAllRegUsesWith(
unsigned FromReg,
unsigned ToReg);
1870 bool rewriteHexBranch(
MachineInstr &BrI,
const CellMap &Inputs);
1871 bool rewriteHexConstDefs(
MachineInstr &MI,
const CellMap &Inputs,
1873 bool rewriteHexConstUses(
MachineInstr &MI,
const CellMap &Inputs);
1886 StringRef getPassName()
const override {
1887 return "Hexagon Constant Propagation";
1892 if (skipFunction(F))
1895 HexagonConstEvaluator HCE(MF);
1896 return MachineConstPropagator(HCE).run(MF);
1905 "Hexagon Constant Propagation",
false,
false)
1908 : MachineConstEvaluator(Fn),
1911 MRI = &Fn.getRegInfo();
1914 bool HexagonConstEvaluator::evaluate(
const MachineInstr &MI,
1915 const CellMap &Inputs, CellMap &Outputs) {
1933 bool Eval = evaluateCOPY(SrcR, Inputs, RC);
1936 Outputs.update(DefR.Reg, RC);
1945 if (Sub1 != SubLo && Sub1 != SubHi)
1947 if (Sub2 != SubLo && Sub2 != SubHi)
1950 bool LoIs1 = (Sub1 == SubLo);
1955 bool Eval = evaluateHexRSEQ32(SrcRL, SrcRH, Inputs, RC);
1958 Outputs.update(DefR.Reg, RC);
1962 bool Eval = evaluateHexCompare(MI, Inputs, Outputs);
1969 case Hexagon::A2_tfrsi:
1970 case Hexagon::A2_tfrpi:
1972 case Hexagon::CONST64:
1982 if (W != 32 && W != 64)
1987 LatticeCell RC = Outputs.get(DefR.Reg);
1989 Outputs.update(DefR.Reg, RC);
1993 case Hexagon::PS_true:
1994 case Hexagon::PS_false:
1996 LatticeCell RC = Outputs.get(DefR.Reg);
1997 bool NonZero = (Opc == Hexagon::PS_true);
1998 uint32_t P = NonZero ? ConstantProperties::NonZero
1999 : ConstantProperties::Zero;
2001 Outputs.update(DefR.Reg, RC);
2005 case Hexagon::A2_and:
2006 case Hexagon::A2_andir:
2007 case Hexagon::A2_andp:
2008 case Hexagon::A2_or:
2009 case Hexagon::A2_orir:
2010 case Hexagon::A2_orp:
2011 case Hexagon::A2_xor:
2012 case Hexagon::A2_xorp:
2014 bool Eval = evaluateHexLogical(MI, Inputs, Outputs);
2020 case Hexagon::A2_combineii:
2021 case Hexagon::A4_combineii:
2027 uint64_t Res = (Hi << 32) | (Lo & 0xFFFFFFFF);
2030 LatticeCell RC = Outputs.get(DefR.Reg);
2032 Outputs.update(DefR.Reg, RC);
2036 case Hexagon::S2_setbit_i:
2040 APInt A(32, (1ull << B),
false);
2042 LatticeCell RC = Outputs.get(DefR.Reg);
2043 bool Eval = evaluateORri(R, A, Inputs, RC);
2046 Outputs.update(DefR.Reg, RC);
2050 case Hexagon::C2_mux:
2051 case Hexagon::C2_muxir:
2052 case Hexagon::C2_muxri:
2053 case Hexagon::C2_muxii:
2055 bool Eval = evaluateHexCondMove(MI, Inputs, Outputs);
2061 case Hexagon::A2_sxtb:
2062 case Hexagon::A2_sxth:
2063 case Hexagon::A2_sxtw:
2064 case Hexagon::A2_zxtb:
2065 case Hexagon::A2_zxth:
2067 bool Eval = evaluateHexExt(MI, Inputs, Outputs);
2073 case Hexagon::S2_ct0:
2074 case Hexagon::S2_ct0p:
2075 case Hexagon::S2_ct1:
2076 case Hexagon::S2_ct1p:
2078 using namespace Hexagon;
2080 bool Ones = (Opc == S2_ct1) || (Opc == S2_ct1p);
2082 assert(Inputs.has(R1.Reg));
2084 bool Eval = evaluateCTBr(R1, !Ones, Ones, Inputs, T);
2091 LatticeCell RC = Outputs.get(DefR.Reg);
2092 for (
unsigned i = 0; i < T.size(); ++i) {
2095 CI = intToConst(C.
trunc(32));
2098 Outputs.update(DefR.Reg, RC);
2102 case Hexagon::S2_cl0:
2103 case Hexagon::S2_cl0p:
2104 case Hexagon::S2_cl1:
2105 case Hexagon::S2_cl1p:
2106 case Hexagon::S2_clb:
2107 case Hexagon::S2_clbp:
2109 using namespace Hexagon;
2111 bool OnlyZeros = (Opc == S2_cl0) || (Opc == S2_cl0p);
2112 bool OnlyOnes = (Opc == S2_cl1) || (Opc == S2_cl1p);
2114 assert(Inputs.has(R1.Reg));
2116 bool Eval = evaluateCLBr(R1, !OnlyOnes, !OnlyZeros, Inputs, T);
2123 LatticeCell RC = Outputs.get(DefR.Reg);
2124 for (
unsigned i = 0; i < T.size(); ++i) {
2127 CI = intToConst(C.
trunc(32));
2130 Outputs.update(DefR.Reg, RC);
2134 case Hexagon::S4_extract:
2135 case Hexagon::S4_extractp:
2136 case Hexagon::S2_extractu:
2137 case Hexagon::S2_extractup:
2139 bool Signed = (Opc == Hexagon::S4_extract) ||
2140 (Opc == Hexagon::S4_extractp);
2145 LatticeCell RC = Outputs.get(DefR.Reg);
2147 APInt Zero(BW, 0,
false);
2148 RC.add(intToConst(Zero));
2151 if (Offset+Bits > BW) {
2158 bool Eval = evaluateEXTRACTr(R1, BW, Bits, Offset, Signed, Inputs, RC);
2161 Outputs.update(DefR.Reg, RC);
2165 case Hexagon::S2_vsplatrb:
2166 case Hexagon::S2_vsplatrh:
2176 bool Eval = evaluateHexVector1(MI, Inputs, Outputs);
2192 bool HexagonConstEvaluator::evaluate(
const Register &R,
2193 const LatticeCell &Input, LatticeCell &Result) {
2199 if (RC != &Hexagon::DoubleRegsRegClass)
2201 if (R.SubReg != Hexagon::isub_lo && R.SubReg != Hexagon::isub_hi)
2205 if (Input.isBottom())
2208 using P = ConstantProperties;
2210 if (Input.isProperty()) {
2212 if (Ps & (P::Zero|P::NaN)) {
2213 uint32_t Ns = (Ps & (P::Zero|P::NaN|P::SignProperties));
2217 if (R.SubReg == Hexagon::isub_hi) {
2218 uint32_t Ns = (Ps & P::SignProperties);
2228 for (
unsigned i = 0; i < Input.size(); ++i) {
2229 const Constant *C = Input.Values[i];
2230 if (!constToInt(C, A))
2235 if (R.SubReg == Hexagon::isub_hi)
2240 memcpy(&V32, &U32,
sizeof V32);
2248 bool HexagonConstEvaluator::evaluate(
const MachineInstr &BrI,
2254 bool SimpleBranch =
false;
2255 bool Negated =
false;
2257 case Hexagon::J2_jumpf:
2258 case Hexagon::J2_jumpfnew:
2259 case Hexagon::J2_jumpfnewpt:
2262 case Hexagon::J2_jumpt:
2263 case Hexagon::J2_jumptnew:
2264 case Hexagon::J2_jumptnewpt:
2267 SimpleBranch =
true;
2269 case Hexagon::J2_jump:
2288 assert(Inputs.has(PR.Reg));
2289 const LatticeCell &PredC = Inputs.get(PR.Reg);
2290 if (PredC.isBottom())
2293 uint32_t Props = PredC.properties();
2294 bool CTrue =
false, CFalse =
false;
2295 if (Props & ConstantProperties::Zero)
2297 else if (Props & ConstantProperties::NonZero)
2300 if (!CTrue && !CFalse)
2306 if ((!Negated && CTrue) || (Negated && CFalse))
2307 Targets.
insert(BranchTarget);
2308 else if ((!Negated && CFalse) || (Negated && CTrue))
2317 bool HexagonConstEvaluator::rewrite(
MachineInstr &MI,
const CellMap &Inputs) {
2319 return rewriteHexBranch(MI, Inputs);
2325 case Hexagon::A2_tfrsi:
2326 case Hexagon::A2_tfrpi:
2328 case Hexagon::CONST64:
2329 case Hexagon::PS_true:
2330 case Hexagon::PS_false:
2338 bool AllDefs, Changed;
2339 Changed = rewriteHexConstDefs(MI, Inputs, AllDefs);
2344 Changed |= rewriteHexConstUses(MI, Inputs);
2351 if (Hexagon::IntRegsRegClass.hasSubClassEq(RC))
2353 if (Hexagon::DoubleRegsRegClass.hasSubClassEq(RC))
2355 if (Hexagon::PredRegsRegClass.hasSubClassEq(RC))
2363 case Hexagon::C2_cmpeq:
2364 case Hexagon::C2_cmpeqp:
2365 case Hexagon::A4_cmpbeq:
2366 case Hexagon::A4_cmpheq:
2367 case Hexagon::A4_cmpbeqi:
2368 case Hexagon::A4_cmpheqi:
2369 case Hexagon::C2_cmpeqi:
2370 case Hexagon::J4_cmpeqn1_t_jumpnv_nt:
2371 case Hexagon::J4_cmpeqn1_t_jumpnv_t:
2372 case Hexagon::J4_cmpeqi_t_jumpnv_nt:
2373 case Hexagon::J4_cmpeqi_t_jumpnv_t:
2374 case Hexagon::J4_cmpeq_t_jumpnv_nt:
2375 case Hexagon::J4_cmpeq_t_jumpnv_t:
2378 case Hexagon::C4_cmpneq:
2379 case Hexagon::C4_cmpneqi:
2380 case Hexagon::J4_cmpeqn1_f_jumpnv_nt:
2381 case Hexagon::J4_cmpeqn1_f_jumpnv_t:
2382 case Hexagon::J4_cmpeqi_f_jumpnv_nt:
2383 case Hexagon::J4_cmpeqi_f_jumpnv_t:
2384 case Hexagon::J4_cmpeq_f_jumpnv_nt:
2385 case Hexagon::J4_cmpeq_f_jumpnv_t:
2388 case Hexagon::C2_cmpgt:
2389 case Hexagon::C2_cmpgtp:
2390 case Hexagon::A4_cmpbgt:
2391 case Hexagon::A4_cmphgt:
2392 case Hexagon::A4_cmpbgti:
2393 case Hexagon::A4_cmphgti:
2394 case Hexagon::C2_cmpgti:
2395 case Hexagon::J4_cmpgtn1_t_jumpnv_nt:
2396 case Hexagon::J4_cmpgtn1_t_jumpnv_t:
2397 case Hexagon::J4_cmpgti_t_jumpnv_nt:
2398 case Hexagon::J4_cmpgti_t_jumpnv_t:
2399 case Hexagon::J4_cmpgt_t_jumpnv_nt:
2400 case Hexagon::J4_cmpgt_t_jumpnv_t:
2401 return Comparison::GTs;
2403 case Hexagon::C4_cmplte:
2404 case Hexagon::C4_cmpltei:
2405 case Hexagon::J4_cmpgtn1_f_jumpnv_nt:
2406 case Hexagon::J4_cmpgtn1_f_jumpnv_t:
2407 case Hexagon::J4_cmpgti_f_jumpnv_nt:
2408 case Hexagon::J4_cmpgti_f_jumpnv_t:
2409 case Hexagon::J4_cmpgt_f_jumpnv_nt:
2410 case Hexagon::J4_cmpgt_f_jumpnv_t:
2411 return Comparison::LEs;
2413 case Hexagon::C2_cmpgtu:
2414 case Hexagon::C2_cmpgtup:
2415 case Hexagon::A4_cmpbgtu:
2416 case Hexagon::A4_cmpbgtui:
2417 case Hexagon::A4_cmphgtu:
2418 case Hexagon::A4_cmphgtui:
2419 case Hexagon::C2_cmpgtui:
2420 case Hexagon::J4_cmpgtui_t_jumpnv_nt:
2421 case Hexagon::J4_cmpgtui_t_jumpnv_t:
2422 case Hexagon::J4_cmpgtu_t_jumpnv_nt:
2423 case Hexagon::J4_cmpgtu_t_jumpnv_t:
2424 return Comparison::GTu;
2426 case Hexagon::J4_cmpltu_f_jumpnv_nt:
2427 case Hexagon::J4_cmpltu_f_jumpnv_t:
2428 return Comparison::GEu;
2430 case Hexagon::J4_cmpltu_t_jumpnv_nt:
2431 case Hexagon::J4_cmpltu_t_jumpnv_t:
2432 return Comparison::LTu;
2434 case Hexagon::J4_cmplt_f_jumpnv_nt:
2435 case Hexagon::J4_cmplt_f_jumpnv_t:
2436 return Comparison::GEs;
2438 case Hexagon::C4_cmplteu:
2439 case Hexagon::C4_cmplteui:
2440 case Hexagon::J4_cmpgtui_f_jumpnv_nt:
2441 case Hexagon::J4_cmpgtui_f_jumpnv_t:
2442 case Hexagon::J4_cmpgtu_f_jumpnv_nt:
2443 case Hexagon::J4_cmpgtu_f_jumpnv_t:
2444 return Comparison::LEu;
2446 case Hexagon::J4_cmplt_t_jumpnv_nt:
2447 case Hexagon::J4_cmplt_t_jumpnv_t:
2448 return Comparison::LTs;
2453 return Comparison::Unk;
2456 APInt HexagonConstEvaluator::getCmpImm(
unsigned Opc,
unsigned OpX,
2458 bool Signed =
false;
2460 case Hexagon::A4_cmpbgtui:
2461 case Hexagon::A4_cmphgtui:
2463 case Hexagon::A4_cmpheqi:
2464 case Hexagon::C4_cmpneqi:
2467 case Hexagon::A4_cmpbeqi:
2469 case Hexagon::C2_cmpgtui:
2470 case Hexagon::C4_cmplteui:
2472 case Hexagon::C2_cmpeqi:
2473 case Hexagon::C2_cmpgti:
2474 case Hexagon::C4_cmpltei:
2477 case Hexagon::J4_cmpeqi_f_jumpnv_nt:
2478 case Hexagon::J4_cmpeqi_f_jumpnv_t:
2479 case Hexagon::J4_cmpeqi_t_jumpnv_nt:
2480 case Hexagon::J4_cmpeqi_t_jumpnv_t:
2481 case Hexagon::J4_cmpgti_f_jumpnv_nt:
2482 case Hexagon::J4_cmpgti_f_jumpnv_t:
2483 case Hexagon::J4_cmpgti_t_jumpnv_nt:
2484 case Hexagon::J4_cmpgti_t_jumpnv_t:
2485 case Hexagon::J4_cmpgtui_f_jumpnv_nt:
2486 case Hexagon::J4_cmpgtui_f_jumpnv_t:
2487 case Hexagon::J4_cmpgtui_t_jumpnv_nt:
2488 case Hexagon::J4_cmpgtui_t_jumpnv_t:
2495 uint64_t Val = MO.
getImm();
2496 return APInt(32, Val, Signed);
2499 void HexagonConstEvaluator::replaceWithNop(
MachineInstr &MI) {
2500 MI.
setDesc(HII.get(Hexagon::A2_nop));
2506 const CellMap &Inputs, LatticeCell &Result) {
2507 assert(Inputs.has(RL.Reg) && Inputs.has(RH.Reg));
2508 LatticeCell
LSL, LSH;
2509 if (!getCell(RL, Inputs, LSL) || !getCell(RH, Inputs, LSH))
2511 if (LSL.isProperty() || LSH.isProperty())
2514 unsigned LN = LSL.size(), HN = LSH.size();
2516 for (
unsigned i = 0; i < LN; ++i) {
2517 bool Eval = constToInt(LSL.Values[i], LoVs[i]);
2522 for (
unsigned i = 0; i < HN; ++i) {
2523 bool Eval = constToInt(LSH.Values[i], HiVs[i]);
2529 for (
unsigned i = 0; i < HiVs.
size(); ++i) {
2530 APInt HV = HiVs[i].zextOrSelf(64) << 32;
2531 for (
unsigned j = 0; j < LoVs.size(); ++j) {
2533 const Constant *C = intToConst(HV | LV);
2535 if (Result.isBottom())
2539 return !Result.isBottom();
2542 bool HexagonConstEvaluator::evaluateHexCompare(
const MachineInstr &MI,
2543 const CellMap &Inputs, CellMap &Outputs) {
2545 bool Classic =
false;
2547 case Hexagon::C2_cmpeq:
2548 case Hexagon::C2_cmpeqp:
2549 case Hexagon::C2_cmpgt:
2550 case Hexagon::C2_cmpgtp:
2551 case Hexagon::C2_cmpgtu:
2552 case Hexagon::C2_cmpgtup:
2553 case Hexagon::C2_cmpeqi:
2554 case Hexagon::C2_cmpgti:
2555 case Hexagon::C2_cmpgtui:
2570 bool Computed = evaluateHexCompare2(Opc, Src1, Src2, Inputs, Result);
2575 LatticeCell L = Outputs.get(DefR.Reg);
2576 uint32_t P = Result ? ConstantProperties::NonZero
2577 : ConstantProperties::Zero;
2579 Outputs.update(DefR.Reg, L);
2587 bool HexagonConstEvaluator::evaluateHexCompare2(
unsigned Opc,
2589 const CellMap &Inputs,
bool &Result) {
2591 bool Reg1 = Src1.
isReg(), Reg2 = Src2.
isReg();
2592 bool Imm1 = Src1.
isImm(), Imm2 = Src2.
isImm();
2597 return evaluateCMPrr(Cmp, R1, R2, Inputs, Result);
2599 APInt A2 = getCmpImm(Opc, 2, Src2);
2600 return evaluateCMPri(Cmp, R1, A2, Inputs, Result);
2603 APInt A1 = getCmpImm(Opc, 1, Src1);
2606 uint32_t NegCmp = Comparison::negate(Cmp);
2607 return evaluateCMPri(NegCmp, R2, A1, Inputs, Result);
2609 APInt A2 = getCmpImm(Opc, 2, Src2);
2610 return evaluateCMPii(Cmp, A1, A2, Result);
2617 bool HexagonConstEvaluator::evaluateHexLogical(
const MachineInstr &MI,
2618 const CellMap &Inputs, CellMap &Outputs) {
2630 case Hexagon::A2_and:
2631 case Hexagon::A2_andp:
2632 Eval = evaluateANDrr(R1,
Register(Src2), Inputs, RC);
2634 case Hexagon::A2_andir: {
2638 Eval = evaluateANDri(R1, A, Inputs, RC);
2641 case Hexagon::A2_or:
2642 case Hexagon::A2_orp:
2643 Eval = evaluateORrr(R1,
Register(Src2), Inputs, RC);
2645 case Hexagon::A2_orir: {
2649 Eval = evaluateORri(R1, A, Inputs, RC);
2652 case Hexagon::A2_xor:
2653 case Hexagon::A2_xorp:
2654 Eval = evaluateXORrr(R1,
Register(Src2), Inputs, RC);
2659 Outputs.update(DefR.Reg, RC);
2664 bool HexagonConstEvaluator::evaluateHexCondMove(
const MachineInstr &MI,
2665 const CellMap &Inputs, CellMap &Outputs) {
2668 assert(Inputs.has(CR.Reg));
2670 if (!getCell(CR, Inputs, LS))
2674 if (Ps & ConstantProperties::Zero)
2676 else if (Ps & ConstantProperties::NonZero)
2683 LatticeCell RC = Outputs.get(DefR.Reg);
2685 if (ValOp.
isImm()) {
2686 int64_t V = ValOp.
getImm();
2688 APInt A(W, V,
true);
2691 Outputs.update(DefR.Reg, RC);
2694 if (ValOp.
isReg()) {
2696 const LatticeCell &LR = Inputs.get(R.Reg);
2698 if (!evaluate(R, LR, LSR))
2701 Outputs.update(DefR.Reg, RC);
2707 bool HexagonConstEvaluator::evaluateHexExt(
const MachineInstr &MI,
2708 const CellMap &Inputs, CellMap &Outputs) {
2711 assert(Inputs.has(R1.Reg));
2716 case Hexagon::A2_sxtb:
2717 case Hexagon::A2_zxtb:
2720 case Hexagon::A2_sxth:
2721 case Hexagon::A2_zxth:
2724 case Hexagon::A2_sxtw:
2729 bool Signed =
false;
2731 case Hexagon::A2_sxtb:
2732 case Hexagon::A2_sxth:
2733 case Hexagon::A2_sxtw:
2740 LatticeCell RC = Outputs.get(DefR.Reg);
2741 bool Eval = Signed ? evaluateSEXTr(R1, BW, Bits, Inputs, RC)
2742 : evaluateZEXTr(R1, BW, Bits, Inputs, RC);
2745 Outputs.update(DefR.Reg, RC);
2749 bool HexagonConstEvaluator::evaluateHexVector1(
const MachineInstr &MI,
2750 const CellMap &Inputs, CellMap &Outputs) {
2754 assert(Inputs.has(R1.Reg));
2755 LatticeCell RC = Outputs.get(DefR.Reg);
2760 case Hexagon::S2_vsplatrb:
2762 Eval = evaluateSplatr(R1, 8, 4, Inputs, RC);
2764 case Hexagon::S2_vsplatrh:
2766 Eval = evaluateSplatr(R1, 16, 4, Inputs, RC);
2774 Outputs.update(DefR.Reg, RC);
2778 bool HexagonConstEvaluator::rewriteHexConstDefs(
MachineInstr &MI,
2779 const CellMap &Inputs,
bool &AllDefs) {
2787 bool Const =
true, HasUse =
false;
2796 if (!MI.
isPHI() && !Inputs.has(R.Reg)) {
2798 <<
" in MI: " <<
MI;
2801 const LatticeCell &L = Inputs.get(R.Reg);
2802 Const &= L.isSingle();
2806 if (HasUse && Const) {
2808 dbgs() <<
"CONST: " <<
MI;
2812 unsigned R = MO.
getReg();
2813 dbgs() <<
printReg(R, &TRI) <<
": " << Inputs.get(R) <<
"\n";
2830 unsigned R = MO.
getReg();
2840 unsigned ChangedNum = 0;
2848 for (
unsigned i = 0, n = DefRegs.
size(); i < n; ++i) {
2849 unsigned R = DefRegs[i];
2850 const LatticeCell &L = Inputs.get(R);
2856 if (!L.isSingle()) {
2859 using P = ConstantProperties;
2861 uint64_t Ps = L.properties();
2862 if (!(Ps & (P::Zero|P::NonZero)))
2868 &HII.get(Hexagon::PS_false) :
2869 &HII.get(Hexagon::PS_true);
2870 unsigned NewR =
MRI->createVirtualRegister(PredRC);
2876 replaceAllRegUsesWith(R, NewR);
2887 assert(W == 32 || W == 64);
2889 NewRC = &Hexagon::IntRegsRegClass;
2891 NewRC = &Hexagon::DoubleRegsRegClass;
2892 unsigned NewR =
MRI->createVirtualRegister(NewRC);
2896 NewD = &HII.get(Hexagon::A2_tfrsi);
2897 NewMI =
BuildMI(B, At, DL, *NewD, NewR)
2901 NewD = &HII.get(Hexagon::A2_tfrpi);
2902 NewMI =
BuildMI(B, At, DL, *NewD, NewR)
2905 int32_t
Hi = V >> 32;
2906 int32_t
Lo = V & 0xFFFFFFFFLL;
2908 NewD = &HII.get(Hexagon::A2_combineii);
2909 NewMI =
BuildMI(B, At, DL, *NewD, NewR)
2913 NewD = &HII.get(Hexagon::CONST64);
2914 NewMI =
BuildMI(B, At, DL, *NewD, NewR)
2923 replaceAllRegUsesWith(R, NewR);
2929 if (!NewInstrs.
empty()) {
2931 dbgs() <<
"In function: " << MF.
getName() <<
"\n";
2932 dbgs() <<
"Rewrite: for " << MI <<
" created " << *NewInstrs[0];
2933 for (
unsigned i = 1; i < NewInstrs.size(); ++i)
2934 dbgs() <<
" " << *NewInstrs[i];
2938 AllDefs = (ChangedNum == DefRegs.
size());
2939 return ChangedNum > 0;
2942 bool HexagonConstEvaluator::rewriteHexConstUses(
MachineInstr &MI,
2943 const CellMap &Inputs) {
2944 bool Changed =
false;
2952 case Hexagon::M2_maci:
2961 assert(Inputs.has(R2.Reg) && Inputs.has(R3.Reg));
2962 LatticeCell LS2, LS3;
2965 bool HasC2 = getCell(R2, Inputs, LS2), HasC3 = getCell(R3, Inputs, LS3);
2966 if (!HasC2 && !HasC3)
2968 bool Zero = ((HasC2 && (LS2.properties() & ConstantProperties::Zero)) ||
2969 (HasC3 && (LS3.properties() & ConstantProperties::Zero)));
2975 unsigned NewR = R1.Reg;
2979 NewR =
MRI->createVirtualRegister(RC);
2980 NewMI =
BuildMI(B, At, DL, HII.
get(TargetOpcode::COPY), NewR)
2983 replaceAllRegUsesWith(DefR.Reg, NewR);
2984 MRI->clearKillFlags(NewR);
2990 if (!LS3.isSingle()) {
2991 if (!LS2.isSingle())
2995 const LatticeCell &LI = Swap ? LS2 : LS3;
3003 const MCInstrDesc &
D = (V >= 0) ? HII.get(Hexagon::M2_macsip)
3004 : HII.get(Hexagon::M2_macsin);
3008 unsigned NewR =
MRI->createVirtualRegister(RC);
3010 NewMI =
BuildMI(B, At, DL, D, NewR)
3014 replaceAllRegUsesWith(DefR.Reg, NewR);
3019 case Hexagon::A2_and:
3023 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
3024 LatticeCell LS1, LS2;
3025 unsigned CopyOf = 0;
3027 if (getCell(R1, Inputs, LS1) && LS1.isSingle()) {
3029 if (constToInt(LS1.Value, M1) && !~M1)
3032 else if (getCell(R2, Inputs, LS2) && LS2.isSingle()) {
3034 if (constToInt(LS2.Value, M1) && !~M1)
3042 unsigned NewR = SR.Reg;
3045 NewR =
MRI->createVirtualRegister(RC);
3046 NewMI =
BuildMI(B, At, DL, HII.
get(TargetOpcode::COPY), NewR)
3049 replaceAllRegUsesWith(DefR.Reg, NewR);
3050 MRI->clearKillFlags(NewR);
3055 case Hexagon::A2_or:
3059 assert(Inputs.has(R1.Reg) && Inputs.has(R2.Reg));
3060 LatticeCell LS1, LS2;
3061 unsigned CopyOf = 0;
3063 using P = ConstantProperties;
3065 if (getCell(R1, Inputs, LS1) && (LS1.properties() & P::Zero))
3067 else if (getCell(R2, Inputs, LS2) && (LS2.properties() & P::Zero))
3074 unsigned NewR = SR.Reg;
3077 NewR =
MRI->createVirtualRegister(RC);
3078 NewMI =
BuildMI(B, At, DL, HII.
get(TargetOpcode::COPY), NewR)
3081 replaceAllRegUsesWith(DefR.Reg, NewR);
3082 MRI->clearKillFlags(NewR);
3097 dbgs() <<
"Rewrite: for " <<
MI;
3099 dbgs() <<
" created " << *NewMI;
3101 dbgs() <<
" modified the instruction itself and created:" << *NewMI;
3108 void HexagonConstEvaluator::replaceAllRegUsesWith(
unsigned FromReg,
3112 for (
auto I =
MRI->use_begin(FromReg),
E =
MRI->use_end();
I !=
E;) {
3119 bool HexagonConstEvaluator::rewriteHexBranch(
MachineInstr &BrI,
3120 const CellMap &Inputs) {
3128 bool Eval = evaluate(BrI, Inputs, Targets, FallsThru);
3129 unsigned NumTargets = Targets.
size();
3130 if (!Eval || NumTargets > 1 || (NumTargets == 1 && FallsThru))
3132 if (BrI.
getOpcode() == Hexagon::J2_jump)
3136 bool Rewritten =
false;
3137 if (NumTargets > 0) {
3138 assert(!FallsThru &&
"This should have been checked before");
3147 const MCInstrDesc &JD = HII.get(Hexagon::J2_jump);
3155 for (
auto &
Op : NI->operands())
3157 NI->eraseFromParent();
3166 replaceWithNop(BrI);
3171 return new HexagonConstPropagation();
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
const_iterator end(StringRef path)
Get end iterator over path.
DILocation * get() const
Get the underlying DILocation.
uint64_t getZExtValue() const
Get zero extended value.
APInt sext(unsigned width) const
Sign extend to a new width.
bool isCall(QueryType Type=AnyInBundle) const
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
MachineBasicBlock * getMBB() const
unsigned getRegState(const MachineOperand &RegOp)
Get all register state flags from machine operand RegOp.
This class represents lattice values for constants.
size_type size() const
Determine the number of elements in the SetVector.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
void push_back(const T &Elt)
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Describe properties that are true of each instruction in the target description file.
unsigned getReg() const
getReg - Returns the register number.
APInt zext(unsigned width) const
Zero extend to a new width.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
bool slt(const APInt &RHS) const
Signed less than comparison.
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 getSubReg() const
unsigned getRegBitWidth(unsigned RCID)
Get the size in bits of a register from the register class RC.
bool isRegSequence() const
constexpr bool isInt< 8 >(int64_t x)
APInt trunc(unsigned width) const
Truncate to new width.
unsigned const TargetRegisterInfo * TRI
static IntegerType * getInt64Ty(LLVMContext &C)
APInt zextOrTrunc(unsigned width) const
Zero extend or truncate to width.
iterator_range< mop_iterator > operands()
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
unsigned getBitWidth() const
Return the number of bits in the APInt.
iterator_range< succ_iterator > successors()
unsigned countTrailingZeros() const
Count the number of trailing zero bits.
void initializeHexagonConstPropagationPass(PassRegistry &Registry)
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
APInt shl(unsigned shiftAmt) const
Left-shift function.
unsigned getNumOperands() const
Retuns the total number of operands.
Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
APInt zextOrSelf(unsigned width) const
Zero extend or truncate to width.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
friend const_iterator begin(StringRef path, Style style)
Get begin iterator over path.
bool remove(const value_type &X)
Remove an item from the set vector.
This file implements a class to represent arbitrary precision integral constant values and operations...
int64_t getSExtValue() const
Get sign extended value.
bool insert(const value_type &X)
Insert a new element into the SetVector.
bool isNegative() const
Return true if the sign bit is set.
const APInt & getValue() const
Return the constant as an APInt value reference.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
bool isBranch(QueryType Type=AnyInBundle) const
Returns true if this is a conditional, unconditional, or indirect branch.
size_type count(const key_type &key) const
Count the number of elements of a given key in the SetVector.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
FunctionPass * createHexagonConstPropagationPass()
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
bool isNegative() const
Determine sign of this APInt.
friend const_iterator end(StringRef path)
Get end iterator over path.
MachineBasicBlock * getBlockNumbered(unsigned N) const
getBlockNumbered - MachineBasicBlocks are automatically numbered when they are inserted into the mach...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
unsigned const MachineRegisterInfo * MRI
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
bool isCompare(QueryType Type=IgnoreBundle) const
Return true if this instruction is a comparison.
This is an important class for using LLVM in a threaded context.
bool ult(const APInt &RHS) const
Unsigned less than comparison.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
ConstantFP - Floating Point Values [float, double].
This file declares a class to represent arbitrary precision floating point values and provide a varie...
void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
FunctionPass class - This class is used to implement most global optimizations.
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
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)
bool isIntN(unsigned N) const
Check if this APInt has an N-bits unsigned integer value.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this 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!) to ensure ...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
bool isDebugInstr() const
void print(raw_ostream &OS, const SlotIndexes *=nullptr) const
print - Print out the MachineFunction in a format suitable for debugging to the specified stream...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
void setIsKill(bool Val=true)
const APFloat & getValueAPF() const
APInt ashr(unsigned ShiftAmt) const
Arithmetic right-shift function.
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.
auto size(R &&Range, typename std::enable_if< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void >::type *=nullptr) -> decltype(std::distance(Range.begin(), Range.end()))
Get the size of a range.
BlockVerifier::State From
void addOperand(MachineFunction &MF, const MachineOperand &Op)
Add the specified operand to the instruction.
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...
Promote Memory to Register
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
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 isLayoutSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB will be emitted immediately after this block, such that if this bloc...
const Function & getFunction() const
Return the LLVM function that this machine code represents.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
unsigned countTrailingOnes() const
Count the number of trailing one bits.
void clear()
Completely clear the SetVector.
Class for arbitrary precision integers.
INITIALIZE_PASS(HexagonConstPropagation, "hexagon-constp", "Hexagon Constant Propagation", false, false) HexagonConstEvaluator
static void clear(coro::Shape &Shape)
bool isUnconditionalBranch(QueryType Type=AnyInBundle) const
Return true if this is a branch which always transfers control flow to some other block...
static void propagate(InstantiatedValue From, InstantiatedValue To, MatchState State, ReachabilitySet &ReachSet, std::vector< WorkListItem > &WorkList)
const MachineBasicBlock * getParent() const
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.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
static IntegerType * getInt32Ty(LLVMContext &C)
LLVM_NODISCARD bool empty() const
bool isZero() const
Return true if the value is positive or negative zero.
bool isNaN() const
Return true if the value is a NaN.
void setReg(unsigned Reg)
Change the register this operand corresponds to.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool isSignedIntN(unsigned N) const
Check if this APInt has an N-bits signed integer value.
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.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
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...
StringRef - Represent a constant reference to a string, i.e.
unsigned countLeadingOnes() const
Count the number of leading one bits.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
void RemoveOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with...
unsigned countLeadingZeros() const
The APInt version of the countLeadingZeros functions in MathExtras.h.
bool operator==(uint64_t V1, const APInt &V2)
const MachineOperand & getOperand(unsigned i) const
bool DebugFlag
This boolean is set to true if the '-debug' command line option is specified.
APInt sextOrSelf(unsigned width) const
Sign extend or truncate to width.
bool isCurrentDebugType(const char *Type)
isCurrentDebugType - Return true if the specified string is the debug type specified on the command l...