2626#include " llvm/ADT/Statistic.h"
2727#include " llvm/Analysis/AssumptionCache.h"
2828#include " llvm/Analysis/CFG.h"
29+ #include " llvm/Analysis/ConstantFolding.h"
2930#include " llvm/Analysis/DomTreeUpdater.h"
3031#include " llvm/Analysis/GlobalsModRef.h"
3132#include " llvm/Analysis/TargetTransformInfo.h"
@@ -262,12 +263,52 @@ static bool iterativelySimplifyCFG(Function &F, const TargetTransformInfo &TTI,
262263 return Changed;
263264}
264265
266+ static void decayOneInputPHIs (BasicBlock &BB) {
267+ if (BB.empty () || !isa<PHINode>(BB.begin ()))
268+ return ;
269+ unsigned NumPreds = cast<PHINode>(BB.front ()).getNumIncomingValues ();
270+ if (NumPreds != 1 )
271+ return ;
272+ for (PHINode &Phi : make_early_inc_range (BB.phis ())) {
273+ if (Value *PhiConst = Phi.hasConstantValue ()) {
274+ Phi.replaceAllUsesWith (PhiConst);
275+ Phi.eraseFromParent ();
276+ // Additionally, constant-fold conditional branch if there is one present,
277+ // and the PHI has decayed into a constant, since it may make another CFG
278+ // edge dead.
279+ if (!isa<Constant>(PhiConst))
280+ continue ;
281+ if (BranchInst *BI = dyn_cast<BranchInst>(BB.getTerminator ()))
282+ if (BI->isConditional ())
283+ if (auto *Cmp = dyn_cast<CmpInst>(BI->getCondition ()))
284+ if (auto *LHS = dyn_cast<Constant>(Cmp->getOperand (0 )))
285+ if (auto *RHS = dyn_cast<Constant>(Cmp->getOperand (1 ))) {
286+ const DataLayout &DL = BB.getModule ()->getDataLayout ();
287+ Constant *ConstCond = ConstantFoldCompareInstOperands (
288+ Cmp->getPredicate (), LHS, RHS, DL);
289+ if (ConstCond)
290+ BI->setCondition (ConstCond);
291+ }
292+ }
293+ }
294+ }
295+
296+ static bool removeUnreachableBlocksAndSimplify (Function &F,
297+ DomTreeUpdater *DTU) {
298+ bool Changed = removeUnreachableBlocks (F, DTU, /* MSSAU=*/ nullptr ,
299+ /* KeepOneInputPHIs=*/ true );
300+ if (Changed)
301+ for (BasicBlock &BB : F)
302+ decayOneInputPHIs (BB);
303+ return Changed;
304+ }
305+
265306static bool simplifyFunctionCFGImpl (Function &F, const TargetTransformInfo &TTI,
266307 DominatorTree *DT,
267308 const SimplifyCFGOptions &Options) {
268309 DomTreeUpdater DTU (DT, DomTreeUpdater::UpdateStrategy::Eager);
269310
270- bool EverChanged = removeUnreachableBlocks (F, DT ? &DTU : nullptr );
311+ bool EverChanged = removeUnreachableBlocksAndSimplify (F, DT ? &DTU : nullptr );
271312 EverChanged |=
272313 tailMergeBlocksWithSimilarFunctionTerminators (F, DT ? &DTU : nullptr );
273314 EverChanged |= iterativelySimplifyCFG (F, TTI, DT ? &DTU : nullptr , Options);
@@ -285,7 +326,7 @@ static bool simplifyFunctionCFGImpl(Function &F, const TargetTransformInfo &TTI,
285326
286327 do {
287328 EverChanged = iterativelySimplifyCFG (F, TTI, DT ? &DTU : nullptr , Options);
288- EverChanged |= removeUnreachableBlocks (F, DT ? &DTU : nullptr );
329+ EverChanged |= removeUnreachableBlocksAndSimplify (F, DT ? &DTU : nullptr );
289330 } while (EverChanged);
290331
291332 return true ;
0 commit comments