9 #define DEBUG_TYPE "hcp" 58 class ConstantProperties {
68 NumericProperties = (Zero|NonZero|Finite|Infinity|NaN|SignedZero),
71 SignProperties = (PosOrZero|NegOrZero),
72 Everything = (NumericProperties|SignProperties)
85 struct RegisterSubReg {
89 explicit RegisterSubReg(
unsigned R,
unsigned SR = 0) :
Reg(R),
SubReg(SR) {}
97 bool operator== (
const RegisterSubReg &R)
const {
98 return (
Reg == R.Reg) && (
SubReg == R.SubReg);
111 enum { Normal, Top, Bottom };
113 static const unsigned MaxCellSize = 4;
117 unsigned IsSpecial:1;
124 const Constant *Values[MaxCellSize];
127 LatticeCell() :
Kind(Top),
Size(0), IsSpecial(
false) {
128 for (
unsigned i = 0; i < MaxCellSize; ++i)
132 bool meet(
const LatticeCell &L);
136 unsigned size()
const {
return Size; }
138 LatticeCell(
const LatticeCell &L) {
141 L.IsSpecial ?
sizeof L.Properties : L.Size *
sizeof(
const Constant *);
142 memcpy(Values, L.Values,
N);
145 IsSpecial = L.IsSpecial;
148 LatticeCell &
operator=(
const LatticeCell &L) {
151 uint32_t N = L.IsSpecial ?
sizeof L.Properties
152 : L.Size *
sizeof(
const Constant *);
153 memcpy(Values, L.Values,
N);
156 IsSpecial = L.IsSpecial;
161 bool isSingle()
const {
return size() == 1; }
162 bool isProperty()
const {
return IsSpecial; }
163 bool isTop()
const {
return Kind == Top; }
164 bool isBottom()
const {
return Kind == Bottom; }
167 bool Changed = (
Kind != Bottom);
183 bool convertToProperty();
193 class MachineConstEvaluator;
195 class MachineConstPropagator {
197 MachineConstPropagator(MachineConstEvaluator &
E) : MCE(
E) {
218 void clear() { Map.clear(); }
224 MapType::const_iterator
F = Map.find(R);
225 return F != Map.end();
228 const LatticeCell &get(
Register R)
const {
231 MapType::const_iterator
F = Map.find(R);
238 void update(
Register R,
const LatticeCell &L) { Map[R] = L; }
243 using MapType = std::map<Register, LatticeCell>;
249 LatticeCell Top, Bottom;
252 using const_iterator = MapType::const_iterator;
254 const_iterator
begin()
const {
return Map.begin(); }
255 const_iterator
end()
const {
return Map.end(); }
264 void visitUsesOf(
unsigned R);
273 MachineConstEvaluator &MCE;
275 using CFGEdge = std::pair<unsigned, unsigned>;
276 using SetOfCFGEdge = std::set<CFGEdge>;
277 using SetOfInstr = std::set<const MachineInstr *>;
278 using QueueOfCFGEdge = std::queue<CFGEdge>;
282 SetOfCFGEdge EdgeExec;
283 SetOfInstr InstrExec;
284 QueueOfCFGEdge FlowQ;
290 class MachineConstEvaluator {
295 virtual ~MachineConstEvaluator() =
default;
312 using CellMap = MachineConstPropagator::CellMap;
313 virtual bool evaluate(
const MachineInstr &
MI,
const CellMap &Inputs,
314 CellMap &Outputs) = 0;
315 virtual bool evaluate(
const RegisterSubReg &R,
const LatticeCell &SrcC,
316 LatticeCell &Result) = 0;
317 virtual bool evaluate(
const MachineInstr &BrI,
const CellMap &Inputs,
319 bool &CanFallThru) = 0;
358 bool getCell(
const RegisterSubReg &R,
const CellMap &Inputs, LatticeCell &RC);
364 bool evaluateCMPrr(
uint32_t Cmp,
const RegisterSubReg &R1,
const RegisterSubReg &
R2,
365 const CellMap &Inputs,
bool &Result);
366 bool evaluateCMPri(
uint32_t Cmp,
const RegisterSubReg &R1,
const APInt &A2,
367 const CellMap &Inputs,
bool &Result);
368 bool evaluateCMPrp(
uint32_t Cmp,
const RegisterSubReg &R1, uint64_t Props2,
369 const CellMap &Inputs,
bool &Result);
377 bool evaluateCOPY(
const RegisterSubReg &R1,
const CellMap &Inputs,
378 LatticeCell &Result);
381 bool evaluateANDrr(
const RegisterSubReg &R1,
const RegisterSubReg &
R2,
382 const CellMap &Inputs, LatticeCell &Result);
383 bool evaluateANDri(
const RegisterSubReg &R1,
const APInt &A2,
384 const CellMap &Inputs, LatticeCell &Result);
386 bool evaluateORrr(
const RegisterSubReg &R1,
const RegisterSubReg &
R2,
387 const CellMap &Inputs, LatticeCell &Result);
388 bool evaluateORri(
const RegisterSubReg &R1,
const APInt &A2,
389 const CellMap &Inputs, LatticeCell &Result);
391 bool evaluateXORrr(
const RegisterSubReg &R1,
const RegisterSubReg &
R2,
392 const CellMap &Inputs, LatticeCell &Result);
393 bool evaluateXORri(
const RegisterSubReg &R1,
const APInt &A2,
394 const CellMap &Inputs, LatticeCell &Result);
398 bool evaluateZEXTr(
const RegisterSubReg &R1,
unsigned Width,
unsigned Bits,
399 const CellMap &Inputs, LatticeCell &Result);
400 bool evaluateZEXTi(
const APInt &A1,
unsigned Width,
unsigned Bits,
402 bool evaluateSEXTr(
const RegisterSubReg &R1,
unsigned Width,
unsigned Bits,
403 const CellMap &Inputs, LatticeCell &Result);
404 bool evaluateSEXTi(
const APInt &A1,
unsigned Width,
unsigned Bits,
408 bool evaluateCLBr(
const RegisterSubReg &R1,
bool Zeros,
bool Ones,
409 const CellMap &Inputs, LatticeCell &Result);
410 bool evaluateCLBi(
const APInt &A1,
bool Zeros,
bool Ones,
APInt &Result);
411 bool evaluateCTBr(
const RegisterSubReg &R1,
bool Zeros,
bool Ones,
412 const CellMap &Inputs, LatticeCell &Result);
413 bool evaluateCTBi(
const APInt &A1,
bool Zeros,
bool Ones,
APInt &Result);
416 bool evaluateEXTRACTr(
const RegisterSubReg &R1,
unsigned Width,
unsigned Bits,
418 LatticeCell &Result);
422 bool evaluateSplatr(
const RegisterSubReg &R1,
unsigned Bits,
unsigned Count,
423 const CellMap &Inputs, LatticeCell &Result);
424 bool evaluateSplati(
const APInt &A1,
unsigned Bits,
unsigned Count,
431 if (isa<ConstantInt>(
C)) {
434 return Zero | PosOrZero | NegOrZero | Finite;
435 uint32_t Props = (NonZero | Finite);
437 return Props | NegOrZero;
438 return Props | PosOrZero;
441 if (isa<ConstantFP>(
C)) {
446 return (Props & ~NumericProperties) | (Zero|Finite);
447 Props = (Props & ~NumericProperties) | NonZero;
449 return (Props & ~NumericProperties) | NaN;
452 return (Props & ~NumericProperties) | Infinity;
462 bool LatticeCell::convertToProperty() {
467 uint32_t Everything = ConstantProperties::Everything;
468 uint32_t Ps = !isTop() ? properties()
484 if (Ps & ConstantProperties::Zero)
486 if (Ps & ConstantProperties::NonZero)
488 if (Ps & ConstantProperties::Finite)
490 if (Ps & ConstantProperties::Infinity)
492 if (Ps & ConstantProperties::NaN)
494 if (Ps & ConstantProperties::PosOrZero)
496 if (Ps & ConstantProperties::NegOrZero)
505 }
else if (isTop()) {
508 for (
unsigned i = 0; i <
size(); ++i) {
521 bool LatticeCell::meet(
const LatticeCell &L) {
522 bool Changed =
false;
524 Changed = setBottom();
525 if (isBottom() || L.isTop())
535 return add(L.properties());
536 for (
unsigned i = 0; i < L.size(); ++i) {
564 if (
Index < MaxCellSize) {
572 bool Changed =
false;
576 Changed = convertToProperty();
578 uint32_t NewPs = Ps & ConstantProperties::deduce(LC);
593 bool Changed = convertToProperty();
595 if (Ps == (Ps & Property))
597 Properties = Property & Ps;
603 uint32_t LatticeCell::properties()
const {
606 assert(!isTop() &&
"Should not call this for a top cell");
611 uint32_t Ps = ConstantProperties::deduce(Values[0]);
612 for (
unsigned i = 1; i <
size(); ++i) {
615 Ps &= ConstantProperties::deduce(Values[i]);
628 void MachineConstPropagator::visitPHI(
const MachineInstr &PN) {
634 RegisterSubReg DefR(MD);
635 assert(DefR.Reg.isVirtual());
637 bool Changed =
false;
642 const LatticeCell &
T = Cells.get(DefR.Reg);
643 Changed = !
T.isBottom();
644 Cells.update(DefR.Reg, Bottom);
646 visitUsesOf(DefR.Reg);
650 LatticeCell DefC = Cells.get(DefR.Reg);
655 if (!EdgeExec.count(CFGEdge(PBN, MBN))) {
661 RegisterSubReg UseR(SO);
664 if (!UseR.Reg.isVirtual())
667 if (!Cells.has(UseR.Reg))
671 bool Eval = MCE.evaluate(UseR, Cells.get(UseR.Reg), SrcC);
673 <<
printReg(UseR.Reg, &MCE.TRI, UseR.SubReg) << SrcC
675 Changed |= Eval ? DefC.meet(SrcC)
677 Cells.update(DefR.Reg, DefC);
682 visitUsesOf(DefR.Reg);
685 void MachineConstPropagator::visitNonBranch(
const MachineInstr &
MI) {
689 bool Eval = MCE.evaluate(
MI, Cells, Outputs);
692 dbgs() <<
" outputs:";
693 for (
auto &
I : Outputs)
694 dbgs() <<
' ' <<
I.second;
702 if (!MO.isReg() || !MO.isDef())
704 RegisterSubReg DefR(MO);
706 if (!DefR.Reg.isVirtual())
708 bool Changed =
false;
711 const LatticeCell &
T = Cells.get(DefR.Reg);
712 Changed = !
T.isBottom();
713 Cells.update(DefR.Reg, Bottom);
717 if (!Outputs.has(DefR.Reg))
719 LatticeCell RC = Cells.get(DefR.Reg);
720 Changed = RC.meet(Outputs.get(DefR.Reg));
721 Cells.update(DefR.Reg, RC);
724 visitUsesOf(DefR.Reg);
732 void MachineConstPropagator::visitBranchesFrom(
const MachineInstr &BrI) {
734 unsigned MBN =
B.getNumber();
739 bool EvalOk =
true, FallsThru =
true;
742 InstrExec.insert(&
MI);
748 EvalOk = EvalOk && MCE.evaluate(
MI, Cells, Targets, FallsThru);
756 if (
B.mayHaveInlineAsmBr())
771 if (Next != MF.
end())
781 LLVM_DEBUG(
dbgs() <<
" failed to evaluate a branch...adding all CFG " 788 unsigned TBN =
TB->getNumber();
791 FlowQ.push(CFGEdge(MBN, TBN));
795 void MachineConstPropagator::visitUsesOf(
unsigned Reg) {
797 << Cells.get(
Reg) <<
'\n');
802 if (!InstrExec.count(&
MI))
806 else if (!
MI.isBranch())
809 visitBranchesFrom(
MI);
821 if (
MI.isDebugInstr())
824 FirstBr =
MI.getIterator();
835 if (
MI.isDebugInstr())
837 if (!InstrExec.count(&
MI))
839 bool Eval = MCE.evaluate(
MI, Cells, Targets, DoNext);
849 if (NextI != MB->getParent()->end())
864 From->removeSuccessor(To);
882 unsigned EntryNum = Entry->getNumber();
885 FlowQ.push(CFGEdge(EntryNum, EntryNum));
887 while (!FlowQ.empty()) {
888 CFGEdge Edge = FlowQ.front();
892 dbgs() <<
"Picked edge " 895 if (Edge.first != EntryNum)
896 if (EdgeExec.count(Edge))
898 EdgeExec.insert(Edge);
908 while (It != End && It->isPHI()) {
909 InstrExec.insert(&*It);
917 while (It != End && It->isDebugInstr())
919 assert(It == End || !It->isPHI());
921 if (It != End && InstrExec.count(&*It))
925 while (It != End && !It->isBranch()) {
926 if (!It->isDebugInstr()) {
927 InstrExec.insert(&*It);
938 visitBranchesFrom(*It);
944 FlowQ.push(CFGEdge(SBN, SSB->getNumber()));
949 dbgs() <<
"Cells after propagation:\n";
950 Cells.print(
dbgs(), MCE.TRI);
951 dbgs() <<
"Dead CFG edges:\n";
953 unsigned BN =
B.getNumber();
956 if (!EdgeExec.count(CFGEdge(BN, SN)))
965 bool Changed =
false;
982 std::vector<MachineBasicBlock*> POT;
996 bool HaveTargets = computeBlockSuccessors(
B, Targets);
999 for (
auto I =
B->rbegin(),
E =
B->rend();
I !=
E; ++
I) {
1001 if (InstrExec.count(&
MI)) {
1002 if (
MI.isBranch() && !HaveTargets)
1004 Changed |= MCE.rewrite(
MI, Cells);
1010 for (
auto I =
B->begin(),
E =
B->end();
I !=
E; ++
I) {
1030 if (!Targets.
count(SB))
1031 ToRemove.push_back(const_cast<MachineBasicBlock*>(SB));
1034 for (
unsigned i = 0, n =
ToRemove.size(); i < n; ++i)
1051 auto Next = std::next(
I);
1052 if (
I->isBranch() && !InstrExec.count(&*
I))
1076 dbgs() <<
"End of MachineConstPropagator (Changed=" << Changed <<
")\n";
1086 bool MachineConstEvaluator::getCell(
const RegisterSubReg &R,
const CellMap &Inputs,
1088 if (!
R.Reg.isVirtual())
1090 const LatticeCell &L = Inputs.get(
R.Reg);
1093 return !RC.isBottom();
1095 bool Eval = evaluate(R, L, RC);
1096 return Eval && !RC.isBottom();
1099 bool MachineConstEvaluator::constToInt(
const Constant *
C,
1108 const ConstantInt *MachineConstEvaluator::intToConst(
const APInt &Val)
const {
1112 bool MachineConstEvaluator::evaluateCMPrr(
uint32_t Cmp,
const RegisterSubReg &R1,
1113 const RegisterSubReg &
R2,
const CellMap &Inputs,
bool &Result) {
1114 assert(Inputs.has(R1.Reg) && Inputs.has(
R2.Reg));
1115 LatticeCell LS1, LS2;
1116 if (!getCell(R1, Inputs, LS1) || !getCell(
R2, Inputs, LS2))
1119 bool IsProp1 = LS1.isProperty();
1120 bool IsProp2 = LS2.isProperty();
1124 return evaluateCMPpp(Cmp, Prop1, LS2.properties(),
Result);
1125 uint32_t NegCmp = Comparison::negate(Cmp);
1126 return evaluateCMPrp(NegCmp,
R2, Prop1, Inputs, Result);
1130 return evaluateCMPrp(Cmp, R1, Prop2, Inputs, Result);
1134 bool IsTrue =
true, IsFalse =
true;
1135 for (
unsigned i = 0; i < LS2.size(); ++i) {
1137 bool Computed = constToInt(LS2.Values[i], A) &&
1138 evaluateCMPri(Cmp, R1, A, Inputs, Res);
1144 assert(!IsTrue || !IsFalse);
1148 return IsTrue || IsFalse;
1151 bool MachineConstEvaluator::evaluateCMPri(
uint32_t Cmp,
const RegisterSubReg &R1,
1152 const APInt &A2,
const CellMap &Inputs,
bool &Result) {
1153 assert(Inputs.has(R1.Reg));
1155 if (!getCell(R1, Inputs,
LS))
1157 if (
LS.isProperty())
1158 return evaluateCMPpi(Cmp,
LS.properties(), A2,
Result);
1161 bool IsTrue =
true, IsFalse =
true;
1162 for (
unsigned i = 0; i <
LS.size(); ++i) {
1164 bool Computed = constToInt(
LS.Values[i], A) &&
1165 evaluateCMPii(Cmp, A, A2, Res);
1171 assert(!IsTrue || !IsFalse);
1175 return IsTrue || IsFalse;
1178 bool MachineConstEvaluator::evaluateCMPrp(
uint32_t Cmp,
const RegisterSubReg &R1,
1179 uint64_t Props2,
const CellMap &Inputs,
bool &Result) {
1180 assert(Inputs.has(R1.Reg));
1182 if (!getCell(R1, Inputs,
LS))
1184 if (
LS.isProperty())
1185 return evaluateCMPpp(Cmp,
LS.properties(), Props2,
Result);
1188 uint32_t NegCmp = Comparison::negate(Cmp);
1189 bool IsTrue =
true, IsFalse =
true;
1190 for (
unsigned i = 0; i <
LS.size(); ++i) {
1192 bool Computed = constToInt(
LS.Values[i], A) &&
1193 evaluateCMPpi(NegCmp, Props2, A, Res);
1199 assert(!IsTrue || !IsFalse);
1201 return IsTrue || IsFalse;
1204 bool MachineConstEvaluator::evaluateCMPii(
uint32_t Cmp,
const APInt &A1,
1205 const APInt &A2,
bool &Result) {
1217 return (Result =
true);
1224 unsigned MaxW = (W1 >= W2) ? W1 : W2;
1225 if (Cmp & Comparison::U) {
1228 if (Cmp & Comparison::L)
1238 if (Cmp & Comparison::L)
1246 const APInt &A2,
bool &Result) {
1251 if (Props & ConstantProperties::NaN)
1256 if (!(Props & ConstantProperties::Finite))
1261 if (Cmp & Comparison::U) {
1265 if (Props & ConstantProperties::Zero)
1267 else if (Props & ConstantProperties::NonZero)
1274 if (Props & ConstantProperties::Zero) {
1282 if (Props & ConstantProperties::Zero) {
1287 ((Cmp & Comparison::L) && !A2.
isNegative()) ||
1291 if (Props & ConstantProperties::PosOrZero) {
1299 if (Props & ConstantProperties::NegOrZero) {
1313 using P = ConstantProperties;
1315 if ((Props1 & P::NaN) && (Props2 & P::NaN))
1317 if (!(Props1 & P::Finite) || !(Props2 & P::Finite))
1320 bool Zero1 = (Props1 & P::Zero), Zero2 = (Props2 & P::Zero);
1321 bool NonZero1 = (Props1 & P::NonZero), NonZero2 = (Props2 & P::NonZero);
1322 if (Zero1 && Zero2) {
1327 if ((Zero1 && NonZero2) || (NonZero1 && Zero2))
1328 return (Result =
true);
1332 if (Cmp & Comparison::U) {
1335 if (Zero1 && NonZero2) {
1339 if (NonZero1 && Zero2) {
1347 bool Poz1 = (Props1 & P::PosOrZero), Poz2 = (Props2 & P::PosOrZero);
1348 bool Nez1 = (Props1 & P::NegOrZero), Nez2 = (Props2 & P::NegOrZero);
1350 if (NonZero1 || NonZero2) {
1356 return (Result =
true);
1359 if (NonZero1 || NonZero2) {
1365 return (Result =
true);
1371 bool MachineConstEvaluator::evaluateCOPY(
const RegisterSubReg &R1,
1372 const CellMap &Inputs, LatticeCell &Result) {
1373 return getCell(R1, Inputs, Result);
1376 bool MachineConstEvaluator::evaluateANDrr(
const RegisterSubReg &R1,
1377 const RegisterSubReg &
R2,
const CellMap &Inputs, LatticeCell &Result) {
1378 assert(Inputs.has(R1.Reg) && Inputs.has(
R2.Reg));
1379 const LatticeCell &L1 = Inputs.get(
R2.Reg);
1380 const LatticeCell &L2 = Inputs.get(
R2.Reg);
1384 if (L2.isBottom()) {
1387 return evaluateANDrr(
R2, R1, Inputs, Result);
1390 if (!evaluate(
R2, L2, LS2))
1392 if (LS2.isBottom() || LS2.isProperty())
1396 for (
unsigned i = 0; i < LS2.size(); ++i) {
1398 bool Eval = constToInt(LS2.Values[i], A) &&
1399 evaluateANDri(R1, A, Inputs, RC);
1404 return !
Result.isBottom();
1407 bool MachineConstEvaluator::evaluateANDri(
const RegisterSubReg &R1,
1408 const APInt &A2,
const CellMap &Inputs, LatticeCell &Result) {
1409 assert(Inputs.has(R1.Reg));
1411 return getCell(R1, Inputs, Result);
1414 RC.add(intToConst(A2));
1420 if (!getCell(R1, Inputs, LS1))
1422 if (LS1.isBottom() || LS1.isProperty())
1426 for (
unsigned i = 0; i < LS1.size(); ++i) {
1427 bool Eval = constToInt(LS1.Values[i], A) &&
1428 evaluateANDii(A, A2, ResA);
1434 return !
Result.isBottom();
1437 bool MachineConstEvaluator::evaluateANDii(
const APInt &A1,
1443 bool MachineConstEvaluator::evaluateORrr(
const RegisterSubReg &R1,
1444 const RegisterSubReg &
R2,
const CellMap &Inputs, LatticeCell &Result) {
1445 assert(Inputs.has(R1.Reg) && Inputs.has(
R2.Reg));
1446 const LatticeCell &L1 = Inputs.get(
R2.Reg);
1447 const LatticeCell &L2 = Inputs.get(
R2.Reg);
1451 if (L2.isBottom()) {
1454 return evaluateORrr(
R2, R1, Inputs, Result);
1457 if (!evaluate(
R2, L2, LS2))
1459 if (LS2.isBottom() || LS2.isProperty())
1463 for (
unsigned i = 0; i < LS2.size(); ++i) {
1465 bool Eval = constToInt(LS2.Values[i], A) &&
1466 evaluateORri(R1, A, Inputs, RC);
1471 return !
Result.isBottom();
1474 bool MachineConstEvaluator::evaluateORri(
const RegisterSubReg &R1,
1475 const APInt &A2,
const CellMap &Inputs, LatticeCell &Result) {
1476 assert(Inputs.has(R1.Reg));
1478 return getCell(R1, Inputs, Result);
1481 RC.add(intToConst(A2));
1487 if (!getCell(R1, Inputs, LS1))
1489 if (LS1.isBottom() || LS1.isProperty())
1493 for (
unsigned i = 0; i < LS1.size(); ++i) {
1494 bool Eval = constToInt(LS1.Values[i], A) &&
1495 evaluateORii(A, A2, ResA);
1501 return !
Result.isBottom();
1504 bool MachineConstEvaluator::evaluateORii(
const APInt &A1,
1510 bool MachineConstEvaluator::evaluateXORrr(
const RegisterSubReg &R1,
1511 const RegisterSubReg &
R2,
const CellMap &Inputs, LatticeCell &Result) {
1512 assert(Inputs.has(R1.Reg) && Inputs.has(
R2.Reg));
1513 LatticeCell LS1, LS2;
1514 if (!getCell(R1, Inputs, LS1) || !getCell(
R2, Inputs, LS2))
1516 if (LS1.isProperty()) {
1517 if (LS1.properties() & ConstantProperties::Zero)
1518 return !(Result = LS2).isBottom();
1521 if (LS2.isProperty()) {
1522 if (LS2.properties() & ConstantProperties::Zero)
1523 return !(Result = LS1).isBottom();
1528 for (
unsigned i = 0; i < LS2.size(); ++i) {
1530 bool Eval = constToInt(LS2.Values[i], A) &&
1531 evaluateXORri(R1, A, Inputs, RC);
1536 return !
Result.isBottom();
1539 bool MachineConstEvaluator::evaluateXORri(
const RegisterSubReg &R1,
1540 const APInt &A2,
const CellMap &Inputs, LatticeCell &Result) {
1541 assert(Inputs.has(R1.Reg));
1543 if (!getCell(R1, Inputs, LS1))
1545 if (LS1.isProperty()) {
1546 if (LS1.properties() & ConstantProperties::Zero) {
1549 return !
Result.isBottom();
1555 for (
unsigned i = 0; i < LS1.size(); ++i) {
1556 bool Eval = constToInt(LS1.Values[i], A) &&
1557 evaluateXORii(A, A2, XA);
1563 return !
Result.isBottom();
1566 bool MachineConstEvaluator::evaluateXORii(
const APInt &A1,
1572 bool MachineConstEvaluator::evaluateZEXTr(
const RegisterSubReg &R1,
unsigned Width,
1573 unsigned Bits,
const CellMap &Inputs, LatticeCell &Result) {
1574 assert(Inputs.has(R1.Reg));
1576 if (!getCell(R1, Inputs, LS1))
1578 if (LS1.isProperty())
1582 for (
unsigned i = 0; i < LS1.size(); ++i) {
1583 bool Eval = constToInt(LS1.Values[i], A) &&
1593 bool MachineConstEvaluator::evaluateZEXTi(
const APInt &A1,
unsigned Width,
1603 bool MachineConstEvaluator::evaluateSEXTr(
const RegisterSubReg &R1,
unsigned Width,
1604 unsigned Bits,
const CellMap &Inputs, LatticeCell &Result) {
1605 assert(Inputs.has(R1.Reg));
1607 if (!getCell(R1, Inputs, LS1))
1609 if (LS1.isBottom() || LS1.isProperty())
1613 for (
unsigned i = 0; i < LS1.size(); ++i) {
1614 bool Eval = constToInt(LS1.Values[i], A) &&
1624 bool MachineConstEvaluator::evaluateSEXTi(
const APInt &A1,
unsigned Width,
1636 if (BW <= 64 &&
Bits != 0) {
1640 V = static_cast<int8_t>(V);
1643 V = static_cast<int16_t>(V);
1646 V = static_cast<int32_t>(V);
1668 bool MachineConstEvaluator::evaluateCLBr(
const RegisterSubReg &R1,
bool Zeros,
1669 bool Ones,
const CellMap &Inputs, LatticeCell &Result) {
1670 assert(Inputs.has(R1.Reg));
1672 if (!getCell(R1, Inputs, LS1))
1674 if (LS1.isBottom() || LS1.isProperty())
1678 for (
unsigned i = 0; i < LS1.size(); ++i) {
1679 bool Eval = constToInt(LS1.Values[i], A) &&
1680 evaluateCLBi(A, Zeros, Ones, CA);
1689 bool MachineConstEvaluator::evaluateCLBi(
const APInt &A1,
bool Zeros,
1690 bool Ones,
APInt &Result) {
1692 if (!Zeros && !Ones)
1695 if (Zeros && (Count == 0))
1697 if (Ones && (Count == 0))
1699 Result =
APInt(BW, static_cast<uint64_t>(Count),
false);
1703 bool MachineConstEvaluator::evaluateCTBr(
const RegisterSubReg &R1,
bool Zeros,
1704 bool Ones,
const CellMap &Inputs, LatticeCell &Result) {
1705 assert(Inputs.has(R1.Reg));
1707 if (!getCell(R1, Inputs, LS1))
1709 if (LS1.isBottom() || LS1.isProperty())
1713 for (
unsigned i = 0; i < LS1.size(); ++i) {
1714 bool Eval = constToInt(LS1.Values[i], A) &&
1715 evaluateCTBi(A, Zeros, Ones, CA);
1724 bool MachineConstEvaluator::evaluateCTBi(
const APInt &A1,
bool Zeros,
1725 bool Ones,
APInt &Result) {
1727 if (!Zeros && !Ones)
1730 if (Zeros && (Count == 0))
1732 if (Ones && (Count == 0))
1734 Result =
APInt(BW, static_cast<uint64_t>(Count),
false);
1738 bool MachineConstEvaluator::evaluateEXTRACTr(
const RegisterSubReg &R1,
1740 const CellMap &Inputs, LatticeCell &Result) {
1741 assert(Inputs.has(R1.Reg));
1744 if (!getCell(R1, Inputs, LS1))
1748 if (LS1.isProperty()) {
1750 if (Ps & ConstantProperties::Zero) {
1759 for (
unsigned i = 0; i < LS1.size(); ++i) {
1760 bool Eval = constToInt(LS1.Values[i], A) &&
1770 bool MachineConstEvaluator::evaluateEXTRACTi(
const APInt &A1,
unsigned Bits,
1785 V = static_cast<uint64_t>(V) >> (64-
Bits);
1796 bool MachineConstEvaluator::evaluateSplatr(
const RegisterSubReg &R1,
1797 unsigned Bits,
unsigned Count,
const CellMap &Inputs,
1798 LatticeCell &Result) {
1799 assert(Inputs.has(R1.Reg));
1801 if (!getCell(R1, Inputs, LS1))
1803 if (LS1.isBottom() || LS1.isProperty())
1807 for (
unsigned i = 0; i < LS1.size(); ++i) {
1808 bool Eval = constToInt(LS1.Values[i], A) &&
1809 evaluateSplati(A,
Bits, Count, SA);
1818 bool MachineConstEvaluator::evaluateSplati(
const APInt &A1,
unsigned Bits,
1819 unsigned Count,
APInt &Result) {
1824 LoBits = LoBits.
zext(SW);
1826 APInt Res(SW, 0,
false);
1827 for (
unsigned i = 0; i < Count; ++i) {
1847 class HexagonConstEvaluator :
public MachineConstEvaluator {
1852 CellMap &Outputs)
override;
1853 bool evaluate(
const RegisterSubReg &R,
const LatticeCell &SrcC,
1854 LatticeCell &Result)
override;
1855 bool evaluate(
const MachineInstr &BrI,
const CellMap &Inputs,
1864 static APInt getCmpImm(
unsigned Opc,
unsigned OpX,
1868 bool evaluateHexRSEQ32(RegisterSubReg RL, RegisterSubReg RH,
const CellMap &Inputs,
1869 LatticeCell &Result);
1870 bool evaluateHexCompare(
const MachineInstr &
MI,
const CellMap &Inputs,
1874 const MachineOperand &Src2,
const CellMap &Inputs,
bool &Result);
1875 bool evaluateHexLogical(
const MachineInstr &
MI,
const CellMap &Inputs,
1877 bool evaluateHexCondMove(
const MachineInstr &
MI,
const CellMap &Inputs,
1879 bool evaluateHexExt(
const MachineInstr &
MI,
const CellMap &Inputs,
1881 bool evaluateHexVector1(
const MachineInstr &
MI,
const CellMap &Inputs,
1883 bool evaluateHexVector2(
const MachineInstr &
MI,
const CellMap &Inputs,
1887 bool rewriteHexBranch(
MachineInstr &BrI,
const CellMap &Inputs);
1888 bool rewriteHexConstDefs(
MachineInstr &
MI,
const CellMap &Inputs,
1890 bool rewriteHexConstUses(
MachineInstr &
MI,
const CellMap &Inputs);
1903 StringRef getPassName()
const override {
1904 return "Hexagon Constant Propagation";
1909 if (skipFunction(
F))
1912 HexagonConstEvaluator HCE(MF);
1913 return MachineConstPropagator(HCE).run(MF);
1922 "Hexagon Constant Propagation",
false,
false)
1925 : MachineConstEvaluator(Fn),
1928 MRI = &Fn.getRegInfo();
1932 const CellMap &Inputs, CellMap &Outputs) {
1935 if (
MI.getNumOperands() == 0 || !
MI.getOperand(0).isReg())
1941 unsigned Opc =
MI.getOpcode();
1942 RegisterSubReg DefR(MD);
1944 if (!DefR.Reg.isVirtual())
1949 RegisterSubReg SrcR(
MI.getOperand(1));
1950 bool Eval = evaluateCOPY(SrcR, Inputs, RC);
1953 Outputs.update(DefR.Reg, RC);
1956 if (
MI.isRegSequence()) {
1957 unsigned Sub1 =
MI.getOperand(2).getImm();
1958 unsigned Sub2 =
MI.getOperand(4).getImm();
1962 if (Sub1 != SubLo && Sub1 != SubHi)
1964 if (Sub2 != SubLo && Sub2 != SubHi)
1967 bool LoIs1 = (Sub1 == SubLo);
1971 RegisterSubReg SrcRL(OpLo), SrcRH(OpHi);
1972 bool Eval = evaluateHexRSEQ32(SrcRL, SrcRH, Inputs, RC);
1975 Outputs.update(DefR.Reg, RC);
1978 if (
MI.isCompare()) {
1979 bool Eval = evaluateHexCompare(
MI, Inputs, Outputs);
1986 case Hexagon::A2_tfrsi:
1987 case Hexagon::A2_tfrpi:
1989 case Hexagon::CONST64:
1997 int64_t V =
MI.getOperand(1).getImm();
1999 if (
W != 32 &&
W != 64)
2004 LatticeCell RC = Outputs.get(DefR.Reg);
2006 Outputs.update(DefR.Reg, RC);
2010 case Hexagon::PS_true:
2011 case Hexagon::PS_false:
2013 LatticeCell RC = Outputs.get(DefR.Reg);
2014 bool NonZero = (Opc == Hexagon::PS_true);
2015 uint32_t P = NonZero ? ConstantProperties::NonZero
2016 : ConstantProperties::Zero;
2018 Outputs.update(DefR.Reg, RC);
2022 case Hexagon::A2_and:
2023 case Hexagon::A2_andir:
2024 case Hexagon::A2_andp:
2025 case Hexagon::A2_or:
2026 case Hexagon::A2_orir:
2027 case Hexagon::A2_orp:
2028 case Hexagon::A2_xor:
2029 case Hexagon::A2_xorp:
2031 bool Eval = evaluateHexLogical(
MI, Inputs, Outputs);
2037 case Hexagon::A2_combineii:
2038 case Hexagon::A4_combineii:
2040 if (!
MI.getOperand(1).isImm() || !
MI.getOperand(2).isImm())
2042 uint64_t
Hi =
MI.getOperand(1).getImm();
2043 uint64_t
Lo =
MI.getOperand(2).getImm();
2044 uint64_t Res = (
Hi << 32) | (
Lo & 0xFFFFFFFF);
2047 LatticeCell RC = Outputs.get(DefR.Reg);
2049 Outputs.update(DefR.Reg, RC);
2053 case Hexagon::S2_setbit_i:
2055 int64_t
B =
MI.getOperand(2).getImm();
2057 APInt A(32, (1ull <<
B),
false);
2058 RegisterSubReg
R(
MI.getOperand(1));
2059 LatticeCell RC = Outputs.get(DefR.Reg);
2060 bool Eval = evaluateORri(R, A, Inputs, RC);
2063 Outputs.update(DefR.Reg, RC);
2067 case Hexagon::C2_mux:
2068 case Hexagon::C2_muxir:
2069 case Hexagon::C2_muxri:
2070 case Hexagon::C2_muxii:
2072 bool Eval = evaluateHexCondMove(
MI, Inputs, Outputs);
2078 case Hexagon::A2_sxtb:
2079 case Hexagon::A2_sxth:
2080 case Hexagon::A2_sxtw:
2081 case Hexagon::A2_zxtb:
2082 case Hexagon::A2_zxth:
2084 bool Eval = evaluateHexExt(
MI, Inputs, Outputs);
2090 case Hexagon::S2_ct0:
2091 case Hexagon::S2_ct0p:
2092 case Hexagon::S2_ct1:
2093 case Hexagon::S2_ct1p:
2095 using namespace Hexagon;
2097 bool Ones = (Opc == S2_ct1) || (Opc == S2_ct1p);
2098 RegisterSubReg R1(
MI.getOperand(1));
2099 assert(Inputs.has(R1.Reg));
2101 bool Eval = evaluateCTBr(R1, !Ones, Ones, Inputs,
T);
2108 LatticeCell RC = Outputs.get(DefR.Reg);
2109 for (
unsigned i = 0; i <
T.size(); ++i) {
2111 if (constToInt(CI,
C) &&
C.getBitWidth() > 32)
2112 CI = intToConst(
C.trunc(32));
2115 Outputs.update(DefR.Reg, RC);
2119 case Hexagon::S2_cl0:
2120 case Hexagon::S2_cl0p:
2121 case Hexagon::S2_cl1:
2122 case Hexagon::S2_cl1p:
2123 case Hexagon::S2_clb:
2124 case Hexagon::S2_clbp:
2126 using namespace Hexagon;
2128 bool OnlyZeros = (Opc == S2_cl0) || (Opc == S2_cl0p);
2129 bool OnlyOnes = (Opc == S2_cl1) || (Opc == S2_cl1p);
2130 RegisterSubReg R1(
MI.getOperand(1));
2131 assert(Inputs.has(R1.Reg));
2133 bool Eval = evaluateCLBr(R1, !OnlyOnes, !OnlyZeros, Inputs,
T);
2140 LatticeCell RC = Outputs.get(DefR.Reg);
2141 for (
unsigned i = 0; i <
T.size(); ++i) {
2143 if (constToInt(CI,
C) &&
C.getBitWidth() > 32)
2144 CI = intToConst(
C.trunc(32));
2147 Outputs.update(DefR.Reg, RC);
2151 case Hexagon::S4_extract:
2152 case Hexagon::S4_extractp:
2153 case Hexagon::S2_extractu:
2154 case Hexagon::S2_extractup:
2156 bool Signed = (Opc == Hexagon::S4_extract) ||
2157 (Opc == Hexagon::S4_extractp);
2158 RegisterSubReg R1(
MI.getOperand(1));
2160 unsigned Bits =
MI.getOperand(2).getImm();
2161 unsigned Offset =
MI.getOperand(3).getImm();
2162 LatticeCell RC = Outputs.get(DefR.Reg);
2164 APInt Zero(BW, 0,
false);
2165 RC.add(intToConst(Zero));
2178 Outputs.update(DefR.Reg, RC);
2182 case Hexagon::S2_vsplatrb:
2183 case Hexagon::S2_vsplatrh:
2193 bool Eval = evaluateHexVector1(
MI, Inputs, Outputs);
2209 bool HexagonConstEvaluator::evaluate(
const RegisterSubReg &R,
2210 const LatticeCell &Input, LatticeCell &Result) {
2216 if (RC != &Hexagon::DoubleRegsRegClass)
2218 if (
R.SubReg != Hexagon::isub_lo &&
R.SubReg != Hexagon::isub_hi)
2222 if (Input.isBottom())
2225 using P = ConstantProperties;
2227 if (Input.isProperty()) {
2229 if (Ps & (P::Zero|P::NaN)) {
2230 uint32_t Ns = (Ps & (P::Zero|P::NaN|P::SignProperties));
2234 if (
R.SubReg == Hexagon::isub_hi) {
2235 uint32_t Ns = (Ps & P::SignProperties);
2245 for (
unsigned i = 0; i < Input.size(); ++i) {
2247 if (!constToInt(
C, A))
2251 uint64_t U =
A.getZExtValue();
2252 if (
R.SubReg == Hexagon::isub_hi)
2257 memcpy(&V32, &U32,
sizeof V32);
2265 bool HexagonConstEvaluator::evaluate(
const MachineInstr &BrI,
2271 bool SimpleBranch =
false;
2272 bool Negated =
false;
2274 case Hexagon::J2_jumpf:
2275 case Hexagon::J2_jumpfnew:
2276 case Hexagon::J2_jumpfnewpt:
2279 case Hexagon::J2_jumpt:
2280 case Hexagon::J2_jumptnew:
2281 case Hexagon::J2_jumptnewpt:
2284 SimpleBranch =
true;
2286 case Hexagon::J2_jump:
2300 RegisterSubReg PR(MD);
2305 assert(Inputs.has(PR.Reg));
2306 const LatticeCell &PredC = Inputs.get(PR.Reg);
2307 if (PredC.isBottom())
2310 uint32_t Props = PredC.properties();
2311 bool CTrue =
false, CFalse =
false;
2312 if (Props & ConstantProperties::Zero)
2314 else if (Props & ConstantProperties::NonZero)
2317 if (!CTrue && !CFalse)
2323 if ((!Negated && CTrue) || (Negated && CFalse))
2325 else if ((!Negated && CFalse) || (Negated && CTrue))
2336 return rewriteHexBranch(
MI, Inputs);
2338 unsigned Opc =
MI.getOpcode();
2342 case Hexagon::A2_tfrsi:
2343 case Hexagon::A2_tfrpi:
2345 case Hexagon::CONST64:
2346 case Hexagon::PS_true:
2347 case Hexagon::PS_false:
2351 unsigned NumOp =
MI.getNumOperands();
2355 bool AllDefs, Changed;
2356 Changed = rewriteHexConstDefs(
MI, Inputs, AllDefs);
2361 Changed |= rewriteHexConstUses(
MI, Inputs);
2368 if (Hexagon::IntRegsRegClass.hasSubClassEq(RC))
2370 if (Hexagon::DoubleRegsRegClass.hasSubClassEq(RC))
2372 if (Hexagon::PredRegsRegClass.hasSubClassEq(RC))
2380 case Hexagon::C2_cmpeq:
2381 case Hexagon::C2_cmpeqp:
2382 case Hexagon::A4_cmpbeq:
2383 case Hexagon::A4_cmpheq:
2384 case Hexagon::A4_cmpbeqi:
2385 case Hexagon::A4_cmpheqi:
2386 case Hexagon::C2_cmpeqi:
2387 case Hexagon::J4_cmpeqn1_t_jumpnv_nt:
2388 case Hexagon::J4_cmpeqn1_t_jumpnv_t:
2389 case Hexagon::J4_cmpeqi_t_jumpnv_nt:
2390 case Hexagon::J4_cmpeqi_t_jumpnv_t:
2391 case Hexagon::J4_cmpeq_t_jumpnv_nt:
2392 case Hexagon::J4_cmpeq_t_jumpnv_t:
2395 case Hexagon::C4_cmpneq:
2396 case Hexagon::C4_cmpneqi:
2397 case Hexagon::J4_cmpeqn1_f_jumpnv_nt:
2398 case Hexagon::J4_cmpeqn1_f_jumpnv_t:
2399 case Hexagon::J4_cmpeqi_f_jumpnv_nt:
2400 case Hexagon::J4_cmpeqi_f_jumpnv_t:
2401 case Hexagon::J4_cmpeq_f_jumpnv_nt:
2402 case Hexagon::J4_cmpeq_f_jumpnv_t:
2405 case Hexagon::C2_cmpgt:
2406 case Hexagon::C2_cmpgtp:
2407 case Hexagon::A4_cmpbgt:
2408 case Hexagon::A4_cmphgt:
2409 case Hexagon::A4_cmpbgti:
2410 case Hexagon::A4_cmphgti:
2411 case Hexagon::C2_cmpgti:
2412 case Hexagon::J4_cmpgtn1_t_jumpnv_nt:
2413 case Hexagon::J4_cmpgtn1_t_jumpnv_t:
2414 case Hexagon::J4_cmpgti_t_jumpnv_nt:
2415 case Hexagon::J4_cmpgti_t_jumpnv_t:
2416 case Hexagon::J4_cmpgt_t_jumpnv_nt:
2417 case Hexagon::J4_cmpgt_t_jumpnv_t:
2418 return Comparison::GTs;
2420 case Hexagon::C4_cmplte:
2421 case Hexagon::C4_cmpltei:
2422 case Hexagon::J4_cmpgtn1_f_jumpnv_nt:
2423 case Hexagon::J4_cmpgtn1_f_jumpnv_t:
2424 case Hexagon::J4_cmpgti_f_jumpnv_nt:
2425 case Hexagon::J4_cmpgti_f_jumpnv_t:
2426 case Hexagon::J4_cmpgt_f_jumpnv_nt:
2427 case Hexagon::J4_cmpgt_f_jumpnv_t:
2428 return Comparison::LEs;
2430 case Hexagon::C2_cmpgtu:
2431 case Hexagon::C2_cmpgtup:
2432 case Hexagon::A4_cmpbgtu:
2433 case Hexagon::A4_cmpbgtui:
2434 case Hexagon::A4_cmphgtu:
2435 case Hexagon::A4_cmphgtui:
2436 case Hexagon::C2_cmpgtui:
2437 case Hexagon::J4_cmpgtui_t_jumpnv_nt:
2438 case Hexagon::J4_cmpgtui_t_jumpnv_t:
2439 case Hexagon::J4_cmpgtu_t_jumpnv_nt:
2440 case Hexagon::J4_cmpgtu_t_jumpnv_t:
2441 return Comparison::GTu;
2443 case Hexagon::J4_cmpltu_f_jumpnv_nt:
2444 case Hexagon::J4_cmpltu_f_jumpnv_t:
2445 return Comparison::GEu;
2447 case Hexagon::J4_cmpltu_t_jumpnv_nt:
2448 case Hexagon::J4_cmpltu_t_jumpnv_t:
2449 return Comparison::LTu;
2451 case Hexagon::J4_cmplt_f_jumpnv_nt:
2452 case Hexagon::J4_cmplt_f_jumpnv_t:
2453 return Comparison::GEs;
2455 case Hexagon::C4_cmplteu:
2456 case Hexagon::C4_cmplteui:
2457 case Hexagon::J4_cmpgtui_f_jumpnv_nt:
2458 case Hexagon::J4_cmpgtui_f_jumpnv_t:
2459 case Hexagon::J4_cmpgtu_f_jumpnv_nt:
2460 case Hexagon::J4_cmpgtu_f_jumpnv_t:
2461 return Comparison::LEu;
2463 case Hexagon::J4_cmplt_t_jumpnv_nt:
2464 case Hexagon::J4_cmplt_t_jumpnv_t:
2465 return Comparison::LTs;
2470 return Comparison::Unk;
2473 APInt HexagonConstEvaluator::getCmpImm(
unsigned Opc,
unsigned OpX,
2477 case Hexagon::A4_cmpbgtui:
2478 case Hexagon::A4_cmphgtui:
2480 case Hexagon::A4_cmpheqi:
2481 case Hexagon::C4_cmpneqi:
2484 case Hexagon::A4_cmpbeqi:
2486 case Hexagon::C2_cmpgtui:
2487 case Hexagon::C4_cmplteui:
2489 case Hexagon::C2_cmpeqi:
2490 case Hexagon::C2_cmpgti:
2491 case Hexagon::C4_cmpltei:
2494 case Hexagon::J4_cmpeqi_f_jumpnv_nt:
2495 case Hexagon::J4_cmpeqi_f_jumpnv_t:
2496 case Hexagon::J4_cmpeqi_t_jumpnv_nt:
2497 case Hexagon::J4_cmpeqi_t_jumpnv_t:
2498 case Hexagon::J4_cmpgti_f_jumpnv_nt:
2499 case Hexagon::J4_cmpgti_f_jumpnv_t:
2500 case Hexagon::J4_cmpgti_t_jumpnv_nt:
2501 case Hexagon::J4_cmpgti_t_jumpnv_t:
2502 case Hexagon::J4_cmpgtui_f_jumpnv_nt:
2503 case Hexagon::J4_cmpgtui_f_jumpnv_t:
2504 case Hexagon::J4_cmpgtui_t_jumpnv_nt:
2505 case Hexagon::J4_cmpgtui_t_jumpnv_t:
2512 uint64_t Val = MO.
getImm();
2517 MI.setDesc(HII.get(Hexagon::A2_nop));
2518 while (
MI.getNumOperands() > 0)
2519 MI.RemoveOperand(0);
2522 bool HexagonConstEvaluator::evaluateHexRSEQ32(RegisterSubReg RL, RegisterSubReg RH,
2523 const CellMap &Inputs, LatticeCell &Result) {
2524 assert(Inputs.has(RL.Reg) && Inputs.has(RH.Reg));
2525 LatticeCell
LSL, LSH;
2526 if (!getCell(RL, Inputs,
LSL) || !getCell(RH, Inputs, LSH))
2528 if (
LSL.isProperty() || LSH.isProperty())
2531 unsigned LN =
LSL.size(), HN = LSH.size();
2533 for (
unsigned i = 0; i < LN; ++i) {
2534 bool Eval = constToInt(
LSL.Values[i], LoVs[i]);
2539 for (
unsigned i = 0; i < HN; ++i) {
2540 bool Eval = constToInt(LSH.Values[i], HiVs[i]);
2546 for (
unsigned i = 0; i < HiVs.size(); ++i) {
2548 for (
unsigned j = 0; j < LoVs.size(); ++j) {
2550 const Constant *
C = intToConst(HV | LV);
2556 return !
Result.isBottom();
2559 bool HexagonConstEvaluator::evaluateHexCompare(
const MachineInstr &
MI,
2560 const CellMap &Inputs, CellMap &Outputs) {
2561 unsigned Opc =
MI.getOpcode();
2562 bool Classic =
false;
2564 case Hexagon::C2_cmpeq:
2565 case Hexagon::C2_cmpeqp:
2566 case Hexagon::C2_cmpgt:
2567 case Hexagon::C2_cmpgtp:
2568 case Hexagon::C2_cmpgtu:
2569 case Hexagon::C2_cmpgtup:
2570 case Hexagon::C2_cmpeqi:
2571 case Hexagon::C2_cmpgti:
2572 case Hexagon::C2_cmpgtui:
2586 unsigned Opc =
MI.getOpcode();
2587 bool Computed = evaluateHexCompare2(Opc, Src1, Src2, Inputs, Result);
2591 RegisterSubReg DefR(
MI.getOperand(0));
2592 LatticeCell L = Outputs.get(DefR.Reg);
2594 : ConstantProperties::Zero;
2596 Outputs.update(DefR.Reg, L);
2604 bool HexagonConstEvaluator::evaluateHexCompare2(
unsigned Opc,
2606 const CellMap &Inputs,
bool &Result) {
2608 bool Reg1 = Src1.
isReg(), Reg2 = Src2.
isReg();
2609 bool Imm1 = Src1.
isImm(), Imm2 = Src2.
isImm();
2611 RegisterSubReg R1(Src1);
2613 RegisterSubReg
R2(Src2);
2614 return evaluateCMPrr(Cmp, R1,
R2, Inputs, Result);
2616 APInt A2 = getCmpImm(Opc, 2, Src2);
2617 return evaluateCMPri(Cmp, R1, A2, Inputs, Result);
2620 APInt A1 = getCmpImm(Opc, 1, Src1);
2622 RegisterSubReg
R2(Src2);
2623 uint32_t NegCmp = Comparison::negate(Cmp);
2624 return evaluateCMPri(NegCmp,
R2, A1, Inputs, Result);
2626 APInt A2 = getCmpImm(Opc, 2, Src2);
2627 return evaluateCMPii(Cmp, A1, A2, Result);
2634 bool HexagonConstEvaluator::evaluateHexLogical(
const MachineInstr &
MI,
2635 const CellMap &Inputs, CellMap &Outputs) {
2636 unsigned Opc =
MI.getOpcode();
2637 if (
MI.getNumOperands() != 3)
2641 RegisterSubReg R1(Src1);
2647 case Hexagon::A2_and:
2648 case Hexagon::A2_andp:
2649 Eval = evaluateANDrr(R1, RegisterSubReg(Src2), Inputs, RC);
2651 case Hexagon::A2_andir: {
2655 Eval = evaluateANDri(R1, A, Inputs, RC);
2658 case Hexagon::A2_or:
2659 case Hexagon::A2_orp:
2660 Eval = evaluateORrr(R1, RegisterSubReg(Src2), Inputs, RC);
2662 case Hexagon::A2_orir: {
2666 Eval = evaluateORri(R1, A, Inputs, RC);
2669 case Hexagon::A2_xor:
2670 case Hexagon::A2_xorp:
2671 Eval = evaluateXORrr(R1, RegisterSubReg(Src2), Inputs, RC);
2675 RegisterSubReg DefR(
MI.getOperand(0));
2676 Outputs.update(DefR.Reg, RC);
2681 bool HexagonConstEvaluator::evaluateHexCondMove(
const MachineInstr &
MI,
2682 const CellMap &Inputs, CellMap &Outputs) {
2684 RegisterSubReg CR(
MI.getOperand(1));
2685 assert(Inputs.has(CR.Reg));
2687 if (!getCell(CR, Inputs,
LS))
2691 if (Ps & ConstantProperties::Zero)
2693 else if (Ps & ConstantProperties::NonZero)
2699 RegisterSubReg DefR(
MI.getOperand(0));
2700 LatticeCell RC = Outputs.get(DefR.Reg);
2702 if (ValOp.
isImm()) {
2703 int64_t V = ValOp.
getImm();
2708 Outputs.update(DefR.Reg, RC);
2711 if (ValOp.
isReg()) {
2712 RegisterSubReg
R(ValOp);
2713 const LatticeCell &LR = Inputs.get(
R.Reg);
2715 if (!evaluate(R, LR,
LSR))
2718 Outputs.update(DefR.Reg, RC);
2724 bool HexagonConstEvaluator::evaluateHexExt(
const MachineInstr &
MI,
2725 const CellMap &Inputs, CellMap &Outputs) {
2727 RegisterSubReg R1(
MI.getOperand(1));
2728 assert(Inputs.has(R1.Reg));
2730 unsigned Opc =
MI.getOpcode();
2733 case Hexagon::A2_sxtb:
2734 case Hexagon::A2_zxtb:
2737 case Hexagon::A2_sxth:
2738 case Hexagon::A2_zxth:
2741 case Hexagon::A2_sxtw:
2750 case Hexagon::A2_sxtb:
2751 case Hexagon::A2_sxth:
2752 case Hexagon::A2_sxtw:
2757 RegisterSubReg DefR(
MI.getOperand(0));
2759 LatticeCell RC = Outputs.get(DefR.Reg);
2760 bool Eval =
Signed ? evaluateSEXTr(R1, BW,
Bits, Inputs, RC)
2761 : evaluateZEXTr(R1, BW,
Bits, Inputs, RC);
2764 Outputs.update(DefR.Reg, RC);
2768 bool HexagonConstEvaluator::evaluateHexVector1(
const MachineInstr &
MI,
2769 const CellMap &Inputs, CellMap &Outputs) {
2771 RegisterSubReg DefR(
MI.getOperand(0));
2772 RegisterSubReg R1(
MI.getOperand(1));
2773 assert(Inputs.has(R1.Reg));
2774 LatticeCell RC = Outputs.get(DefR.Reg);
2777 unsigned Opc =
MI.getOpcode();
2779 case Hexagon::S2_vsplatrb:
2781 Eval = evaluateSplatr(R1, 8, 4, Inputs, RC);
2783 case Hexagon::S2_vsplatrh:
2785 Eval = evaluateSplatr(R1, 16, 4, Inputs, RC);
2793 Outputs.update(DefR.Reg, RC);
2797 bool HexagonConstEvaluator::rewriteHexConstDefs(
MachineInstr &
MI,
2798 const CellMap &Inputs,
bool &AllDefs) {
2806 bool Const =
true, HasUse =
false;
2810 RegisterSubReg
R(MO);
2811 if (!
R.Reg.isVirtual())
2815 if (!
MI.isPHI() && !Inputs.has(
R.Reg)) {
2817 <<
" in MI: " <<
MI;
2820 const LatticeCell &L = Inputs.get(
R.Reg);
2821 Const &= L.isSingle();
2825 if (HasUse && Const) {
2827 dbgs() <<
"CONST: " <<
MI;
2857 DefRegs.push_back(R);
2862 unsigned ChangedNum = 0;
2870 for (
unsigned i = 0, n = DefRegs.size(); i < n; ++i) {
2871 unsigned R = DefRegs[i];
2872 const LatticeCell &L = Inputs.get(R);
2878 if (!L.isSingle()) {
2881 using P = ConstantProperties;
2883 uint64_t Ps = L.properties();
2884 if (!(Ps & (P::Zero|P::NonZero)))
2890 &HII.get(Hexagon::PS_false) :
2891 &HII.get(Hexagon::PS_true);
2892 Register NewR =
MRI->createVirtualRegister(PredRC);
2898 replaceAllRegUsesWith(R, NewR);
2902 if (!constToInt(L.Value, A) || !
A.isSignedIntN(64))
2908 int64_t V =
A.getSExtValue();
2911 NewRC = &Hexagon::IntRegsRegClass;
2913 NewRC = &Hexagon::DoubleRegsRegClass;
2914 Register NewR =
MRI->createVirtualRegister(NewRC);
2918 NewD = &HII.get(Hexagon::A2_tfrsi);
2922 if (
A.isSignedIntN(8)) {
2923 NewD = &HII.get(Hexagon::A2_tfrpi);
2927 int32_t
Hi = V >> 32;
2928 int32_t
Lo = V & 0xFFFFFFFFLL;
2930 NewD = &HII.get(Hexagon::A2_combineii);
2936 NewD = &HII.get(Hexagon::CONST64);
2947 replaceAllRegUsesWith(R, NewR);
2953 if (!NewInstrs.
empty()) {
2955 dbgs() <<
"In function: " << MF.
getName() <<
"\n";
2956 dbgs() <<
"Rewrite: for " <<
MI <<
" created " << *NewInstrs[0];
2957 for (
unsigned i = 1; i < NewInstrs.size(); ++i)
2958 dbgs() <<
" " << *NewInstrs[i];
2962 AllDefs = (ChangedNum == DefRegs.size());
2963 return ChangedNum > 0;
2966 bool HexagonConstEvaluator::rewriteHexConstUses(
MachineInstr &
MI,
2967 const CellMap &Inputs) {
2968 bool Changed =
false;
2969 unsigned Opc =
MI.getOpcode();
2976 case Hexagon::M2_maci:
2981 RegisterSubReg DefR(
MI.getOperand(0));
2983 RegisterSubReg
R2(
MI.getOperand(2));
2984 RegisterSubReg R3(
MI.getOperand(3));
2985 assert(Inputs.has(
R2.Reg) && Inputs.has(R3.Reg));
2986 LatticeCell LS2, LS3;
2989 bool HasC2 = getCell(
R2, Inputs, LS2), HasC3 = getCell(R3, Inputs, LS3);
2990 if (!HasC2 && !HasC3)
2992 bool Zero = ((HasC2 && (LS2.properties() & ConstantProperties::Zero)) ||
2993 (HasC3 && (LS3.properties() & ConstantProperties::Zero)));
2998 RegisterSubReg R1(Acc);
2999 unsigned NewR = R1.Reg;
3003 NewR =
MRI->createVirtualRegister(RC);
3004 NewMI =
BuildMI(
B, At,
DL, HII.get(TargetOpcode::COPY), NewR)
3007 replaceAllRegUsesWith(DefR.Reg, NewR);
3008 MRI->clearKillFlags(NewR);
3014 if (!LS3.isSingle()) {
3015 if (!LS2.isSingle())
3019 const LatticeCell &LI = Swap ? LS2 : LS3;
3024 if (!constToInt(LI.Value, A) || !
A.isSignedIntN(8))
3026 int64_t V =
A.getSExtValue();
3027 const MCInstrDesc &
D = (V >= 0) ? HII.get(Hexagon::M2_macsip)
3028 : HII.get(Hexagon::M2_macsin);
3038 replaceAllRegUsesWith(DefR.Reg, NewR);
3043 case Hexagon::A2_and:
3045 RegisterSubReg R1(
MI.getOperand(1));
3046 RegisterSubReg
R2(
MI.getOperand(2));
3047 assert(Inputs.has(R1.Reg) && Inputs.has(
R2.Reg));
3048 LatticeCell LS1, LS2;
3049 unsigned CopyOf = 0;
3051 if (getCell(R1, Inputs, LS1) && LS1.isSingle()) {
3053 if (constToInt(LS1.Value,
M1) && !~
M1)
3056 else if (getCell(
R2, Inputs, LS2) && LS2.isSingle()) {
3058 if (constToInt(LS2.Value,
M1) && !~
M1)
3064 RegisterSubReg SR(SO);
3065 RegisterSubReg DefR(
MI.getOperand(0));
3066 unsigned NewR = SR.Reg;
3069 NewR =
MRI->createVirtualRegister(RC);
3070 NewMI =
BuildMI(
B, At,
DL, HII.get(TargetOpcode::COPY), NewR)
3073 replaceAllRegUsesWith(DefR.Reg, NewR);
3074 MRI->clearKillFlags(NewR);
3079 case Hexagon::A2_or:
3081 RegisterSubReg R1(
MI.getOperand(1));
3082 RegisterSubReg
R2(
MI.getOperand(2));
3083 assert(Inputs.has(R1.Reg) && Inputs.has(
R2.Reg));
3084 LatticeCell LS1, LS2;
3085 unsigned CopyOf = 0;
3087 using P = ConstantProperties;
3089 if (getCell(R1, Inputs, LS1) && (LS1.properties() & P::Zero))
3091 else if (getCell(
R2, Inputs, LS2) && (LS2.properties() & P::Zero))
3096 RegisterSubReg SR(SO);
3097 RegisterSubReg DefR(
MI.getOperand(0));
3098 unsigned NewR = SR.Reg;
3101 NewR =
MRI->createVirtualRegister(RC);
3102 NewMI =
BuildMI(
B, At,
DL, HII.get(TargetOpcode::COPY), NewR)
3105 replaceAllRegUsesWith(DefR.Reg, NewR);
3106 MRI->clearKillFlags(NewR);
3121 dbgs() <<
"Rewrite: for " <<
MI;
3123 dbgs() <<
" created " << *NewMI;
3125 dbgs() <<
" modified the instruction itself and created:" << *NewMI;
3132 void HexagonConstEvaluator::replaceAllRegUsesWith(
Register FromReg,
3136 for (
auto I =
MRI->use_begin(FromReg),
E =
MRI->use_end();
I !=
E;) {
3143 bool HexagonConstEvaluator::rewriteHexBranch(
MachineInstr &BrI,
3144 const CellMap &Inputs) {
3152 bool Eval = evaluate(BrI, Inputs, Targets, FallsThru);
3153 unsigned NumTargets = Targets.
size();
3154 if (!Eval || NumTargets > 1 || (NumTargets == 1 && FallsThru))
3156 if (BrI.
getOpcode() == Hexagon::J2_jump)
3160 bool Rewritten =
false;
3161 if (NumTargets > 0) {
3162 assert(!FallsThru &&
"This should have been checked before");
3165 bool Moot =
B.isLayoutSuccessor(TargetB);
3171 const MCInstrDesc &JD = HII.get(Hexagon::J2_jump);
3179 for (
auto &
Op : NI->operands())
3181 NI->eraseFromParent();
3190 replaceWithNop(BrI);
3195 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.
uint64_t getZExtValue() const
Get zero extended value.
APInt sext(unsigned width) const
Sign extend to a new width.
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.
unsigned M1(unsigned Val)
size_type size() const
Determine the number of elements in the SetVector.
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
LLVM_NODISCARD bool empty() const
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.
APInt zext(unsigned width) const
Zero extend to a new width.
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.
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.
Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
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()
Function & getFunction()
Return the LLVM function that this machine code represents.
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.
APInt zextOrSelf(unsigned width) const
Zero extend or truncate to width.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
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.
bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
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()
static Comparison getCmp(SelectionDAG &DAG, SDValue CmpOp0, SDValue CmpOp1, ISD::CondCode Cond, const SDLoc &DL, SDValue Chain=SDValue(), bool IsSignaling=false)
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.
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.
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.
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!...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
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.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
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.
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.
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,...
Representation of each machine instruction.
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)
bool isZero() const
Return true if the value is positive or negative zero.
bool isNaN() const
Return true if the value is a NaN.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
static bool rewrite(Function &F)
iterator getFirstNonPHI()
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Root & operator=(Root &&)=delete
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
A vector that has set insertion semantics.
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
This class implements an extremely fast bulk output stream that can only output to a stream.
ReachingDefAnalysis InstSet & ToRemove
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)
Register getReg() const
getReg - Returns the register number.
const MachineOperand & getOperand(unsigned i) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
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...
Wrapper class representing virtual and physical registers.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL