llvm.org GIT mirror llvm / e6cc3ad
[IPSCCP] Use PredicateInfo to propagate facts from cmp instructions. This patch updates IPSCCP to use PredicateInfo to propagate facts to true branches predicated by EQ and to false branches predicated by NE. As a follow up, we should be able to extend it to also propagate additional facts about nonnull. Reviewers: davide, mssimpso, dberlin, efriedma Reviewed By: davide, dberlin Differential Revision: https://reviews.llvm.org/D45330 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@333268 91177308-0d34-0410-b5e6-96231b3b80d8 Florian Hahn 1 year, 3 months ago
9 changed file(s) with 223 addition(s) and 15 deletion(s). Raw diff Collapse all Expand all
2020 #ifndef LLVM_TRANSFORMS_SCALAR_SCCP_H
2121 #define LLVM_TRANSFORMS_SCALAR_SCCP_H
2222
23 #include "llvm/ADT/STLExtras.h"
2324 #include "llvm/Analysis/TargetLibraryInfo.h"
2425 #include "llvm/IR/DataLayout.h"
2526 #include "llvm/IR/Function.h"
2627 #include "llvm/IR/Module.h"
2728 #include "llvm/IR/PassManager.h"
29 #include "llvm/Transforms/Utils/PredicateInfo.h"
2830
2931 namespace llvm {
3032
3638 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
3739 };
3840
39 bool runIPSCCP(Module &M, const DataLayout &DL, const TargetLibraryInfo *TLI);
41 bool runIPSCCP(
42 Module &M, const DataLayout &DL, const TargetLibraryInfo *TLI,
43 function_ref(Function &)> getPredicateInfo);
4044 } // end namespace llvm
4145
4246 #endif // LLVM_TRANSFORMS_SCALAR_SCCP_H
0 #include "llvm/Transforms/IPO/SCCP.h"
1 #include "llvm/Analysis/AssumptionCache.h"
12 #include "llvm/Analysis/TargetLibraryInfo.h"
23 #include "llvm/Transforms/IPO.h"
34 #include "llvm/Transforms/Scalar/SCCP.h"
78 PreservedAnalyses IPSCCPPass::run(Module &M, ModuleAnalysisManager &AM) {
89 const DataLayout &DL = M.getDataLayout();
910 auto &TLI = AM.getResult(M);
10 if (!runIPSCCP(M, DL, &TLI))
11 auto &FAM = AM.getResult(M).getManager();
12 auto getPredicateInfo =
13 [&FAM](Function &F) -> std::unique_ptr {
14 return make_unique(F,
15 FAM.getResult(F),
16 FAM.getResult(F));
17 };
18
19 if (!runIPSCCP(M, DL, &TLI, getPredicateInfo))
1120 return PreservedAnalyses::all();
1221 return PreservedAnalyses::none();
1322 }
3342 const DataLayout &DL = M.getDataLayout();
3443 const TargetLibraryInfo *TLI =
3544 &getAnalysis().getTLI();
36 return runIPSCCP(M, DL, TLI);
45
46 auto getPredicateInfo =
47 [this](Function &F) -> std::unique_ptr {
48 return make_unique(
49 F, this->getAnalysis(F).getDomTree(),
50 this->getAnalysis().getAssumptionCache(F));
51 };
52
53 return runIPSCCP(M, DL, TLI, getPredicateInfo);
3754 }
3855
3956 void getAnalysisUsage(AnalysisUsage &AU) const override {
57 AU.addRequired();
58 AU.addRequired();
4059 AU.addRequired();
4160 }
4261 };
4867 INITIALIZE_PASS_BEGIN(IPSCCPLegacyPass, "ipsccp",
4968 "Interprocedural Sparse Conditional Constant Propagation",
5069 false, false)
70 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
5171 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
5272 INITIALIZE_PASS_END(IPSCCPLegacyPass, "ipsccp",
5373 "Interprocedural Sparse Conditional Constant Propagation",
5454 #include "llvm/Support/ErrorHandling.h"
5555 #include "llvm/Support/raw_ostream.h"
5656 #include "llvm/Transforms/Scalar.h"
57 #include "llvm/Transforms/Utils/PredicateInfo.h"
5758 #include
5859 #include
5960 #include
247248 using Edge = std::pair;
248249 DenseSet KnownFeasibleEdges;
249250
251 DenseMap> PredInfos;
252 DenseMap> AdditionalUsers;
253
250254 public:
255 void addPredInfo(Function &F, std::unique_ptr PI) {
256 PredInfos[&F] = std::move(PI);
257 }
258
259 const PredicateBase *getPredicateInfoFor(Instruction *I) {
260 auto PI = PredInfos.find(I->getParent()->getParent());
261 if (PI == PredInfos.end())
262 return nullptr;
263 return PI->second->getPredicateInfoFor(I);
264 }
265
251266 SCCPSolver(const DataLayout &DL, const TargetLibraryInfo *tli)
252267 : DL(DL), TLI(tli) {}
253268
560575 void OperandChangedState(Instruction *I) {
561576 if (BBExecutable.count(I->getParent())) // Inst is executable?
562577 visit(*I);
578 }
579
580 // Add U as additional user of V.
581 void addAdditionalUser(Value *V, User *U) {
582 auto Iter = AdditionalUsers.insert({V, {}});
583 Iter.first->second.insert(U);
584 }
585
586 // Mark I's users as changed, including AdditionalUsers.
587 void markUsersAsChanged(Value *I) {
588 for (User *U : I->users())
589 if (auto *UI = dyn_cast(U))
590 OperandChangedState(UI);
591
592 auto Iter = AdditionalUsers.find(I);
593 if (Iter != AdditionalUsers.end()) {
594 for (User *U : Iter->second)
595 if (auto *UI = dyn_cast(U))
596 OperandChangedState(UI);
597 }
563598 }
564599
565600 private:
11561191 Function *F = CS.getCalledFunction();
11571192 Instruction *I = CS.getInstruction();
11581193
1194 if (auto *II = dyn_cast(I)) {
1195 if (II->getIntrinsicID() == Intrinsic::ssa_copy) {
1196 if (ValueState[I].isOverdefined())
1197 return;
1198
1199 auto *PI = getPredicateInfoFor(I);
1200 if (!PI)
1201 return;
1202
1203 auto *PBranch = dyn_cast(getPredicateInfoFor(I));
1204 if (!PBranch)
1205 return mergeInValue(ValueState[I], I, getValueState(PI->OriginalOp));
1206
1207 Value *CopyOf = I->getOperand(0);
1208 Value *Cond = PBranch->Condition;
1209
1210 // Everything below relies on the condition being a comparison.
1211 auto *Cmp = dyn_cast(Cond);
1212 if (!Cmp)
1213 return mergeInValue(ValueState[I], I, getValueState(PI->OriginalOp));
1214
1215 Value *CmpOp0 = Cmp->getOperand(0);
1216 Value *CmpOp1 = Cmp->getOperand(1);
1217 if (CopyOf != CmpOp0 && CopyOf != CmpOp1)
1218 return mergeInValue(ValueState[I], I, getValueState(PI->OriginalOp));
1219
1220 if (CmpOp0 != CopyOf)
1221 std::swap(CmpOp0, CmpOp1);
1222
1223 LatticeVal OriginalVal = getValueState(CopyOf);
1224 LatticeVal EqVal = getValueState(CmpOp1);
1225 LatticeVal &IV = ValueState[I];
1226 if (PBranch->TrueEdge && Cmp->getPredicate() == CmpInst::ICMP_EQ) {
1227 addAdditionalUser(CmpOp1, I);
1228 if (OriginalVal.isConstant())
1229 mergeInValue(IV, I, OriginalVal);
1230 else
1231 mergeInValue(IV, I, EqVal);
1232 return;
1233 }
1234 if (!PBranch->TrueEdge && Cmp->getPredicate() == CmpInst::ICMP_NE) {
1235 addAdditionalUser(CmpOp1, I);
1236 if (OriginalVal.isConstant())
1237 mergeInValue(IV, I, OriginalVal);
1238 else
1239 mergeInValue(IV, I, EqVal);
1240 return;
1241 }
1242
1243 return mergeInValue(IV, I, getValueState(PBranch->OriginalOp));
1244 }
1245 }
1246
11591247 // The common case is that we aren't tracking the callee, either because we
11601248 // are not doing interprocedural analysis or the callee is indirect, or is
11611249 // external. Handle these cases first.
12671355 // since all of its users will have already been marked as overdefined
12681356 // Update all of the users of this instruction's value.
12691357 //
1270 for (User *U : I->users())
1271 if (auto *UI = dyn_cast(U))
1272 OperandChangedState(UI);
1358 markUsersAsChanged(I);
12731359 }
12741360
12751361 // Process the instruction work list.
12861372 // Update all of the users of this instruction's value.
12871373 //
12881374 if (I->getType()->isStructTy() || !getValueState(I).isOverdefined())
1289 for (User *U : I->users())
1290 if (auto *UI = dyn_cast(U))
1291 OperandChangedState(UI);
1375 markUsersAsChanged(I);
12921376 }
12931377
12941378 // Process the basic block work list.
18541938 }
18551939 }
18561940
1857 bool llvm::runIPSCCP(Module &M, const DataLayout &DL,
1858 const TargetLibraryInfo *TLI) {
1941 bool llvm::runIPSCCP(
1942 Module &M, const DataLayout &DL, const TargetLibraryInfo *TLI,
1943 function_ref(Function &)> getPredicateInfo) {
18591944 SCCPSolver Solver(DL, TLI);
18601945
18611946 // Loop over all functions, marking arguments to those with their addresses
18641949 if (F.isDeclaration())
18651950 continue;
18661951
1952 Solver.addPredInfo(F, getPredicateInfo(F));
18671953 // Determine if we can track the function's return values. If so, add the
18681954 // function to the solver's set of return-tracked functions.
18691955 if (canTrackReturnsInterprocedurally(&F))
19822068 F.getBasicBlockList().erase(DeadBB);
19832069 }
19842070 BlocksToErase.clear();
2071
2072 for (BasicBlock &BB : F) {
2073 for (BasicBlock::iterator BI = BB.begin(), E = BB.end(); BI != E;) {
2074 Instruction *Inst = &*BI++;
2075 if (const PredicateBase *PI = Solver.getPredicateInfoFor(Inst)) {
2076 if (auto *II = dyn_cast(Inst)) {
2077 if (II->getIntrinsicID() == Intrinsic::ssa_copy) {
2078 Value *Op = II->getOperand(0);
2079 Inst->replaceAllUsesWith(Op);
2080 Inst->eraseFromParent();
2081 continue;
2082 }
2083 }
2084 Inst->replaceAllUsesWith(PI->OriginalOp);
2085 Inst->eraseFromParent();
2086 }
2087 }
2088 }
19852089 }
19862090
19872091 // If we inferred constant or undef return values for a function, we replaced
4040 ; CHECK-O2-NEXT: Running analysis: ProfileSummaryAnalysis
4141 ; CHECK-O2-NEXT: Running analysis: OptimizationRemarkEmitterAnalysis
4242 ; CHECK-O2-NEXT: Running pass: IPSCCPPass
43 ; CHECK-O2-DAG: Running analysis: AssumptionAnalysis on foo
44 ; CHECK-O2-DAG: Running analysis: DominatorTreeAnalysis on foo
4345 ; CHECK-O2-NEXT: Running pass: CalledValuePropagationPass
4446 ; CHECK-O-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor<{{.*}}PostOrderFunctionAttrsPass>
4547 ; CHECK-O-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}SCC
5557 ; CHECK-O-NEXT: Running pass: WholeProgramDevirtPass
5658 ; CHECK-O2-NEXT: Running pass: GlobalOptPass
5759 ; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PromotePass>
58 ; CHECK-O2-NEXT: Running analysis: DominatorTreeAnalysis
59 ; CHECK-O2-NEXT: Running analysis: AssumptionAnalysis
6060 ; CHECK-O2-NEXT: Running pass: ConstantMergePass
6161 ; CHECK-O2-NEXT: Running pass: DeadArgumentEliminationPass
6262 ; CHECK-O2-NEXT: Running pass: ModuleToFunctionPassAdaptor<{{.*}}PassManager{{.*}}>
2727 ; CHECK-NEXT: Force set function attributes
2828 ; CHECK-NEXT: Infer set function attributes
2929 ; CHECK-NEXT: Interprocedural Sparse Conditional Constant Propagation
30 ; CHECK-NEXT: Unnamed pass: implement Pass::getPassName()
3031 ; CHECK-NEXT: Called Value Propagation
3132 ; CHECK-NEXT: Global Variable Optimizer
3233 ; CHECK-NEXT: Unnamed pass: implement Pass::getPassName()
275276 ; CHECK-NEXT: Module Verifier
276277 ; CHECK-NEXT: Bitcode Writer
277278 ; CHECK-NEXT: Pass Arguments:
279 ; CHECK-NEXT: FunctionPass Manager
280 ; CHECK-NEXT: Dominator Tree Construction
281 ; CHECK-NEXT: Pass Arguments:
278282 ; CHECK-NEXT: Target Library Information
279283 ; CHECK-NEXT: FunctionPass Manager
280284 ; CHECK-NEXT: Dominator Tree Construction
2929 ; CHECK-NEXT: FunctionPass Manager
3030 ; CHECK-NEXT: Call-site splitting
3131 ; CHECK-NEXT: Interprocedural Sparse Conditional Constant Propagation
32 ; CHECK-NEXT: Unnamed pass: implement Pass::getPassName()
3233 ; CHECK-NEXT: Called Value Propagation
3334 ; CHECK-NEXT: Global Variable Optimizer
3435 ; CHECK-NEXT: Unnamed pass: implement Pass::getPassName()
278279 ; CHECK-NEXT: Simplify the CFG
279280 ; CHECK-NEXT: Module Verifier
280281 ; CHECK-NEXT: Bitcode Writer
282 ; CHECK-NEXT: Pass Arguments:
283 ; CHECK-NEXT: FunctionPass Manager
284 ; CHECK-NEXT: Dominator Tree Construction
281285 ; CHECK-NEXT: Pass Arguments:
282286 ; CHECK-NEXT: Target Library Information
283287 ; CHECK-NEXT: FunctionPass Manager
2727 ; CHECK-NEXT: Force set function attributes
2828 ; CHECK-NEXT: Infer set function attributes
2929 ; CHECK-NEXT: Interprocedural Sparse Conditional Constant Propagation
30 ; CHECK-NEXT: Unnamed pass: implement Pass::getPassName()
3031 ; CHECK-NEXT: Called Value Propagation
3132 ; CHECK-NEXT: Global Variable Optimizer
3233 ; CHECK-NEXT: Unnamed pass: implement Pass::getPassName()
261262 ; CHECK-NEXT: Module Verifier
262263 ; CHECK-NEXT: Bitcode Writer
263264 ; CHECK-NEXT: Pass Arguments:
265 ; CHECK-NEXT: FunctionPass Manager
266 ; CHECK-NEXT: Dominator Tree Construction
267 ; CHECK-NEXT: Pass Arguments:
264268 ; CHECK-NEXT: Target Library Information
265269 ; CHECK-NEXT: FunctionPass Manager
266270 ; CHECK-NEXT: Dominator Tree Construction
88 %c1 = icmp eq i8 %v, 0
99 br i1 %c1, label %true, label %false
1010 true:
11 ; CHECK: %ca = musttail call i8* @side_effects(i8 %v)
11 ; CHECK: %ca = musttail call i8* @side_effects(i8 0)
1212 ; CHECK: ret i8* %ca
1313 %ca = musttail call i8* @side_effects(i8 %v)
1414 ret i8* %ca
3333 ; is always `null`.
3434 ; The call can't be removed due to `external` call above, though.
3535
36 ; CHECK: %ca = musttail call i8* @start(i8 %v)
36 ; CHECK: %ca = musttail call i8* @start(i8 0)
3737 %ca = musttail call i8* @start(i8 %v)
3838
3939 ; Thus the result must be returned anyway
0 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; RUN: opt < %s -ipsccp -S | FileCheck %s
2
3 define i32 @test1(i32 %v) {
4 ; CHECK-LABEL: @test1(
5 ; CHECK-NEXT: Entry:
6 ; CHECK-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[V:%.*]], 10
7 ; CHECK-NEXT: br i1 [[TOBOOL1]], label [[T:%.*]], label [[F:%.*]]
8 ; CHECK: T:
9 ; CHECK-NEXT: [[R:%.*]] = call i32 @callee(i32 20)
10 ; CHECK-NEXT: ret i32 [[R]]
11 ; CHECK: F:
12 ; CHECK-NEXT: [[X:%.*]] = call i32 @callee(i32 [[V]])
13 ; CHECK-NEXT: ret i32 [[X]]
14 ;
15 Entry:
16 %tobool1 = icmp eq i32 %v, 10
17 br i1 %tobool1, label %T, label %F
18
19 T:
20 %a = add i32 %v, 10
21 %r = call i32 @callee(i32 %a)
22 ret i32 %r
23
24 F:
25 %x = call i32 @callee(i32 %v)
26 ret i32 %x
27 }
28
29
30 define internal i32 @test2(i32 %v, i32 %c) {
31 ; CHECK-LABEL: @test2(
32 ; CHECK-NEXT: Entry:
33 ; CHECK-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[V:%.*]], 99
34 ; CHECK-NEXT: br i1 [[TOBOOL1]], label [[T:%.*]], label [[F:%.*]]
35 ; CHECK: T:
36 ; CHECK-NEXT: [[R:%.*]] = call i32 @callee(i32 109)
37 ; CHECK-NEXT: ret i32 [[R]]
38 ; CHECK: F:
39 ; CHECK-NEXT: [[X:%.*]] = call i32 @callee(i32 [[V]])
40 ; CHECK-NEXT: ret i32 [[X]]
41 ;
42 Entry:
43 %tobool1 = icmp eq i32 %v, %c
44 br i1 %tobool1, label %T, label %F
45
46 T:
47 %a = add i32 %v, 10
48 %r = call i32 @callee(i32 %a)
49 ret i32 %r
50
51 F:
52 %x = call i32 @callee(i32 %v)
53 ret i32 %x
54 }
55
56 define i32 @caller_test2(i32 %v) {
57 ; CHECK-LABEL: @caller_test2(
58 ; CHECK-NEXT: entry:
59 ; CHECK-NEXT: [[R:%.*]] = call i32 @test2(i32 [[V:%.*]], i32 99)
60 ; CHECK-NEXT: ret i32 [[R]]
61 ;
62 entry:
63 %r = call i32 @test2(i32 %v, i32 99)
64 ret i32 %r
65 }
66
67 declare i32 @callee(i32)