llvm.org GIT mirror llvm / cb4031e
Recommit r333268: [IPSCCP] Use PredicateInfo to propagate facts from cmp instructions. r335150 should resolve the issues with the clang-with-thin-lto-ubuntu and clang-with-lto-ubuntu builders. Original message: 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@335206 91177308-0d34-0410-b5e6-96231b3b80d8 Florian Hahn 1 year, 2 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()
272273 ; CHECK-NEXT: Module Verifier
273274 ; CHECK-NEXT: Bitcode Writer
274275 ; CHECK-NEXT: Pass Arguments:
276 ; CHECK-NEXT: FunctionPass Manager
277 ; CHECK-NEXT: Dominator Tree Construction
278 ; CHECK-NEXT: Pass Arguments:
275279 ; CHECK-NEXT: Target Library Information
276280 ; CHECK-NEXT: FunctionPass Manager
277281 ; 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()
275276 ; CHECK-NEXT: Simplify the CFG
276277 ; CHECK-NEXT: Module Verifier
277278 ; CHECK-NEXT: Bitcode Writer
279 ; CHECK-NEXT: Pass Arguments:
280 ; CHECK-NEXT: FunctionPass Manager
281 ; CHECK-NEXT: Dominator Tree Construction
278282 ; CHECK-NEXT: Pass Arguments:
279283 ; CHECK-NEXT: Target Library Information
280284 ; 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()
258259 ; CHECK-NEXT: Module Verifier
259260 ; CHECK-NEXT: Bitcode Writer
260261 ; CHECK-NEXT: Pass Arguments:
262 ; CHECK-NEXT: FunctionPass Manager
263 ; CHECK-NEXT: Dominator Tree Construction
264 ; CHECK-NEXT: Pass Arguments:
261265 ; CHECK-NEXT: Target Library Information
262266 ; CHECK-NEXT: FunctionPass Manager
263267 ; 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)