@@ -5,7 +5,7 @@ use crate::env::Env;
55use crate :: error:: Result ;
66use crate :: ir:: insn:: InsnKind ;
77use crate :: ir:: value:: VrType ;
8- use crate :: ir:: { Function , InsnId , InsertPos , Value } ;
8+ use crate :: ir:: { Function , InsertPos , InsnId , Value } ;
99use crate :: { internal, invalid} ;
1010
1111use super :: prepare:: { create_alloc, ensure_extra} ;
@@ -67,8 +67,15 @@ pub fn pre_spill(env: &mut Env, func: &mut Function, cg: &mut CgState) -> Result
6767 cg. extra_mut ( v) . w += 1 ;
6868 let adj = cg. extra ( v) . adj . clone ( ) ;
6969 for u in adj {
70- // u is in the clique if it appears earlier in the SEO.
71- if seo[ ..i] . contains ( & u) {
70+ // On a chordal graph, every earlier neighbor of `v` in a perfect
71+ // elimination order is mutually adjacent and therefore belongs to
72+ // this clique. Our interference graph is not always chordal, so an
73+ // MCS order is not necessarily perfect; only keep `u` if it is
74+ // adjacent to every value already in `q`. Otherwise `q` is merely an
75+ // earlier-neighbor set, and treating it as an oversized clique can
76+ // force bogus spills or fail with "no spillable VR" even when the
77+ // graph is colorable.
78+ if seo[ ..i] . contains ( & u) && q. iter ( ) . all ( |& x| cg. extra ( u) . adj . contains ( & x) ) {
7279 q. push ( u) ;
7380 cg. extra_mut ( u) . w += 1 ;
7481 }
@@ -110,7 +117,10 @@ pub fn spill(
110117) -> Result < ( ) > {
111118 let _ = env;
112119 for & v in to_spill {
113- if matches ! ( func. insn( v) . kind, InsnKind :: Call { .. } | InsnKind :: AllocArray { .. } ) {
120+ if matches ! (
121+ func. insn( v) . kind,
122+ InsnKind :: Call { .. } | InsnKind :: AllocArray { .. }
123+ ) {
114124 return Err ( internal ! ( "attempted to spill a call/allocarray" ) ) ;
115125 }
116126 let users = func. insn ( v) . users . clone ( ) ;
@@ -157,11 +167,7 @@ fn spill_one_use(
157167) -> Result < ( ) > {
158168 match func. insn ( user) . kind . clone ( ) {
159169 // A store of the spilled value into its own slot: nothing to do.
160- InsnKind :: Store
161- if func. insn ( user) . values . first ( ) == Some ( & Value :: Insn ( user) ) =>
162- {
163- Ok ( ( ) )
164- }
170+ InsnKind :: Store if func. insn ( user) . values . first ( ) == Some ( & Value :: Insn ( user) ) => Ok ( ( ) ) ,
165171 InsnKind :: Phi => {
166172 // Reload at the end of each predecessor block contributing v.
167173 let entries = func. insn ( user) . phi . clone ( ) ;
@@ -268,9 +274,7 @@ pub fn pick_spill_victim(func: &Function, cg: &CgState, failed: InsnId) -> Resul
268274 }
269275 }
270276 best. ok_or_else ( || {
271- crate :: error:: Error :: RegAlloc (
272- "coloring failed and no spillable value is available" . into ( ) ,
273- )
277+ crate :: error:: Error :: RegAlloc ( "coloring failed and no spillable value is available" . into ( ) )
274278 } )
275279}
276280
0 commit comments