llvm.org GIT mirror llvm / e5ae839
[LVI] Take guards into account Teach LVI to gather control dependant constraints from guards. Reviewed By: sanjoy Differential Revision: https://reviews.llvm.org/D23358 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@278518 91177308-0d34-0410-b5e6-96231b3b80d8 Artur Pilipenko 3 years ago
2 changed file(s) with 124 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
2525 #include "llvm/IR/Dominators.h"
2626 #include "llvm/IR/Instructions.h"
2727 #include "llvm/IR/IntrinsicInst.h"
28 #include "llvm/IR/Intrinsics.h"
2829 #include "llvm/IR/LLVMContext.h"
2930 #include "llvm/IR/PatternMatch.h"
3031 #include "llvm/IR/ValueHandle.h"
470471 BasicBlock *BB);
471472 bool solveBlockValueCast(LVILatticeVal &BBLV, Instruction *BBI,
472473 BasicBlock *BB);
473 void intersectAssumeBlockValueConstantRange(Value *Val, LVILatticeVal &BBLV,
474 Instruction *BBI);
474 void intersectAssumeOrGuardBlockValueConstantRange(Value *Val,
475 LVILatticeVal &BBLV,
476 Instruction *BBI);
475477
476478 void solve();
477479
863865
864866 // If we can determine a constraint on the value given conditions assumed by
865867 // the program, intersect those constraints with BBLV
866 void LazyValueInfoCache::intersectAssumeBlockValueConstantRange(Value *Val,
867 LVILatticeVal &BBLV,
868 Instruction *BBI) {
868 void LazyValueInfoCache::intersectAssumeOrGuardBlockValueConstantRange(
869 Value *Val, LVILatticeVal &BBLV, Instruction *BBI) {
869870 BBI = BBI ? BBI : dyn_cast(Val);
870871 if (!BBI)
871872 return;
878879 continue;
879880
880881 BBLV = intersect(BBLV, getValueFromCondition(Val, I->getArgOperand(0)));
882 }
883
884 // If guards are not used in the module, don't spend time looking for them
885 auto *GuardDecl = BBI->getModule()->getFunction(
886 Intrinsic::getName(Intrinsic::experimental_guard));
887 if (!GuardDecl || GuardDecl->use_empty())
888 return;
889
890 for (BasicBlock::iterator I = BBI->getIterator(),
891 E = BBI->getParent()->begin(); I != E; I--) {
892 Value *Cond = nullptr;
893 if (!match(&*I, m_Intrinsic(m_Value(Cond))))
894 continue;
895 BBLV = intersect(BBLV, getValueFromCondition(Val, Cond));
881896 }
882897 }
883898
10421057 ConstantRange LHSRange = ConstantRange(OperandBitWidth);
10431058 if (hasBlockValue(BBI->getOperand(0), BB)) {
10441059 LVILatticeVal LHSVal = getBlockValue(BBI->getOperand(0), BB);
1045 intersectAssumeBlockValueConstantRange(BBI->getOperand(0), LHSVal, BBI);
1060 intersectAssumeOrGuardBlockValueConstantRange(BBI->getOperand(0), LHSVal,
1061 BBI);
10461062 if (LHSVal.isConstantRange())
10471063 LHSRange = LHSVal.getConstantRange();
10481064 }
11191135 ConstantRange LHSRange = ConstantRange(OperandBitWidth);
11201136 if (hasBlockValue(BBI->getOperand(0), BB)) {
11211137 LVILatticeVal LHSVal = getBlockValue(BBI->getOperand(0), BB);
1122 intersectAssumeBlockValueConstantRange(BBI->getOperand(0), LHSVal, BBI);
1138 intersectAssumeOrGuardBlockValueConstantRange(BBI->getOperand(0), LHSVal,
1139 BBI);
11231140 if (LHSVal.isConstantRange())
11241141 LHSRange = LHSVal.getConstantRange();
11251142 }
13621379
13631380 // Try to intersect ranges of the BB and the constraint on the edge.
13641381 LVILatticeVal InBlock = getBlockValue(Val, BBFrom);
1365 intersectAssumeBlockValueConstantRange(Val, InBlock, BBFrom->getTerminator());
1382 intersectAssumeOrGuardBlockValueConstantRange(Val, InBlock,
1383 BBFrom->getTerminator());
13661384 // We can use the context instruction (generically the ultimate instruction
13671385 // the calling pass is trying to simplify) here, even though the result of
13681386 // this function is generally cached when called from the solve* functions
13711389 // functions, the context instruction is not provided. When called from
13721390 // LazyValueInfoCache::getValueOnEdge, the context instruction is provided,
13731391 // but then the result is not cached.
1374 intersectAssumeBlockValueConstantRange(Val, InBlock, CxtI);
1392 intersectAssumeOrGuardBlockValueConstantRange(Val, InBlock, CxtI);
13751393
13761394 Result = intersect(LocalResult, InBlock);
13771395 return true;
13881406 solve();
13891407 }
13901408 LVILatticeVal Result = getBlockValue(V, BB);
1391 intersectAssumeBlockValueConstantRange(V, Result, CxtI);
1409 intersectAssumeOrGuardBlockValueConstantRange(V, Result, CxtI);
13921410
13931411 DEBUG(dbgs() << " Result = " << Result << "\n");
13941412 return Result;
14041422 LVILatticeVal Result = LVILatticeVal::getOverdefined();
14051423 if (auto *I = dyn_cast(V))
14061424 Result = getFromRangeMetadata(I);
1407 intersectAssumeBlockValueConstantRange(V, Result, CxtI);
1425 intersectAssumeOrGuardBlockValueConstantRange(V, Result, CxtI);
14081426
14091427 DEBUG(dbgs() << " Result = " << Result << "\n");
14101428 return Result;
0 ; RUN: opt -correlated-propagation -S < %s | FileCheck %s
1
2 declare void @llvm.experimental.guard(i1,...)
3
4 define i1 @test1(i32 %a) {
5 ; CHECK-LABEL: @test1(
6 ; CHECK: %alive = icmp eq i32 %a, 8
7 ; CHECK-NEXT: %result = or i1 false, %alive
8 %cmp = icmp ult i32 %a, 16
9 call void(i1,...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
10 %dead = icmp eq i32 %a, 16
11 %alive = icmp eq i32 %a, 8
12 %result = or i1 %dead, %alive
13 ret i1 %result
14 }
15
16 define i1 @test2(i32 %a) {
17 ; CHECK-LABEL: @test2(
18 ; CHECK: continue:
19 ; CHECK-NEXT: %alive = icmp eq i32 %a, 8
20 ; CHECK-NEXT: %result = or i1 false, %alive
21 %cmp = icmp ult i32 %a, 16
22 call void(i1,...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
23 br label %continue
24
25 continue:
26 %dead = icmp eq i32 %a, 16
27 %alive = icmp eq i32 %a, 8
28 %result = or i1 %dead, %alive
29 ret i1 %result
30 }
31
32 define i1 @test3(i32 %a, i1 %flag) {
33 ; CHECK-LABEL: @test3(
34 ; CHECK: continue:
35 ; CHECK-NEXT: %alive.1 = icmp eq i32 %a, 16
36 ; CHECK-NEXT: %alive.2 = icmp eq i32 %a, 8
37 ; CHECK-NEXT: %result = or i1 %alive.1, %alive.2
38 br i1 %flag, label %true, label %false
39
40 true:
41 %cmp = icmp ult i32 %a, 16
42 call void(i1,...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
43 br label %continue
44
45 false:
46 br label %continue
47
48 continue:
49 %alive.1 = icmp eq i32 %a, 16
50 %alive.2 = icmp eq i32 %a, 8
51 %result = or i1 %alive.1, %alive.2
52 ret i1 %result
53 }
54
55 define i1 @test4(i32 %a, i1 %flag) {
56 ; CHECK-LABEL: @test4(
57 ; CHECK: continue:
58 ; CHECK-NEXT: %alive = icmp eq i32 %a, 12
59 ; CHECK-NEXT: %result = or i1 false, %alive
60 br i1 %flag, label %true, label %false
61
62 true:
63 %cmp.t = icmp ult i32 %a, 16
64 call void(i1,...) @llvm.experimental.guard(i1 %cmp.t) [ "deopt"() ]
65 br label %continue
66
67 false:
68 %cmp.f = icmp ult i32 %a, 12
69 call void(i1,...) @llvm.experimental.guard(i1 %cmp.f) [ "deopt"() ]
70 br label %continue
71
72 continue:
73 %dead = icmp eq i32 %a, 16
74 %alive = icmp eq i32 %a, 12
75 %result = or i1 %dead, %alive
76 ret i1 %result
77 }
78
79 define i1 @test5(i32 %a) {
80 ; CHECK-LABEL: @test5(
81 ; CHECK: continue:
82 ; CHECK-NEXT: %alive = icmp eq i32 %a.plus.8, 16
83 ; CHECK-NEXT: %result = or i1 false, %alive
84 %cmp = icmp ult i32 %a, 16
85 call void(i1,...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
86 %a.plus.8 = add i32 %a, 8
87 br label %continue
88
89 continue:
90 %dead = icmp eq i32 %a.plus.8, 24
91 %alive = icmp eq i32 %a.plus.8, 16
92 %result = or i1 %dead, %alive
93 ret i1 %result
94 }