2010-08-31 15:48:34 +08:00
|
|
|
//===- CorrelatedValuePropagation.cpp - Propagate CFG-derived info --------===//
|
2010-08-28 07:31:36 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2010-08-31 15:48:34 +08:00
|
|
|
// This file implements the Correlated Value Propagation pass.
|
2010-08-28 07:31:36 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2016-07-07 07:26:29 +08:00
|
|
|
#include "llvm/Transforms/Scalar/CorrelatedValuePropagation.h"
|
2017-10-14 05:17:07 +08:00
|
|
|
#include "llvm/ADT/DepthFirstIterator.h"
|
|
|
|
#include "llvm/ADT/Optional.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/ADT/Statistic.h"
|
2015-09-10 18:22:12 +08:00
|
|
|
#include "llvm/Analysis/GlobalsModRef.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/Analysis/InstructionSimplify.h"
|
|
|
|
#include "llvm/Analysis/LazyValueInfo.h"
|
2017-10-14 05:17:07 +08:00
|
|
|
#include "llvm/IR/Attributes.h"
|
|
|
|
#include "llvm/IR/BasicBlock.h"
|
2014-03-04 19:45:46 +08:00
|
|
|
#include "llvm/IR/CFG.h"
|
2017-10-14 05:17:07 +08:00
|
|
|
#include "llvm/IR/CallSite.h"
|
|
|
|
#include "llvm/IR/Constant.h"
|
2016-08-10 21:08:34 +08:00
|
|
|
#include "llvm/IR/ConstantRange.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/Constants.h"
|
2017-10-14 05:17:07 +08:00
|
|
|
#include "llvm/IR/DerivedTypes.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/Function.h"
|
2017-10-14 05:17:07 +08:00
|
|
|
#include "llvm/IR/InstrTypes.h"
|
|
|
|
#include "llvm/IR/Instruction.h"
|
2013-01-02 19:36:10 +08:00
|
|
|
#include "llvm/IR/Instructions.h"
|
2017-11-11 03:13:35 +08:00
|
|
|
#include "llvm/IR/IntrinsicInst.h"
|
|
|
|
#include "llvm/IR/IRBuilder.h"
|
2017-10-14 05:17:07 +08:00
|
|
|
#include "llvm/IR/Operator.h"
|
|
|
|
#include "llvm/IR/PassManager.h"
|
|
|
|
#include "llvm/IR/Type.h"
|
|
|
|
#include "llvm/IR/Value.h"
|
2010-08-28 07:31:36 +08:00
|
|
|
#include "llvm/Pass.h"
|
2017-10-14 05:17:07 +08:00
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/CommandLine.h"
|
2013-02-24 23:34:43 +08:00
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2017-04-26 21:52:13 +08:00
|
|
|
#include "llvm/Transforms/Scalar.h"
|
2010-08-28 07:31:36 +08:00
|
|
|
#include "llvm/Transforms/Utils/Local.h"
|
2017-10-14 05:17:07 +08:00
|
|
|
#include <cassert>
|
|
|
|
#include <utility>
|
|
|
|
|
2010-08-28 07:31:36 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2014-04-22 10:55:47 +08:00
|
|
|
#define DEBUG_TYPE "correlated-value-propagation"
|
|
|
|
|
2010-09-04 03:08:37 +08:00
|
|
|
STATISTIC(NumPhis, "Number of phis propagated");
|
|
|
|
STATISTIC(NumSelects, "Number of selects propagated");
|
|
|
|
STATISTIC(NumMemAccess, "Number of memory access targets propagated");
|
2010-09-04 06:47:08 +08:00
|
|
|
STATISTIC(NumCmps, "Number of comparisons propagated");
|
2015-11-04 09:43:54 +08:00
|
|
|
STATISTIC(NumReturns, "Number of return values propagated");
|
2012-03-10 03:21:15 +08:00
|
|
|
STATISTIC(NumDeadCases, "Number of switch cases removed");
|
2016-03-14 11:24:28 +08:00
|
|
|
STATISTIC(NumSDivs, "Number of sdiv converted to udiv");
|
2016-10-12 21:41:38 +08:00
|
|
|
STATISTIC(NumAShrs, "Number of ashr converted to lshr");
|
2016-07-14 20:23:48 +08:00
|
|
|
STATISTIC(NumSRems, "Number of srem converted to urem");
|
2017-11-11 03:13:35 +08:00
|
|
|
STATISTIC(NumOverflows, "Number of overflow checks removed");
|
2010-08-31 06:45:55 +08:00
|
|
|
|
2017-02-24 06:29:00 +08:00
|
|
|
static cl::opt<bool> DontProcessAdds("cvp-dont-process-adds", cl::init(true));
|
|
|
|
|
2010-08-28 07:31:36 +08:00
|
|
|
namespace {
|
2017-10-14 05:17:07 +08:00
|
|
|
|
2010-08-31 15:48:34 +08:00
|
|
|
class CorrelatedValuePropagation : public FunctionPass {
|
2010-08-28 07:31:36 +08:00
|
|
|
public:
|
|
|
|
static char ID;
|
2017-10-14 05:17:07 +08:00
|
|
|
|
2010-10-20 01:21:58 +08:00
|
|
|
CorrelatedValuePropagation(): FunctionPass(ID) {
|
|
|
|
initializeCorrelatedValuePropagationPass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
2010-12-15 08:52:44 +08:00
|
|
|
|
2014-03-05 17:10:37 +08:00
|
|
|
bool runOnFunction(Function &F) override;
|
2010-12-15 08:52:44 +08:00
|
|
|
|
2014-03-05 17:10:37 +08:00
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
2018-01-13 05:06:48 +08:00
|
|
|
AU.addRequired<DominatorTreeWrapperPass>();
|
2016-06-14 06:01:25 +08:00
|
|
|
AU.addRequired<LazyValueInfoWrapperPass>();
|
2015-09-10 18:22:12 +08:00
|
|
|
AU.addPreserved<GlobalsAAWrapperPass>();
|
2010-08-28 07:31:36 +08:00
|
|
|
}
|
|
|
|
};
|
2017-10-14 05:17:07 +08:00
|
|
|
|
|
|
|
} // end anonymous namespace
|
2010-08-28 07:31:36 +08:00
|
|
|
|
2010-08-31 15:48:34 +08:00
|
|
|
char CorrelatedValuePropagation::ID = 0;
|
2017-10-14 05:17:07 +08:00
|
|
|
|
2010-10-13 03:48:12 +08:00
|
|
|
INITIALIZE_PASS_BEGIN(CorrelatedValuePropagation, "correlated-propagation",
|
|
|
|
"Value Propagation", false, false)
|
2018-01-13 05:06:48 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
|
2016-06-14 06:01:25 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(LazyValueInfoWrapperPass)
|
2010-10-13 03:48:12 +08:00
|
|
|
INITIALIZE_PASS_END(CorrelatedValuePropagation, "correlated-propagation",
|
2010-10-08 06:25:06 +08:00
|
|
|
"Value Propagation", false, false)
|
2010-08-28 07:31:36 +08:00
|
|
|
|
|
|
|
// Public interface to the Value Propagation pass
|
2010-08-31 15:48:34 +08:00
|
|
|
Pass *llvm::createCorrelatedValuePropagationPass() {
|
|
|
|
return new CorrelatedValuePropagation();
|
2010-08-28 07:31:36 +08:00
|
|
|
}
|
|
|
|
|
2016-05-26 01:39:54 +08:00
|
|
|
static bool processSelect(SelectInst *S, LazyValueInfo *LVI) {
|
2010-08-31 07:34:17 +08:00
|
|
|
if (S->getType()->isVectorTy()) return false;
|
2010-09-04 03:08:37 +08:00
|
|
|
if (isa<Constant>(S->getOperand(0))) return false;
|
2010-12-15 08:52:44 +08:00
|
|
|
|
2014-09-08 04:29:59 +08:00
|
|
|
Constant *C = LVI->getConstant(S->getOperand(0), S->getParent(), S);
|
2010-08-28 07:31:36 +08:00
|
|
|
if (!C) return false;
|
2010-12-15 08:52:44 +08:00
|
|
|
|
2010-08-28 07:31:36 +08:00
|
|
|
ConstantInt *CI = dyn_cast<ConstantInt>(C);
|
|
|
|
if (!CI) return false;
|
2010-12-15 08:52:44 +08:00
|
|
|
|
2010-12-15 08:55:35 +08:00
|
|
|
Value *ReplaceWith = S->getOperand(1);
|
|
|
|
Value *Other = S->getOperand(2);
|
|
|
|
if (!CI->isOne()) std::swap(ReplaceWith, Other);
|
|
|
|
if (ReplaceWith == S) ReplaceWith = UndefValue::get(S->getType());
|
|
|
|
|
|
|
|
S->replaceAllUsesWith(ReplaceWith);
|
2010-08-31 07:34:17 +08:00
|
|
|
S->eraseFromParent();
|
|
|
|
|
2010-08-31 06:45:55 +08:00
|
|
|
++NumSelects;
|
2010-12-15 08:52:44 +08:00
|
|
|
|
2010-08-28 07:31:36 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-01-29 13:59:55 +08:00
|
|
|
static bool processPHI(PHINode *P, LazyValueInfo *LVI,
|
|
|
|
const SimplifyQuery &SQ) {
|
2010-08-31 07:34:17 +08:00
|
|
|
bool Changed = false;
|
2010-12-15 08:52:44 +08:00
|
|
|
|
2010-08-28 07:31:36 +08:00
|
|
|
BasicBlock *BB = P->getParent();
|
2010-08-31 07:34:17 +08:00
|
|
|
for (unsigned i = 0, e = P->getNumIncomingValues(); i < e; ++i) {
|
|
|
|
Value *Incoming = P->getIncomingValue(i);
|
|
|
|
if (isa<Constant>(Incoming)) continue;
|
2010-12-15 08:52:44 +08:00
|
|
|
|
2018-01-29 13:59:55 +08:00
|
|
|
Value *V = LVI->getConstantOnEdge(Incoming, P->getIncomingBlock(i), BB, P);
|
2010-12-15 08:52:44 +08:00
|
|
|
|
2015-05-13 06:31:47 +08:00
|
|
|
// Look if the incoming value is a select with a scalar condition for which
|
|
|
|
// LVI can tells us the value. In that case replace the incoming value with
|
|
|
|
// the appropriate value of the select. This often allows us to remove the
|
|
|
|
// select later.
|
2013-02-24 23:34:43 +08:00
|
|
|
if (!V) {
|
|
|
|
SelectInst *SI = dyn_cast<SelectInst>(Incoming);
|
|
|
|
if (!SI) continue;
|
|
|
|
|
2015-05-13 06:31:47 +08:00
|
|
|
Value *Condition = SI->getCondition();
|
|
|
|
if (!Condition->getType()->isVectorTy()) {
|
2015-06-06 12:56:51 +08:00
|
|
|
if (Constant *C = LVI->getConstantOnEdge(
|
|
|
|
Condition, P->getIncomingBlock(i), BB, P)) {
|
|
|
|
if (C->isOneValue()) {
|
2015-05-13 06:31:47 +08:00
|
|
|
V = SI->getTrueValue();
|
2015-06-06 12:56:51 +08:00
|
|
|
} else if (C->isZeroValue()) {
|
2015-05-13 06:31:47 +08:00
|
|
|
V = SI->getFalseValue();
|
|
|
|
}
|
|
|
|
// Once LVI learns to handle vector types, we could also add support
|
|
|
|
// for vector type constants that are not all zeroes or all ones.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Look if the select has a constant but LVI tells us that the incoming
|
|
|
|
// value can never be that constant. In that case replace the incoming
|
|
|
|
// value with the other value of the select. This often allows us to
|
|
|
|
// remove the select later.
|
|
|
|
if (!V) {
|
|
|
|
Constant *C = dyn_cast<Constant>(SI->getFalseValue());
|
|
|
|
if (!C) continue;
|
|
|
|
|
|
|
|
if (LVI->getPredicateOnEdge(ICmpInst::ICMP_EQ, SI, C,
|
|
|
|
P->getIncomingBlock(i), BB, P) !=
|
|
|
|
LazyValueInfo::False)
|
|
|
|
continue;
|
|
|
|
V = SI->getTrueValue();
|
|
|
|
}
|
2013-02-24 23:34:43 +08:00
|
|
|
|
|
|
|
DEBUG(dbgs() << "CVP: Threading PHI over " << *SI << '\n');
|
|
|
|
}
|
|
|
|
|
|
|
|
P->setIncomingValue(i, V);
|
2010-08-31 07:34:17 +08:00
|
|
|
Changed = true;
|
2010-08-28 07:31:36 +08:00
|
|
|
}
|
2010-11-17 01:41:24 +08:00
|
|
|
|
2017-04-29 03:55:38 +08:00
|
|
|
if (Value *V = SimplifyInstruction(P, SQ)) {
|
2010-11-17 01:41:24 +08:00
|
|
|
P->replaceAllUsesWith(V);
|
2010-08-28 07:31:36 +08:00
|
|
|
P->eraseFromParent();
|
2010-08-31 07:34:17 +08:00
|
|
|
Changed = true;
|
2010-08-28 07:31:36 +08:00
|
|
|
}
|
2010-11-17 01:41:24 +08:00
|
|
|
|
2012-03-10 03:21:15 +08:00
|
|
|
if (Changed)
|
|
|
|
++NumPhis;
|
2010-12-15 08:52:44 +08:00
|
|
|
|
2010-08-31 07:34:17 +08:00
|
|
|
return Changed;
|
2010-08-28 07:31:36 +08:00
|
|
|
}
|
|
|
|
|
2016-05-26 01:39:54 +08:00
|
|
|
static bool processMemAccess(Instruction *I, LazyValueInfo *LVI) {
|
2014-04-25 13:29:35 +08:00
|
|
|
Value *Pointer = nullptr;
|
2010-09-04 03:08:37 +08:00
|
|
|
if (LoadInst *L = dyn_cast<LoadInst>(I))
|
|
|
|
Pointer = L->getPointerOperand();
|
|
|
|
else
|
|
|
|
Pointer = cast<StoreInst>(I)->getPointerOperand();
|
2010-12-15 08:52:44 +08:00
|
|
|
|
2010-09-04 03:08:37 +08:00
|
|
|
if (isa<Constant>(Pointer)) return false;
|
2010-12-15 08:52:44 +08:00
|
|
|
|
2014-09-08 04:29:59 +08:00
|
|
|
Constant *C = LVI->getConstant(Pointer, I->getParent(), I);
|
2010-09-04 03:08:37 +08:00
|
|
|
if (!C) return false;
|
2010-12-15 08:52:44 +08:00
|
|
|
|
2010-09-04 03:08:37 +08:00
|
|
|
++NumMemAccess;
|
|
|
|
I->replaceUsesOfWith(Pointer, C);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-07-02 00:41:59 +08:00
|
|
|
/// See if LazyValueInfo's ability to exploit edge conditions or range
|
|
|
|
/// information is sufficient to prove this comparison. Even for local
|
|
|
|
/// conditions, this can sometimes prove conditions instcombine can't by
|
[LVI/CVP] Teach LVI about range metadata
Somewhat shockingly for an analysis pass which is computing constant ranges, LVI did not understand the ranges provided by range metadata.
As part of this change, I included a change to CVP primarily because doing so made it much easier to write small self contained test cases. CVP was previously only handling the non-local operand case, but given that LVI can sometimes figure out information about instructions standalone, I don't see any reason to restrict this. There could possibly be a compile time impact from this, but I suspect it should be minimal. If anyone has an example which substaintially regresses, please let me know. I could restrict the block local handling to ICmps feeding Terminator instructions if needed.
Note that this patch continues a somewhat bad practice in LVI. In many cases, we know facts about values, and separate context sensitive facts about values. LVI makes no effort to distinguish and will frequently cache the same value fact repeatedly for different contexts. I would like to change this, but that's a large enough change that I want it to go in separately with clear documentation of what's changing. Other examples of this include the non-null handling, and arguments.
As a meta comment: the entire motivation of this change was being able to write smaller (aka reasonable sized) test cases for a future patch teaching LVI about select instructions.
Differential Revision: http://reviews.llvm.org/D13543
llvm-svn: 251606
2015-10-29 11:57:17 +08:00
|
|
|
/// exploiting range information.
|
2016-05-26 01:39:54 +08:00
|
|
|
static bool processCmp(CmpInst *C, LazyValueInfo *LVI) {
|
2010-09-04 06:47:08 +08:00
|
|
|
Value *Op0 = C->getOperand(0);
|
|
|
|
Constant *Op1 = dyn_cast<Constant>(C->getOperand(1));
|
|
|
|
if (!Op1) return false;
|
2010-12-15 08:52:44 +08:00
|
|
|
|
2015-11-04 09:43:54 +08:00
|
|
|
// As a policy choice, we choose not to waste compile time on anything where
|
|
|
|
// the comparison is testing local values. While LVI can sometimes reason
|
|
|
|
// about such cases, it's not its primary purpose. We do make sure to do
|
|
|
|
// the block local query for uses from terminator instructions, but that's
|
|
|
|
// handled in the code for each terminator.
|
|
|
|
auto *I = dyn_cast<Instruction>(Op0);
|
|
|
|
if (I && I->getParent() == C->getParent())
|
|
|
|
return false;
|
|
|
|
|
[LVI/CVP] Teach LVI about range metadata
Somewhat shockingly for an analysis pass which is computing constant ranges, LVI did not understand the ranges provided by range metadata.
As part of this change, I included a change to CVP primarily because doing so made it much easier to write small self contained test cases. CVP was previously only handling the non-local operand case, but given that LVI can sometimes figure out information about instructions standalone, I don't see any reason to restrict this. There could possibly be a compile time impact from this, but I suspect it should be minimal. If anyone has an example which substaintially regresses, please let me know. I could restrict the block local handling to ICmps feeding Terminator instructions if needed.
Note that this patch continues a somewhat bad practice in LVI. In many cases, we know facts about values, and separate context sensitive facts about values. LVI makes no effort to distinguish and will frequently cache the same value fact repeatedly for different contexts. I would like to change this, but that's a large enough change that I want it to go in separately with clear documentation of what's changing. Other examples of this include the non-null handling, and arguments.
As a meta comment: the entire motivation of this change was being able to write smaller (aka reasonable sized) test cases for a future patch teaching LVI about select instructions.
Differential Revision: http://reviews.llvm.org/D13543
llvm-svn: 251606
2015-10-29 11:57:17 +08:00
|
|
|
LazyValueInfo::Tristate Result =
|
|
|
|
LVI->getPredicateAt(C->getPredicate(), Op0, Op1, C);
|
2010-09-04 06:47:08 +08:00
|
|
|
if (Result == LazyValueInfo::Unknown) return false;
|
|
|
|
|
|
|
|
++NumCmps;
|
|
|
|
if (Result == LazyValueInfo::True)
|
|
|
|
C->replaceAllUsesWith(ConstantInt::getTrue(C->getContext()));
|
|
|
|
else
|
|
|
|
C->replaceAllUsesWith(ConstantInt::getFalse(C->getContext()));
|
|
|
|
C->eraseFromParent();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-07-02 00:41:59 +08:00
|
|
|
/// Simplify a switch instruction by removing cases which can never fire. If the
|
|
|
|
/// uselessness of a case could be determined locally then constant propagation
|
|
|
|
/// would already have figured it out. Instead, walk the predecessors and
|
|
|
|
/// statically evaluate cases based on information available on that edge. Cases
|
|
|
|
/// that cannot fire no matter what the incoming edge can safely be removed. If
|
|
|
|
/// a case fires on every incoming edge then the entire switch can be removed
|
|
|
|
/// and replaced with a branch to the case destination.
|
2016-05-26 01:39:54 +08:00
|
|
|
static bool processSwitch(SwitchInst *SI, LazyValueInfo *LVI) {
|
2012-03-09 21:45:18 +08:00
|
|
|
Value *Cond = SI->getCondition();
|
|
|
|
BasicBlock *BB = SI->getParent();
|
|
|
|
|
|
|
|
// If the condition was defined in same block as the switch then LazyValueInfo
|
|
|
|
// currently won't say anything useful about it, though in theory it could.
|
|
|
|
if (isa<Instruction>(Cond) && cast<Instruction>(Cond)->getParent() == BB)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// If the switch is unreachable then trying to improve it is a waste of time.
|
|
|
|
pred_iterator PB = pred_begin(BB), PE = pred_end(BB);
|
|
|
|
if (PB == PE) return false;
|
|
|
|
|
2017-06-24 04:28:35 +08:00
|
|
|
// Analyse each switch case in turn.
|
2012-03-09 21:45:18 +08:00
|
|
|
bool Changed = false;
|
2017-03-26 10:49:23 +08:00
|
|
|
for (auto CI = SI->case_begin(), CE = SI->case_end(); CI != CE;) {
|
2017-04-12 15:27:28 +08:00
|
|
|
ConstantInt *Case = CI->getCaseValue();
|
2012-03-09 21:45:18 +08:00
|
|
|
|
|
|
|
// Check to see if the switch condition is equal to/not equal to the case
|
|
|
|
// value on every incoming edge, equal/not equal being the same each time.
|
|
|
|
LazyValueInfo::Tristate State = LazyValueInfo::Unknown;
|
|
|
|
for (pred_iterator PI = PB; PI != PE; ++PI) {
|
|
|
|
// Is the switch condition equal to the case value?
|
|
|
|
LazyValueInfo::Tristate Value = LVI->getPredicateOnEdge(CmpInst::ICMP_EQ,
|
2014-09-08 04:29:59 +08:00
|
|
|
Cond, Case, *PI,
|
|
|
|
BB, SI);
|
2012-03-09 21:45:18 +08:00
|
|
|
// Give up on this case if nothing is known.
|
|
|
|
if (Value == LazyValueInfo::Unknown) {
|
|
|
|
State = LazyValueInfo::Unknown;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this was the first edge to be visited, record that all other edges
|
|
|
|
// need to give the same result.
|
|
|
|
if (PI == PB) {
|
|
|
|
State = Value;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this case is known to fire for some edges and known not to fire for
|
|
|
|
// others then there is nothing we can do - give up.
|
|
|
|
if (Value != State) {
|
|
|
|
State = LazyValueInfo::Unknown;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (State == LazyValueInfo::False) {
|
|
|
|
// This case never fires - remove it.
|
2017-04-12 15:27:28 +08:00
|
|
|
CI->getCaseSuccessor()->removePredecessor(BB);
|
2017-03-26 10:49:23 +08:00
|
|
|
CI = SI->removeCase(CI);
|
|
|
|
CE = SI->case_end();
|
2012-09-28 18:42:50 +08:00
|
|
|
|
|
|
|
// The condition can be modified by removePredecessor's PHI simplification
|
|
|
|
// logic.
|
|
|
|
Cond = SI->getCondition();
|
|
|
|
|
2012-03-10 03:21:15 +08:00
|
|
|
++NumDeadCases;
|
2012-03-09 21:45:18 +08:00
|
|
|
Changed = true;
|
2017-03-26 10:49:23 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (State == LazyValueInfo::True) {
|
2012-03-09 21:45:18 +08:00
|
|
|
// This case always fires. Arrange for the switch to be turned into an
|
|
|
|
// unconditional branch by replacing the switch condition with the case
|
|
|
|
// value.
|
|
|
|
SI->setCondition(Case);
|
2012-03-10 03:21:15 +08:00
|
|
|
NumDeadCases += SI->getNumCases();
|
2012-03-09 21:45:18 +08:00
|
|
|
Changed = true;
|
|
|
|
break;
|
|
|
|
}
|
2017-03-26 10:49:23 +08:00
|
|
|
|
2017-06-24 04:28:40 +08:00
|
|
|
// Increment the case iterator since we didn't delete it.
|
2017-03-26 10:49:23 +08:00
|
|
|
++CI;
|
2012-03-09 21:45:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (Changed)
|
|
|
|
// If the switch has been simplified to the point where it can be replaced
|
|
|
|
// by a branch then do so now.
|
|
|
|
ConstantFoldTerminator(BB);
|
|
|
|
|
|
|
|
return Changed;
|
|
|
|
}
|
|
|
|
|
2017-11-11 03:13:35 +08:00
|
|
|
// See if we can prove that the given overflow intrinsic will not overflow.
|
|
|
|
static bool willNotOverflow(IntrinsicInst *II, LazyValueInfo *LVI) {
|
|
|
|
using OBO = OverflowingBinaryOperator;
|
2017-12-06 02:14:24 +08:00
|
|
|
auto NoWrap = [&] (Instruction::BinaryOps BinOp, unsigned NoWrapKind) {
|
|
|
|
Value *RHS = II->getOperand(1);
|
2017-11-11 03:13:35 +08:00
|
|
|
ConstantRange RRange = LVI->getConstantRange(RHS, II->getParent(), II);
|
|
|
|
ConstantRange NWRegion = ConstantRange::makeGuaranteedNoWrapRegion(
|
2017-12-06 02:14:24 +08:00
|
|
|
BinOp, RRange, NoWrapKind);
|
2017-11-11 03:13:35 +08:00
|
|
|
// As an optimization, do not compute LRange if we do not need it.
|
|
|
|
if (NWRegion.isEmptySet())
|
|
|
|
return false;
|
2017-12-06 02:14:24 +08:00
|
|
|
Value *LHS = II->getOperand(0);
|
2017-11-11 03:13:35 +08:00
|
|
|
ConstantRange LRange = LVI->getConstantRange(LHS, II->getParent(), II);
|
|
|
|
return NWRegion.contains(LRange);
|
|
|
|
};
|
|
|
|
switch (II->getIntrinsicID()) {
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
case Intrinsic::uadd_with_overflow:
|
2017-12-06 02:14:24 +08:00
|
|
|
return NoWrap(Instruction::Add, OBO::NoUnsignedWrap);
|
2017-11-11 03:13:35 +08:00
|
|
|
case Intrinsic::sadd_with_overflow:
|
2017-12-06 02:14:24 +08:00
|
|
|
return NoWrap(Instruction::Add, OBO::NoSignedWrap);
|
|
|
|
case Intrinsic::usub_with_overflow:
|
|
|
|
return NoWrap(Instruction::Sub, OBO::NoUnsignedWrap);
|
|
|
|
case Intrinsic::ssub_with_overflow:
|
|
|
|
return NoWrap(Instruction::Sub, OBO::NoSignedWrap);
|
2017-11-11 03:13:35 +08:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void processOverflowIntrinsic(IntrinsicInst *II) {
|
|
|
|
Value *NewOp = nullptr;
|
|
|
|
switch (II->getIntrinsicID()) {
|
|
|
|
default:
|
2017-12-06 02:14:24 +08:00
|
|
|
llvm_unreachable("Unexpected instruction.");
|
2017-11-11 03:13:35 +08:00
|
|
|
case Intrinsic::uadd_with_overflow:
|
|
|
|
case Intrinsic::sadd_with_overflow:
|
|
|
|
NewOp = BinaryOperator::CreateAdd(II->getOperand(0), II->getOperand(1),
|
|
|
|
II->getName(), II);
|
|
|
|
break;
|
2017-12-06 02:14:24 +08:00
|
|
|
case Intrinsic::usub_with_overflow:
|
|
|
|
case Intrinsic::ssub_with_overflow:
|
|
|
|
NewOp = BinaryOperator::CreateSub(II->getOperand(0), II->getOperand(1),
|
|
|
|
II->getName(), II);
|
|
|
|
break;
|
2017-11-11 03:13:35 +08:00
|
|
|
}
|
|
|
|
++NumOverflows;
|
|
|
|
IRBuilder<> B(II);
|
|
|
|
Value *NewI = B.CreateInsertValue(UndefValue::get(II->getType()), NewOp, 0);
|
|
|
|
NewI = B.CreateInsertValue(NewI, ConstantInt::getFalse(II->getContext()), 1);
|
|
|
|
II->replaceAllUsesWith(NewI);
|
|
|
|
II->eraseFromParent();
|
|
|
|
}
|
|
|
|
|
2016-07-02 00:41:59 +08:00
|
|
|
/// Infer nonnull attributes for the arguments at the specified callsite.
|
2016-05-26 01:39:54 +08:00
|
|
|
static bool processCallSite(CallSite CS, LazyValueInfo *LVI) {
|
2017-06-01 03:23:09 +08:00
|
|
|
SmallVector<unsigned, 4> ArgNos;
|
2015-09-16 01:51:50 +08:00
|
|
|
unsigned ArgNo = 0;
|
2015-12-02 14:58:49 +08:00
|
|
|
|
2017-12-06 02:14:24 +08:00
|
|
|
if (auto *II = dyn_cast<IntrinsicInst>(CS.getInstruction())) {
|
2017-11-11 03:13:35 +08:00
|
|
|
if (willNotOverflow(II, LVI)) {
|
|
|
|
processOverflowIntrinsic(II);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-16 01:51:50 +08:00
|
|
|
for (Value *V : CS.args()) {
|
|
|
|
PointerType *Type = dyn_cast<PointerType>(V->getType());
|
2016-02-11 06:22:41 +08:00
|
|
|
// Try to mark pointer typed parameters as non-null. We skip the
|
|
|
|
// relatively expensive analysis for constants which are obviously either
|
|
|
|
// null or non-null to start with.
|
2017-04-15 04:19:02 +08:00
|
|
|
if (Type && !CS.paramHasAttr(ArgNo, Attribute::NonNull) &&
|
2016-02-11 06:22:41 +08:00
|
|
|
!isa<Constant>(V) &&
|
2015-09-16 01:51:50 +08:00
|
|
|
LVI->getPredicateAt(ICmpInst::ICMP_EQ, V,
|
|
|
|
ConstantPointerNull::get(Type),
|
2015-12-02 14:58:49 +08:00
|
|
|
CS.getInstruction()) == LazyValueInfo::False)
|
2017-06-01 03:23:09 +08:00
|
|
|
ArgNos.push_back(ArgNo);
|
2015-09-16 01:51:50 +08:00
|
|
|
ArgNo++;
|
|
|
|
}
|
2015-12-02 14:58:49 +08:00
|
|
|
|
2015-09-16 01:51:50 +08:00
|
|
|
assert(ArgNo == CS.arg_size() && "sanity check");
|
|
|
|
|
2017-06-01 03:23:09 +08:00
|
|
|
if (ArgNos.empty())
|
2015-12-02 14:58:49 +08:00
|
|
|
return false;
|
|
|
|
|
Rename AttributeSet to AttributeList
Summary:
This class is a list of AttributeSetNodes corresponding the function
prototype of a call or function declaration. This class used to be
called ParamAttrListPtr, then AttrListPtr, then AttributeSet. It is
typically accessed by parameter and return value index, so
"AttributeList" seems like a more intuitive name.
Rename AttributeSetImpl to AttributeListImpl to follow suit.
It's useful to rename this class so that we can rename AttributeSetNode
to AttributeSet later. AttributeSet is the set of attributes that apply
to a single function, argument, or return value.
Reviewers: sanjoy, javed.absar, chandlerc, pete
Reviewed By: pete
Subscribers: pete, jholewinski, arsenm, dschuff, mehdi_amini, jfb, nhaehnle, sbc100, void, llvm-commits
Differential Revision: https://reviews.llvm.org/D31102
llvm-svn: 298393
2017-03-22 00:57:19 +08:00
|
|
|
AttributeList AS = CS.getAttributes();
|
2015-12-02 14:58:49 +08:00
|
|
|
LLVMContext &Ctx = CS.getInstruction()->getContext();
|
2017-06-01 03:23:09 +08:00
|
|
|
AS = AS.addParamAttribute(Ctx, ArgNos,
|
|
|
|
Attribute::get(Ctx, Attribute::NonNull));
|
2015-12-02 14:58:49 +08:00
|
|
|
CS.setAttributes(AS);
|
|
|
|
|
|
|
|
return true;
|
2015-09-16 01:51:50 +08:00
|
|
|
}
|
|
|
|
|
2016-07-14 20:23:48 +08:00
|
|
|
static bool hasPositiveOperands(BinaryOperator *SDI, LazyValueInfo *LVI) {
|
2016-03-14 11:24:28 +08:00
|
|
|
Constant *Zero = ConstantInt::get(SDI->getType(), 0);
|
|
|
|
for (Value *O : SDI->operands()) {
|
2016-07-14 20:23:48 +08:00
|
|
|
auto Result = LVI->getPredicateAt(ICmpInst::ICMP_SGE, O, Zero, SDI);
|
2016-03-14 11:24:28 +08:00
|
|
|
if (Result != LazyValueInfo::True)
|
|
|
|
return false;
|
|
|
|
}
|
2016-07-14 20:23:48 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool processSRem(BinaryOperator *SDI, LazyValueInfo *LVI) {
|
2017-10-13 06:39:52 +08:00
|
|
|
if (SDI->getType()->isVectorTy() ||
|
2016-07-14 20:23:48 +08:00
|
|
|
!hasPositiveOperands(SDI, LVI))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
++NumSRems;
|
|
|
|
auto *BO = BinaryOperator::CreateURem(SDI->getOperand(0), SDI->getOperand(1),
|
|
|
|
SDI->getName(), SDI);
|
|
|
|
SDI->replaceAllUsesWith(BO);
|
|
|
|
SDI->eraseFromParent();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// See if LazyValueInfo's ability to exploit edge conditions or range
|
|
|
|
/// information is sufficient to prove the both operands of this SDiv are
|
|
|
|
/// positive. If this is the case, replace the SDiv with a UDiv. Even for local
|
|
|
|
/// conditions, this can sometimes prove conditions instcombine can't by
|
|
|
|
/// exploiting range information.
|
|
|
|
static bool processSDiv(BinaryOperator *SDI, LazyValueInfo *LVI) {
|
2017-10-13 06:39:52 +08:00
|
|
|
if (SDI->getType()->isVectorTy() ||
|
2016-07-14 20:23:48 +08:00
|
|
|
!hasPositiveOperands(SDI, LVI))
|
|
|
|
return false;
|
2016-03-14 11:24:28 +08:00
|
|
|
|
|
|
|
++NumSDivs;
|
|
|
|
auto *BO = BinaryOperator::CreateUDiv(SDI->getOperand(0), SDI->getOperand(1),
|
|
|
|
SDI->getName(), SDI);
|
|
|
|
BO->setIsExact(SDI->isExact());
|
|
|
|
SDI->replaceAllUsesWith(BO);
|
|
|
|
SDI->eraseFromParent();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-10-12 21:41:38 +08:00
|
|
|
static bool processAShr(BinaryOperator *SDI, LazyValueInfo *LVI) {
|
2017-10-13 06:39:52 +08:00
|
|
|
if (SDI->getType()->isVectorTy())
|
2016-10-12 21:41:38 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
Constant *Zero = ConstantInt::get(SDI->getType(), 0);
|
|
|
|
if (LVI->getPredicateAt(ICmpInst::ICMP_SGE, SDI->getOperand(0), Zero, SDI) !=
|
|
|
|
LazyValueInfo::True)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
++NumAShrs;
|
|
|
|
auto *BO = BinaryOperator::CreateLShr(SDI->getOperand(0), SDI->getOperand(1),
|
|
|
|
SDI->getName(), SDI);
|
|
|
|
BO->setIsExact(SDI->isExact());
|
|
|
|
SDI->replaceAllUsesWith(BO);
|
|
|
|
SDI->eraseFromParent();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-08-10 21:08:34 +08:00
|
|
|
static bool processAdd(BinaryOperator *AddOp, LazyValueInfo *LVI) {
|
2017-10-14 05:17:07 +08:00
|
|
|
using OBO = OverflowingBinaryOperator;
|
2016-08-10 21:08:34 +08:00
|
|
|
|
2017-02-24 06:29:00 +08:00
|
|
|
if (DontProcessAdds)
|
|
|
|
return false;
|
|
|
|
|
2017-10-13 06:39:52 +08:00
|
|
|
if (AddOp->getType()->isVectorTy())
|
2016-08-10 21:08:34 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
bool NSW = AddOp->hasNoSignedWrap();
|
|
|
|
bool NUW = AddOp->hasNoUnsignedWrap();
|
|
|
|
if (NSW && NUW)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
BasicBlock *BB = AddOp->getParent();
|
|
|
|
|
|
|
|
Value *LHS = AddOp->getOperand(0);
|
|
|
|
Value *RHS = AddOp->getOperand(1);
|
|
|
|
|
|
|
|
ConstantRange LRange = LVI->getConstantRange(LHS, BB, AddOp);
|
|
|
|
|
|
|
|
// Initialize RRange only if we need it. If we know that guaranteed no wrap
|
|
|
|
// range for the given LHS range is empty don't spend time calculating the
|
|
|
|
// range for the RHS.
|
|
|
|
Optional<ConstantRange> RRange;
|
|
|
|
auto LazyRRange = [&] () {
|
|
|
|
if (!RRange)
|
|
|
|
RRange = LVI->getConstantRange(RHS, BB, AddOp);
|
|
|
|
return RRange.getValue();
|
|
|
|
};
|
|
|
|
|
|
|
|
bool Changed = false;
|
|
|
|
if (!NUW) {
|
2017-05-16 15:05:38 +08:00
|
|
|
ConstantRange NUWRange = ConstantRange::makeGuaranteedNoWrapRegion(
|
|
|
|
BinaryOperator::Add, LRange, OBO::NoUnsignedWrap);
|
2016-08-10 21:08:34 +08:00
|
|
|
if (!NUWRange.isEmptySet()) {
|
|
|
|
bool NewNUW = NUWRange.contains(LazyRRange());
|
|
|
|
AddOp->setHasNoUnsignedWrap(NewNUW);
|
|
|
|
Changed |= NewNUW;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!NSW) {
|
2017-05-16 15:05:38 +08:00
|
|
|
ConstantRange NSWRange = ConstantRange::makeGuaranteedNoWrapRegion(
|
|
|
|
BinaryOperator::Add, LRange, OBO::NoSignedWrap);
|
2016-08-10 21:08:34 +08:00
|
|
|
if (!NSWRange.isEmptySet()) {
|
|
|
|
bool NewNSW = NSWRange.contains(LazyRRange());
|
|
|
|
AddOp->setHasNoSignedWrap(NewNSW);
|
|
|
|
Changed |= NewNSW;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Changed;
|
|
|
|
}
|
|
|
|
|
2016-05-26 01:39:54 +08:00
|
|
|
static Constant *getConstantAt(Value *V, Instruction *At, LazyValueInfo *LVI) {
|
2015-11-04 09:43:54 +08:00
|
|
|
if (Constant *C = LVI->getConstant(V, At->getParent(), At))
|
|
|
|
return C;
|
|
|
|
|
|
|
|
// TODO: The following really should be sunk inside LVI's core algorithm, or
|
|
|
|
// at least the outer shims around such.
|
|
|
|
auto *C = dyn_cast<CmpInst>(V);
|
|
|
|
if (!C) return nullptr;
|
|
|
|
|
|
|
|
Value *Op0 = C->getOperand(0);
|
|
|
|
Constant *Op1 = dyn_cast<Constant>(C->getOperand(1));
|
|
|
|
if (!Op1) return nullptr;
|
|
|
|
|
|
|
|
LazyValueInfo::Tristate Result =
|
|
|
|
LVI->getPredicateAt(C->getPredicate(), Op0, Op1, At);
|
|
|
|
if (Result == LazyValueInfo::Unknown)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
return (Result == LazyValueInfo::True) ?
|
|
|
|
ConstantInt::getTrue(C->getContext()) :
|
|
|
|
ConstantInt::getFalse(C->getContext());
|
|
|
|
}
|
|
|
|
|
2017-04-27 01:41:46 +08:00
|
|
|
static bool runImpl(Function &F, LazyValueInfo *LVI, const SimplifyQuery &SQ) {
|
2010-09-01 02:55:52 +08:00
|
|
|
bool FnChanged = false;
|
2017-02-08 10:48:25 +08:00
|
|
|
// Visiting in a pre-order depth-first traversal causes us to simplify early
|
|
|
|
// blocks before querying later blocks (which require us to analyze early
|
|
|
|
// blocks). Eagerly simplifying shallow blocks means there is strictly less
|
|
|
|
// work to do for deep blocks. This also means we don't visit unreachable
|
2017-12-06 01:59:07 +08:00
|
|
|
// blocks.
|
2017-02-08 10:48:25 +08:00
|
|
|
for (BasicBlock *BB : depth_first(&F.getEntryBlock())) {
|
2010-09-01 02:55:52 +08:00
|
|
|
bool BBChanged = false;
|
2016-12-31 02:00:55 +08:00
|
|
|
for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) {
|
2015-10-14 02:26:00 +08:00
|
|
|
Instruction *II = &*BI++;
|
2010-09-04 03:08:37 +08:00
|
|
|
switch (II->getOpcode()) {
|
|
|
|
case Instruction::Select:
|
2016-05-26 01:39:54 +08:00
|
|
|
BBChanged |= processSelect(cast<SelectInst>(II), LVI);
|
2010-09-04 03:08:37 +08:00
|
|
|
break;
|
|
|
|
case Instruction::PHI:
|
2018-01-29 13:59:55 +08:00
|
|
|
BBChanged |= processPHI(cast<PHINode>(II), LVI, SQ);
|
2010-09-04 03:08:37 +08:00
|
|
|
break;
|
2010-09-04 06:47:08 +08:00
|
|
|
case Instruction::ICmp:
|
|
|
|
case Instruction::FCmp:
|
2016-05-26 01:39:54 +08:00
|
|
|
BBChanged |= processCmp(cast<CmpInst>(II), LVI);
|
2010-09-04 06:47:08 +08:00
|
|
|
break;
|
2010-09-04 03:08:37 +08:00
|
|
|
case Instruction::Load:
|
|
|
|
case Instruction::Store:
|
2016-05-26 01:39:54 +08:00
|
|
|
BBChanged |= processMemAccess(II, LVI);
|
2010-09-04 03:08:37 +08:00
|
|
|
break;
|
2015-09-16 01:51:50 +08:00
|
|
|
case Instruction::Call:
|
|
|
|
case Instruction::Invoke:
|
2016-05-26 01:39:54 +08:00
|
|
|
BBChanged |= processCallSite(CallSite(II), LVI);
|
2015-09-16 01:51:50 +08:00
|
|
|
break;
|
2016-07-14 20:23:48 +08:00
|
|
|
case Instruction::SRem:
|
|
|
|
BBChanged |= processSRem(cast<BinaryOperator>(II), LVI);
|
|
|
|
break;
|
2016-03-14 11:24:28 +08:00
|
|
|
case Instruction::SDiv:
|
2016-05-26 01:39:54 +08:00
|
|
|
BBChanged |= processSDiv(cast<BinaryOperator>(II), LVI);
|
2016-03-14 11:24:28 +08:00
|
|
|
break;
|
2016-10-12 21:41:38 +08:00
|
|
|
case Instruction::AShr:
|
|
|
|
BBChanged |= processAShr(cast<BinaryOperator>(II), LVI);
|
|
|
|
break;
|
2016-08-10 21:08:34 +08:00
|
|
|
case Instruction::Add:
|
|
|
|
BBChanged |= processAdd(cast<BinaryOperator>(II), LVI);
|
|
|
|
break;
|
2010-09-04 03:08:37 +08:00
|
|
|
}
|
2010-08-28 07:31:36 +08:00
|
|
|
}
|
2010-12-15 08:52:44 +08:00
|
|
|
|
2016-12-31 02:00:55 +08:00
|
|
|
Instruction *Term = BB->getTerminator();
|
2012-03-09 21:45:18 +08:00
|
|
|
switch (Term->getOpcode()) {
|
|
|
|
case Instruction::Switch:
|
2016-05-26 01:39:54 +08:00
|
|
|
BBChanged |= processSwitch(cast<SwitchInst>(Term), LVI);
|
2012-03-09 21:45:18 +08:00
|
|
|
break;
|
2015-11-04 09:43:54 +08:00
|
|
|
case Instruction::Ret: {
|
|
|
|
auto *RI = cast<ReturnInst>(Term);
|
|
|
|
// Try to determine the return value if we can. This is mainly here to
|
|
|
|
// simplify the writing of unit tests, but also helps to enable IPO by
|
|
|
|
// constant folding the return values of callees.
|
|
|
|
auto *RetVal = RI->getReturnValue();
|
|
|
|
if (!RetVal) break; // handle "ret void"
|
|
|
|
if (isa<Constant>(RetVal)) break; // nothing to do
|
2016-05-26 01:39:54 +08:00
|
|
|
if (auto *C = getConstantAt(RetVal, RI, LVI)) {
|
2015-11-04 09:43:54 +08:00
|
|
|
++NumReturns;
|
|
|
|
RI->replaceUsesOfWith(RetVal, C);
|
|
|
|
BBChanged = true;
|
|
|
|
}
|
2012-03-09 21:45:18 +08:00
|
|
|
}
|
2017-06-16 09:53:20 +08:00
|
|
|
}
|
2012-03-09 21:45:18 +08:00
|
|
|
|
2010-09-01 02:55:52 +08:00
|
|
|
FnChanged |= BBChanged;
|
2010-08-31 15:55:56 +08:00
|
|
|
}
|
2010-12-15 08:52:44 +08:00
|
|
|
|
2010-09-01 02:55:52 +08:00
|
|
|
return FnChanged;
|
2010-08-28 08:11:12 +08:00
|
|
|
}
|
2016-07-07 07:26:29 +08:00
|
|
|
|
|
|
|
bool CorrelatedValuePropagation::runOnFunction(Function &F) {
|
|
|
|
if (skipFunction(F))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
LazyValueInfo *LVI = &getAnalysis<LazyValueInfoWrapperPass>().getLVI();
|
2017-04-29 03:55:38 +08:00
|
|
|
return runImpl(F, LVI, getBestSimplifyQuery(*this, F));
|
2016-07-07 07:26:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
PreservedAnalyses
|
|
|
|
CorrelatedValuePropagationPass::run(Function &F, FunctionAnalysisManager &AM) {
|
|
|
|
|
|
|
|
LazyValueInfo *LVI = &AM.getResult<LazyValueAnalysis>(F);
|
2017-04-29 03:55:38 +08:00
|
|
|
bool Changed = runImpl(F, LVI, getBestSimplifyQuery(AM, F));
|
2016-07-07 07:26:29 +08:00
|
|
|
|
|
|
|
if (!Changed)
|
|
|
|
return PreservedAnalyses::all();
|
|
|
|
PreservedAnalyses PA;
|
|
|
|
PA.preserve<GlobalsAA>();
|
|
|
|
return PA;
|
|
|
|
}
|