1 ! Copyright (C) 2008, 2010 Slava Pestov.
2 ! See https://factorcode.org/license.txt for BSD license.
3 USING: accessors assocs compiler.cfg.def-use
4 compiler.cfg.instructions compiler.cfg.predecessors
5 compiler.cfg.renaming compiler.cfg.rpo compiler.cfg.utilities
6 grouping kernel namespaces sequences ;
7 IN: compiler.cfg.copy-prop
15 ! Initialized per-basic-block; a mapping from inputs to dst for
16 ! eliminating redundant ##phi instructions
19 : resolve ( vreg -- vreg )
22 : (record-copy) ( dst src copies -- )
23 swapd maybe-set-at [ changed? on ] when ; inline
25 : record-copy ( dst src -- )
26 copies get (record-copy) ; inline
28 : record-copies ( seq -- )
29 copies get '[ dup _ (record-copy) ] each ; inline
31 GENERIC: visit-insn ( insn -- )
34 [ dst>> ] [ src>> resolve ] bi
35 [ record-copy ] [ drop ] if* ;
37 : useless-phi ( dst inputs -- ) first record-copy ;
39 : redundant-phi ( dst inputs -- ) phis get at record-copy ;
41 : record-phi ( dst inputs -- )
42 [ phis get set-at ] [ drop dup record-copy ] 2bi ;
45 [ dst>> ] [ inputs>> values [ resolve ] map ] bi
46 dup phis get key? [ redundant-phi ] [
50 [ drop record-phi ] if
53 M: vreg-insn visit-insn
54 defs-vregs record-copies ;
56 M: insn visit-insn drop ;
58 : (collect-copies) ( cfg -- )
64 : collect-copies ( cfg -- )
73 GENERIC: update-insn ( insn -- keep? )
75 M: ##copy update-insn drop f ;
78 dup call-next-method drop
79 [ dst>> ] [ inputs>> values ] bi [ = not ] with any? ;
81 M: vreg-insn update-insn rename-insn-uses t ;
83 M: insn update-insn drop t ;
85 : rename-copies ( cfg -- )
86 copies get renamings set
87 [ [ update-insn ] filter! ] simple-optimization ;
91 ! Certain parts of the GVN pass may come together here and
92 ! sabotage the correctness of the CFG:
94 ! 1) compiler.cfg.gvn.comparisons:fold-branch may remove some
95 ! predecessors of a block (hence predecessors-changed at the
96 ! end of compiler.cfg.gvn:value-numbering).
98 ! 2) At the moment in compiler.cfg.gvn:value-numbering,
99 ! ##phis with equivalent inputs (i.e., identical value
100 ! numbers) will be converted into ##copy insns; thus, some
101 ! ##copies may show up *before* ##phis within a basic block,
102 ! even though ##phis should come at the very beginning of a
105 ! Thus, the call to needs-predecessors in copy-propagation may
106 ! wind up failing to prune dead inputs to particular ##phis in
107 ! a block (if they're preceded by ##copies). However,
108 ! copy-propagation will remove the ##copies that
109 ! value-numbering introduces. So, a band-aid solution is to
110 ! suffix a predecessors-changed to copy-propagation, so that
111 ! future calls to needs-predecessors (particularly in
112 ! compiler.cfg.dce:eliminate-dead-code) will finally correct
113 ! the ##phi nodes left over after value-numbering.
115 ! A better solution (and the eventual goal) would be to have
116 ! value-numbering subsume copy-propagation, thus eliminating
117 ! this pass altogether.
121 : copy-propagation ( cfg -- )