fix[venom]: fix invalid phis after SCCP#4181
fix[venom]: fix invalid phis after SCCP#4181charles-cooper merged 16 commits intovyperlang:masterfrom
phis after SCCP#4181Conversation
|
shouldn't we fix up the phi nodes during sccp directly? |
vyper/venom/passes/sccp/sccp.py
Outdated
| self.cfg_dirty = True | ||
| for bb in inst.parent.cfg_out: | ||
| if bb.label == target: | ||
| self.cfg_phi_fix_needed.add(bb) |
There was a problem hiding this comment.
Why not self._fix_phi_bb_r(bb, OrderedSet()) here and remove all the need for self.cfg_phi_fix_needed and iterating later?
There was a problem hiding this comment.
The reason was not to iterate over some basic block multiple times. Since solutions only detects start from which the occurrence of faulty phi node could be possible but not the end there could be a lot of overlap. In this case since I iterate over possible positions of the faulty phi nodes at the end I visit every possible basic block only once.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #4181 +/- ##
==========================================
- Coverage 91.35% 88.22% -3.14%
==========================================
Files 109 109
Lines 15641 15672 +31
Branches 3443 3454 +11
==========================================
- Hits 14289 13826 -463
- Misses 920 1314 +394
- Partials 432 532 +100 ☔ View full report in Codecov by Sentry. |
vyper/venom/passes/sccp/sccp.py
Outdated
| from_src_bb = filter(lambda x: x[0] == src_bb.label, phi_inst.phi_operands) | ||
| operands = list(map(lambda x: x[1], from_src_bb)) |
There was a problem hiding this comment.
please use a list comprehension here
| from_src_bb = filter(lambda x: x[0] == src_bb.label, phi_inst.phi_operands) | |
| operands = list(map(lambda x: x[1], from_src_bb)) | |
| operands = [op for label, op in phi_inst.phi_operands if label == src_bb.label] |
vyper/venom/passes/sccp/sccp.py
Outdated
|
|
||
| assert len(operands) == 1 | ||
| assert isinstance(operands[0], IRVariable) | ||
| assert phi_inst.output is not None |
There was a problem hiding this comment.
| assert phi_inst.output is not None | |
| assert phi_inst.output is not None | |
vyper/venom/passes/sccp/sccp.py
Outdated
| self.cfg_dirty = True | ||
| for bb in inst.parent.cfg_out: | ||
| if bb.label == target: | ||
| self.cfg_phi_fix_needed.add(bb) |
There was a problem hiding this comment.
| self.cfg_phi_fix_needed.add(bb) | |
| self.cfg_phi_fix_needed.add(bb) | |
| break |
vyper/venom/passes/sccp/sccp.py
Outdated
| for next_bb in bb.cfg_out: | ||
| self._fix_phi_bb_r(next_bb, visited) | ||
|
|
||
| def _fix_phi_node_inst(self, phi_inst: IRInstruction): |
There was a problem hiding this comment.
| def _fix_phi_node_inst(self, phi_inst: IRInstruction): | |
| def _fix_phi_inst(self, phi_inst: IRInstruction): |
vyper/venom/passes/sccp/sccp.py
Outdated
| inst.operands[i] = lat | ||
|
|
||
| def _fix_phi_nodes(self): | ||
| visited: OrderedSet[IRBasicBlock] = OrderedSet() |
There was a problem hiding this comment.
why keep track of visited, instead of just iterating over fn.get_basic_blocks()?
vyper/venom/passes/sccp/sccp.py
Outdated
| assert len(operands) == 1 | ||
| assert isinstance(operands[0], IRVariable) | ||
| assert phi_inst.output is not None | ||
| phi_inst.output.value = operands[0] |
There was a problem hiding this comment.
why modify the instruction if it gets removed on the next line?
vyper/venom/passes/sccp/sccp.py
Outdated
| self._fix_phi_bb_r(next_bb, visited) | ||
|
|
||
| def _fix_phi_node_inst(self, phi_inst: IRInstruction): | ||
| if len(phi_inst.parent.cfg_in) != 1: |
There was a problem hiding this comment.
when can this happen? shouldn't we handle this case?
|
i pushed some cleanup here: HodanPlodky#2. it feels like a kludge though, since it seems like we really should be fixing up these phi nodes inside of |
simplify the cleanup - transforming phis to store instead of removing them
charles-cooper
left a comment
There was a problem hiding this comment.
pushed some stuff, lgtm now. @harkal mind taking a look?
phis after SCCP
This commit reduces `phi` nodes which, after SCCP, refer to a basic block which is unreachable. This could happen when the SCCP would replace a `jnz` by a `jmp` instruction, resulting in a `phi` instruction which refers to a non-existent block, or a `phi` instruction in a basic block which only has one predecessor. This commit reduces such `phi` instructions into `store` instructions. --------- Co-authored-by: Harry Kalogirou <[email protected]> Co-authored-by: Charles Cooper <[email protected]>
What I did
Fix for issues #4162 and #4070
How I did it
Removed the phi nodes which were not in use after
SCCPpass. This could happen when theSCCPwould replacejnzbyjmpinstruction and by this removing need forphiinstruction (this is the case in #4162). More over the when merging the basic block in theSimplifyCFGPassthere could be problem when renaming the labels inphinodes since it went only into the firstcfg_outbasic block (this is the case in #4070)How to verify it
So far both of the POC from compile correctly
Commit message