43 #define DEBUG_TYPE "chr" 45 #define CHR_DEBUG(X) LLVM_DEBUG(X) 48 cl::desc(
"Apply CHR for all functions"));
52 cl::desc(
"CHR considers a branch bias greater than this ratio as biased"));
56 cl::desc(
"CHR merges a group of N branches/selects where N >= this value"));
60 cl::desc(
"Specify file to retrieve the list of modules to apply CHR to"));
64 cl::desc(
"Specify file to retrieve the list of functions to apply CHR to"));
73 errs() <<
"Error: Couldn't read the chr-module-list file " <<
CHRModuleList <<
"\n";
76 StringRef Buf = FileOrErr->get()->getBuffer();
78 Buf.
split(Lines,
'\n');
91 StringRef Buf = FileOrErr->get()->getBuffer();
93 Buf.
split(Lines,
'\n');
103 class ControlHeightReductionLegacyPass :
public FunctionPass {
128 "Reduce control height in the hot paths",
136 "Reduce control height in the hot paths",
140 return new ControlHeightReductionLegacyPass();
146 CHRStats() : NumBranches(0), NumBranchesDelta(0),
147 WeightedNumBranchesDelta(0) {}
149 OS <<
"CHRStats: NumBranches " << NumBranches
150 <<
" NumBranchesDelta " << NumBranchesDelta
151 <<
" WeightedNumBranchesDelta " << WeightedNumBranchesDelta;
153 uint64_t NumBranches;
155 uint64_t NumBranchesDelta;
157 uint64_t WeightedNumBranchesDelta;
163 RegInfo() : R(
nullptr), HasBranch(
false) {}
164 RegInfo(
Region *RegionIn) : R(RegionIn), HasBranch(
false) {}
177 CHRScope(RegInfo RI) : BranchInsertPoint(
nullptr) {
178 assert(RI.R &&
"Null RegionIn");
179 RegInfos.push_back(RI);
182 Region *getParentRegion() {
183 assert(RegInfos.size() > 0 &&
"Empty CHRScope");
185 assert(Parent &&
"Unexpected to call this on the top-level region");
190 assert(RegInfos.size() > 0 &&
"Empty CHRScope");
191 return RegInfos.front().R->getEntry();
195 assert(RegInfos.size() > 0 &&
"Empty CHRScope");
196 return RegInfos.back().R->getExit();
199 bool appendable(CHRScope *Next) {
203 BasicBlock *NextEntry = Next->getEntryBlock();
204 if (getExitBlock() != NextEntry)
207 Region *LastRegion = RegInfos.back().R;
216 void append(CHRScope *Next) {
217 assert(RegInfos.size() > 0 &&
"Empty CHRScope");
218 assert(Next->RegInfos.size() > 0 &&
"Empty CHRScope");
219 assert(getParentRegion() == Next->getParentRegion() &&
221 assert(getExitBlock() == Next->getEntryBlock() &&
223 for (RegInfo &RI : Next->RegInfos)
224 RegInfos.push_back(RI);
225 for (CHRScope *Sub : Next->Subs)
229 void addSub(CHRScope *SubIn) {
231 bool IsChild =
false;
232 for (RegInfo &RI : RegInfos)
233 if (RI.R == SubIn->getParentRegion()) {
237 assert(IsChild &&
"Must be a child");
239 Subs.push_back(SubIn);
245 assert(Boundary &&
"Boundary null");
246 assert(RegInfos.begin()->R != Boundary &&
247 "Can't be split at beginning");
248 auto BoundaryIt =
std::find_if(RegInfos.begin(), RegInfos.end(),
249 [&Boundary](
const RegInfo& RI) {
250 return Boundary == RI.R;
252 if (BoundaryIt == RegInfos.end())
256 TailRegInfos.
insert(TailRegInfos.
begin(), BoundaryIt, RegInfos.end());
257 RegInfos.resize(BoundaryIt - RegInfos.begin());
259 for (RegInfo &RI : TailRegInfos)
260 TailRegionSet.
insert(RI.R);
261 for (
auto It = Subs.begin(); It != Subs.end(); ) {
263 assert(Sub &&
"null Sub");
264 Region *Parent = Sub->getParentRegion();
265 if (TailRegionSet.
count(Parent)) {
270 [&Parent](
const RegInfo& RI) {
271 return Parent == RI.R;
272 }) != RegInfos.end() &&
277 assert(HoistStopMap.empty() &&
"MapHoistStops must be empty");
278 return new CHRScope(TailRegInfos, TailSubs);
283 for (
const RegInfo &RI : RegInfos)
284 if (RI.R->contains(Parent))
313 HoistStopMapTy HoistStopMap;
318 : RegInfos(RegInfosIn), Subs(SubsIn), BranchInsertPoint(
nullptr) {}
326 :
F(Fin),
BFI(BFIin), DT(DTin), PSI(PSIin), RI(RIin), ORE(OREin) {}
329 for (CHRScope *Scope : Scopes) {
341 Region *R = RI.getTopLevelRegion();
342 CHRScope *Scope = findScopes(R,
nullptr,
nullptr, Output);
349 CHRScope *findScope(
Region *R);
350 void checkScopeHoistable(CHRScope *Scope);
362 void classifyBiasedScopes(CHRScope *Scope, CHRScope *OutermostScope);
369 void setCHRRegions(CHRScope *Scope, CHRScope *OutermostScope);
376 void cloneScopeBlocks(CHRScope *Scope,
385 void fixupBranchesAndSelects(CHRScope *Scope,
389 void fixupBranch(
Region *R,
397 void addToMergedCondition(
bool IsTrueBiased,
Value *Cond,
401 Value *&MergedCondition);
431 const CHRStats &
Stats) {
462 CHR_DEBUG(
dbgs() <<
"CHR IR dump " << Label <<
" " << ModuleName <<
" " 471 assert(RegInfos.size() > 0 &&
"Empty CHRScope");
473 OS << RegInfos.size() <<
", Regions[";
474 for (
const RegInfo &RI : RegInfos) {
475 OS << RI.R->getNameStr();
478 if (RI.Selects.size() > 0)
479 OS <<
" S" << RI.Selects.size();
482 if (RegInfos[0].R->getParent()) {
483 OS <<
"], Parent " << RegInfos[0].R->getParent()->getNameStr();
489 for (CHRScope *Sub : Subs) {
497 return isa<BinaryOperator>(
I) || isa<CastInst>(I) || isa<SelectInst>(
I) ||
498 isa<GetElementPtrInst>(I) || isa<CmpInst>(
I) ||
499 isa<InsertElementInst>(I) || isa<ExtractElementInst>(
I) ||
500 isa<ShuffleVectorInst>(I) || isa<ExtractValueInst>(
I) ||
501 isa<InsertValueInst>(I);
518 std::set<Value *> Result;
519 if (
auto *
I = dyn_cast<Instruction>(V)) {
529 Result.insert(OpResult.begin(), OpResult.end());
533 if (isa<Argument>(V)) {
551 assert(InsertPoint &&
"Null InsertPoint");
552 if (
auto *
I = dyn_cast<Instruction>(V)) {
553 assert(DT.
getNode(
I->getParent()) &&
"DT must contain I's parent block");
555 if (Unhoistables.
count(
I)) {
570 bool AllOpsHoisted =
true;
573 AllOpsHoisted =
false;
594 if (!MD)
return false;
596 if (MDName->
getString() !=
"branch_weights" ||
601 if (!TrueWeight || !FalseWeight)
604 uint64_t FalseWt = FalseWeight->getValue().getZExtValue();
605 uint64_t SumWt = TrueWt + FalseWt;
607 assert(SumWt >= TrueWt && SumWt >= FalseWt &&
608 "Overflow calculating branch probabilities.");
624 template <
typename K,
typename S,
typename M>
629 if (TrueProb >= Threshold) {
631 BiasMap[
Key] = TrueProb;
633 }
else if (FalseProb >= Threshold) {
634 FalseSet.insert(Key);
635 BiasMap[
Key] = FalseProb;
657 "Invariant from findScopes");
668 TrueBiasedRegionsGlobal, FalseBiasedRegionsGlobal,
681 TrueProb, FalseProb))
686 return checkBias(SI, TrueProb, FalseProb,
687 TrueBiasedSelectsGlobal, FalseBiasedSelectsGlobal,
708 assert(HoistPoint &&
"Null HoistPoint");
715 EntryBlockSelectSet.
insert(SI);
719 if (EntryBlockSelectSet.
count(&
I) > 0) {
721 "HoistPoint must be the first one in Selects");
730 CHRScope * CHR::findScope(
Region *R) {
731 CHRScope *Result =
nullptr;
734 assert(Entry &&
"Entry must not be null");
736 "Only top level region has a null exit");
747 bool EntryInSubregion = RI.getRegionFor(Entry) != R;
748 if (EntryInSubregion)
761 CHR_DEBUG(
dbgs() <<
"BI.isConditional " << BI->isConditional() <<
"\n");
764 if (BI && BI->isConditional()) {
769 if (S0 != S1 && (S0 == Exit || S1 == Exit)) {
772 BI, R, TrueBiasedRegionsGlobal, FalseBiasedRegionsGlobal,
774 Result =
new CHRScope(RI);
775 Scopes.insert(Result);
781 <<
"Branch not biased";
802 if (
E->isSubRegion())
810 if (
auto *
SI = dyn_cast<SelectInst>(&
I)) {
816 if (Selects.
size() > 0) {
817 auto AddSelects = [&](RegInfo &RI) {
818 for (
auto *
SI : Selects)
820 TrueBiasedSelectsGlobal,
821 FalseBiasedSelectsGlobal,
823 RI.Selects.push_back(
SI);
827 <<
"Select not biased";
834 Result =
new CHRScope(RI);
835 Scopes.insert(Result);
837 CHR_DEBUG(
dbgs() <<
"Found select(s) in a region with a branch\n");
838 AddSelects(Result->RegInfos[0]);
844 checkScopeHoistable(Result);
871 void CHR::checkScopeHoistable(CHRScope *Scope) {
872 RegInfo &RI = Scope->RegInfos[0];
875 auto *
Branch = RI.HasBranch ?
878 if (RI.HasBranch || !Selects.empty()) {
890 for (
auto it = Selects.begin(); it != Selects.end(); ) {
892 if (SI == InsertPoint) {
897 DT, Unhoistables,
nullptr);
902 "DropUnhoistableSelect", SI)
903 <<
"Dropped unhoistable select";
905 it = Selects.erase(it);
908 Unhoistables.erase(SI);
915 if (RI.HasBranch && InsertPoint !=
Branch) {
917 DT, Unhoistables,
nullptr);
922 assert(InsertPoint !=
Branch &&
"Branch must not be the hoist point");
926 dbgs() <<
"SI " << *
SI <<
"\n";
931 "DropSelectUnhoistableBranch",
SI)
932 <<
"Dropped select due to unhoistable branch";
937 return SI->getParent() == EntryBB;
939 Unhoistables.clear();
947 "Branch can't be already above the hoist point");
949 DT, Unhoistables,
nullptr) &&
950 "checkHoistValue for branch");
952 for (
auto *
SI : Selects) {
953 assert(!DT.dominates(
SI, InsertPoint) &&
954 "SI can't be already above the hoist point");
956 Unhoistables,
nullptr) &&
957 "checkHoistValue for selects");
963 for (
auto *
SI : Selects) {
974 CHRScope *Result = findScope(R);
976 CHRScope *ConsecutiveSubscope =
nullptr;
978 for (
auto It = R->
begin(); It != R->
end(); ++It) {
979 const std::unique_ptr<Region> &SubR = *It;
980 auto NextIt = std::next(It);
981 Region *NextSubR = NextIt != R->
end() ? NextIt->get() :
nullptr;
982 CHR_DEBUG(
dbgs() <<
"Looking at subregion " << SubR.get()->getNameStr()
984 CHRScope *SubCHRScope = findScopes(SubR.get(), NextSubR, R, Scopes);
986 CHR_DEBUG(
dbgs() <<
"Subregion Scope " << *SubCHRScope <<
"\n");
991 if (!ConsecutiveSubscope)
992 ConsecutiveSubscope = SubCHRScope;
993 else if (!ConsecutiveSubscope->appendable(SubCHRScope)) {
994 Subscopes.
push_back(ConsecutiveSubscope);
995 ConsecutiveSubscope = SubCHRScope;
997 ConsecutiveSubscope->append(SubCHRScope);
999 if (ConsecutiveSubscope) {
1000 Subscopes.
push_back(ConsecutiveSubscope);
1002 ConsecutiveSubscope =
nullptr;
1005 if (ConsecutiveSubscope) {
1006 Subscopes.
push_back(ConsecutiveSubscope);
1008 for (CHRScope *Sub : Subscopes) {
1011 Result->addSub(Sub);
1023 auto *BI = cast<BranchInst>(RI.R->getEntry()->getTerminator());
1024 ConditionValues.
insert(BI->getCondition());
1029 return ConditionValues;
1045 dbgs() <<
"shouldSplit " << *InsertPoint <<
" PrevConditionValues ";
1046 for (
Value *V : PrevConditionValues) {
1047 dbgs() << *V <<
", ";
1049 dbgs() <<
" ConditionValues ";
1050 for (
Value *V : ConditionValues) {
1051 dbgs() << *V <<
", ";
1054 assert(InsertPoint &&
"Null InsertPoint");
1056 for (
Value *V : ConditionValues) {
1058 CHR_DEBUG(
dbgs() <<
"Split. checkHoistValue false " << *V <<
"\n");
1065 if (!PrevConditionValues.empty() && !ConditionValues.empty()) {
1067 std::set<Value *> PrevBases, Bases;
1068 for (
Value *V : PrevConditionValues) {
1070 PrevBases.insert(BaseValues.begin(), BaseValues.end());
1072 for (
Value *V : ConditionValues) {
1074 Bases.insert(BaseValues.begin(), BaseValues.end());
1077 dbgs() <<
"PrevBases ";
1078 for (
Value *V : PrevBases) {
1079 dbgs() << *V <<
", ";
1081 dbgs() <<
" Bases ";
1082 for (
Value *V : Bases) {
1083 dbgs() << *V <<
", ";
1086 std::set<Value *> Intersection;
1087 std::set_intersection(PrevBases.begin(), PrevBases.end(),
1088 Bases.begin(), Bases.end(),
1089 std::inserter(Intersection, Intersection.begin()));
1090 if (Intersection.empty()) {
1102 for (RegInfo &RI : Scope->RegInfos)
1105 for (CHRScope *Sub : Scope->Subs)
1111 for (CHRScope *Scope : Input) {
1112 assert(!Scope->BranchInsertPoint &&
1113 "BranchInsertPoint must not be set");
1116 splitScope(Scope,
nullptr,
nullptr,
nullptr, Output, Unhoistables);
1119 for (CHRScope *Scope : Output) {
1120 assert(Scope->BranchInsertPoint &&
"BranchInsertPoint must be set");
1133 assert(OuterConditionValues &&
"Null OuterConditionValues");
1134 assert(OuterInsertPoint &&
"Null OuterInsertPoint");
1136 bool PrevSplitFromOuter =
true;
1144 for (RegInfo &RI : RegInfos) {
1148 dbgs() <<
"ConditionValues ";
1149 for (
Value *V : ConditionValues) {
1150 dbgs() << *V <<
", ";
1153 if (RI.R == RegInfos[0].R) {
1158 << RI.R->getNameStr() <<
"\n");
1159 if (
shouldSplit(OuterInsertPoint, *OuterConditionValues,
1160 ConditionValues, DT, Unhoistables)) {
1161 PrevConditionValues = ConditionValues;
1162 PrevInsertPoint = InsertPoint;
1165 "SplitScopeFromOuter",
1166 RI.R->getEntry()->getTerminator())
1167 <<
"Split scope from outer due to unhoistable branch/select " 1168 <<
"and/or lack of common condition values";
1173 PrevSplitFromOuter =
false;
1174 PrevConditionValues = *OuterConditionValues;
1175 PrevConditionValues.
insert(ConditionValues.begin(),
1176 ConditionValues.end());
1177 PrevInsertPoint = OuterInsertPoint;
1181 PrevConditionValues = ConditionValues;
1182 PrevInsertPoint = InsertPoint;
1186 << RI.R->getNameStr() <<
"\n");
1187 if (
shouldSplit(PrevInsertPoint, PrevConditionValues, ConditionValues,
1188 DT, Unhoistables)) {
1189 CHRScope *Tail = Scope->split(RI.R);
1192 SplitsSplitFromOuter.
push_back(PrevSplitFromOuter);
1193 SplitsConditionValues.
push_back(PrevConditionValues);
1194 SplitsInsertPoints.
push_back(PrevInsertPoint);
1196 PrevConditionValues = ConditionValues;
1197 PrevInsertPoint = InsertPoint;
1198 PrevSplitFromOuter =
true;
1201 "SplitScopeFromPrev",
1202 RI.R->getEntry()->getTerminator())
1203 <<
"Split scope from previous due to unhoistable branch/select " 1204 <<
"and/or lack of common condition values";
1208 PrevConditionValues.
insert(ConditionValues.begin(), ConditionValues.end());
1213 SplitsSplitFromOuter.
push_back(PrevSplitFromOuter);
1214 SplitsConditionValues.
push_back(PrevConditionValues);
1215 assert(PrevInsertPoint &&
"Null PrevInsertPoint");
1216 SplitsInsertPoints.
push_back(PrevInsertPoint);
1218 Splits.
size() == SplitsSplitFromOuter.
size() &&
1219 Splits.
size() == SplitsInsertPoints.
size() &&
"Mismatching sizes");
1220 for (
size_t I = 0;
I < Splits.
size(); ++
I) {
1221 CHRScope *
Split = Splits[
I];
1227 for (CHRScope *Sub : Split->Subs) {
1229 Sub, Split, &SplitConditionValues, SplitInsertPoint, Output,
1233 Split->Subs = NewSubs;
1236 for (
size_t I = 0;
I < Splits.
size(); ++
I) {
1237 CHRScope *
Split = Splits[
I];
1238 if (SplitsSplitFromOuter[
I]) {
1241 Split->BranchInsertPoint = SplitsInsertPoints[
I];
1242 CHR_DEBUG(
dbgs() <<
"BranchInsertPoint " << *SplitsInsertPoints[I]
1251 "If no outer (top-level), must return no nested ones");
1256 for (CHRScope *Scope : Scopes) {
1257 assert(Scope->TrueBiasedRegions.empty() && Scope->FalseBiasedRegions.empty() &&
"Empty");
1258 classifyBiasedScopes(Scope, Scope);
1260 dbgs() <<
"classifyBiasedScopes " << *Scope <<
"\n";
1261 dbgs() <<
"TrueBiasedRegions ";
1262 for (
Region *R : Scope->TrueBiasedRegions) {
1266 dbgs() <<
"FalseBiasedRegions ";
1267 for (
Region *R : Scope->FalseBiasedRegions) {
1271 dbgs() <<
"TrueBiasedSelects ";
1273 dbgs() << *SI <<
", ";
1276 dbgs() <<
"FalseBiasedSelects ";
1277 for (
SelectInst *SI : Scope->FalseBiasedSelects) {
1278 dbgs() << *SI <<
", ";
1284 void CHR::classifyBiasedScopes(CHRScope *Scope, CHRScope *OutermostScope) {
1285 for (RegInfo &RI : Scope->RegInfos) {
1288 if (TrueBiasedRegionsGlobal.count(R) > 0)
1289 OutermostScope->TrueBiasedRegions.insert(R);
1290 else if (FalseBiasedRegionsGlobal.count(R) > 0)
1291 OutermostScope->FalseBiasedRegions.insert(R);
1296 if (TrueBiasedSelectsGlobal.count(SI) > 0)
1297 OutermostScope->TrueBiasedSelects.insert(SI);
1298 else if (FalseBiasedSelectsGlobal.count(SI) > 0)
1299 OutermostScope->FalseBiasedSelects.insert(SI);
1304 for (CHRScope *Sub : Scope->Subs) {
1305 classifyBiasedScopes(Sub, OutermostScope);
1310 unsigned NumBiased = Scope->TrueBiasedRegions.size() +
1311 Scope->FalseBiasedRegions.size() +
1312 Scope->TrueBiasedSelects.size() +
1313 Scope->FalseBiasedSelects.size();
1319 for (CHRScope *Scope : Input) {
1322 CHR_DEBUG(
dbgs() <<
"Filtered out by biased branches truthy-regions " 1323 << Scope->TrueBiasedRegions.size()
1324 <<
" falsy-regions " << Scope->FalseBiasedRegions.size()
1325 <<
" true-selects " << Scope->TrueBiasedSelects.size()
1326 <<
" false-selects " << Scope->FalseBiasedSelects.size() <<
"\n");
1330 "DropScopeWithOneBranchOrSelect",
1331 Scope->RegInfos[0].R->getEntry()->getTerminator())
1332 <<
"Drop scope with < " 1334 <<
" biased branch(es) or select(s)";
1344 for (CHRScope *Scope : Input) {
1345 assert(Scope->HoistStopMap.empty() && Scope->CHRRegions.empty() &&
1347 setCHRRegions(Scope, Scope);
1350 dbgs() <<
"setCHRRegions HoistStopMap " << *Scope <<
"\n";
1351 for (
auto pair : Scope->HoistStopMap) {
1352 Region *R = pair.first;
1353 dbgs() <<
"Region " << R->getNameStr() <<
"\n";
1354 for (Instruction *I : pair.second) {
1355 dbgs() <<
"HoistStop " << *I <<
"\n";
1358 dbgs() <<
"CHRRegions" <<
"\n";
1359 for (RegInfo &RI : Scope->CHRRegions) {
1360 dbgs() << RI.R->getNameStr() <<
"\n";
1365 void CHR::setCHRRegions(CHRScope *Scope, CHRScope *OutermostScope) {
1370 for (RegInfo &RI : Scope->RegInfos) {
1375 Instruction *InsertPoint = OutermostScope->BranchInsertPoint;
1376 for (RegInfo &RI : Scope->RegInfos) {
1379 bool IsHoisted =
false;
1381 assert((OutermostScope->TrueBiasedRegions.count(R) > 0 ||
1382 OutermostScope->FalseBiasedRegions.count(R) > 0) &&
1383 "Must be truthy or falsy");
1384 auto *BI = cast<BranchInst>(R->
getEntry()->getTerminator());
1386 bool IsHoistable =
checkHoistValue(BI->getCondition(), InsertPoint, DT,
1387 Unhoistables, &HoistStops);
1388 assert(IsHoistable &&
"Must be hoistable");
1389 (void)(IsHoistable);
1393 assert((OutermostScope->TrueBiasedSelects.count(SI) > 0 ||
1394 OutermostScope->FalseBiasedSelects.count(SI) > 0) &&
1395 "Must be true or false biased");
1398 Unhoistables, &HoistStops);
1399 assert(IsHoistable &&
"Must be hoistable");
1400 (void)(IsHoistable);
1404 OutermostScope->CHRRegions.push_back(RI);
1405 OutermostScope->HoistStopMap[R] = HoistStops;
1408 for (CHRScope *Sub : Scope->Subs)
1409 setCHRRegions(Sub, OutermostScope);
1413 return Scope1->RegInfos[0].R->getDepth() < Scope2->RegInfos[0].R->getDepth();
1426 HoistStopMapTy &HoistStopMap,
1429 auto IT = HoistStopMap.find(R);
1430 assert(
IT != HoistStopMap.end() &&
"Region must be in hoist stop map");
1432 if (
auto *
I = dyn_cast<Instruction>(V)) {
1433 if (
I == HoistPoint)
1435 if (HoistStops.count(
I))
1437 if (
auto *PN = dyn_cast<PHINode>(
I))
1438 if (TrivialPHIs.
count(PN))
1449 hoistValue(
Op, HoistPoint, R, HoistStopMap, HoistedSet, TrivialPHIs);
1451 I->moveBefore(HoistPoint);
1462 for (
const RegInfo &RI : Scope->CHRRegions) {
1464 bool IsTrueBiased = Scope->TrueBiasedRegions.count(R);
1465 bool IsFalseBiased = Scope->FalseBiasedRegions.count(R);
1466 if (RI.HasBranch && (IsTrueBiased || IsFalseBiased)) {
1467 auto *BI = cast<BranchInst>(R->
getEntry()->getTerminator());
1468 hoistValue(BI->getCondition(), HoistPoint, R, Scope->HoistStopMap,
1469 HoistedSet, TrivialPHIs);
1472 bool IsTrueBiased = Scope->TrueBiasedSelects.count(SI);
1473 bool IsFalseBiased = Scope->FalseBiasedSelects.count(SI);
1474 if (!(IsTrueBiased || IsFalseBiased))
1477 HoistedSet, TrivialPHIs);
1488 if (U == ExcludedUser)
1490 if (isa<BranchInst>(U) && cast<BranchInst>(U)->isConditional())
1492 if (isa<SelectInst>(U) && cast<SelectInst>(U)->getCondition() == ICmp)
1497 if (U == ExcludedUser)
1499 if (
auto *BI = dyn_cast<BranchInst>(U)) {
1500 assert(BI->isConditional() &&
"Must be conditional");
1501 BI->swapSuccessors();
1509 if (
auto *
SI = dyn_cast<SelectInst>(U)) {
1511 Value *TrueValue =
SI->getTrueValue();
1512 Value *FalseValue =
SI->getFalseValue();
1513 SI->setTrueValue(FalseValue);
1514 SI->setFalseValue(TrueValue);
1515 SI->swapProfMetadata();
1516 if (Scope->TrueBiasedSelects.count(
SI)) {
1517 assert(Scope->FalseBiasedSelects.count(
SI) == 0 &&
1518 "Must not be already in");
1519 Scope->FalseBiasedSelects.insert(
SI);
1520 }
else if (Scope->FalseBiasedSelects.count(
SI)) {
1521 assert(Scope->TrueBiasedSelects.count(
SI) == 0 &&
1522 "Must not be already in");
1523 Scope->TrueBiasedSelects.insert(
SI);
1541 for (RegInfo &RI : Scope->RegInfos) {
1544 BlocksInScopeSet.
insert(BB);
1549 dbgs() <<
"Inserting redudant phis\n";
1551 dbgs() <<
"BlockInScope " << BB->getName() <<
"\n";
1556 for (
User *U :
I.users()) {
1557 if (
auto *UI = dyn_cast<Instruction>(U)) {
1558 if (BlocksInScopeSet.
count(UI->getParent()) == 0 &&
1560 !(isa<PHINode>(UI) && UI->getParent() == ExitBlock)) {
1562 CHR_DEBUG(
dbgs() <<
"Used outside scope by user " << *UI <<
"\n");
1564 }
else if (UI->getParent() == EntryBlock && isa<PHINode>(UI)) {
1569 <<
"Used at entry block (for a back edge) by a phi user " 1575 if (Users.
size() > 0) {
1579 unsigned PredCount = std::distance(
pred_begin(ExitBlock),
1582 &ExitBlock->
front());
1589 for (
unsigned J = 0, NumOps = UI->getNumOperands(); J < NumOps; ++J) {
1590 if (UI->getOperand(J) == &
I) {
1591 UI->setOperand(J, PN);
1605 auto HasBiasedBranchOrSelect = [](RegInfo &RI, CHRScope *Scope) {
1606 if (Scope->TrueBiasedRegions.count(RI.R) ||
1607 Scope->FalseBiasedRegions.count(RI.R))
1610 if (Scope->TrueBiasedSelects.count(SI) ||
1611 Scope->FalseBiasedSelects.count(SI))
1615 for (RegInfo &RI : Scope->CHRRegions) {
1616 assert(HasBiasedBranchOrSelect(RI, Scope) &&
1617 "Must have biased branch or select");
1625 CHRScope *Scope,
BasicBlock *PreEntryBlock) {
1627 for (RegInfo &RI : Scope->CHRRegions) {
1629 bool IsTrueBiased = Scope->TrueBiasedRegions.count(R);
1630 bool IsFalseBiased = Scope->FalseBiasedRegions.count(R);
1631 if (RI.HasBranch && (IsTrueBiased || IsFalseBiased)) {
1632 auto *BI = cast<BranchInst>(R->
getEntry()->getTerminator());
1633 Value *V = BI->getCondition();
1635 if (
auto *
I = dyn_cast<Instruction>(V)) {
1637 assert((
I->getParent() == PreEntryBlock ||
1638 !Scope->contains(
I)) &&
1639 "Must have been hoisted to PreEntryBlock or outside the scope");
1643 bool IsTrueBiased = Scope->TrueBiasedSelects.count(SI);
1644 bool IsFalseBiased = Scope->FalseBiasedSelects.count(SI);
1645 if (!(IsTrueBiased || IsFalseBiased))
1649 if (
auto *
I = dyn_cast<Instruction>(V)) {
1651 assert((
I->getParent() == PreEntryBlock ||
1652 !Scope->contains(
I)) &&
1653 "Must have been hoisted to PreEntryBlock or outside the scope");
1662 assert(Scope->RegInfos.size() >= 1 &&
"Should have at least one Region");
1663 Region *FirstRegion = Scope->RegInfos[0].R;
1664 BasicBlock *EntryBlock = FirstRegion->getEntry();
1665 Region *LastRegion = Scope->RegInfos[Scope->RegInfos.size() - 1].R;
1687 <<
" at " << *Scope->BranchInsertPoint <<
"\n");
1689 SplitBlock(EntryBlock, Scope->BranchInsertPoint, &DT);
1690 assert(NewEntryBlock->getSinglePredecessor() == EntryBlock &&
1691 "NewEntryBlock's only pred must be EntryBlock");
1692 FirstRegion->replaceEntryRecursive(NewEntryBlock);
1699 cloneScopeBlocks(Scope, PreEntryBlock, ExitBlock, LastRegion, VMap);
1703 BranchInst *MergedBr = createMergedBranch(PreEntryBlock, EntryBlock,
1704 NewEntryBlock, VMap);
1719 fixupBranchesAndSelects(Scope, PreEntryBlock, MergedBr,
1720 ProfileCount ? ProfileCount.
getValue() : 0);
1726 void CHR::cloneScopeBlocks(CHRScope *Scope,
1737 for (RegInfo &RI : Scope->RegInfos)
1740 assert(BB != PreEntryBlock &&
"Don't copy the preetntry block");
1750 F.getBasicBlockList(),
1751 NewBlocks[0]->getIterator(),
F.end());
1754 for (
unsigned i = 0, e = NewBlocks.
size(); i != e; ++i)
1764 for (
unsigned I = 0, NumOps = PN.getNumIncomingValues();
I < NumOps;
1768 Value *V = PN.getIncomingValue(
I);
1769 auto It = VMap.
find(V);
1770 if (It != VMap.
end()) V = It->second;
1771 assert(VMap.
find(Pred) != VMap.
end() &&
"Pred must have been cloned");
1772 PN.addIncoming(V, cast<BasicBlock>(VMap[Pred]));
1785 "SplitBlock did not work correctly!");
1787 "NewEntryBlock's only pred must be EntryBlock");
1789 "NewEntryBlock must have been copied");
1795 cast<BasicBlock>(VMap[NewEntryBlock]),
1798 assert(NewEntryBlock->getSinglePredecessor() == EntryBlock &&
1799 "NewEntryBlock's only pred must be EntryBlock");
1805 void CHR::fixupBranchesAndSelects(CHRScope *Scope,
1811 uint64_t NumCHRedBranches = 0;
1813 for (RegInfo &RI : Scope->CHRRegions) {
1816 fixupBranch(R, Scope, IRB, MergedCondition, CHRBranchBias);
1820 fixupSelect(SI, Scope, IRB, MergedCondition, CHRBranchBias);
1824 Stats.NumBranchesDelta += NumCHRedBranches - 1;
1825 Stats.WeightedNumBranchesDelta += (NumCHRedBranches - 1) * ProfileCount;
1831 <<
"Merged " <<
ore::NV(
"NumCHRedBranches", NumCHRedBranches)
1832 <<
" branches or selects";
1836 Weights.
push_back(static_cast<uint32_t>(CHRBranchBias.scale(1000)));
1837 Weights.
push_back(static_cast<uint32_t>(CHRBranchBias.getCompl().scale(1000)));
1840 CHR_DEBUG(
dbgs() <<
"CHR branch bias " << Weights[0] <<
":" << Weights[1]
1846 void CHR::fixupBranch(
Region *R, CHRScope *Scope,
1848 Value *&MergedCondition,
1850 bool IsTrueBiased = Scope->TrueBiasedRegions.count(R);
1851 assert((IsTrueBiased || Scope->FalseBiasedRegions.count(R)) &&
1852 "Must be truthy or falsy");
1853 auto *BI = cast<BranchInst>(R->
getEntry()->getTerminator());
1854 assert(BranchBiasMap.find(R) != BranchBiasMap.end() &&
1855 "Must be in the bias map");
1859 if (CHRBranchBias > Bias)
1860 CHRBranchBias = Bias;
1864 assert(RegionExitBlock &&
"Null ExitBlock");
1865 assert((IfThen == RegionExitBlock || IfElse == RegionExitBlock) &&
1866 IfThen != IfElse &&
"Invariant from findScopes");
1867 if (IfThen == RegionExitBlock) {
1873 <<
" IfElse " << IfElse->
getName() <<
"\n");
1874 Value *Cond = BI->getCondition();
1875 BasicBlock *HotTarget = IsTrueBiased ? IfThen : IfElse;
1876 bool ConditionTrue = HotTarget == BI->getSuccessor(0);
1877 addToMergedCondition(ConditionTrue, Cond, BI, Scope, IRB,
1880 assert(ConditionTrue == (HotTarget == BI->getSuccessor(0)) &&
1881 "The successor shouldn't change");
1882 Value *NewCondition = ConditionTrue ?
1885 BI->setCondition(NewCondition);
1892 Value *&MergedCondition,
1894 bool IsTrueBiased = Scope->TrueBiasedSelects.count(SI);
1896 Scope->FalseBiasedSelects.count(SI)) &&
"Must be biased");
1897 assert(SelectBiasMap.find(SI) != SelectBiasMap.end() &&
1898 "Must be in the bias map");
1902 if (CHRBranchBias > Bias)
1903 CHRBranchBias = Bias;
1905 addToMergedCondition(IsTrueBiased, Cond, SI, Scope, IRB,
1907 Value *NewCondition = IsTrueBiased ?
1915 void CHR::addToMergedCondition(
bool IsTrueBiased,
Value *Cond,
1919 Value *&MergedCondition) {
1921 MergedCondition = IRB.
CreateAnd(MergedCondition, Cond);
1927 if (
auto *ICmp = dyn_cast<ICmpInst>(Cond))
1929 MergedCondition = IRB.
CreateAnd(MergedCondition, Cond);
1935 MergedCondition = IRB.
CreateAnd(MergedCondition, Negate);
1943 for (CHRScope *Scope : CHRScopes) {
1944 transformScopes(Scope, TrivialPHIs);
1946 std::ostringstream oss;
1947 oss <<
" after transformScopes " << I++;
1948 dumpIR(
F, oss.str().c_str(),
nullptr));
1955 dbgs() << Label <<
" " << Scopes.
size() <<
"\n";
1956 for (CHRScope *Scope : Scopes) {
1957 dbgs() << *Scope <<
"\n";
1967 bool Changed =
false;
1970 dbgs() <<
"RegionInfo:\n";
1976 findScopes(AllScopes);
1985 splitScopes(AllScopes, SplitScopes);
1990 classifyBiasedScopes(SplitScopes);
1996 filterScopes(SplitScopes, FilteredScopes);
2001 setCHRRegions(FilteredScopes, SetScopes);
2008 sortScopes(SetScopes, SortedScopes);
2012 dbgs() <<
"RegionInfo:\n";
2016 if (!SortedScopes.
empty()) {
2017 transformScopes(SortedScopes);
2027 <<
"Reduced the number of branches in hot paths by " 2030 <<
ore::NV(
"WeightedNumBranchesDelta",
Stats.WeightedNumBranchesDelta)
2031 <<
" (weighted by PGO count)";
2040 getAnalysis<BlockFrequencyInfoWrapperPass>().getBFI();
2041 DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree();
2043 getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
2044 RegionInfo &RI = getAnalysis<RegionInfoPass>().getRegionInfo();
2045 std::unique_ptr<OptimizationRemarkEmitter> OwnedORE =
2046 llvm::make_unique<OptimizationRemarkEmitter>(&
F);
2047 return CHR(F, BFI, DT, PSI, RI, *OwnedORE.get()).run();
2062 auto &MAM = MAMProxy.getManager();
2066 bool Changed = CHR(F,
BFI, DT, PSI, RI, ORE).
run();
Legacy wrapper pass to provide the GlobalsAAResult object.
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
static ConstantInt * getFalse(LLVMContext &Context)
static bool checkMDProf(MDNode *MD, BranchProbability &TrueProb, BranchProbability &FalseProb)
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static void hoistValue(Value *V, Instruction *HoistPoint, Region *R, HoistStopMapTy &HoistStopMap, DenseSet< Instruction *> &HoistedSet, DenseSet< PHINode *> &TrivialPHIs)
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
uint64_t getZExtValue() const
Get zero extended value.
DiagnosticInfoOptimizationBase::Argument NV
void dropAllReferences()
Drop all references to operands.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents lattice values for constants.
This is the interface for a simple mod/ref and alias analysis over globals.
Value * CreateXor(Value *LHS, Value *RHS, const Twine &Name="")
static bool checkBias(K *Key, BranchProbability TrueProb, BranchProbability FalseProb, S &TrueSet, S &FalseSet, M &BiasMap)
Implements a dense probed hash-table based set.
static DenseSet< Value * > getCHRConditionValuesForRegion(RegInfo &RI)
void push_back(const T &Elt)
Analysis providing profile information.
BasicBlock * getSuccessor(unsigned i) const
StringRef getName() const
Get a short "name" for the module.
static std::pair< StringRef, StringRef > split(StringRef Str, char Separator)
Checked version of split, to ensure mandatory subparts.
static bool checkBiasedSelect(SelectInst *SI, Region *R, DenseSet< SelectInst *> &TrueBiasedSelectsGlobal, DenseSet< SelectInst *> &FalseBiasedSelectsGlobal, DenseMap< SelectInst *, BranchProbability > &SelectBiasMap)
Analysis pass which computes a DominatorTree.
static void parseCHRFilterFiles()
static cl::opt< double > CHRBiasThreshold("chr-bias-threshold", cl::init(0.99), cl::Hidden, cl::desc("CHR considers a branch bias greater than this ratio as biased"))
const MDOperand & getOperand(unsigned I) const
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 void getSelectsInScope(CHRScope *Scope, DenseSet< Instruction *> &Output)
BlockT * getExit() const
Get the exit BasicBlock of the Region.
static BranchProbability getCHRBiasThreshold()
return AArch64::GPR64RegClass contains(Reg)
void dump() const
Support for debugging, callable in GDB: V->dump()
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
ControlHeightReductionPass()
This class represents the LLVM 'select' instruction.
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc.
An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
static bool checkBiasedBranch(BranchInst *BI, Region *R, DenseSet< Region *> &TrueBiasedRegionsGlobal, DenseSet< Region *> &FalseBiasedRegionsGlobal, DenseMap< Region *, BranchProbability > &BranchBiasMap)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Legacy analysis pass which computes BlockFrequencyInfo.
static bool shouldApply(Function &F, ProfileSummaryInfo &PSI)
static void LLVM_ATTRIBUTE_UNUSED assertBranchOrSelectConditionHoisted(CHRScope *Scope, BasicBlock *PreEntryBlock)
block placement Basic Block Placement Stats
static cl::opt< unsigned > CHRMergeThreshold("chr-merge-threshold", cl::init(2), cl::Hidden, cl::desc("CHR merges a group of N branches/selects where N >= this value"))
static cl::opt< bool > ForceCHR("force-chr", cl::init(false), cl::Hidden, cl::desc("Apply CHR for all functions"))
static cl::opt< std::string > CHRFunctionList("chr-function-list", cl::init(""), cl::Hidden, cl::desc("Specify file to retrieve the list of functions to apply CHR to"))
const T & getValue() const LLVM_LVALUE_FUNCTION
static bool checkHoistValue(Value *V, Instruction *InsertPoint, DominatorTree &DT, DenseSet< Instruction *> &Unhoistables, DenseSet< Instruction *> *HoistStops)
iterator find(const KeyT &Val)
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
const APInt & getValue() const
Return the constant as an APInt value reference.
static void hoistScopeConditions(CHRScope *Scope, Instruction *HoistPoint, DenseSet< PHINode *> &TrivialPHIs)
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
If this flag is set, the remapper knows that only local values within a function (such as an instruct...
StringRef getString() const
bool hasProfileSummary()
Returns true if profile summary is available.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
static bool runOnFunction(Function &F, bool PostInlining)
initializer< Ty > init(const Ty &Val)
static bool shouldSplit(Instruction *InsertPoint, DenseSet< Value *> &PrevConditionValues, DenseSet< Value *> &ConditionValues, DominatorTree &DT, DenseSet< Instruction *> &Unhoistables)
A set of analyses that are preserved following a run of a transformation pass.
const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
static void insertTrivialPHIs(CHRScope *Scope, BasicBlock *EntryBlock, BasicBlock *ExitBlock, DenseSet< PHINode *> &TrivialPHIs)
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
LLVM Basic Block Representation.
Conditional or Unconditional Branch instruction.
An analysis pass based on the new PM to deliver ProfileSummaryInfo.
static std::set< Value * > getBaseValues(Value *V, DominatorTree &DT)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static StringSet CHRFunctions
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
static cl::opt< std::string > CHRModuleList("chr-module-list", cl::init(""), cl::Hidden, cl::desc("Specify file to retrieve the list of modules to apply CHR to"))
const Instruction & front() const
std::pair< iterator, bool > insert(const ValueT &V)
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...
Represent the analysis usage information of a pass.
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
This instruction compares its operands according to the predicate given to the constructor.
Analysis pass providing a never-invalidated alias analysis result.
static bool isHoistableInstructionType(Instruction *I)
FunctionPass class - This class is used to implement most global optimizations.
Interval::pred_iterator pred_end(Interval *I)
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
self_iterator getIterator()
auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly...
bool isTopLevelRegion() const
Check if a Region is the TopLevel region.
auto remove_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly...
const Value * getCondition() const
void initializeControlHeightReductionLegacyPassPass(PassRegistry &)
Used in the streaming interface as the general argument type.
static void LLVM_ATTRIBUTE_UNUSED assertCHRRegionsHaveBiasedBranchOrSelect(CHRScope *Scope)
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Class to represent profile counts.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
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.
void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
std::pair< typename base::iterator, bool > insert(StringRef Key)
const InstListType & getInstList() const
Return the underlying instruction list container.
Analysis pass which computes BlockFrequencyInfo.
This is the shared class of boolean and integer constants.
BlockT * getEntry() const
Get the entry BasicBlock of the Region.
An analysis over an "inner" IR unit that provides access to an analysis manager over a "outer" IR uni...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
bool dominates(const Instruction *Def, const Use &U) const
Return true if Def dominates a use in User.
LLVM_NODISCARD std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
static BranchProbability getBranchProbability(uint64_t Numerator, uint64_t Denominator)
static bool negateICmpIfUsedByBranchOrSelectOnly(ICmpInst *ICmp, Instruction *ExcludedUser, CHRScope *Scope)
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=nullptr)
bool isConditional() const
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
pred_range predecessors(BasicBlock *BB)
static void LLVM_ATTRIBUTE_UNUSED dumpScopes(SmallVectorImpl< CHRScope *> &Scopes, const char *Label)
static ConstantInt * getTrue(LLVMContext &Context)
void setPredicate(Predicate P)
Set the predicate for this instruction to the specified value.
Analysis pass that exposes the RegionInfo for a function.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static StringSet CHRModules
void push_back(pointer val)
BasicBlock * CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, const Twine &NameSuffix="", Function *F=nullptr, ClonedCodeInfo *CodeInfo=nullptr, DebugInfoFinder *DIFinder=nullptr)
Return a copy of the specified basic block, but without embedding the block into a particular functio...
iterator_range< user_iterator > users()
void RemapInstruction(Instruction *I, ValueToValueMapTy &VM, RemapFlags Flags=RF_None, ValueMapTypeRemapper *TypeMapper=nullptr, ValueMaterializer *Materializer=nullptr)
Convert the instruction operands from referencing the current values into those specified by VM...
static cl::opt< unsigned > Threshold("loop-unswitch-threshold", cl::desc("Max loop size to unswitch"), cl::init(100), cl::Hidden)
iterator insert(iterator I, T &&Elt)
void setCondition(Value *V)
If this flag is set, the remapper ignores missing function-local entries (Argument, Instruction, BasicBlock) that are not in the value map.
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::ZeroOrMore, cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate IT block based on arch"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow deprecated IT based on ARMv8"), clEnumValN(NoRestrictedIT, "arm-no-restrict-it", "Allow IT blocks based on ARMv7")))
static void LLVM_ATTRIBUTE_UNUSED dumpIR(Function &F, const char *Label, CHRStats *Stats)
std::string getNameStr() const
Returns the name of the Region.
Predicate getPredicate() const
Return the predicate for this instruction.
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
bool isFunctionEntryHot(const Function *F)
Returns true if F has hot function entry.
bool contains(const BlockT *BB) const
Check if the region contains a BasicBlock.
LLVM_NODISCARD bool empty() const
StringRef getName() const
Return a constant reference to the value's name.
static bool isHoistable(Instruction *I, DominatorTree &DT)
static bool hasAtLeastTwoBiasedBranches(CHRScope *Scope)
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
bool isUnconditional() const
raw_ostream & operator<<(raw_ostream &OS, const APInt &I)
Value * CreateAnd(Value *LHS, Value *RHS, const Twine &Name="")
void setCondition(Value *V)
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
RegionT * getParent() const
Get the parent of the Region.
static Instruction * getBranchInsertPoint(RegInfo &RI)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool isSafeToSpeculativelyExecute(const Value *V, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr)
Return true if the instruction does not have any effects besides calculating the result and does not ...
Module * getParent()
Get the module that this global value is contained inside of...
LLVM Value Representation.
StringSet - A wrapper for StringMap that provides set-like functionality.
BasicBlock * SplitBlock(BasicBlock *Old, Instruction *SplitPt, DominatorTree *DT=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Split the specified block at the specified instruction - everything before SplitPt stays in Old and e...
This class implements an extremely fast bulk output stream that can only output to a stream...
StringRef - Represent a constant reference to a string, i.e.
A container for analyses that lazily runs them and caches their results.
FunctionPass * createControlHeightReductionLegacyPass()
Legacy analysis pass which computes a DominatorTree.
bool CHRScopeSorter(CHRScope *Scope1, CHRScope *Scope2)
#define LLVM_ATTRIBUTE_UNUSED
static void Split(std::vector< std::string > &V, StringRef S)
Splits a string of comma separated items in to a vector of strings.
INITIALIZE_PASS_BEGIN(ControlHeightReductionLegacyPass, "chr", "Reduce control height in the hot paths", false, false) INITIALIZE_PASS_END(ControlHeightReductionLegacyPass
unsigned getNumOperands() const
Return number of MDNode operands.
OutputIt copy(R &&Range, OutputIt Out)
iterator_range< element_iterator > elements()
const BasicBlock * getParent() const