You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/DeveloperGuide/DynamaticFeaturesAndOptimizations/FTD/GSAAnalysis.md
+121-1Lines changed: 121 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -151,4 +151,124 @@ Therefore, the condition of a μ gate is defined as the **negation of the loop e
151
151
152
152
#### Note:
153
153
The `getLoopExitCondition` function computes the overall exit condition by OR-ing the conditions of all loop exiting blocks. This function relies on `getBlockLoopExitCondition`, which computes the exit condition for a single block.
154
-
## Convert ϕ Gates into γ Gates
154
+
155
+
## Convert ϕ Gates into γ Gates
156
+
157
+
All remaining ϕ gates (i.e., those not turned into μ gates) must be converted into γ gates.
158
+
However, a single γ gate is only a **two-input multiplexer**, while a ϕ can have multiple inputs.
159
+
To handle this, we build a tree of γ gates, each driven by a simple condition.
160
+
The following steps describe the process.
161
+
162
+
### Input Ordering
163
+
The inputs of a ϕ are sorted based on the dominance relationship between their originating basic blocks.
164
+
165
+
- If block Bi dominates block Bj, then the input from Bi is placed before Bj.
166
+
167
+
- This ordering does not affect the semantics of the ϕ (ϕ is order-less), but it simplifies later analysis.
168
+
169
+
### Step 2. Find Common Dominator
170
+
171
+
Find **the nearest common dominator** among all input blocks of the ϕ.
172
+
This block acts as the root for path exploration.
173
+
174
+
### Step 3. Path Identification
175
+
176
+
For each input operand:
177
+
178
+
- Find all paths from the common dominator to the ϕ’s block that **pass through the operand’s block** but **avoid later operand blocks**.
179
+
180
+
- Paths are explored using a modified DFS that:
181
+
182
+
- finds all possible paths between two blocks,
183
+
184
+
- avoids certain “blocked” nodes,
185
+
186
+
- and allows a block to be revisited only if it is both the start and end (for loop cases).
187
+
188
+
**Operands from the same block:**
189
+
190
+
If one block produces multiple values (operands) for the same ϕ, the DFS initially gives them identical paths.
191
+
192
+
To disambiguate, we filter the paths by the sender block (the block immediately before the ϕ in the path).
193
+
Only paths whose sender matches the operand’s recorded sender are kept.
194
+
195
+
### Step 4. Boolean Conditions
196
+
197
+
For each operand, compute a Boolean expression representing when that operand is chosen:
198
+
199
+
- The condition of a path = AND of all branch conditions along that path.
200
+
201
+
- The condition of an operand = OR of the conditions of all valid paths.
202
+
203
+
- The resulting Boolean expressions are minimized.
204
+
205
+
All Boolean conditions (cofactors) are collected and sorted by the index of their originating block.
206
+
207
+
### Step 5. Build the γ Tree
208
+
209
+
The `expandGammaTree` function takes a ϕ gate (with its inputs and Boolean conditions) and recursively builds a binary tree of γ gates.
210
+
Each γ is a two-input MUX driven by one simple Boolean condition.
211
+
212
+
The process works as follows:
213
+
214
+
**1. Pick a cofactor (condition):**
215
+
216
+
The function starts from the queue of cofactors (Boolean conditions associated with blocks). Since they are ordered by block index, the first cofactor we take is guaranteed to be common to all input expressions (because the blocks associated with it dominate the others). This ensures that splitting on this cofactor applies consistently across all inputs.
217
+
218
+
**2. Split expressions by condition:**
219
+
220
+
For each input expression (operand + condition):
221
+
222
+
- Restrict the Boolean expression once assuming the cofactor = `true`.
223
+
224
+
- Restrict it again assuming the cofactor = `false`.
225
+
226
+
- Add the non-zero result(s) to either `conditionsTrueExpressions` or `conditionsFalseExpressions`.
227
+
228
+
**3. Build γ inputs:**
229
+
230
+
Now we decide what should feed the true and false inputs of the γ gate being built:
231
+
232
+
- If a side has **more than one expression**, this means multiple operands could be selected under that branch of the condition. To resolve this, we recursively call `expandGammaTree` on that subset. The resulting γ gate from the recursion becomes the input of the current γ.
233
+
234
+
- If a side has `exactly one expression`, its operand is directly assigned as the input of the current γ.
235
+
236
+
- If a side has `no expressions`, it means this branch of the condition is never taken. In that case, an empty (null) input is created.
237
+
238
+
**4. Create the γ gate:**
239
+
240
+
A new γ is generated:
241
+
242
+
- Its inputs are the “true” and “false” operands from the step above.
243
+
244
+
- Its condition is the cofactor currently being expanded.
245
+
246
+
- Internally, its output is temporarily set to the original ϕ’s result (only the root γ of the tree will preserve this).
247
+
248
+
**5. Placement rule:**
249
+
250
+
Normally, new γ gates are placed in the **same block as the original ϕ**.
251
+
252
+
However, there is one special case: when the ϕ was introduced during `convertPhiToMu` to resolve multiple loop-carried inputs. These temporary ϕs (marked with muGenerated) cannot have their γ replacements placed in the loop header.
253
+
254
+
**Why is this a problem?**
255
+
256
+
When we later run direct path analysis for control dependencies, the control signal that drives such a γ is generated inside the loop body.
257
+
If we place the γ in the loop header:
258
+
259
+
- The γ would appear before its control signal producer.
260
+
261
+
- In the direct path search from the function entry (bb0) to the γ, we would never encounter the block that generates the control signal.
262
+
263
+
264
+
**The fix:**
265
+
266
+
For γs created from these muGenerated phis, we instead place them **in the same block as their condition producer**.
267
+
268
+
### Step 6. Reconnect Uses
269
+
270
+
Once a ϕ is replaced by its γ tree:
271
+
272
+
- All gates that previously used the ϕ’s output are updated to use the root γ gate instead.
0 commit comments