1
1
/*========================== begin_copyright_notice ============================
2
2
3
- Copyright (C) 2023 Intel Corporation
3
+ Copyright (C) 2023-2024 Intel Corporation
4
4
5
5
SPDX-License-Identifier: MIT
6
6
@@ -14,84 +14,175 @@ SPDX-License-Identifier: Apache-2.0 with LLVM-exception
14
14
15
15
============================= end_copyright_notice ===========================*/
16
16
17
- # TODO: Once upstreamed, update with LLORG revision & adjust per community review
18
-
19
- diff -Naur "a/llvm/include/llvm/Analysis/ScalarEvolution.h" "b/llvm/include/llvm/Analysis/ScalarEvolution.h"
20
- --- "a/llvm/include/llvm/Analysis/ScalarEvolution.h" 2023-09-27 19:27:08.174510600 +0200
21
- +++ "b/llvm/include/llvm/Analysis/ScalarEvolution.h" 2023-09-27 18:41:11.301171800 +0200
22
- @@ -1292,6 +1292,9 @@
23
- /// Mark predicate values currently being processed by isImpliedCond.
24
- SmallPtrSet<const Value *, 6> PendingLoopPredicates;
25
-
26
- + /// Set of Phis processed in createSCEVIter.
27
- + SmallPtrSet<const PHINode*, 6> PendingPhiSCEVIter;
17
+ diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
18
+ index 51558a37b..a2069980a 100644
19
+ --- a/llvm/include/llvm/Analysis/ScalarEvolution.h
20
+ +++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
21
+ @@ -1613,6 +1613,9 @@ private:
22
+ /// Provide the special handling we need to analyze PHI SCEVs.
23
+ const SCEV *createNodeForPHI(PHINode *PN);
24
+
25
+ + /// Helper function to get a single start and back edge value from a phi node.
26
+ + std::pair<Value*, Value*> getStartAndBackEdgeValues(PHINode *PN);
28
27
+
29
- /// Mark SCEVUnknown Phis currently being processed by getRangeRef.
30
- SmallPtrSet<const PHINode *, 6> PendingPhiRanges;
28
+ /// Helper function called from createNodeForPHI.
29
+ const SCEV *createAddRecFromPHI(PHINode *PN);
30
+
31
+ diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
32
+ index fc9517ebb..facfe1c7d 100644
33
+ --- a/llvm/lib/Analysis/ScalarEvolution.cpp
34
+ +++ b/llvm/lib/Analysis/ScalarEvolution.cpp
35
+ @@ -5529,10 +5529,11 @@ const SCEV *ScalarEvolution::createSimpleAffineAddRec(PHINode *PN,
36
+ return PHISCEV;
37
+ }
38
+
39
+ - const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
40
+ + std::pair<Value *, Value *>
41
+ + ScalarEvolution::getStartAndBackEdgeValues(PHINode *PN) {
42
+ const Loop *L = LI.getLoopFor(PN->getParent());
43
+ if (!L || L->getHeader() != PN->getParent())
44
+ - return nullptr;
45
+ + return {};
46
+
47
+ // The loop may have multiple entrances or multiple exits; we can analyze
48
+ // this phi as an addrec if it has a unique entry value and a unique
49
+ @@ -5555,10 +5556,18 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
50
+ }
51
+ }
52
+ if (!BEValueV || !StartValueV)
53
+ - return nullptr;
54
+ + return {};
55
+ + return {StartValueV, BEValueV};
56
+ + }
31
57
32
- diff -Naur "a/llvm/lib/Analysis/ScalarEvolution.cpp" "b/llvm/lib/Analysis/ScalarEvolution.cpp"
33
- --- "a/llvm/lib/Analysis/ScalarEvolution.cpp" 2023-09-27 19:27:08.189098000 +0200
34
- +++ "b/llvm/lib/Analysis/ScalarEvolution.cpp" 2023-09-27 19:05:40.601713600 +0200
35
- @@ -7004,6 +7004,13 @@
58
+ - assert(ValueExprMap.find_as(PN) == ValueExprMap.end() &&
59
+ - "PHI node already processed?");
60
+ + const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
61
+ + // The loop may have multiple entrances or multiple exits; we can analyze
62
+ + // this phi as an addrec if it has a unique entry value and a unique
63
+ + // backedge value.
64
+ + std::pair<Value *, Value *> StartAndBEValueV = getStartAndBackEdgeValues(PN);
65
+ + Value *BEValueV = StartAndBEValueV.second, *StartValueV = StartAndBEValueV.first;
66
+ + if (!BEValueV || !StartValueV)
67
+ + return nullptr;
68
+
69
+ // First, try to find AddRec expression without creating a fictituos symbolic
70
+ // value for PN.
71
+ @@ -5572,6 +5581,7 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
72
+ // Using this symbolic name for the PHI, analyze the value coming around
73
+ // the back-edge.
74
+ const SCEV *BEValue = getSCEV(BEValueV);
75
+ + const Loop *L = LI.getLoopFor(PN->getParent());
76
+
77
+ // NOTE: If BEValue is loop invariant, we know that the PHI node just
78
+ // has a special value for the first iteration of the loop.
79
+ @@ -5772,8 +5782,15 @@ static bool IsAvailableOnEntry(const Loop *L, DominatorTree &DT, const SCEV *S,
80
+ // Try to match a control flow sequence that branches out at BI and merges back
81
+ // at Merge into a "C ? LHS : RHS" select pattern. Return true on a successful
82
+ // match.
83
+ - static bool BrPHIToSelect(DominatorTree &DT, BranchInst *BI, PHINode *Merge,
84
+ - Value *&C, Value *&LHS, Value *&RHS) {
85
+ + static bool BrPHIToSelect(DominatorTree &DT, PHINode *Merge, Value *&C,
86
+ + Value *&LHS, Value *&RHS) {
87
+ +
88
+ + BasicBlock *IDom = DT[Merge->getParent()]->getIDom()->getBlock();
89
+ + assert(IDom && "At least the entry block should dominate PN");
90
+ +
91
+ + auto *BI = dyn_cast<BranchInst>(IDom->getTerminator());
92
+ + if (!BI || !BI->isConditional())
93
+ + return false;
94
+ C = BI->getCondition();
95
+
96
+ BasicBlockEdge LeftEdge(BI->getParent(), BI->getSuccessor(0));
97
+ @@ -5802,6 +5819,11 @@ static bool BrPHIToSelect(DominatorTree &DT, BranchInst *BI, PHINode *Merge,
98
+ return false;
99
+ }
100
+
101
+ + static bool BrPHIToSelect(DominatorTree& DT, PHINode* Merge) {
102
+ + Value *Cond = nullptr, *LHS = nullptr, *RHS = nullptr;
103
+ + return BrPHIToSelect(DT, Merge, Cond, LHS, RHS);
104
+ + }
105
+ +
106
+ const SCEV *ScalarEvolution::createNodeFromSelectLikePHI(PHINode *PN) {
107
+ auto IsReachable =
108
+ [&](BasicBlock *BB) { return DT.isReachableFromEntry(BB); };
109
+ @@ -5824,18 +5846,16 @@ const SCEV *ScalarEvolution::createNodeFromSelectLikePHI(PHINode *PN) {
110
+ // V = phi [ %x, %left ], [ %y, %right ]
111
+ //
112
+ // as "select %cond, %x, %y"
113
+ -
114
+ - BasicBlock *IDom = DT[PN->getParent()]->getIDom()->getBlock();
115
+ - assert(IDom && "At least the entry block should dominate PN");
116
+ -
117
+ - auto *BI = dyn_cast<BranchInst>(IDom->getTerminator());
118
+ Value *Cond = nullptr, *LHS = nullptr, *RHS = nullptr;
119
+
120
+ - if (BI && BI->isConditional() &&
121
+ - BrPHIToSelect(DT, BI, PN, Cond, LHS, RHS) &&
122
+ + // do not run over cycled PHIs while processing createNodeFromSelectLikePHI
123
+ + const SCEV* S = nullptr;
124
+ + if (BrPHIToSelect(DT, PN, Cond, LHS, RHS) &&
125
+ IsAvailableOnEntry(L, DT, getSCEV(LHS), PN->getParent()) &&
126
+ - IsAvailableOnEntry(L, DT, getSCEV(RHS), PN->getParent()))
127
+ - return createNodeForSelectOrPHI(PN, Cond, LHS, RHS);
128
+ + IsAvailableOnEntry(L, DT, getSCEV(RHS), PN->getParent())) {
129
+ + S = createNodeForSelectOrPHI(PN, Cond, LHS, RHS);
130
+ + }
131
+ + return S;
132
+ }
133
+
134
+ return nullptr;
135
+ @@ -7004,6 +7024,7 @@ const SCEV *ScalarEvolution::createSCEVIter(Value *V) {
36
136
37
137
Stack.emplace_back(V, true);
38
138
Stack.emplace_back(V, false);
39
- +
40
- + if (isa<PHINode>(V) &&
41
- + !PendingPhiSCEVIter.insert(cast<PHINode>(V)).second) {
42
- + // cycled back to createSCEVIter while processing this Phi, bail
43
- + return getUnknown(V);
44
- + }
45
139
+
46
140
while (!Stack.empty()) {
47
141
auto E = Stack.pop_back_val();
48
142
Value *CurV = E.getPointer();
49
- @@ -7016,6 +7023,10 @@
50
- // If all operands have been visited already, create the SCEV.
51
- if (E.getInt()) {
52
- CreatedSCEV = createSCEV(CurV);
53
- + } else if (isa<PHINode>(CurV) &&
54
- + PendingPhiSCEVIter.count(cast<PHINode>(CurV)) > 0) {
55
- + // cycled Phi, try to get its SCEV
56
- + CreatedSCEV = createSCEV(CurV);
57
- } else {
58
- // Otherwise get the operands we need to create SCEV's for before creating
59
- // the SCEV for CurV. If the SCEV for CurV can be constructed trivially,
60
- @@ -7025,12 +7036,17 @@
61
-
62
- if (CreatedSCEV) {
143
+ @@ -7023,14 +7044,15 @@ const SCEV *ScalarEvolution::createSCEVIter(Value *V) {
144
+ CreatedSCEV = getOperandsToCreate(CurV, Ops);
145
+ }
146
+
147
+ - if (CreatedSCEV) {
148
+ + if (CreatedSCEV)
63
149
insertValueToMap(CurV, CreatedSCEV);
64
- + if (isa<PHINode>(CurV))
65
- + PendingPhiSCEVIter.erase(cast<PHINode>(CurV));
66
- } else {
150
+ - } else {
151
+ + else {
67
152
// Queue CurV for SCEV creation, followed by its's operands which need to
68
153
// be constructed first.
69
154
Stack.emplace_back(CurV, true);
70
155
- for (Value *Op : Ops)
71
- + if (isa<PHINode>(CurV))
72
- + PendingPhiSCEVIter.insert(cast<PHINode>(CurV));
73
156
+ for (Value *Op : Ops) {
74
157
Stack.emplace_back(Op, false);
75
158
+ }
76
159
}
77
160
}
78
161
79
- @@ -7153,7 +7169,8 @@
162
+ @@ -7152,9 +7174,24 @@ ScalarEvolution::getOperandsToCreate(Value *V, SmallVectorImpl<Value *> &Ops) {
163
+ case Instruction::IntToPtr:
80
164
return getUnknown(V);
81
165
82
- case Instruction::PHI:
166
+ - case Instruction::PHI:
83
167
- // Keep constructing SCEVs' for phis recursively for now.
84
- + for (auto& Op : cast<PHINode>(U)->operands())
85
- + Ops.push_back(Op);
168
+ + case Instruction::PHI: {
169
+ + PHINode *PN = cast<PHINode>(U);
170
+ +
171
+ + if (PN->getNumIncomingValues() == 2) {
172
+ + std::pair<Value *, Value *> StartAndBEValueV =
173
+ + getStartAndBackEdgeValues(PN);
174
+ + if (StartAndBEValueV.first && StartAndBEValueV.second)
175
+ + // resolve recursively - may create cycles
176
+ + return nullptr;
177
+ + else if (BrPHIToSelect(DT, PN))
178
+ + // resolve iteratively - does not create cycles
179
+ + for (auto &Op : PN->operands())
180
+ + Ops.push_back(Op);
181
+ + }
182
+ +
183
+ + // resolve iteratively - does not create SCEV cycles (trivially resolved)
86
184
return nullptr;
185
+ + }
87
186
88
187
case Instruction::Select: {
89
- @@ -13405,6 +13422,8 @@
90
- auto ValueIt = ValueExprMap.find_as(ValueAndOffset.first);
91
- if (ValueIt != ValueExprMap.end())
92
- ValueExprMap.erase(ValueIt);
93
- + if (isa<PHINode>(ValueAndOffset.first))
94
- + PendingPhiSCEVIter.erase(cast<PHINode>(ValueAndOffset.first));
95
- }
96
- }
97
- ExprValueMap.erase(ExprIt);
188
+ // Check if U is a select that can be simplified to a SCEVUnknown.
0 commit comments