42#include "llvm/IR/IntrinsicsHexagon.h"
77#define DEBUG_TYPE "hexagon-lir"
83 cl::desc(
"Disable generation of memcpy in loop idiom recognition"));
87 cl::desc(
"Disable generation of memmove in loop idiom recognition"));
91 "check guarding the memmove."));
95 cl::desc(
"Threshold (in bytes) to perform the transformation, if the "
96 "runtime loop count (mem transfer size) is known at compile-time."));
100 cl::desc(
"Only enable generating memmove in non-nested loops"));
104 cl::desc(
"Enable Hexagon-specific memcpy for volatile destination."));
111class HexagonLoopIdiomRecognize {
117 :
AA(
AA), DT(DT), LF(LF), TLI(TLI), SE(SE), ORE(ORE) {}
122 int getSCEVStride(
const SCEVAddRecExpr *StoreEv);
123 bool isLegalStore(
Loop *CurLoop, StoreInst *SI);
124 void collectStores(
Loop *CurLoop, BasicBlock *BB,
125 SmallVectorImpl<StoreInst *> &Stores);
126 bool processCopyingStore(
Loop *CurLoop, StoreInst *SI,
const SCEV *BECount);
127 bool coverLoop(
Loop *L, SmallVectorImpl<Instruction *> &Insts)
const;
128 bool runOnLoopBlock(
Loop *CurLoop, BasicBlock *BB,
const SCEV *BECount,
129 SmallVectorImpl<BasicBlock *> &ExitBlocks);
130 bool runOnCountableLoop(
Loop *L);
133 const DataLayout *DL;
136 const TargetLibraryInfo *TLI;
138 OptimizationRemarkEmitter &ORE;
139 bool HasMemcpy, HasMemmove;
142class HexagonLoopIdiomRecognizeLegacyPass :
public LoopPass {
146 explicit HexagonLoopIdiomRecognizeLegacyPass() : LoopPass(ID) {}
148 StringRef getPassName()
const override {
149 return "Recognize Hexagon-specific loop idioms";
152 void getAnalysisUsage(AnalysisUsage &AU)
const override {
160 AU.
addRequired<OptimizationRemarkEmitterWrapperPass>();
164 bool runOnLoop(
Loop *L, LPPassManager &LPM)
override;
170 Rule(StringRef
N, FuncType
F) : Name(
N), Fn(
F) {}
175 void addRule(StringRef
N,
const Rule::FuncType &
F) {
176 Rules.push_back(Rule(
N,
F));
180 struct WorkListType {
181 WorkListType() =
default;
183 void push_back(
Value *V) {
185 if (S.insert(V).second)
189 Value *pop_front_val() {
196 bool empty()
const {
return Q.empty(); }
199 std::deque<Value *> Q;
203 using ValueSetType = std::set<Value *>;
205 std::vector<Rule> Rules;
209 using ValueMapType = DenseMap<Value *, Value *>;
220 void print(raw_ostream &OS,
const Value *V)
const;
224 friend struct Simplifier;
229 template <
typename FuncT>
void traverse(
Value *V, FuncT
F);
230 void record(
Value *V);
232 void unuse(
Value *V);
234 bool equal(
const Instruction *
I,
const Instruction *J)
const;
245 PE(
const Simplifier::Context &c,
Value *v =
nullptr) : C(c), V(
v) {}
247 const Simplifier::Context &C;
253 P.C.print(OS,
P.V ?
P.V :
P.C.Root);
259char HexagonLoopIdiomRecognizeLegacyPass::ID = 0;
262 "Recognize Hexagon-specific loop idioms",
false,
false)
274template <typename FuncT>
275void Simplifier::Context::traverse(
Value *V, FuncT
F) {
280 Instruction *U = dyn_cast<Instruction>(Q.pop_front_val());
281 if (!U || U->getParent())
285 for (Value *Op : U->operands())
293 OS <<
V <<
'(' << *
V <<
')';
297 if (
U->getParent()) {
299 U->printAsOperand(OS,
true);
304 unsigned N =
U->getNumOperands();
307 OS <<
U->getOpcodeName();
308 for (
const Value *
Op :
U->operands()) {
316void Simplifier::Context::initialize(Instruction *Exp) {
326 Value *
V = Q.pop_front_val();
334 M.insert({
U,
U->clone()});
338 for (std::pair<Value*,Value*>
P : M) {
340 for (
unsigned i = 0, n =
U->getNumOperands(); i != n; ++i) {
341 auto F =
M.find(
U->getOperand(i));
343 U->setOperand(i,
F->second);
347 auto R =
M.find(Exp);
355void Simplifier::Context::record(
Value *V) {
363void Simplifier::Context::use(
Value *V) {
371void Simplifier::Context::unuse(
Value *V) {
395 if (!U ||
U->getParent())
397 for (
unsigned i = 0, n =
U->getNumOperands(); i != n; ++i) {
400 U->setOperand(i, NewV);
410void Simplifier::Context::replace(
Value *OldV,
Value *NewV) {
426 Value *
V = Q.pop_front_val();
428 if (!U ||
U->getParent())
432 NewV = subst(NewV, V, DupV);
440 Root = subst(Root, OldV, NewV);
444void Simplifier::Context::cleanup() {
445 for (
Value *V : Clones) {
448 U->dropAllReferences();
451 for (
Value *V : Clones) {
458bool Simplifier::Context::equal(
const Instruction *
I,
459 const Instruction *J)
const {
462 if (!
I->isSameOperationAs(J))
465 return I->isIdenticalTo(J);
467 for (
unsigned i = 0, n =
I->getNumOperands(); i != n; ++i) {
474 if (!
equal(InI, InJ))
476 }
else if (InI != InJ || !InI)
488 Value *
V = Q.pop_front_val();
492 if (!U ||
U->getParent())
494 if (SubI &&
equal(SubI, U))
503void Simplifier::Context::link(Instruction *
I, BasicBlock *
B,
513 I->insertInto(
B, At);
516Value *Simplifier::Context::materialize(BasicBlock *
B,
530 if (
Count++ >= Limit)
533 if (!U ||
U->getParent() || !
C.Used.count(U))
536 for (Rule &R : Rules) {
551 return Count < Limit ?
C.Root :
nullptr;
562 class PolynomialMultiplyRecognize {
564 explicit PolynomialMultiplyRecognize(
Loop *loop,
const DataLayout &dl,
565 const DominatorTree &dt,
const TargetLibraryInfo &tli,
567 : CurLoop(loop),
DL(dl), DT(dt), TLI(tli), SE(se) {}
572 using ValueSeq = SetVector<Value *>;
574 IntegerType *getPmpyType()
const {
575 LLVMContext &Ctx = CurLoop->getHeader()->getParent()->getContext();
579 bool isPromotableTo(
Value *V, IntegerType *Ty);
580 void promoteTo(Instruction *In, IntegerType *DestTy, BasicBlock *LoopB);
581 bool promoteTypes(BasicBlock *LoopB, BasicBlock *ExitB);
583 Value *getCountIV(BasicBlock *BB);
584 bool findCycle(
Value *Out,
Value *In, ValueSeq &Cycle);
585 void classifyCycle(Instruction *DivI, ValueSeq &Cycle, ValueSeq &Early,
587 bool classifyInst(Instruction *UseI, ValueSeq &Early, ValueSeq &Late);
588 bool commutesWithShift(Instruction *
I);
589 bool highBitsAreZero(
Value *V,
unsigned IterCount);
590 bool keepsHighBitsZero(
Value *V,
unsigned IterCount);
591 bool isOperandShifted(Instruction *
I,
Value *
Op);
592 bool convertShiftsToLeft(BasicBlock *LoopB, BasicBlock *ExitB,
594 void cleanupLoopBody(BasicBlock *LoopB);
596 struct ParsedValues {
597 ParsedValues() =
default;
605 unsigned IterCount = 0;
610 bool matchLeftShift(SelectInst *SelI,
Value *CIV, ParsedValues &PV);
611 bool matchRightShift(SelectInst *SelI, ParsedValues &PV);
612 bool scanSelect(SelectInst *SI, BasicBlock *LoopB, BasicBlock *PrehB,
613 Value *CIV, ParsedValues &PV,
bool PreScan);
614 unsigned getInverseMxN(
unsigned QP);
617 void setupPreSimplifier(Simplifier &S);
618 void setupPostSimplifier(Simplifier &S);
621 const DataLayout &
DL;
622 const DominatorTree &DT;
623 const TargetLibraryInfo &TLI;
629Value *PolynomialMultiplyRecognize::getCountIV(BasicBlock *BB) {
631 if (std::distance(PI, PE) != 2)
637 Value *InitV = PN->getIncomingValueForBlock(
PB);
640 Value *IterV = PN->getIncomingValueForBlock(BB);
644 if (BO->getOpcode() != Instruction::Add)
646 Value *IncV =
nullptr;
647 if (BO->getOperand(0) == PN)
648 IncV = BO->getOperand(1);
649 else if (BO->getOperand(1) == PN)
650 IncV = BO->getOperand(0);
662 for (
auto UI =
I->user_begin(), UE =
I->user_end(); UI != UE;) {
663 Use &TheUse = UI.getUse();
666 if (BB ==
II->getParent())
667 II->replaceUsesOfWith(
I, J);
671bool PolynomialMultiplyRecognize::matchLeftShift(SelectInst *SelI,
672 Value *CIV, ParsedValues &PV) {
684 using namespace PatternMatch;
687 Value *
A =
nullptr, *
B =
nullptr, *
C =
nullptr;
697 Value *
X =
nullptr, *Sh1 =
nullptr;
725 Value *ShouldSameV =
nullptr, *ShouldXoredV =
nullptr;
728 ShouldXoredV = FalseV;
730 ShouldSameV = FalseV;
731 ShouldXoredV = TrueV;
734 Value *Q =
nullptr, *
R =
nullptr, *
Y =
nullptr, *
Z =
nullptr;
740 if (ShouldSameV ==
Y)
742 else if (ShouldSameV == Z)
785bool PolynomialMultiplyRecognize::matchRightShift(SelectInst *SelI,
798 using namespace PatternMatch;
825 Value *
R =
nullptr, *Q =
nullptr;
855bool PolynomialMultiplyRecognize::scanSelect(SelectInst *SelI,
856 BasicBlock *LoopB, BasicBlock *PrehB,
Value *CIV, ParsedValues &PV,
858 using namespace PatternMatch;
897 if (matchLeftShift(SelI, CIV, PV)) {
906 if (SelI != RPhi->getIncomingValueForBlock(LoopB))
912 if (CurLoop->isLoopInvariant(PV.X)) {
922 Value *Var =
nullptr, *Inv =
nullptr, *X1 =
nullptr, *X2 =
nullptr;
927 if (!I1 ||
I1->getParent() != LoopB) {
930 }
else if (!I2 || I2->getParent() != LoopB) {
941 Value *EntryP = RPhi->getIncomingValueForBlock(PrehB);
948 if (matchRightShift(SelI, PV)) {
962bool PolynomialMultiplyRecognize::isPromotableTo(
Value *Val,
963 IntegerType *DestTy) {
980 switch (
In->getOpcode()) {
981 case Instruction::PHI:
982 case Instruction::ZExt:
983 case Instruction::And:
984 case Instruction::Or:
985 case Instruction::Xor:
986 case Instruction::LShr:
987 case Instruction::Select:
988 case Instruction::Trunc:
990 case Instruction::ICmp:
992 return CI->isEquality() || CI->isUnsigned();
994 case Instruction::Add:
995 return In->hasNoSignedWrap() &&
In->hasNoUnsignedWrap();
1000void PolynomialMultiplyRecognize::promoteTo(Instruction *In,
1001 IntegerType *DestTy, BasicBlock *LoopB) {
1002 Type *OrigTy =
In->getType();
1006 if (!
In->getType()->isIntegerTy(1))
1007 In->mutateType(DestTy);
1012 unsigned N =
P->getNumIncomingValues();
1013 for (
unsigned i = 0; i !=
N; ++i) {
1017 Value *InV =
P->getIncomingValue(i);
1020 if (Ty !=
P->getType()) {
1025 P->setIncomingValue(i, InV);
1030 if (
Op->getType() ==
Z->getType())
1031 Z->replaceAllUsesWith(
Op);
1032 Z->eraseFromParent();
1039 T->replaceAllUsesWith(
And);
1040 T->eraseFromParent();
1045 for (
unsigned i = 0, n =
In->getNumOperands(); i != n; ++i) {
1047 if (CI->getBitWidth() < DestBW)
1048 In->setOperand(i, ConstantInt::get(DestTy, CI->getZExtValue()));
1052bool PolynomialMultiplyRecognize::promoteTypes(BasicBlock *LoopB,
1053 BasicBlock *ExitB) {
1061 IntegerType *DestTy = getPmpyType();
1065 for (PHINode &
P : ExitB->
phis()) {
1066 if (
P.getNumIncomingValues() != 1)
1068 assert(
P.getIncomingBlock(0) == LoopB);
1070 if (!
T ||
T->getBitWidth() > DestBW)
1075 for (Instruction &In : *LoopB)
1076 if (!
In.isTerminator() && !isPromotableTo(&In, DestTy))
1081 for (Instruction *In : LoopIns)
1082 if (!
In->isTerminator())
1083 promoteTo(In, DestTy, LoopB);
1087 for (
auto I = ExitB->
begin();
I != End; ++
I) {
1091 Type *Ty0 =
P->getIncomingValue(0)->getType();
1092 Type *PTy =
P->getType();
1100 P->replaceAllUsesWith(
T);
1110bool PolynomialMultiplyRecognize::findCycle(
Value *Out,
Value *In,
1117 bool HadPhi =
false;
1119 for (
auto *U :
Out->users()) {
1121 if (
I ==
nullptr ||
I->getParent() != BB)
1129 if (IsPhi && HadPhi)
1132 if (!Cycle.insert(
I))
1134 if (findCycle(
I, In, Cycle))
1138 return !Cycle.
empty();
1141void PolynomialMultiplyRecognize::classifyCycle(Instruction *DivI,
1142 ValueSeq &Cycle, ValueSeq &Early, ValueSeq &Late) {
1148 unsigned I,
N = Cycle.size();
1149 for (
I = 0;
I <
N; ++
I) {
1160 ValueSeq &
First = !IsE ? Early : Late;
1161 for (
unsigned J = 0; J <
I; ++J)
1162 First.insert(Cycle[J]);
1164 ValueSeq &Second = IsE ? Early : Late;
1165 Second.insert(Cycle[
I]);
1166 for (++
I;
I <
N; ++
I) {
1177bool PolynomialMultiplyRecognize::classifyInst(Instruction *UseI,
1178 ValueSeq &Early, ValueSeq &Late) {
1182 if (UseI->
getOpcode() == Instruction::Select) {
1184 if (Early.count(TV) || Early.count(FV)) {
1185 if (Late.count(TV) || Late.count(FV))
1188 }
else if (Late.count(TV) || Late.count(FV)) {
1189 if (Early.count(TV) || Early.count(FV))
1201 bool AE =
true,
AL =
true;
1203 if (Early.count(&*
I))
1205 else if (Late.count(&*
I))
1229bool PolynomialMultiplyRecognize::commutesWithShift(Instruction *
I) {
1230 switch (
I->getOpcode()) {
1231 case Instruction::And:
1232 case Instruction::Or:
1233 case Instruction::Xor:
1234 case Instruction::LShr:
1235 case Instruction::Shl:
1236 case Instruction::Select:
1237 case Instruction::ICmp:
1238 case Instruction::PHI:
1246bool PolynomialMultiplyRecognize::highBitsAreZero(
Value *V,
1247 unsigned IterCount) {
1252 KnownBits
Known(
T->getBitWidth());
1254 return Known.countMinLeadingZeros() >= IterCount;
1257bool PolynomialMultiplyRecognize::keepsHighBitsZero(
Value *V,
1258 unsigned IterCount) {
1262 return C->getValue().countl_zero() >= IterCount;
1265 switch (
I->getOpcode()) {
1266 case Instruction::And:
1267 case Instruction::Or:
1268 case Instruction::Xor:
1269 case Instruction::LShr:
1270 case Instruction::Select:
1271 case Instruction::ICmp:
1272 case Instruction::PHI:
1273 case Instruction::ZExt:
1281bool PolynomialMultiplyRecognize::isOperandShifted(Instruction *
I,
Value *
Op) {
1282 unsigned Opc =
I->getOpcode();
1283 if (
Opc == Instruction::Shl ||
Opc == Instruction::LShr)
1284 return Op !=
I->getOperand(1);
1288bool PolynomialMultiplyRecognize::convertShiftsToLeft(BasicBlock *LoopB,
1289 BasicBlock *ExitB,
unsigned IterCount) {
1290 Value *CIV = getCountIV(LoopB);
1294 if (CIVTy ==
nullptr)
1298 ValueSeq Early, Late, Cycled;
1301 for (Instruction &
I : *LoopB) {
1302 using namespace PatternMatch;
1308 if (!findCycle(&
I, V,
C))
1313 classifyCycle(&
I,
C, Early, Late);
1314 Cycled.insert_range(
C);
1321 for (
unsigned i = 0; i <
Users.size(); ++i) {
1328 if (!commutesWithShift(R))
1330 for (User *U :
R->users()) {
1339 if (!classifyInst(
T, Early, Late))
1350 for (
unsigned i = 0; i <
Internal.size(); ++i) {
1356 if (
T &&
T->getParent() != LoopB)
1362 for (
Value *V : Inputs)
1363 if (!highBitsAreZero(V, IterCount))
1366 if (!keepsHighBitsZero(V, IterCount))
1371 std::map<Value*,Value*> ShiftMap;
1373 using CastMapType = std::map<std::pair<Value *, Type *>,
Value *>;
1375 CastMapType CastMap;
1378 IntegerType *Ty) ->
Value * {
1379 auto [
H,
Inserted] = CM.try_emplace(std::make_pair(V, Ty));
1381 H->second = IRB.CreateIntCast(V, Ty,
false);
1385 for (
auto I = LoopB->begin(),
E = LoopB->end();
I !=
E; ++
I) {
1386 using namespace PatternMatch;
1399 for (
auto &J :
I->operands()) {
1401 if (!isOperandShifted(&*
I,
Op))
1409 auto F = ShiftMap.find(
Op);
1410 Value *
W = (
F != ShiftMap.end()) ?
F->second :
nullptr;
1412 IRB.SetInsertPoint(&*
I);
1416 Value *ShAmt = CIV, *ShVal =
Op;
1419 if (Late.count(&*
I))
1420 ShVal = IRB.CreateShl(
Op, ConstantInt::get(VTy, 1));
1424 if (VTy->getBitWidth() < ATy->getBitWidth())
1425 ShVal = upcast(CastMap, IRB, ShVal, ATy);
1427 ShAmt = upcast(CastMap, IRB, ShAmt, VTy);
1430 W = IRB.CreateShl(ShVal, ShAmt);
1431 ShiftMap.insert(std::make_pair(
Op, W));
1433 I->replaceUsesOfWith(
Op, W);
1443 for (
auto P = ExitB->
begin(), Q = ExitB->
end();
P != Q; ++
P) {
1447 Value *
U = PN->getIncomingValueForBlock(LoopB);
1448 if (!
Users.count(U))
1450 Value *S = IRB.CreateLShr(PN, ConstantInt::get(PN->getType(), IterCount));
1451 PN->replaceAllUsesWith(S);
1462void PolynomialMultiplyRecognize::cleanupLoopBody(BasicBlock *LoopB) {
1463 for (
auto &
I : *LoopB)
1465 I.replaceAllUsesWith(SV);
1471unsigned PolynomialMultiplyRecognize::getInverseMxN(
unsigned QP) {
1474 std::array<char,32> Q,
C;
1476 for (
unsigned i = 0; i < 32; ++i) {
1493 for (
unsigned i = 1; i < 32; ++i) {
1501 for (
unsigned j = 0;
j < i; ++
j)
1502 T =
T ^ (
C[j] & Q[i-j]);
1507 for (
unsigned i = 0; i < 32; ++i)
1517 Module *
M = At->getParent()->getParent()->getParent();
1522 unsigned IC = PV.IterCount;
1524 if (PV.M !=
nullptr)
1525 P0 =
P =
B.CreateXor(
P, PV.M);
1530 if (PV.IterCount != 32)
1531 P =
B.CreateAnd(
P, BMI);
1535 assert(QI && QI->getBitWidth() <= 32);
1538 unsigned M = (1 << PV.IterCount) - 1;
1539 unsigned Tmp = (QI->getZExtValue() | 1) &
M;
1540 unsigned QV = getInverseMxN(Tmp) &
M;
1541 auto *QVI = ConstantInt::get(QI->getType(), QV);
1542 P =
B.CreateCall(PMF, {
P, QVI});
1543 P =
B.CreateTrunc(
P, QI->getType());
1545 P =
B.CreateAnd(
P, BMI);
1548 Value *
R =
B.CreateCall(PMF, {
P, Q});
1550 if (PV.M !=
nullptr)
1551 R =
B.CreateXor(R,
B.CreateIntCast(P0,
R->getType(),
false));
1558 return CI->getValue().isNonNegative();
1562 switch (
I->getOpcode()) {
1563 case Instruction::LShr:
1565 return SI->getZExtValue() > 0;
1567 case Instruction::Or:
1568 case Instruction::Xor:
1571 case Instruction::And:
1578void PolynomialMultiplyRecognize::setupPreSimplifier(Simplifier &S) {
1579 S.addRule(
"sink-zext",
1582 if (
I->getOpcode() != Instruction::ZExt)
1587 switch (
T->getOpcode()) {
1588 case Instruction::And:
1589 case Instruction::Or:
1590 case Instruction::Xor:
1596 return B.CreateBinOp(
1598 B.CreateZExt(
T->getOperand(0),
I->getType()),
1599 B.CreateZExt(
T->getOperand(1),
I->getType()));
1601 S.addRule(
"xor/and -> and/xor",
1604 if (
I->getOpcode() != Instruction::Xor)
1610 if (And0->
getOpcode() != Instruction::And ||
1621 "sink binop into select",
1631 Value *
X = Sel->getTrueValue(), *
Y = Sel->getFalseValue();
1633 return B.CreateSelect(Sel->getCondition(),
B.CreateBinOp(
Op,
X, Z),
1634 B.CreateBinOp(
Op,
Y, Z));
1639 Value *
Y = Sel->getTrueValue(), *
Z = Sel->getFalseValue();
1640 return B.CreateSelect(Sel->getCondition(),
B.CreateBinOp(
Op,
X,
Y),
1641 B.CreateBinOp(
Op,
X, Z));
1646 "fold select-select",
1656 if (Sel0->getCondition() ==
C)
1657 return B.CreateSelect(
C, Sel0->getTrueValue(),
1661 if (Sel1->getCondition() ==
C)
1663 Sel1->getFalseValue());
1667 S.addRule(
"or-signbit -> xor-signbit",
1670 if (
I->getOpcode() != Instruction::Or)
1677 return IRBuilder<>(M).CreateXor(
I->getOperand(0), Msb);
1679 S.addRule(
"sink lshr into binop",
1682 if (
I->getOpcode() != Instruction::LShr)
1684 BinaryOperator *BitOp =
1689 case Instruction::And:
1690 case Instruction::Or:
1691 case Instruction::Xor:
1697 Value *S =
I->getOperand(1);
1702 S.addRule(
"expose bitop-const",
1705 auto IsBitOp = [](
unsigned Op) ->
bool {
1707 case Instruction::And:
1708 case Instruction::Or:
1709 case Instruction::Xor:
1715 if (!BitOp1 || !IsBitOp(BitOp1->
getOpcode()))
1717 BinaryOperator *BitOp2 =
1719 if (!BitOp2 || !IsBitOp(BitOp2->
getOpcode()))
1730 S.addRule(
"select with trunc cond to select with icmp cond",
1739 using namespace PatternMatch;
1745 Type *Ty =
X->getType();
1746 Value *
And =
B.CreateAnd(
X, ConstantInt::get(Ty, 1));
1748 : ICmpInst::ICMP_EQ,
1749 And, ConstantInt::get(Ty, 0));
1755void PolynomialMultiplyRecognize::setupPostSimplifier(Simplifier &S) {
1756 S.addRule(
"(and (xor (and x a) y) b) -> (and (xor x y) b), if b == b&a",
1758 if (
I->getOpcode() != Instruction::And)
1764 if (
Xor->getOpcode() != Instruction::Xor)
1769 if (!And0 || And0->
getOpcode() != Instruction::And)
1776 if (V0 != (V0 &
V1))
1779 return B.CreateAnd(
B.CreateXor(And0->
getOperand(0), And1), C0);
1783bool PolynomialMultiplyRecognize::recognize() {
1784 LLVM_DEBUG(
dbgs() <<
"Starting PolynomialMultiplyRecognize on loop\n"
1785 << *CurLoop <<
'\n');
1794 if (LoopB != CurLoop->getLoopLatch())
1797 if (ExitB ==
nullptr)
1799 BasicBlock *EntryB = CurLoop->getLoopPreheader();
1800 if (EntryB ==
nullptr)
1803 unsigned IterCount = 0;
1804 const SCEV *CT = SE.getBackedgeTakenCount(CurLoop);
1808 IterCount = CV->getValue()->getZExtValue() + 1;
1810 Value *CIV = getCountIV(LoopB);
1815 PV.IterCount = IterCount;
1816 LLVM_DEBUG(
dbgs() <<
"Loop IV: " << *CIV <<
"\nIterCount: " << IterCount
1819 setupPreSimplifier(PreSimp);
1827 bool FoundPreScan =
false;
1828 auto FeedsPHI = [LoopB](
const Value *
V) ->
bool {
1829 for (
const Value *U :
V->users()) {
1831 if (
P->getParent() == LoopB)
1836 for (Instruction &In : *LoopB) {
1838 if (!SI || !FeedsPHI(SI))
1841 Simplifier::Context
C(SI);
1842 Value *
T = PreSimp.simplify(
C);
1844 LLVM_DEBUG(
dbgs() <<
"scanSelect(pre-scan): " << PE(
C, SelI) <<
'\n');
1845 if (scanSelect(SelI, LoopB, EntryB, CIV, PV,
true)) {
1846 FoundPreScan =
true;
1848 Value *NewSel =
C.materialize(LoopB,
SI->getIterator());
1849 SI->replaceAllUsesWith(NewSel);
1856 if (!FoundPreScan) {
1866 if (!promoteTypes(LoopB, ExitB))
1869 Simplifier PostSimp;
1870 setupPostSimplifier(PostSimp);
1871 for (Instruction &In : *LoopB) {
1873 if (!SI || !FeedsPHI(SI))
1875 Simplifier::Context
C(SI);
1876 Value *
T = PostSimp.simplify(
C);
1879 Value *NewSel =
C.materialize(LoopB,
SI->getIterator());
1880 SI->replaceAllUsesWith(NewSel);
1886 if (!convertShiftsToLeft(LoopB, ExitB, IterCount))
1888 cleanupLoopBody(LoopB);
1892 bool FoundScan =
false;
1893 for (Instruction &In : *LoopB) {
1898 FoundScan = scanSelect(SelI, LoopB, EntryB, CIV, PV,
false);
1905 StringRef PP = (PV.M ?
"(P+M)" :
"P");
1907 dbgs() <<
"Found pmpy idiom: R = " << PP <<
".Q\n";
1909 dbgs() <<
"Found inverse pmpy idiom: R = (" << PP <<
"/Q).Q) + "
1911 dbgs() <<
" Res:" << *PV.Res <<
"\n P:" << *PV.P <<
"\n";
1913 dbgs() <<
" M:" << *PV.M <<
"\n";
1914 dbgs() <<
" Q:" << *PV.Q <<
"\n";
1915 dbgs() <<
" Iteration count:" << PV.IterCount <<
"\n";
1919 Value *PM = generate(At, PV);
1923 if (PM->
getType() != PV.Res->getType())
1924 PM =
IRBuilder<>(&*At).CreateIntCast(PM, PV.Res->getType(),
false);
1926 PV.Res->replaceAllUsesWith(PM);
1927 PV.Res->eraseFromParent();
1931int HexagonLoopIdiomRecognize::getSCEVStride(
const SCEVAddRecExpr *S) {
1933 return SC->getAPInt().getSExtValue();
1937bool HexagonLoopIdiomRecognize::isLegalStore(
Loop *CurLoop, StoreInst *SI) {
1942 Value *StoredVal =
SI->getValueOperand();
1943 Value *StorePtr =
SI->getPointerOperand();
1947 if ((SizeInBits & 7) || (SizeInBits >> 32) != 0)
1954 if (!StoreEv || StoreEv->getLoop() != CurLoop || !StoreEv->isAffine()) {
1956 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NonAffineStorePtr",
1957 SI->getDebugLoc(),
SI->getParent())
1958 <<
"store pointer is not an affine AddRec";
1965 int Stride = getSCEVStride(StoreEv);
1968 unsigned StoreSize =
DL->getTypeStoreSize(
SI->getValueOperand()->getType());
1969 if (StoreSize !=
unsigned(std::abs(Stride))) {
1971 return OptimizationRemarkMissed(
DEBUG_TYPE,
"StrideSizeMismatch",
1972 SI->getDebugLoc(),
SI->getParent())
1973 <<
"stride does not match store size";
1982 return OptimizationRemarkMissed(
DEBUG_TYPE,
"StoreNotFeedingLoad",
1983 SI->getDebugLoc(),
SI->getParent())
1984 <<
"store value is not a simple load";
1994 if (!LoadEv || LoadEv->getLoop() != CurLoop || !LoadEv->isAffine()) {
1996 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NonAffineLoadPtr",
1998 <<
"load pointer is not an affine AddRec";
2004 if (StoreEv->getOperand(1) != LoadEv->getOperand(1))
2016 const SCEV *BECount,
unsigned StoreSize,
2036 for (
auto *
B : L->blocks())
2038 if (Ignored.
count(&
I) == 0 &&
2045void HexagonLoopIdiomRecognize::collectStores(
Loop *CurLoop, BasicBlock *BB,
2046 SmallVectorImpl<StoreInst*> &Stores) {
2048 for (Instruction &
I : *BB)
2050 if (isLegalStore(CurLoop, SI))
2054bool HexagonLoopIdiomRecognize::processCopyingStore(
Loop *CurLoop,
2055 StoreInst *SI,
const SCEV *BECount) {
2057 "Expected only non-volatile stores, or Hexagon-specific memcpy"
2058 "to volatile destination.");
2060 Value *StorePtr =
SI->getPointerOperand();
2062 unsigned Stride = getSCEVStride(StoreEv);
2063 unsigned StoreSize =
DL->getTypeStoreSize(
SI->getValueOperand()->getType());
2064 if (Stride != StoreSize)
2079 SCEVExpander Expander(*SE,
"hexagon-loop-idiom");
2089 Value *StoreBasePtr = Expander.expandCodeFor(StoreEv->getStart(),
2090 Builder.getPtrTy(
SI->getPointerAddressSpace()), ExpPt);
2091 Value *LoadBasePtr =
nullptr;
2093 bool Overlap =
false;
2094 bool DestVolatile =
SI->isVolatile();
2100 if (StoreSize != 4 ||
DL->getTypeSizeInBits(BECountTy) > 32) {
2104 if (StoreBasePtr && (LoadBasePtr != StoreBasePtr)) {
2106 StoreBasePtr =
nullptr;
2110 LoadBasePtr =
nullptr;
2116 SmallPtrSet<Instruction*, 2> Ignore1;
2119 StoreSize, *AA, Ignore1)) {
2123 BECount, StoreSize, *AA, Ignore1)) {
2126 return OptimizationRemarkMissed(
DEBUG_TYPE,
"MemoryAlias",
2127 SI->getDebugLoc(),
SI->getParent())
2128 <<
"memory aliasing prevents memcpy/memmove";
2130 goto CleanupAndExit;
2139 return OptimizationRemarkMissed(
DEBUG_TYPE,
"MemcpyDisabled",
2140 SI->getDebugLoc(),
SI->getParent())
2141 <<
"memcpy idiom is disabled or unavailable";
2143 goto CleanupAndExit;
2149 if (
Func->hasFnAttribute(Attribute::AlwaysInline))
2150 goto CleanupAndExit;
2156 SmallVector<Instruction*,2> Insts;
2159 if (!coverLoop(CurLoop, Insts)) {
2161 return OptimizationRemarkMissed(
DEBUG_TYPE,
"ExtraLoopInstructions",
2162 SI->getDebugLoc(),
SI->getParent())
2163 <<
"loop contains instructions beyond load/store pair";
2165 goto CleanupAndExit;
2170 return OptimizationRemarkMissed(
DEBUG_TYPE,
"MemmoveDisabled",
2171 SI->getDebugLoc(),
SI->getParent())
2172 <<
"memmove idiom is disabled or unavailable";
2174 goto CleanupAndExit;
2179 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NestedLoop",
2180 SI->getDebugLoc(),
SI->getParent())
2181 <<
"memmove skipped for nested loop";
2183 goto CleanupAndExit;
2189 LoadBasePtr = Expander.expandCodeFor(LoadEv->getStart(),
2192 SmallPtrSet<Instruction*, 2> Ignore2;
2195 StoreSize, *AA, Ignore2))
2196 goto CleanupAndExit;
2199 bool StridePos = getSCEVStride(LoadEv) >= 0;
2202 if (!StridePos && DestVolatile)
2203 goto CleanupAndExit;
2205 bool RuntimeCheck = (Overlap || DestVolatile);
2210 SmallVector<BasicBlock*, 8> ExitBlocks;
2212 if (ExitBlocks.
size() != 1)
2213 goto CleanupAndExit;
2214 ExitB = ExitBlocks[0];
2219 LLVMContext &Ctx =
SI->getContext();
2220 BECount = SE->getTruncateOrZeroExtend(BECount,
IntPtrTy);
2223 const SCEV *NumBytesS =
2226 NumBytesS = SE->getMulExpr(NumBytesS, SE->getConstant(
IntPtrTy, StoreSize),
2228 Value *NumBytes = Expander.expandCodeFor(NumBytesS,
IntPtrTy, ExpPt);
2239 if (Threshold != 0 &&
C < Threshold)
2240 goto CleanupAndExit;
2242 goto CleanupAndExit;
2247 Loop *ParentL = LF->getLoopFor(Preheader);
2248 StringRef HeaderName = Header->getName();
2257 for (
auto &In : *Header) {
2265 DT->addNewBlock(NewPreheader, Preheader);
2266 DT->changeImmediateDominator(Header, NewPreheader);
2276 Value *LowA = StridePos ? SA : LA;
2277 Value *HighA = StridePos ? LA : SA;
2278 Value *CmpA = Builder.CreateICmpULT(LowA, HighA);
2283 Value *Dist = Builder.CreateSub(LowA, HighA);
2284 Value *CmpD = Builder.CreateICmpSLE(NumBytes, Dist);
2285 Value *CmpEither = Builder.CreateOr(
Cond, CmpD);
2288 if (Threshold != 0) {
2290 Value *Thr = ConstantInt::get(Ty, Threshold);
2291 Value *CmpB = Builder.CreateICmpULT(Thr, NumBytes);
2292 Value *CmpBoth = Builder.CreateAnd(
Cond, CmpB);
2296 Func, NewPreheader);
2300 Builder.CreateCondBr(
Cond, MemmoveB, NewPreheader);
2303 DT->addNewBlock(MemmoveB, Preheader);
2307 ExitD = DT->findNearestCommonDominator(ExitD,
PB);
2315 if (ExitD && DT->dominates(Preheader, ExitD)) {
2323 CondBuilder.CreateBr(ExitB);
2327 Type *Int32Ty = Type::getInt32Ty(Ctx);
2328 Type *PtrTy = PointerType::get(Ctx, 0);
2329 Type *VoidTy = Type::getVoidTy(Ctx);
2333 StringRef HexagonVolatileMemcpyName =
2335 RTLIB::impl_hexagon_memcpy_forward_vp4cp4n2);
2336 FunctionCallee Fn =
M->getOrInsertFunction(
2337 HexagonVolatileMemcpyName, VoidTy, PtrTy, PtrTy, Int32Ty);
2339 const SCEV *OneS = SE->getConstant(Int32Ty, 1);
2340 const SCEV *BECount32 = SE->getTruncateOrZeroExtend(BECount, Int32Ty);
2341 const SCEV *NumWordsS = SE->getAddExpr(BECount32, OneS,
SCEV::FlagNUW);
2342 Value *NumWords = Expander.expandCodeFor(NumWordsS, Int32Ty,
2348 NewCall = CondBuilder.CreateCall(Fn,
2349 {StoreBasePtr, LoadBasePtr, NumWords});
2351 NewCall = CondBuilder.CreateMemMove(
2352 StoreBasePtr,
SI->getAlign(), LoadBasePtr, LI->
getAlign(), NumBytes);
2355 NewCall = Builder.CreateMemCpy(StoreBasePtr,
SI->getAlign(), LoadBasePtr,
2364 LLVM_DEBUG(
dbgs() <<
" Formed " << (Overlap ?
"memmove: " :
"memcpy: ")
2366 <<
" from load ptr=" << *LoadEv <<
" at: " << *LI <<
"\n"
2367 <<
" from store ptr=" << *StoreEv <<
" at: " << *SI
2372 return OptimizationRemark(
DEBUG_TYPE,
"LoopToMemmove", DLoc,
2374 <<
"converted loop to memmove";
2378 return OptimizationRemark(
DEBUG_TYPE,
"LoopToMemcpy", DLoc,
2380 <<
"converted loop to memcpy";
2390bool HexagonLoopIdiomRecognize::coverLoop(
Loop *L,
2391 SmallVectorImpl<Instruction*> &Insts)
const {
2392 SmallPtrSet<BasicBlock *, 8> LoopBlocks;
2401 for (
unsigned i = 0; i < Worklist.size(); ++i) {
2403 for (
auto I =
In->op_begin(),
E =
In->op_end();
I !=
E; ++
I) {
2410 Worklist.insert(OpI);
2418 for (
auto *
B :
L->blocks()) {
2419 for (
auto &In : *
B) {
2422 if (!Worklist.count(&In) &&
In.mayHaveSideEffects())
2424 for (
auto *K :
In.users()) {
2429 if (LF->getLoopFor(UseB) != L)
2441bool HexagonLoopIdiomRecognize::runOnLoopBlock(
Loop *CurLoop, BasicBlock *BB,
2442 const SCEV *BECount, SmallVectorImpl<BasicBlock*> &ExitBlocks) {
2446 auto DominatedByBB = [
this,BB] (
BasicBlock *EB) ->
bool {
2447 return DT->dominates(BB, EB);
2449 if (!
all_of(ExitBlocks, DominatedByBB))
2452 bool MadeChange =
false;
2454 SmallVector<StoreInst*,8> Stores;
2455 collectStores(CurLoop, BB, Stores);
2458 for (
auto &SI : Stores)
2459 MadeChange |= processCopyingStore(CurLoop, SI, BECount);
2464bool HexagonLoopIdiomRecognize::runOnCountableLoop(
Loop *L) {
2465 PolynomialMultiplyRecognize PMR(L, *
DL, *DT, *TLI, *SE);
2466 if (PMR.recognize()) {
2468 return OptimizationRemark(
DEBUG_TYPE,
"PolynomialMultiply",
2469 L->getStartLoc(),
L->getHeader())
2470 <<
"recognized polynomial multiply idiom";
2475 if (!HasMemcpy && !HasMemmove)
2478 const SCEV *BECount = SE->getBackedgeTakenCount(L);
2480 "runOnCountableLoop() called on a loop without a predictable"
2481 "backedge-taken count");
2483 SmallVector<BasicBlock *, 8> ExitBlocks;
2484 L->getUniqueExitBlocks(ExitBlocks);
2489 for (
auto *BB :
L->getBlocks()) {
2491 if (LF->getLoopFor(BB) != L)
2493 Changed |= runOnLoopBlock(L, BB, BECount, ExitBlocks);
2499bool HexagonLoopIdiomRecognize::run(
Loop *L) {
2500 const Module &
M = *
L->getHeader()->getParent()->getParent();
2506 if (!
L->getLoopPreheader()) {
2508 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NoPreheader",
2509 L->getStartLoc(),
L->getHeader())
2510 <<
"loop not in canonical form (no preheader)";
2516 StringRef
Name =
L->getHeader()->getParent()->getName();
2517 if (Name ==
"memset" || Name ==
"memcpy" || Name ==
"memmove")
2520 DL = &
L->getHeader()->getDataLayout();
2522 HasMemcpy = TLI->has(LibFunc_memcpy);
2523 HasMemmove = TLI->has(LibFunc_memmove);
2525 if (SE->hasLoopInvariantBackedgeTakenCount(L))
2526 return runOnCountableLoop(L);
2529 return OptimizationRemarkMissed(
DEBUG_TYPE,
"NonCountableLoop",
2530 L->getStartLoc(),
L->getHeader())
2531 <<
"backedge-taken count is not loop-invariant";
2536bool HexagonLoopIdiomRecognizeLegacyPass::runOnLoop(
Loop *L,
2537 LPPassManager &LPM) {
2541 auto *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
2542 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
2543 auto *LF = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
2544 auto *TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
2545 *
L->getHeader()->getParent());
2546 auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
2547 auto &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
2548 return HexagonLoopIdiomRecognize(AA, DT, LF, TLI, SE, ORE).run(L);
2552 return new HexagonLoopIdiomRecognizeLegacyPass();
2560 return HexagonLoopIdiomRecognize(&AR.
AA, &AR.
DT, &AR.
LI, &AR.
TLI, &AR.
SE, ORE)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
This file contains the simple types necessary to represent the attributes associated with functions a...
static const Function * getParent(const Value *V)
static void cleanup(BlockFrequencyInfoImplBase &BFI)
Clear all memory not needed downstream.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ATTRIBUTE_USED
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
static cl::opt< unsigned > SimplifyLimit("hlir-simplify-limit", cl::init(10000), cl::Hidden, cl::desc("Maximum number of simplification steps in HLIR"))
static cl::opt< bool > DisableMemcpyIdiom("disable-memcpy-idiom", cl::Hidden, cl::init(false), cl::desc("Disable generation of memcpy in loop idiom recognition"))
static void replaceAllUsesOfWithIn(Value *I, Value *J, BasicBlock *BB)
static cl::opt< unsigned > RuntimeMemSizeThreshold("runtime-mem-idiom-threshold", cl::Hidden, cl::init(0), cl::desc("Threshold (in bytes) for the runtime " "check guarding the memmove."))
static cl::opt< bool > HexagonVolatileMemcpy("disable-hexagon-volatile-memcpy", cl::Hidden, cl::init(false), cl::desc("Enable Hexagon-specific memcpy for volatile destination."))
static cl::opt< bool > DisableMemmoveIdiom("disable-memmove-idiom", cl::Hidden, cl::init(false), cl::desc("Disable generation of memmove in loop idiom recognition"))
static cl::opt< unsigned > CompileTimeMemSizeThreshold("compile-time-mem-idiom-threshold", cl::Hidden, cl::init(64), cl::desc("Threshold (in bytes) to perform the transformation, if the " "runtime loop count (mem transfer size) is known at compile-time."))
static bool mayLoopAccessLocation(Value *Ptr, ModRefInfo Access, Loop *L, const SCEV *BECount, unsigned StoreSize, AliasAnalysis &AA, SmallPtrSetImpl< Instruction * > &Ignored)
mayLoopAccessLocation - Return true if the specified loop might access the specified pointer location...
static bool hasZeroSignBit(const Value *V)
static cl::opt< bool > OnlyNonNestedMemmove("only-nonnested-memmove-idiom", cl::Hidden, cl::init(true), cl::desc("Only enable generating memmove in non-nested loops"))
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
iv Induction Variable Users
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
Move duplicate certain instructions close to their use
This header provides classes for managing per-loop analyses.
Machine Check Debug Module
This file provides utility analysis objects describing memory locations.
uint64_t IntrinsicInst * II
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
const SmallVectorImpl< MachineOperand > & Cond
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
bool isSignMask() const
Check if the APInt's value is returned by getSignMask.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
LLVM_ABI AnalysisUsage & addRequiredID(const void *ID)
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
BinaryOps getOpcode() const
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
const APInt & getValue() const
Return the constant as an APInt value reference.
void setIDom(DomTreeNodeBase *NewIDom)
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
user_iterator user_begin()
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
This class provides an interface for updating the loop pass manager based on mutations to the loop ne...
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
Value * getPointerOperand()
Align getAlign() const
Return the alignment of the access that is being performed.
static LocationSize precise(uint64_t Value)
static constexpr LocationSize afterPointer()
Any location after the base pointer (but still within the underlying object).
BlockT * getHeader() const
void addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase< BlockT, LoopT > &LI)
This method is used by other analyses to update loop information.
BlockT * getLoopPreheader() const
If there is a preheader for this loop, return it.
void getUniqueExitBlocks(SmallVectorImpl< BlockT * > &ExitBlocks) const
Return all unique successor blocks of this loop.
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
The legacy pass manager's analysis pass to compute loop information.
Represents a single loop in the control flow graph.
Representation for a specific memory location.
void setIncomingBlock(unsigned i, BasicBlock *BB)
int getBasicBlockIndex(const BasicBlock *BB) const
Return the first index of the specified basic block in the value list for this PHI.
Pass interface - Implemented by all 'passes'.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
This class represents a constant integer value.
SCEVUse getOperand(unsigned i) const
This class represents an analyzed expression in the program.
static constexpr auto FlagNUW
Type * getType() const
Return the LLVM type of this SCEV expression.
The main scalar evolution driver.
const Value * getFalseValue() const
const Value * getCondition() const
const Value * getTrueValue() const
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
void push_back(const T &Elt)
Provides information about what library functions are available for the current target.
bool isVoidTy() const
Return true if this is 'void'.
A Use represents the edge between a Value definition and its users.
User * getUser() const
Returns the User that contains this Use.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
const ParentTy * getParent() const
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
CastInst_match< OpTy, TruncInst > m_Trunc(const OpTy &Op)
Matches Trunc.
BinaryOp_match< LHS, RHS, Instruction::Xor > m_Xor(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
CmpClass_match< LHS, RHS, ICmpInst, true > m_c_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
Matches an ICmp with a predicate over LHS and RHS in either order.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Xor, true > m_c_Xor(const LHS &L, const RHS &R)
Matches an Xor with LHS and RHS in either order.
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
BinaryOp_match< LHS, RHS, Instruction::LShr > m_LShr(const LHS &L, const RHS &R)
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
LLVM_ABI void link(std::unique_ptr< LinkGraph > G, std::unique_ptr< JITLinkContext > Ctx)
Link the given graph.
NodeAddr< UseNode * > Use
NodeAddr< FuncNode * > Func
friend class Instruction
Iterator for Instructions in a `BasicBlock.
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
This is an optimization pass for GlobalISel generic memory operations.
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
If the specified value is a trivially dead instruction, delete it.
@ Known
Known to have no common set bits.
auto pred_end(const MachineBasicBlock *BB)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
constexpr from_range_t from_range
Pass * createHexagonLoopIdiomPass()
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
LLVM_ABI char & LoopSimplifyID
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
LLVM_ABI Value * simplifyInstruction(Instruction *I, const SimplifyQuery &Q)
See if we can compute a simplified version of this instruction.
DomTreeNodeBase< BasicBlock > DomTreeNode
AnalysisManager< Loop, LoopStandardAnalysisResults & > LoopAnalysisManager
The loop analysis manager.
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
bool isModOrRefSet(const ModRefInfo MRI)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
void replace(R &&Range, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace which take ranges instead of having to pass begin/end explicitly.
@ Xor
Bitwise or logical XOR of integers.
@ And
Bitwise or logical AND of integers.
@ Sub
Subtraction of integers.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
PredIterator< BasicBlock, Value::user_iterator > pred_iterator
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
auto pred_begin(const MachineBasicBlock *BB)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI PreservedAnalyses getLoopPassPreservedAnalyses()
Returns the minimum set of Analyses that all loop passes must preserve.
auto predecessors(const MachineBasicBlock *BB)
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
bool equal(L &&LRange, R &&RRange)
Wrapper function around std::equal to detect if pair-wise elements between two ranges are the same.
AAResults AliasAnalysis
Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U)
The adaptor from a function pass to a loop pass computes these analyses and makes them available to t...
static StringRef getLibcallImplName(RTLIB::LibcallImpl CallImpl)
Get the libcall routine name for the specified libcall implementation.