10 #define DEBUG_TYPE "hexagon-lir" 78 cl::desc(
"Disable generation of memcpy in loop idiom recognition"));
82 cl::desc(
"Disable generation of memmove in loop idiom recognition"));
86 "check guarding the memmove."));
90 cl::desc(
"Threshold (in bytes) to perform the transformation, if the " 91 "runtime loop count (mem transfer size) is known at compile-time."));
95 cl::desc(
"Only enable generating memmove in non-nested loops"));
99 cl::desc(
"Enable Hexagon-specific memcpy for volatile destination."));
105 =
"hexagon_memcpy_forward_vp4cp4n2";
117 class HexagonLoopIdiomRecognize :
public LoopPass {
121 explicit HexagonLoopIdiomRecognize() :
LoopPass(ID) {
126 return "Recognize Hexagon-specific loop idioms";
152 bool runOnCountableLoop(
Loop *L);
160 bool HasMemcpy, HasMemmove;
165 using FuncType = std::function<Value* (Instruction*, LLVMContext&)>;
171 void addRule(
StringRef N,
const Rule::FuncType &
F) {
172 Rules.push_back(Rule(N, F));
176 struct WorkListType {
177 WorkListType() =
default;
179 void push_back(
Value* V) {
181 if (!S.count(V)) { Q.push_back(V); S.insert(V); }
184 Value *pop_front_val() {
185 Value *V = Q.front(); Q.pop_front(); S.erase(V);
189 bool empty()
const {
return Q.empty(); }
192 std::deque<Value*> Q;
196 using ValueSetType = std::set<Value *>;
198 std::vector<Rule> Rules;
220 friend struct Simplifier;
225 template <
typename FuncT>
void traverse(
Value *V, FuncT F);
226 void record(
Value *V);
228 void unuse(
Value *V);
249 P.C.print(OS, P.V ? P.V : P.C.Root);
258 "Recognize Hexagon-specific loop idioms",
false,
false)
267 "Recognize Hexagon-specific loop
idioms",
false, false)
269 template <typename FuncT>
288 OS << V <<
'(' << *V <<
')';
292 if (U->getParent()) {
294 U->printAsOperand(OS,
true);
299 unsigned N = U->getNumOperands();
302 OS << U->getOpcodeName();
303 for (
const Value *
Op : U->operands()) {
321 Value *V = Q.pop_front_val();
322 if (M.find(V) != M.end())
325 if (isa<PHINode>(U) || U->getParent() != Block)
327 for (
Value *
Op : U->operands())
329 M.insert({U, U->clone()});
333 for (std::pair<Value*,Value*>
P : M) {
342 auto R = M.find(Exp);
350 void Simplifier::Context::record(
Value *V) {
366 void Simplifier::Context::unuse(
Value *V) {
367 if (!isa<Instruction>(V) || cast<Instruction>(V)->
getParent() !=
nullptr)
421 Value *V = Q.pop_front_val();
427 NewV = subst(NewV, V, DupV);
435 Root = subst(Root, OldV, NewV);
440 for (
Value *V : Clones) {
446 for (
Value *V : Clones) {
469 if (!
equal(InI, InJ))
471 }
else if (InI != InJ || !InI)
483 Value *V = Q.pop_front_val();
489 if (SubI &&
equal(SubI, U))
513 if (
Instruction *RootI = dyn_cast<Instruction>(Root))
525 if (Count++ >= Limit)
528 if (!U || U->
getParent() || !C.Used.count(U))
530 bool Changed =
false;
531 for (Rule &R : Rules) {
532 Value *
W = R.Fn(U, C.Ctx);
546 return Count < Limit ? C.Root :
nullptr;
557 class PolynomialMultiplyRecognize {
559 explicit PolynomialMultiplyRecognize(
Loop *loop,
const DataLayout &dl,
562 : CurLoop(loop), DL(dl), DT(dt), TLI(tli), SE(se) {}
570 LLVMContext &Ctx = CurLoop->getHeader()->getParent()->getContext();
579 bool findCycle(
Value *Out,
Value *In, ValueSeq &Cycle);
580 void classifyCycle(
Instruction *DivI, ValueSeq &Cycle, ValueSeq &Early,
582 bool classifyInst(
Instruction *UseI, ValueSeq &Early, ValueSeq &Late);
584 bool highBitsAreZero(
Value *V,
unsigned IterCount);
585 bool keepsHighBitsZero(
Value *V,
unsigned IterCount);
591 struct ParsedValues {
592 ParsedValues() =
default;
600 unsigned IterCount = 0;
606 bool matchRightShift(
SelectInst *SelI, ParsedValues &PV);
608 Value *CIV, ParsedValues &PV,
bool PreScan);
609 unsigned getInverseMxN(
unsigned QP);
612 void setupPreSimplifier(Simplifier &S);
613 void setupPostSimplifier(Simplifier &S);
626 if (std::distance(PI, PE) != 2)
628 BasicBlock *PB = (*PI == BB) ? *std::next(PI) : *PI;
630 for (
auto I = BB->
begin(),
E = BB->
end(); I !=
E && isa<PHINode>(
I); ++
I) {
631 auto *PN = cast<PHINode>(
I);
632 Value *InitV = PN->getIncomingValueForBlock(PB);
633 if (!isa<ConstantInt>(InitV) || !cast<ConstantInt>(InitV)->
isZero())
635 Value *IterV = PN->getIncomingValueForBlock(BB);
636 if (!isa<BinaryOperator>(IterV))
641 Value *IncV =
nullptr;
642 if (BO->getOperand(0) == PN)
643 IncV = BO->getOperand(1);
644 else if (BO->getOperand(1) == PN)
645 IncV = BO->getOperand(0);
649 if (
auto *
T = dyn_cast<ConstantInt>(IncV))
650 if (
T->getZExtValue() == 1)
658 Use &TheUse = UI.getUse();
660 if (
auto *II = dyn_cast<Instruction>(TheUse.
getUser()))
662 II->replaceUsesOfWith(I, J);
666 bool PolynomialMultiplyRecognize::matchLeftShift(
SelectInst *SelI,
667 Value *CIV, ParsedValues &PV) {
682 Value *A =
nullptr, *B =
nullptr, *C =
nullptr;
692 Value *
X =
nullptr, *Sh1 =
nullptr;
720 Value *ShouldSameV =
nullptr, *ShouldXoredV =
nullptr;
723 ShouldXoredV = FalseV;
725 ShouldSameV = FalseV;
726 ShouldXoredV = TrueV;
729 Value *Q =
nullptr, *R =
nullptr, *
Y =
nullptr, *
Z =
nullptr;
735 if (ShouldSameV ==
Y)
737 else if (ShouldSameV ==
Z)
781 bool PolynomialMultiplyRecognize::matchRightShift(
SelectInst *SelI,
824 Value *R =
nullptr, *Q =
nullptr;
856 bool PolynomialMultiplyRecognize::scanSelect(
SelectInst *SelI,
898 if (matchLeftShift(SelI, CIV, PV)) {
907 if (SelI != RPhi->getIncomingValueForBlock(LoopB))
913 if (CurLoop->isLoopInvariant(PV.X)) {
923 Value *Var =
nullptr, *Inv =
nullptr, *X1 =
nullptr, *X2 =
nullptr;
928 if (!I1 || I1->getParent() != LoopB) {
931 }
else if (!I2 || I2->getParent() != LoopB) {
942 Value *EntryP = RPhi->getIncomingValueForBlock(PrehB);
949 if (matchRightShift(SelI, PV)) {
952 if (PV.Inv && !isa<ConstantInt>(PV.Q))
963 bool PolynomialMultiplyRecognize::isPromotableTo(
Value *Val,
982 case Instruction::PHI:
983 case Instruction::ZExt:
984 case Instruction::And:
985 case Instruction::Or:
986 case Instruction::Xor:
987 case Instruction::LShr:
989 case Instruction::Trunc:
991 case Instruction::ICmp:
992 if (
CmpInst *CI = cast<CmpInst>(In))
993 return CI->isEquality() || CI->isUnsigned();
1001 void PolynomialMultiplyRecognize::promoteTo(
Instruction *
In,
1011 if (
PHINode *
P = dyn_cast<PHINode>(In)) {
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);
1028 }
else if (
ZExtInst *
Z = dyn_cast<ZExtInst>(In)) {
1031 Z->replaceAllUsesWith(Op);
1032 Z->eraseFromParent();
1035 if (
TruncInst *
T = dyn_cast<TruncInst>(In)) {
1039 T->replaceAllUsesWith(And);
1040 T->eraseFromParent();
1047 if (CI->getType()->getBitWidth() < DestBW)
1052 bool PolynomialMultiplyRecognize::promoteTypes(
BasicBlock *LoopB,
1066 if (
P.getNumIncomingValues() != 1)
1068 assert(
P.getIncomingBlock(0) == LoopB);
1070 if (!T || T->getBitWidth() > DestBW)
1076 if (!In.
isTerminator() && !isPromotableTo(&In, DestTy))
1080 std::vector<Instruction*> LoopIns;
1081 std::transform(LoopB->begin(), LoopB->end(), std::back_inserter(LoopIns),
1084 promoteTo(In, DestTy, LoopB);
1089 for (
auto I = ExitB->
begin(); I != End; ++
I) {
1105 cast<Instruction>(
T)->setOperand(0, P);
1112 bool PolynomialMultiplyRecognize::findCycle(
Value *Out,
Value *In,
1118 auto *BB = cast<Instruction>(Out)->
getParent();
1119 bool HadPhi =
false;
1121 for (
auto U : Out->
users()) {
1123 if (I ==
nullptr || I->
getParent() != BB)
1130 bool IsPhi = isa<PHINode>(
I);
1131 if (IsPhi && HadPhi)
1137 if (findCycle(I, In, Cycle))
1141 return !Cycle.empty();
1144 void PolynomialMultiplyRecognize::classifyCycle(
Instruction *DivI,
1145 ValueSeq &Cycle, ValueSeq &Early, ValueSeq &Late) {
1151 unsigned I,
N = Cycle.size();
1152 for (I = 0; I <
N; ++
I) {
1156 else if (!isa<PHINode>(V))
1163 ValueSeq &First = !IsE ? Early : Late;
1164 for (
unsigned J = 0; J <
I; ++J)
1165 First.insert(Cycle[J]);
1167 ValueSeq &Second = IsE ? Early : Late;
1168 Second.insert(Cycle[I]);
1169 for (++I; I <
N; ++
I) {
1171 if (DivI == V || isa<PHINode>(V))
1177 First.insert(Cycle[I]);
1180 bool PolynomialMultiplyRecognize::classifyInst(
Instruction *UseI,
1181 ValueSeq &Early, ValueSeq &Late) {
1187 if (Early.count(TV) || Early.count(FV)) {
1188 if (Late.count(TV) || Late.count(FV))
1191 }
else if (Late.count(TV) || Late.count(FV)) {
1192 if (Early.count(TV) || Early.count(FV))
1204 bool AE =
true,
AL =
true;
1206 if (Early.count(&*I))
1208 else if (Late.count(&*I))
1232 bool PolynomialMultiplyRecognize::commutesWithShift(
Instruction *I) {
1234 case Instruction::And:
1235 case Instruction::Or:
1236 case Instruction::Xor:
1237 case Instruction::LShr:
1238 case Instruction::Shl:
1240 case Instruction::ICmp:
1241 case Instruction::PHI:
1249 bool PolynomialMultiplyRecognize::highBitsAreZero(
Value *V,
1250 unsigned IterCount) {
1257 return Known.countMinLeadingZeros() >= IterCount;
1260 bool PolynomialMultiplyRecognize::keepsHighBitsZero(
Value *V,
1261 unsigned IterCount) {
1264 if (
auto *C = dyn_cast<ConstantInt>(V))
1265 return C->getValue().countLeadingZeros() >= IterCount;
1267 if (
auto *I = dyn_cast<Instruction>(V)) {
1269 case Instruction::And:
1270 case Instruction::Or:
1271 case Instruction::Xor:
1272 case Instruction::LShr:
1274 case Instruction::ICmp:
1275 case Instruction::PHI:
1276 case Instruction::ZExt:
1286 if (Opc == Instruction::Shl || Opc == Instruction::LShr)
1291 bool PolynomialMultiplyRecognize::convertShiftsToLeft(
BasicBlock *LoopB,
1293 Value *CIV = getCountIV(LoopB);
1297 if (CIVTy ==
nullptr)
1301 ValueSeq Early, Late, Cycled;
1311 if (!findCycle(&I, V, C))
1316 classifyCycle(&I, C, Early, Late);
1317 Cycled.insert(C.begin(), C.end());
1323 ValueSeq
Users(Cycled.begin(), Cycled.end());
1324 for (
unsigned i = 0; i <
Users.size(); ++i) {
1326 if (!isa<IntegerType>(V->
getType()))
1328 auto *R = cast<Instruction>(V);
1331 if (!commutesWithShift(R))
1333 for (
auto I = R->user_begin(),
E = R->user_end(); I !=
E; ++
I) {
1334 auto *
T = cast<Instruction>(*I);
1338 if (
T->getParent() != LoopB || RShifts.count(
T) || isa<PHINode>(
T))
1342 if (!classifyInst(
T, Early, Late))
1351 ValueSeq Internal(
Users.begin(),
Users.end());
1353 for (
unsigned i = 0; i < Internal.size(); ++i) {
1357 for (
Value *Op : R->operands()) {
1359 if (
T &&
T->getParent() != LoopB)
1362 Internal.insert(Op);
1365 for (
Value *V : Inputs)
1366 if (!highBitsAreZero(V, IterCount))
1368 for (
Value *V : Internal)
1369 if (!keepsHighBitsZero(V, IterCount))
1374 std::map<Value*,Value*> ShiftMap;
1376 using CastMapType = std::map<std::pair<Value *, Type *>,
Value *>;
1378 CastMapType CastMap;
1380 auto upcast = [] (CastMapType &CM,
IRBuilder<> &IRB, Value *V,
1382 auto H = CM.find(std::make_pair(V, Ty));
1385 Value *CV = IRB.CreateIntCast(V, Ty,
false);
1386 CM.insert(std::make_pair(std::make_pair(V, Ty), CV));
1390 for (
auto I = LoopB->begin(),
E = LoopB->end(); I !=
E; ++
I) {
1393 if (isa<PHINode>(I) || !
Users.count(&*I))
1405 Value *Op = J.get();
1406 if (!isOperandShifted(&*I, Op))
1408 if (
Users.count(Op))
1411 if (isa<ConstantInt>(Op) && cast<ConstantInt>(
Op)->
isZero())
1414 auto F = ShiftMap.find(Op);
1415 Value *
W = (
F != ShiftMap.end()) ?
F->second :
nullptr;
1417 IRB.SetInsertPoint(&*I);
1421 Value *ShAmt = CIV, *ShVal =
Op;
1422 auto *VTy = cast<IntegerType>(ShVal->getType());
1423 auto *ATy = cast<IntegerType>(ShAmt->
getType());
1424 if (Late.count(&*I))
1429 if (VTy->getBitWidth() < ATy->getBitWidth())
1430 ShVal = upcast(CastMap, IRB, ShVal, ATy);
1432 ShAmt = upcast(CastMap, IRB, ShAmt, VTy);
1435 W = IRB.CreateShl(ShVal, ShAmt);
1436 ShiftMap.insert(std::make_pair(Op, W));
1448 for (
auto P = ExitB->
begin(), Q = ExitB->
end();
P != Q; ++
P) {
1449 if (!isa<PHINode>(
P))
1451 auto *PN = cast<PHINode>(
P);
1452 Value *U = PN->getIncomingValueForBlock(LoopB);
1453 if (!
Users.count(U))
1456 PN->replaceAllUsesWith(S);
1461 cast<User>(S)->replaceUsesOfWith(S, PN);
1467 void PolynomialMultiplyRecognize::cleanupLoopBody(
BasicBlock *LoopB) {
1468 for (
auto &I : *LoopB)
1472 for (
auto I = LoopB->begin(),
N =
I; I != LoopB->end(); I =
N) {
1478 unsigned PolynomialMultiplyRecognize::getInverseMxN(
unsigned QP) {
1481 std::array<char,32> Q,
C;
1483 for (
unsigned i = 0; i < 32; ++i) {
1500 for (
unsigned i = 1; i < 32; ++i) {
1508 for (
unsigned j = 0; j < i; ++j)
1509 T = T ^ (C[j] & Q[i-j]);
1514 for (
unsigned i = 0; i < 32; ++i)
1524 Module *M = At->getParent()->getParent()->getParent();
1527 Value *
P = PV.P, *Q = PV.Q, *P0 =
P;
1528 unsigned IC = PV.IterCount;
1530 if (PV.M !=
nullptr)
1536 if (PV.IterCount != 32)
1541 assert(QI && QI->getBitWidth() <= 32);
1544 unsigned M = (1 << PV.IterCount) - 1;
1545 unsigned Tmp = (QI->getZExtValue() | 1) & M;
1546 unsigned QV = getInverseMxN(Tmp) & M;
1556 if (PV.M !=
nullptr)
1563 if (
const auto *CI = dyn_cast<const ConstantInt>(V))
1564 return (CI->getType()->getSignBit() & CI->getSExtValue()) == 0;
1569 case Instruction::LShr:
1570 if (
const auto SI = dyn_cast<const ConstantInt>(I->
getOperand(1)))
1571 return SI->getZExtValue() > 0;
1573 case Instruction::Or:
1574 case Instruction::Xor:
1577 case Instruction::And:
1584 void PolynomialMultiplyRecognize::setupPreSimplifier(Simplifier &S) {
1585 S.addRule(
"sink-zext",
1588 if (I->
getOpcode() != Instruction::ZExt)
1594 case Instruction::And:
1595 case Instruction::Or:
1596 case Instruction::Xor:
1606 S.addRule(
"xor/and -> and/xor",
1615 if (And0->
getOpcode() != Instruction::And ||
1616 And1->getOpcode() != Instruction::And)
1618 if (And0->
getOperand(1) != And1->getOperand(1))
1624 S.addRule(
"sink binop into select",
1634 Value *
X = Sel->getTrueValue(), *
Y = Sel->getFalseValue();
1643 Value *
Y = Sel->getTrueValue(), *
Z = Sel->getFalseValue();
1650 S.addRule(
"fold select-select",
1660 if (Sel0->getCondition() ==
C)
1664 if (Sel1->getCondition() ==
C)
1669 S.addRule(
"or-signbit -> xor-signbit",
1681 S.addRule(
"sink lshr into binop",
1684 if (I->
getOpcode() != Instruction::LShr)
1690 case Instruction::And:
1691 case Instruction::Or:
1692 case Instruction::Xor:
1703 S.addRule(
"expose bitop-const",
1706 auto IsBitOp = [](
unsigned Op) ->
bool {
1708 case Instruction::And:
1709 case Instruction::Or:
1710 case Instruction::Xor:
1716 if (!BitOp1 || !IsBitOp(BitOp1->
getOpcode()))
1719 if (!BitOp2 || !IsBitOp(BitOp2->
getOpcode()))
1732 void PolynomialMultiplyRecognize::setupPostSimplifier(Simplifier &S) {
1733 S.addRule(
"(and (xor (and x a) y) b) -> (and (xor x y) b), if b == b&a",
1741 if (Xor->
getOpcode() != Instruction::Xor)
1746 if (!And0 || And0->
getOpcode() != Instruction::And)
1753 if (V0 != (V0 & V1))
1760 bool PolynomialMultiplyRecognize::recognize() {
1761 LLVM_DEBUG(
dbgs() <<
"Starting PolynomialMultiplyRecognize on loop\n" 1762 << *CurLoop <<
'\n');
1771 if (LoopB != CurLoop->getLoopLatch())
1774 if (ExitB ==
nullptr)
1776 BasicBlock *EntryB = CurLoop->getLoopPreheader();
1777 if (EntryB ==
nullptr)
1780 unsigned IterCount = 0;
1781 const SCEV *CT = SE.getBackedgeTakenCount(CurLoop);
1782 if (isa<SCEVCouldNotCompute>(CT))
1784 if (
auto *CV = dyn_cast<SCEVConstant>(CT))
1785 IterCount = CV->getValue()->getZExtValue() + 1;
1787 Value *CIV = getCountIV(LoopB);
1790 PV.IterCount = IterCount;
1791 LLVM_DEBUG(
dbgs() <<
"Loop IV: " << *CIV <<
"\nIterCount: " << IterCount
1794 setupPreSimplifier(PreSimp);
1802 bool FoundPreScan =
false;
1803 auto FeedsPHI = [LoopB](
const Value *V) ->
bool {
1805 if (
const auto *
P = dyn_cast<const PHINode>(U))
1806 if (
P->getParent() == LoopB)
1813 if (!SI || !FeedsPHI(SI))
1817 Value *
T = PreSimp.simplify(C);
1818 SelectInst *SelI = (T && isa<SelectInst>(
T)) ? cast<SelectInst>(
T) : SI;
1819 LLVM_DEBUG(
dbgs() <<
"scanSelect(pre-scan): " << PE(C, SelI) <<
'\n');
1820 if (scanSelect(SelI, LoopB, EntryB, CIV, PV,
true)) {
1821 FoundPreScan =
true;
1831 if (!FoundPreScan) {
1841 if (!promoteTypes(LoopB, ExitB))
1844 Simplifier PostSimp;
1845 setupPostSimplifier(PostSimp);
1848 if (!SI || !FeedsPHI(SI))
1851 Value *
T = PostSimp.simplify(C);
1852 SelectInst *SelI = dyn_cast_or_null<SelectInst>(
T);
1861 if (!convertShiftsToLeft(LoopB, ExitB, IterCount))
1863 cleanupLoopBody(LoopB);
1867 bool FoundScan =
false;
1873 FoundScan = scanSelect(SelI, LoopB, EntryB, CIV, PV,
false);
1882 dbgs() <<
"Found pmpy idiom: R = " << PP <<
".Q\n";
1884 dbgs() <<
"Found inverse pmpy idiom: R = (" << PP <<
"/Q).Q) + " 1886 dbgs() <<
" Res:" << *PV.Res <<
"\n P:" << *PV.P <<
"\n";
1888 dbgs() <<
" M:" << *PV.M <<
"\n";
1889 dbgs() <<
" Q:" << *PV.Q <<
"\n";
1890 dbgs() <<
" Iteration count:" << PV.IterCount <<
"\n";
1894 Value *PM = generate(At, PV);
1898 if (PM->getType() != PV.Res->getType())
1901 PV.Res->replaceAllUsesWith(PM);
1902 PV.Res->eraseFromParent();
1906 int HexagonLoopIdiomRecognize::getSCEVStride(
const SCEVAddRecExpr *S) {
1908 return SC->getAPInt().getSExtValue();
1912 bool HexagonLoopIdiomRecognize::isLegalStore(
Loop *CurLoop,
StoreInst *
SI) {
1921 uint64_t SizeInBits = DL->getTypeSizeInBits(StoredVal->
getType());
1922 if ((SizeInBits & 7) || (SizeInBits >> 32) != 0)
1929 if (!StoreEv || StoreEv->getLoop() != CurLoop || !StoreEv->isAffine())
1934 int Stride = getSCEVStride(StoreEv);
1938 if (StoreSize !=
unsigned(
std::abs(Stride)))
1951 if (!LoadEv || LoadEv->getLoop() != CurLoop || !LoadEv->isAffine())
1955 if (StoreEv->getOperand(1) != LoadEv->getOperand(1))
1967 const SCEV *BECount,
unsigned StoreSize,
1977 if (
const SCEVConstant *BECst = dyn_cast<SCEVConstant>(BECount))
1987 for (
auto *B : L->
blocks())
1989 if (Ignored.
count(&I) == 0 &&
1997 void HexagonLoopIdiomRecognize::collectStores(
Loop *CurLoop,
BasicBlock *BB,
2001 if (
StoreInst *SI = dyn_cast<StoreInst>(&I))
2002 if (isLegalStore(CurLoop, SI))
2006 bool HexagonLoopIdiomRecognize::processCopyingStore(
Loop *CurLoop,
2009 "Expected only non-volatile stores, or Hexagon-specific memcpy" 2010 "to volatile destination.");
2013 auto *StoreEv = cast<SCEVAddRecExpr>(SE->getSCEV(StorePtr));
2014 unsigned Stride = getSCEVStride(StoreEv);
2016 if (Stride != StoreSize)
2043 Value *LoadBasePtr =
nullptr;
2045 bool Overlap =
false;
2052 if (StoreSize != 4 || DL->getTypeSizeInBits(BECountTy) > 32) {
2056 if (StoreBasePtr && (LoadBasePtr != StoreBasePtr)) {
2058 StoreBasePtr =
nullptr;
2062 LoadBasePtr =
nullptr;
2071 StoreSize, *AA, Ignore1)) {
2075 BECount, StoreSize, *AA, Ignore1)) {
2077 goto CleanupAndExit;
2085 goto CleanupAndExit;
2091 goto CleanupAndExit;
2100 if (!coverLoop(CurLoop, Insts))
2101 goto CleanupAndExit;
2104 goto CleanupAndExit;
2107 goto CleanupAndExit;
2118 StoreSize, *AA, Ignore2))
2119 goto CleanupAndExit;
2122 bool StridePos = getSCEVStride(LoadEv) >= 0;
2125 if (!StridePos && DestVolatile)
2126 goto CleanupAndExit;
2128 bool RuntimeCheck = (Overlap || DestVolatile);
2135 if (ExitBlocks.
size() != 1)
2136 goto CleanupAndExit;
2137 ExitB = ExitBlocks[0];
2143 BECount = SE->getTruncateOrZeroExtend(BECount, IntPtrTy);
2146 const SCEV *NumBytesS =
2147 SE->getAddExpr(BECount, SE->getOne(IntPtrTy),
SCEV::FlagNUW);
2149 NumBytesS = SE->getMulExpr(NumBytesS, SE->getConstant(IntPtrTy, StoreSize),
2152 if (
Instruction *In = dyn_cast<Instruction>(NumBytes))
2160 if (
ConstantInt *CI = dyn_cast<ConstantInt>(NumBytes)) {
2161 uint64_t C = CI->getZExtValue();
2162 if (Threshold != 0 && C < Threshold)
2163 goto CleanupAndExit;
2165 goto CleanupAndExit;
2170 Loop *ParentL = LF->getLoopFor(Preheader);
2180 for (
auto &In : *Header) {
2188 DT->addNewBlock(NewPreheader, Preheader);
2189 DT->changeImmediateDominator(Header, NewPreheader);
2199 Value *LowA = StridePos ? SA : LA;
2200 Value *HighA = StridePos ? LA : SA;
2211 if (Threshold != 0) {
2219 Func, NewPreheader);
2226 DT->addNewBlock(MemmoveB, Preheader);
2231 ExitD = DT->findNearestCommonDominator(ExitD, PB);
2239 if (ExitD && DT->dominates(Preheader, ExitD)) {
2256 Int32PtrTy, Int32PtrTy, Int32Ty);
2260 const SCEV *OneS = SE->getConstant(Int32Ty, 1);
2261 const SCEV *BECount32 = SE->getTruncateOrZeroExtend(BECount, Int32Ty);
2265 if (
Instruction *In = dyn_cast<Instruction>(NumWords))
2275 NewCall = CondBuilder.
CreateCall(Fn, {Op0, Op1, NumWords});
2292 LLVM_DEBUG(
dbgs() <<
" Formed " << (Overlap ?
"memmove: " :
"memcpy: ")
2294 <<
" from load ptr=" << *LoadEv <<
" at: " << *LI <<
"\n" 2295 <<
" from store ptr=" << *StoreEv <<
" at: " << *SI
2304 bool HexagonLoopIdiomRecognize::coverLoop(
Loop *L,
2307 for (
auto *B : L->
blocks())
2316 for (
unsigned i = 0; i < Worklist.size(); ++i) {
2323 if (!LoopBlocks.
count(PB))
2325 Worklist.insert(OpI);
2333 for (
auto *B : L->
blocks()) {
2334 for (
auto &In : *B) {
2335 if (isa<BranchInst>(In) || isa<DbgInfoIntrinsic>(
In))
2337 if (!Worklist.count(&In) && In.mayHaveSideEffects())
2339 for (
const auto &K : In.
users()) {
2344 if (LF->getLoopFor(UseB) != L)
2356 bool HexagonLoopIdiomRecognize::runOnLoopBlock(
Loop *CurLoop,
BasicBlock *BB,
2361 auto DominatedByBB = [
this,BB] (
BasicBlock *EB) ->
bool {
2362 return DT->dominates(BB, EB);
2364 if (!
all_of(ExitBlocks, DominatedByBB))
2367 bool MadeChange =
false;
2370 collectStores(CurLoop, BB, Stores);
2373 for (
auto &SI : Stores)
2374 MadeChange |= processCopyingStore(CurLoop, SI, BECount);
2379 bool HexagonLoopIdiomRecognize::runOnCountableLoop(
Loop *L) {
2380 PolynomialMultiplyRecognize PMR(L, *DL, *DT, *TLI, *SE);
2381 if (PMR.recognize())
2384 if (!HasMemcpy && !HasMemmove)
2387 const SCEV *BECount = SE->getBackedgeTakenCount(L);
2388 assert(!isa<SCEVCouldNotCompute>(BECount) &&
2389 "runOnCountableLoop() called on a loop without a predictable" 2390 "backedge-taken count");
2395 bool Changed =
false;
2400 if (LF->getLoopFor(BB) != L)
2402 Changed |= runOnLoopBlock(L, BB, BECount, ExitBlocks);
2423 if (Name ==
"memset" || Name ==
"memcpy" || Name ==
"memmove")
2426 AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
2428 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
2429 LF = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
2430 TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
2431 SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
2433 HasMemcpy = TLI->has(LibFunc_memcpy);
2434 HasMemmove = TLI->has(LibFunc_memmove);
2436 if (SE->hasLoopInvariantBackedgeTakenCount(L))
2437 return runOnCountableLoop(L);
2442 return new HexagonLoopIdiomRecognize();
The access may reference and may modify the value stored in memory.
Pass interface - Implemented by all 'passes'.
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 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."))
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, OptimizationRemarkEmitter *ORE=nullptr, bool UseInstrInfo=true)
Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...
Value * getValueOperand()
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
IntegerType * getType() const
getType - Specialize the getType() method to always return an IntegerType, which reduces the amount o...
A parsed version of the target data layout string in and methods for querying it. ...
const std::string & getTargetTriple() const
Get the target triple which is a string describing the target host.
BranchInst * CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False, MDNode *BranchWeights=nullptr, MDNode *Unpredictable=nullptr)
Create a conditional 'br Cond, TrueDest, FalseDest' instruction.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
This class is the base class for the comparison instructions.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
void dropAllReferences()
Drop all references to operands.
bool isSameOperationAs(const Instruction *I, unsigned flags=0) const
This function determines if the specified instruction executes the same operation as the current one...
This class represents lattice values for constants.
BinaryOps getOpcode() const
Value * CreateICmpULT(Value *LHS, Value *RHS, const Twine &Name="")
Constant * getOrInsertFunction(StringRef Name, FunctionType *T, AttributeList AttributeList)
Look up the specified function in the module symbol table.
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
A Module instance is used to store all the information related to an LLVM module. ...
static constexpr LocationSize unknown()
This class represents zero extension of integer types.
void push_back(const T &Elt)
static cl::opt< bool > DisableMemmoveIdiom("disable-memmove-idiom", cl::Hidden, cl::init(false), cl::desc("Disable generation of memmove in loop idiom recognition"))
The main scalar evolution driver.
This class represents a function call, abstracting a target machine's calling convention.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Get a value with low bits set.
static PointerType * getInt32PtrTy(LLVMContext &C, unsigned AS=0)
BlockT * getLoopPreheader() const
If there is a preheader for this loop, return it.
const Value * getTrueValue() const
Externally visible function.
LLVMContext & getContext() const
All values hold a context through their type.
bool isTerminator() const
static LocationSize precise(uint64_t Value)
void deleteValue()
Delete a pointer to a generic Value.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly...
static void cleanup(BlockFrequencyInfoImplBase &BFI)
Clear all memory not needed downstream.
An instruction for reading from memory.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
iv Induction Variable Users
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...
bool hasNoSignedWrap() const
Determine whether the no signed wrap flag is set.
INITIALIZE_PASS_BEGIN(HexagonLoopIdiomRecognize, "hexagon-loop-idiom", "Recognize Hexagon-specific loop idioms", false, false) INITIALIZE_PASS_END(HexagonLoopIdiomRecognize
iterator begin()
Instruction iterator methods.
bool isIdenticalTo(const Instruction *I) const
Return true if the specified instruction is exactly identical to the current one. ...
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
bool match(Val *V, const Pattern &P)
AnalysisUsage & addRequired()
const Module * getModule() const
Return the module owning the function this basic block belongs to, or nullptr if the function does no...
#define INITIALIZE_PASS_DEPENDENCY(depName)
amdgpu Simplify well known AMD library false Value Value const Twine & Name
BinaryOp_match< LHS, RHS, Instruction::Xor > m_Xor(const LHS &L, const RHS &R)
This class represents the LLVM 'select' instruction.
static const char * HexagonVolatileMemcpyName
const DataLayout & getDataLayout() const
Get the data layout for the module's target platform.
int getBasicBlockIndex(const BasicBlock *BB) const
Return the first index of the specified basic block in the value list for this PHI.
A Use represents the edge between a Value definition and its users.
static Optional< unsigned > getOpcode(ArrayRef< VPValue *> Values)
Returns the opcode of Values or ~0 if they do not all agree.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
bool isIntegerTy() const
True if this is an instance of IntegerType.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
IntegerType * getIntPtrTy(const DataLayout &DL, unsigned AddrSpace=0)
Fetch the type representing a pointer to an integer value.
This file contains the simple types necessary to represent the attributes associated with functions a...
void setName(const Twine &Name)
Change the name of the value.
CallInst * CreateMemMove(Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign, uint64_t Size, bool isVolatile=false, MDNode *TBAATag=nullptr, MDNode *ScopeTag=nullptr, MDNode *NoAliasTag=nullptr)
Create and insert a memmove between the specified pointers.
zlib-gnu style compression
This file implements a class to represent arbitrary precision integral constant values and operations...
BlockT * getHeader() const
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
User * getUser() const LLVM_READONLY
Returns the User that contains this Use.
Value * CreateBitCast(Value *V, Type *DestTy, const Twine &Name="")
Type * getType() const
All values are typed, get the type of this value.
void addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase< BlockT, LoopT > &LI)
This method is used by other analyses to update loop information.
This node represents a polynomial recurrence on the trip count of the specified loop.
CastClass_match< OpTy, Instruction::ZExt > m_ZExt(const OpTy &Op)
Matches ZExt.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
An instruction for storing to memory.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Value * CreateZExt(Value *V, Type *DestTy, const Twine &Name="")
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
Function * getDeclaration(Module *M, ID id, ArrayRef< Type *> Tys=None)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
This class represents a truncation of integer types.
void SetInsertPoint(BasicBlock *TheBB)
This specifies that created instructions should be appended to the end of the specified block...
Value * getOperand(unsigned i) const
void replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
Value * CreateOr(Value *LHS, Value *RHS, const Twine &Name="")
#define LLVM_ATTRIBUTE_USED
void clear()
Erase the contents of the InsertedExpressions map so that users trying to expand the same expression ...
initializer< Ty > init(const Ty &Val)
const SCEV * getOperand(unsigned i) const
BinaryOp_match< LHS, RHS, Instruction::LShr > m_LShr(const LHS &L, const RHS &R)
void initializeHexagonLoopIdiomRecognizePass(PassRegistry &)
const Instruction * getFirstNonPHI() const
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Value * CreateSelect(Value *C, Value *True, Value *False, const Twine &Name="", Instruction *MDFrom=nullptr)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Interval::pred_iterator pred_begin(Interval *I)
pred_begin/pred_end - define methods so that Intervals may be used just like BasicBlocks can with the...
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
Represent the analysis usage information of a pass.
static Type * getVoidTy(LLVMContext &C)
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Value * expandCodeFor(const SCEV *SH, Type *Ty, Instruction *I)
Insert code to directly compute the specified SCEV expression into the program.
static void replace(Module &M, GlobalVariable *Old, GlobalVariable *New)
Interval::pred_iterator pred_end(Interval *I)
Value * getPointerOperand()
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
self_iterator getIterator()
Class to represent integer types.
std::pair< NoneType, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
static cl::opt< bool > OnlyNonNestedMemmove("only-nonnested-memmove-idiom", cl::Hidden, cl::init(true), cl::desc("Only enable generating memmove in non-nested loops"))
const Value * getCondition() const
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr)
If the specified value is a trivially dead instruction, delete it.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
static void replaceAllUsesOfWithIn(Value *I, Value *J, BasicBlock *BB)
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
PointerType * getInt8PtrTy(unsigned AddrSpace=0)
Fetch the type representing a pointer to an 8-bit integer value.
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Value * CreateTrunc(Value *V, Type *DestTy, const Twine &Name="")
Triple - Helper class for working with autoconf configuration names.
hexagon loop Recognize Hexagon specific loop idioms
static cl::opt< unsigned > SimplifyLimit("hlir-simplify-limit", cl::init(10000), cl::Hidden, cl::desc("Maximum number of simplification steps in HLIR"))
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
Representation for a specific memory location.
const InstListType & getInstList() const
Return the underlying instruction list container.
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Iterator for intrusive lists based on ilist_node.
unsigned getNumOperands() const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
This is the shared class of boolean and integer constants.
Type * getType() const
Return the LLVM type of this SCEV expression.
void setIncomingBlock(unsigned i, BasicBlock *BB)
AnalysisUsage & addRequiredID(const void *ID)
Value * CreateIntCast(Value *V, Type *DestTy, bool isSigned, const Twine &Name="")
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Module.h This file contains the declarations for the Module class.
Provides information about what library functions are available for the current target.
CHAIN = SC CHAIN, Imm128 - System call.
CallInst * CreateMemCpy(Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign, uint64_t Size, bool isVolatile=false, MDNode *TBAATag=nullptr, MDNode *TBAAStructTag=nullptr, MDNode *ScopeTag=nullptr, MDNode *NoAliasTag=nullptr)
Create and insert a memcpy between the specified pointers.
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.
void setLinkage(LinkageTypes LT)
void setOperand(unsigned i, Value *Val)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
The access may modify the value stored in memory.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, ArrayRef< StringRef > StandardNames)
Initialize the set of available library functions based on the specified target triple.
iterator_range< user_iterator > users()
static cl::opt< bool > DisableMemcpyIdiom("disable-memcpy-idiom", cl::Hidden, cl::init(false), cl::desc("Disable generation of memcpy in loop idiom recognition"))
static cl::opt< unsigned > Threshold("loop-unswitch-threshold", cl::desc("Max loop size to unswitch"), cl::init(100), cl::Hidden)
This class uses information about analyze scalars to rewrite expressions in canonical form...
const Value * getFalseValue() const
LoopT * getParentLoop() const
static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC)
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
bool isVolatile() const
Return true if this is a store to a volatile memory location.
iterator insert(iterator where, pointer New)
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
unsigned getAlignment() const
Return the alignment of the access that is being performed.
This class represents an analyzed expression in the program.
static IntegerType * getInt32Ty(LLVMContext &C)
Represents a single loop in the control flow graph.
ArrayRef< BlockT * > getBlocks() const
Get a list of the basic blocks which make up this loop.
This file provides utility analysis objects describing memory locations.
StringRef getName() const
Return a constant reference to the value's name.
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_NODISCARD ModRefInfo intersectModRef(const ModRefInfo MRI1, const ModRefInfo MRI2)
APFloat abs(APFloat X)
Returns the absolute value of the argument.
Pass * createHexagonLoopIdiomPass()
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
uint64_t getSignBit() const
Return a uint64_t with just the most significant bit set (the sign bit, if the value is treated as a ...
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
CallInst * CreateCall(FunctionType *FTy, Value *Callee, ArrayRef< Value *> Args=None, const Twine &Name="", MDNode *FPMathTag=nullptr)
bool hasNoUnsignedWrap() const
Determine whether the no unsigned wrap flag is set.
raw_ostream & operator<<(raw_ostream &OS, const APInt &I)
unsigned getAlignment() const
Return the alignment of the access that is being performed.
void mutateType(Type *Ty)
Mutate the type of this Value to be of the specified type.
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
Value * CreatePtrToInt(Value *V, Type *DestTy, const Twine &Name="")
OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate P)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere...
unsigned getPointerAddressSpace() const
Returns the address space of the pointer operand.
cl::opt< bool > HexagonVolatileMemcpy("disable-hexagon-volatile-memcpy", cl::Hidden, cl::init(false), cl::desc("Enable Hexagon-specific memcpy for volatile destination."))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
user_iterator user_begin()
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
BranchInst * CreateBr(BasicBlock *Dest)
Create an unconditional 'br label X' instruction.
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
static const Function * getParent(const Value *V)
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
This class implements an extremely fast bulk output stream that can only output to a stream...
ModRefInfo
Flags indicating whether a memory access modifies or references memory.
The legacy pass manager's analysis pass to compute loop information.
void getUniqueExitBlocks(SmallVectorImpl< BlockT *> &ExitBlocks) const
Return all unique successor blocks of this loop.
bool hasOneUse() const
Return true if there is exactly one user of this value.
StringRef - Represent a constant reference to a string, i.e.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Legacy analysis pass which computes a DominatorTree.
LLVM_NODISCARD bool isModOrRefSet(const ModRefInfo MRI)
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object...
ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc)
getModRefInfo (for call sites) - Return information about whether a particular call site modifies or ...
iterator_range< block_iterator > blocks() const
Value * SimplifyInstruction(Instruction *I, const SimplifyQuery &Q, OptimizationRemarkEmitter *ORE=nullptr)
See if we can compute a simplified version of this instruction.
Value * CreateICmpSLE(Value *LHS, Value *RHS, const Twine &Name="")
Value * getPointerOperand()
static bool hasZeroSignBit(const Value *V)
const BasicBlock * getParent() const
This class represents a constant integer value.
CmpClass_match< LHS, RHS, ICmpInst, ICmpInst::Predicate > m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R)
void setIDom(DomTreeNodeBase *NewIDom)
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.