llvm.org GIT mirror llvm / 2cd65e1
Revert r333268: [IPSCCP] Use PredicateInfo to propagate facts from... Reverting this to see if this is causing the failures of the clang-with-thin-lto-ubuntu bot. [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@333323 91177308-0d34-0410-b5e6-96231b3b80d8 Florian Hahn 1 year, 3 months ago
9 changed file(s) with 15 addition(s) and 223 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"
2423 #include "llvm/Analysis/TargetLibraryInfo.h"
2524 #include "llvm/IR/DataLayout.h"
2625 #include "llvm/IR/Function.h"
2726 #include "llvm/IR/Module.h"
2827 #include "llvm/IR/PassManager.h"
29 #include "llvm/Transforms/Utils/PredicateInfo.h"
3028
3129 namespace llvm {
3230
3836 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
3937 };
4038
41 bool runIPSCCP(
42 Module &M, const DataLayout &DL, const TargetLibraryInfo *TLI,
43 function_ref(Function &)> getPredicateInfo);
39 bool runIPSCCP(Module &M, const DataLayout &DL, const TargetLibraryInfo *TLI);
4440 } // end namespace llvm
4541
4642 #endif // LLVM_TRANSFORMS_SCALAR_SCCP_H
0 #include "llvm/Transforms/IPO/SCCP.h"
1 #include "llvm/Analysis/AssumptionCache.h"
21 #include "llvm/Analysis/TargetLibraryInfo.h"
32 #include "llvm/Transforms/IPO.h"
43 #include "llvm/Transforms/Scalar/SCCP.h"
87 PreservedAnalyses IPSCCPPass::run(Module &M, ModuleAnalysisManager &AM) {
98 const DataLayout &DL = M.getDataLayout();
109 auto &TLI = AM.getResult(M);
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))
10 if (!runIPSCCP(M, DL, &TLI))
2011 return PreservedAnalyses::all();
2112 return PreservedAnalyses::none();
2213 }
4233 const DataLayout &DL = M.getDataLayout();
4334 const TargetLibraryInfo *TLI =
4435 &getAnalysis().getTLI();
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);
36 return runIPSCCP(M, DL, TLI);
5437 }
5538
5639 void getAnalysisUsage(AnalysisUsage &AU) const override {
57 AU.addRequired();
58 AU.addRequired();
5940 AU.addRequired();
6041 }
6142 };
6748 INITIALIZE_PASS_BEGIN(IPSCCPLegacyPass, "ipsccp",
6849 "Interprocedural Sparse Conditional Constant Propagation",
6950 false, false)
70 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
7151 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
7252 INITIALIZE_PASS_END(IPSCCPLegacyPass, "ipsccp",
7353 "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"
5857 #include
5958 #include
6059 #include
248247 using Edge = std::pair;
249248 DenseSet KnownFeasibleEdges;
250249
251 DenseMap> PredInfos;
252 DenseMap> AdditionalUsers;
253
254250 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
266251 SCCPSolver(const DataLayout &DL, const TargetLibraryInfo *tli)
267252 : DL(DL), TLI(tli) {}
268253
575560 void OperandChangedState(Instruction *I) {
576561 if (BBExecutable.count(I->getParent())) // Inst is executable?
577562 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 }
598563 }
599564
600565 private:
11911156 Function *F = CS.getCalledFunction();
11921157 Instruction *I = CS.getInstruction();
11931158
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
12471159 // The common case is that we aren't tracking the callee, either because we
12481160 // are not doing interprocedural analysis or the callee is indirect, or is
12491161 // external. Handle these cases first.
13551267 // since all of its users will have already been marked as overdefined
13561268 // Update all of the users of this instruction's value.
13571269 //
1358 markUsersAsChanged(I);
1270 for (User *U : I->users())
1271 if (auto *UI = dyn_cast(U))
1272 OperandChangedState(UI);
13591273 }
13601274
13611275 // Process the instruction work list.
13721286 // Update all of the users of this instruction's value.
13731287 //
13741288 if (I->getType()->isStructTy() || !getValueState(I).isOverdefined())
1375 markUsersAsChanged(I);
1289 for (User *U : I->users())
1290 if (auto *UI = dyn_cast(U))
1291 OperandChangedState(UI);
13761292 }
13771293
13781294 // Process the basic block work list.
19381854 }
19391855 }
19401856
1941 bool llvm::runIPSCCP(
1942 Module &M, const DataLayout &DL, const TargetLibraryInfo *TLI,
1943 function_ref(Function &)> getPredicateInfo) {
1857 bool llvm::runIPSCCP(Module &M, const DataLayout &DL,
1858 const TargetLibraryInfo *TLI) {
19441859 SCCPSolver Solver(DL, TLI);
19451860
19461861 // Loop over all functions, marking arguments to those with their addresses
19491864 if (F.isDeclaration())
19501865 continue;
19511866
1952 Solver.addPredInfo(F, getPredicateInfo(F));
19531867 // Determine if we can track the function's return values. If so, add the
19541868 // function to the solver's set of return-tracked functions.
19551869 if (canTrackReturnsInterprocedurally(&F))
20681982 F.getBasicBlockList().erase(DeadBB);
20691983 }
20701984 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 }
20891985 }
20901986
20911987 // 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
4543 ; CHECK-O2-NEXT: Running pass: CalledValuePropagationPass
4644 ; CHECK-O-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor<{{.*}}PostOrderFunctionAttrsPass>
4745 ; CHECK-O-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}SCC
5755 ; CHECK-O-NEXT: Running pass: WholeProgramDevirtPass
5856 ; CHECK-O2-NEXT: Running pass: GlobalOptPass
5957 ; 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()
3130 ; CHECK-NEXT: Called Value Propagation
3231 ; CHECK-NEXT: Global Variable Optimizer
3332 ; CHECK-NEXT: Unnamed pass: implement Pass::getPassName()
276275 ; CHECK-NEXT: Module Verifier
277276 ; CHECK-NEXT: Bitcode Writer
278277 ; CHECK-NEXT: Pass Arguments:
279 ; CHECK-NEXT: FunctionPass Manager
280 ; CHECK-NEXT: Dominator Tree Construction
281 ; CHECK-NEXT: Pass Arguments:
282278 ; CHECK-NEXT: Target Library Information
283279 ; CHECK-NEXT: FunctionPass Manager
284280 ; 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()
3332 ; CHECK-NEXT: Called Value Propagation
3433 ; CHECK-NEXT: Global Variable Optimizer
3534 ; CHECK-NEXT: Unnamed pass: implement Pass::getPassName()
280279 ; CHECK-NEXT: Module Verifier
281280 ; CHECK-NEXT: Bitcode Writer
282281 ; CHECK-NEXT: Pass Arguments:
283 ; CHECK-NEXT: FunctionPass Manager
284 ; CHECK-NEXT: Dominator Tree Construction
285 ; CHECK-NEXT: Pass Arguments:
286282 ; CHECK-NEXT: Target Library Information
287283 ; CHECK-NEXT: FunctionPass Manager
288284 ; CHECK-NEXT: Dominator Tree Construction
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()
3130 ; CHECK-NEXT: Called Value Propagation
3231 ; CHECK-NEXT: Global Variable Optimizer
3332 ; CHECK-NEXT: Unnamed pass: implement Pass::getPassName()
262261 ; CHECK-NEXT: Module Verifier
263262 ; CHECK-NEXT: Bitcode Writer
264263 ; CHECK-NEXT: Pass Arguments:
265 ; CHECK-NEXT: FunctionPass Manager
266 ; CHECK-NEXT: Dominator Tree Construction
267 ; CHECK-NEXT: Pass Arguments:
268264 ; CHECK-NEXT: Target Library Information
269265 ; CHECK-NEXT: FunctionPass Manager
270266 ; 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 0)
11 ; CHECK: %ca = musttail call i8* @side_effects(i8 %v)
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 0)
36 ; CHECK: %ca = musttail call i8* @start(i8 %v)
3737 %ca = musttail call i8* @start(i8 %v)
3838
3939 ; Thus the result must be returned anyway
+0
-68
test/Transforms/SCCP/ipsccp-predicated.ll less more
None ; 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)