gccrs: Handle conditional moves in BIR drop analysis - #4777
Conversation
| = compute_entry_states (function); | ||
|
|
||
| // Keep the existing backend handling for straight-line CFGs. | ||
| const bool record_straight_line_backend_drops = is_straight_line (function); |
There was a problem hiding this comment.
This is a specific bridge from BIR Drop analysis to the existing backend.
It stores the results using HirId and updates definitely_dead.
It is only used for straight-line CFGs because the backend does not support Conditional Drops yet.
| namespace BIR { | ||
| namespace { | ||
|
|
||
| struct BlockInitializationState |
There was a problem hiding this comment.
In order to merge states from different blocks, I make the state associate to block
And I added a ‘reachable’ parameter to track if a block is visited.
The previous straight-line analysis used one state while processing statements.
But in conditional cases, there are three different states that need to be represented (Static / Dead / Conditional).
The original representation could only represent two states.
So I added maybe_initialized, maybe_uninitialized to track these three states.
| } | ||
|
|
||
| static void | ||
| update_state_for_statement (Function &function, Statement &statement, |
There was a problem hiding this comment.
When implementing the conditional cases, I “update initialize/uninitialized based on statements” two times in different places.
- The first time is because blocks need to merge states, so need to find the state and pass it to the next blocks.
- The second time is to use the result to decide whether a Drop is Conditional, Static, or Dead.
Therefore, I extracted this logic from the old function into a new helper.
| queued[ENTRY_BASIC_BLOCK.value] = true; | ||
|
|
||
| // Propagate block states until the last block. | ||
| while (!worklist.empty ()) |
There was a problem hiding this comment.
To keep track of blocks that still need to be processed, I use a while loop, worklist and queued to achieve this.
So in the end
- Block that has not been reached yet
- Block that already reached but its state changes after merging with another state.
will be added into the worklist.
(queued is to record whether a block is already in the worklist. )
| { | ||
| const size_t block_count = function.basic_blocks.size (); | ||
|
|
||
| for (size_t i = 0; i < block_count; i++) |
There was a problem hiding this comment.
I loop here again because I need to wait until the state stops changing.
And I
- save state
- Because if the state might still change, the result may need to be overwritten many times. This will also increase time usage.
- classify/set Drop
- Because the classification depends on the state. If the state keeps changing, the classification might be wrong.
- handle Straight-line backend
- Because the DropStyle is already known, so the result can be passed to the backend.
- update state for statement
- Because Drop classification needs the stable state, so need to update again here.
0e87c5f to
ad7ea9c
Compare
ad7ea9c to
dd9f96d
Compare
Track whole-local initialization across BIR control-flow branches. When a local is moved on only some paths, mark its Drop as conditional. Keep the existing backend handling for straight-line CFGs and add tests for static, dead and conditional Drops. gcc/rust/ChangeLog: * checks/errors/borrowck/rust-bir-drop-analysis.cc (struct BlockInitializationState): New struct. (is_straight_line): New function. (set_initialized): Likewise. (set_uninitialized): Likewise. (merge_state): Likewise. (update_state_for_statement): Likewise. (classify_drop): Likewise. (compute_entry_states): Likewise. (record_drop_for_straight_line_backend): Likewise. (annotate_drop_statements): Likewise. (DropAnalysis::analyze): Propagate initialization state across the CFG and classify Drop statements. * checks/errors/borrowck/rust-bir-drop-analysis.h: Update class comment. gcc/testsuite/ChangeLog: * rust/borrowck/drop_analysis_conditional_move.rs: New test. Signed-off-by: Lishin <lishin1008@gmail.com>
Head branch was pushed to by a user without write access
dd9f96d to
7e91f41
Compare
This patch extends the BIR Drop state analysis from straight-line control flow to conditional control flow.
It tracks whether each local variable may be
initializedoruninitializedat the entry of each basic block.Take conditional move as example,
For example,
The analysis stops when the
worklistbecomes empty.A Drop is classified as:
1.1. Drop(x): Static
2.1. Drop(x): Dead
3.1. Drop(x): Conditional
It covers the following conditional control-flow cases: