1// Implementation of public inline member functions for RTL SSA     -*- C++ -*-
2// Copyright (C) 2020-2022 Free Software Foundation, Inc.
3//
4// This file is part of GCC.
5//
6// GCC is free software; you can redistribute it and/or modify it under
7// the terms of the GNU General Public License as published by the Free
8// Software Foundation; either version 3, or (at your option) any later
9// version.
10//
11// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12// WARRANTY; without even the implied warranty of MERCHANTABILITY or
13// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14// for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with GCC; see the file COPYING3.  If not see
18// <http://www.gnu.org/licenses/>.
19
20// This file contains inline implementations of public member functions that
21// are too large to be written in the class definition.  It also contains
22// some non-inline template definitions of public member functions.
23// See the comments above the function declarations for details.
24//
25// The file also contains the bare minimum of private and protected inline
26// member functions that are needed to make the public functions compile.
27namespace rtl_ssa {
28
29inline void
30access_array_builder::reserve (unsigned int num_accesses)
31{
32  obstack_make_room (m_obstack, num_accesses * sizeof (access_info *));
33}
34
35inline void
36access_array_builder::quick_push (access_info *access)
37{
38  obstack_ptr_grow_fast (m_obstack, access);
39}
40
41inline array_slice<access_info *>
42access_array_builder::finish ()
43{
44  auto num_accesses = obstack_object_size (m_obstack) / sizeof (access_info *);
45  if (num_accesses == 0)
46    return {};
47
48  auto **base = static_cast<access_info **> (obstack_finish (m_obstack));
49  keep ();
50  return { base, num_accesses };
51}
52
53inline bool
54access_info::is_set_with_nondebug_insn_uses () const
55{
56  return m_is_set_with_nondebug_insn_uses;
57}
58
59inline bool
60use_info::is_in_debug_insn () const
61{
62  return m_insn_or_phi.is_first () && m_is_in_debug_insn_or_phi;
63}
64
65inline bb_info *
66use_info::bb () const
67{
68  if (m_insn_or_phi.is_first ())
69    return m_insn_or_phi.known_first ()->bb ();
70  return m_insn_or_phi.known_second ()->bb ();
71}
72
73inline ebb_info *
74use_info::ebb () const
75{
76  return bb ()->ebb ();
77}
78
79inline use_info *
80use_info::prev_use () const
81{
82  return m_last_use_or_prev_use.second_or_null ();
83}
84
85inline use_info *
86use_info::next_use () const
87{
88  return m_last_nondebug_insn_use_or_next_use.second_or_null ();
89}
90
91inline bool
92use_info::is_first_use () const
93{
94  return m_last_use_or_prev_use.is_first ();
95}
96
97inline bool
98use_info::is_last_use () const
99{
100  return m_last_nondebug_insn_use_or_next_use.is_first ();
101}
102
103inline use_info *
104use_info::next_nondebug_insn_use () const
105{
106  if (m_is_last_nondebug_insn_use)
107    return nullptr;
108  return m_last_nondebug_insn_use_or_next_use.known_second ();
109}
110
111inline use_info *
112use_info::next_any_insn_use () const
113{
114  // This is used less often than next_nondebug_insn_use, so it doesn't
115  // seem worth having an m_is_last_nondebug_insn_use-style end marker.
116  if (use_info *use = next_use ())
117    if (use->is_in_any_insn ())
118      return use;
119  return nullptr;
120}
121
122inline use_info *
123use_info::prev_phi_use () const
124{
125  // This is used less often than next_nondebug_insn_use, so it doesn't
126  // seem worth having an m_is_last_nondebug_insn_use-style end marker.
127  if (use_info *use = prev_use ())
128    if (use->is_in_phi ())
129      return use;
130  return nullptr;
131}
132
133// Return the last use of any kind in the list.  Only valid when is_first ()
134// is true.
135inline use_info *
136use_info::last_use () const
137{
138  return m_last_use_or_prev_use.known_first ();
139}
140
141// Return the last nondebug insn use in the list, or null if none.  Only valid
142// when is_last_use () is true.
143inline use_info *
144use_info::last_nondebug_insn_use () const
145{
146  return m_last_nondebug_insn_use_or_next_use.known_first ();
147}
148
149inline def_info *
150def_info::prev_def () const
151{
152  return m_last_def_or_prev_def.second_or_null ();
153}
154
155inline def_info *
156def_info::next_def () const
157{
158  return m_splay_root_or_next_def.second_or_null ();
159}
160
161inline bool
162def_info::is_first_def () const
163{
164  return m_last_def_or_prev_def.is_first ();
165}
166
167inline bool
168def_info::is_last_def () const
169{
170  return m_splay_root_or_next_def.is_first ();
171}
172
173inline bb_info *
174def_info::bb () const
175{
176  return m_insn->bb ();
177}
178
179inline ebb_info *
180def_info::ebb () const
181{
182  return m_insn->ebb ();
183}
184
185inline clobber_group *
186clobber_info::group () const
187{
188  if (!m_group || !m_group->has_been_superceded ())
189    return m_group;
190  return const_cast<clobber_info *> (this)->recompute_group ();
191}
192
193inline use_info *
194set_info::last_use () const
195{
196  return m_first_use ? m_first_use->last_use () : nullptr;
197}
198
199inline use_info *
200set_info::first_nondebug_insn_use () const
201{
202  if (m_is_set_with_nondebug_insn_uses)
203    return m_first_use;
204  return nullptr;
205}
206
207inline use_info *
208set_info::last_nondebug_insn_use () const
209{
210  if (m_is_set_with_nondebug_insn_uses)
211    return m_first_use->last_use ()->last_nondebug_insn_use ();
212  return nullptr;
213}
214
215inline use_info *
216set_info::first_any_insn_use () const
217{
218  if (m_first_use->is_in_any_insn ())
219    return m_first_use;
220  return nullptr;
221}
222
223inline use_info *
224set_info::last_phi_use () const
225{
226  if (m_first_use)
227    {
228      use_info *last = m_first_use->last_use ();
229      if (last->is_in_phi ())
230	return last;
231    }
232  return nullptr;
233}
234
235inline bool
236set_info::has_nondebug_uses () const
237{
238  return has_nondebug_insn_uses () || has_phi_uses ();
239}
240
241inline bool
242set_info::has_nondebug_insn_uses () const
243{
244  return m_is_set_with_nondebug_insn_uses;
245}
246
247inline bool
248set_info::has_phi_uses () const
249{
250  return m_first_use && m_first_use->last_use ()->is_in_phi ();
251}
252
253inline use_info *
254set_info::single_nondebug_use () const
255{
256  if (!has_phi_uses ())
257    return single_nondebug_insn_use ();
258  if (!has_nondebug_insn_uses ())
259    return single_phi_use ();
260  return nullptr;
261}
262
263inline use_info *
264set_info::single_nondebug_insn_use () const
265{
266  use_info *first = first_nondebug_insn_use ();
267  if (first && !first->next_nondebug_insn_use ())
268    return first;
269  return nullptr;
270}
271
272inline use_info *
273set_info::single_phi_use () const
274{
275  use_info *last = last_phi_use ();
276  if (last && !last->prev_phi_use ())
277    return last;
278  return nullptr;
279}
280
281inline bool
282set_info::is_local_to_ebb () const
283{
284  if (!m_first_use)
285    return true;
286
287  use_info *last = m_first_use->last_use ();
288  if (last->is_in_phi ())
289    return false;
290
291  last = last->last_nondebug_insn_use ();
292  return !last || last->ebb () == ebb ();
293}
294
295inline iterator_range<use_iterator>
296set_info::all_uses () const
297{
298  return { m_first_use, nullptr };
299}
300
301inline iterator_range<reverse_use_iterator>
302set_info::reverse_all_uses () const
303{
304  return { last_use (), nullptr };
305}
306
307inline iterator_range<nondebug_insn_use_iterator>
308set_info::nondebug_insn_uses () const
309{
310  return { first_nondebug_insn_use (), nullptr };
311}
312
313inline iterator_range<reverse_use_iterator>
314set_info::reverse_nondebug_insn_uses () const
315{
316  return { last_nondebug_insn_use (), nullptr };
317}
318
319inline iterator_range<any_insn_use_iterator>
320set_info::all_insn_uses () const
321{
322  return { first_any_insn_use (), nullptr };
323}
324
325inline iterator_range<phi_use_iterator>
326set_info::phi_uses () const
327{
328  return { last_phi_use (), nullptr };
329}
330
331inline use_array
332phi_info::inputs () const
333{
334  if (m_num_inputs == 1)
335    return use_array (&m_single_input, 1);
336  return use_array (m_inputs, m_num_inputs);
337}
338
339inline use_info *
340phi_info::input_use (unsigned int i) const
341{
342  if (m_num_inputs == 1)
343    return as_a<use_info *> (m_single_input);
344  return as_a<use_info *> (m_inputs[i]);
345}
346
347inline set_info *
348phi_info::input_value (unsigned int i) const
349{
350  return input_use (i)->def ();
351}
352
353inline def_info *
354def_node::first_def () const
355{
356  // This should get optimized into an AND with -2.
357  if (m_clobber_or_set.is_first ())
358    return m_clobber_or_set.known_first ();
359  return m_clobber_or_set.known_second ();
360}
361
362inline clobber_info *
363clobber_group::first_clobber () const
364{
365  return m_clobber_or_set.known_first ();
366}
367
368inline iterator_range<def_iterator>
369clobber_group::clobbers () const
370{
371  return { first_clobber (), m_last_clobber->next_def () };
372}
373
374inline def_info *
375def_mux::first_def () const
376{
377  if (is_first ())
378    return known_first ();
379  return known_second ()->first_def ();
380}
381
382inline def_info *
383def_mux::last_def () const
384{
385  if (is_first ())
386    return known_first ();
387
388  def_node *node = known_second ();
389  if (auto *clobber = ::dyn_cast<clobber_group *> (node))
390    return clobber->last_clobber ();
391
392  return node->first_def ();
393}
394
395inline set_info *
396def_mux::set () const
397{
398  if (is_first ())
399    return ::safe_dyn_cast<set_info *> (known_first ());
400  return ::dyn_cast<set_info *> (known_second ()->first_def ());
401}
402
403inline def_info *
404def_lookup::last_def_of_prev_group () const
405{
406  if (!mux)
407    return nullptr;
408
409  if (comparison > 0)
410    return mux.last_def ();
411
412  return mux.first_def ()->prev_def ();
413}
414
415inline def_info *
416def_lookup::first_def_of_next_group () const
417{
418  if (!mux)
419    return nullptr;
420
421  if (comparison < 0)
422    return mux.first_def ();
423
424  return mux.last_def ()->next_def ();
425}
426
427inline set_info *
428def_lookup::matching_set () const
429{
430  if (comparison == 0)
431    return mux.set ();
432  return nullptr;
433}
434
435inline def_info *
436def_lookup::matching_set_or_last_def_of_prev_group () const
437{
438  if (set_info *set = matching_set ())
439    return set;
440  return last_def_of_prev_group ();
441}
442
443inline def_info *
444def_lookup::matching_set_or_first_def_of_next_group () const
445{
446  if (set_info *set = matching_set ())
447    return set;
448  return first_def_of_next_group ();
449}
450
451inline insn_note::insn_note (insn_note_kind kind)
452  : m_next_note (nullptr),
453    m_kind (kind),
454    m_data8 (0),
455    m_data16 (0),
456    m_data32 (0)
457{
458}
459
460template<typename T>
461inline T
462insn_note::as_a ()
463{
464  using deref_type = decltype (*std::declval<T> ());
465  using derived = typename std::remove_reference<deref_type>::type;
466  gcc_checking_assert (m_kind == derived::kind);
467  return static_cast<T> (this);
468}
469
470template<typename T>
471inline T
472insn_note::dyn_cast ()
473{
474  using deref_type = decltype (*std::declval<T> ());
475  using derived = typename std::remove_reference<deref_type>::type;
476  if (m_kind == derived::kind)
477    return static_cast<T> (this);
478  return nullptr;
479}
480
481inline bool
482insn_info::operator< (const insn_info &other) const
483{
484  if (this == &other)
485    return false;
486
487  if (__builtin_expect (m_point != other.m_point, 1))
488    return m_point < other.m_point;
489
490  return slow_compare_with (other) < 0;
491}
492
493inline bool
494insn_info::operator> (const insn_info &other) const
495{
496  return other < *this;
497}
498
499inline bool
500insn_info::operator<= (const insn_info &other) const
501{
502  return !(other < *this);
503}
504
505inline bool
506insn_info::operator>= (const insn_info &other) const
507{
508  return !(*this < other);
509}
510
511inline int
512insn_info::compare_with (const insn_info *other) const
513{
514  if (this == other)
515    return 0;
516
517  if (__builtin_expect (m_point != other->m_point, 1))
518    // Assume that points remain in [0, INT_MAX].
519    return m_point - other->m_point;
520
521  return slow_compare_with (*other);
522}
523
524inline insn_info *
525insn_info::prev_nondebug_insn () const
526{
527  gcc_checking_assert (!is_debug_insn ());
528  return m_prev_insn_or_last_debug_insn.known_first ();
529}
530
531inline insn_info *
532insn_info::next_nondebug_insn () const
533{
534  gcc_checking_assert (!is_debug_insn ());
535  const insn_info *from = this;
536  if (insn_info *first_debug = m_next_nondebug_or_debug_insn.second_or_null ())
537    from = first_debug->last_debug_insn ();
538  return from->m_next_nondebug_or_debug_insn.known_first ();
539}
540
541inline insn_info *
542insn_info::prev_any_insn () const
543{
544  const insn_info *from = this;
545  if (insn_info *last_debug = m_prev_insn_or_last_debug_insn.second_or_null ())
546    // This instruction is the first in a subsequence of debug instructions.
547    // Move to the following nondebug instruction.
548    from = last_debug->m_next_nondebug_or_debug_insn.known_first ();
549  return from->m_prev_insn_or_last_debug_insn.known_first ();
550}
551
552inline insn_info *
553insn_info::next_any_insn () const
554{
555  // This should get optimized into an AND with -2.
556  if (m_next_nondebug_or_debug_insn.is_first ())
557    return m_next_nondebug_or_debug_insn.known_first ();
558  return m_next_nondebug_or_debug_insn.known_second ();
559}
560
561inline bool
562insn_info::is_phi () const
563{
564  return this == ebb ()->phi_insn ();
565}
566
567inline bool
568insn_info::is_bb_head () const
569{
570  return this == m_bb->head_insn ();
571}
572
573inline bool
574insn_info::is_bb_end () const
575{
576  return this == m_bb->end_insn ();
577}
578
579inline ebb_info *
580insn_info::ebb () const
581{
582  return m_bb->ebb ();
583}
584
585inline int
586insn_info::uid () const
587{
588  return m_cost_or_uid < 0 ? m_cost_or_uid : INSN_UID (m_rtl);
589}
590
591inline use_array
592insn_info::uses () const
593{
594  return use_array (m_accesses + m_num_defs, m_num_uses);
595}
596
597inline bool
598insn_info::has_call_clobbers () const
599{
600  return find_note<insn_call_clobbers_note> ();
601}
602
603inline def_array
604insn_info::defs () const
605{
606  return def_array (m_accesses, m_num_defs);
607}
608
609inline unsigned int
610insn_info::cost () const
611{
612  if (m_cost_or_uid < 0)
613    return 0;
614  if (m_cost_or_uid == UNKNOWN_COST)
615    calculate_cost ();
616  return m_cost_or_uid;
617}
618
619template<typename T>
620inline const T *
621insn_info::find_note () const
622{
623  // We could break if the note kind is > T::kind, but since the number
624  // of notes should be very small, the check is unlikely to pay for itself.
625  for (const insn_note *note = first_note (); note; note = note->next_note ())
626    if (note->kind () == T::kind)
627      return static_cast<const T *> (note);
628  return nullptr;
629}
630
631// Only valid for debug instructions that come after a nondebug instruction,
632// and so start a subsequence of debug instructions.  Return the last debug
633// instruction in the subsequence.
634inline insn_info *
635insn_info::last_debug_insn () const
636{
637  return m_prev_insn_or_last_debug_insn.known_second ();
638}
639
640inline insn_range_info::insn_range_info (insn_info *first, insn_info *last)
641  : first (first), last (last)
642{
643}
644
645inline bool
646insn_range_info::operator== (const insn_range_info &other) const
647{
648  return first == other.first && last == other.last;
649}
650
651inline bool
652insn_range_info::operator!= (const insn_range_info &other) const
653{
654  return first != other.first || last != other.last;
655}
656
657inline insn_info *
658insn_range_info::singleton () const
659{
660  return first == last ? last : nullptr;
661}
662
663inline bool
664insn_range_info::includes (insn_info *insn) const
665{
666  return *insn >= *first && *insn <= *last;
667}
668
669inline insn_info *
670insn_range_info::clamp_insn_to_range (insn_info *insn) const
671{
672  if (*first > *insn)
673    return first;
674  if (*last < *insn)
675    return last;
676  return insn;
677}
678
679inline bool
680insn_range_info::is_subrange_of (const insn_range_info &other) const
681{
682  return *first >= *other.first && *last <= *other.last;
683}
684
685inline iterator_range<any_insn_iterator>
686bb_info::all_insns () const
687{
688  return { m_head_insn, m_end_insn->next_any_insn () };
689}
690
691inline iterator_range<reverse_any_insn_iterator>
692bb_info::reverse_all_insns () const
693{
694  return { m_end_insn, m_head_insn->prev_any_insn () };
695}
696
697inline iterator_range<nondebug_insn_iterator>
698bb_info::nondebug_insns () const
699{
700  return { m_head_insn, m_end_insn->next_nondebug_insn () };
701}
702
703inline iterator_range<reverse_nondebug_insn_iterator>
704bb_info::reverse_nondebug_insns () const
705{
706  return { m_end_insn, m_head_insn->prev_nondebug_insn () };
707}
708
709inline iterator_range<any_insn_iterator>
710bb_info::real_insns () const
711{
712  return { m_head_insn->next_any_insn (), m_end_insn };
713}
714
715inline iterator_range<reverse_any_insn_iterator>
716bb_info::reverse_real_insns () const
717{
718  return { m_end_insn->prev_any_insn (), m_head_insn };
719}
720
721inline iterator_range<nondebug_insn_iterator>
722bb_info::real_nondebug_insns () const
723{
724  return { m_head_insn->next_nondebug_insn (), m_end_insn };
725}
726
727inline iterator_range<reverse_nondebug_insn_iterator>
728bb_info::reverse_real_nondebug_insns () const
729{
730  return { m_end_insn->prev_nondebug_insn (), m_head_insn };
731}
732
733inline bool
734ebb_call_clobbers_info::clobbers (resource_info resource) const
735{
736  // Only register clobbers are tracked this way.  Other clobbers are
737  // recorded explicitly.
738  return (resource.is_reg ()
739	  && m_abi->clobbers_reg_p (resource.mode, resource.regno));
740}
741
742inline ebb_info *
743ebb_info::prev_ebb () const
744{
745  if (bb_info *prev_bb = m_first_bb->prev_bb ())
746    return prev_bb->ebb ();
747  return nullptr;
748}
749
750inline ebb_info *
751ebb_info::next_ebb () const
752{
753  if (bb_info *next_bb = m_last_bb->next_bb ())
754    return next_bb->ebb ();
755  return nullptr;
756}
757
758inline iterator_range<phi_iterator>
759ebb_info::phis () const
760{
761  return { m_first_phi, nullptr };
762}
763
764inline iterator_range<bb_iterator>
765ebb_info::bbs () const
766{
767  return { m_first_bb, m_last_bb->next_bb () };
768}
769
770inline iterator_range<reverse_bb_iterator>
771ebb_info::reverse_bbs () const
772{
773  return { m_last_bb, m_first_bb->prev_bb () };
774}
775
776inline iterator_range<any_insn_iterator>
777ebb_info::all_insns () const
778{
779  return { m_phi_insn, m_last_bb->end_insn ()->next_any_insn () };
780}
781
782inline iterator_range<reverse_any_insn_iterator>
783ebb_info::reverse_all_insns () const
784{
785  return { m_last_bb->end_insn (), m_phi_insn->prev_any_insn () };
786}
787
788inline iterator_range<nondebug_insn_iterator>
789ebb_info::nondebug_insns () const
790{
791  return { m_phi_insn, m_last_bb->end_insn ()->next_nondebug_insn () };
792}
793
794inline iterator_range<reverse_nondebug_insn_iterator>
795ebb_info::reverse_nondebug_insns () const
796{
797  return { m_last_bb->end_insn (), m_phi_insn->prev_nondebug_insn () };
798}
799
800inline insn_range_info
801ebb_info::insn_range () const
802{
803  return { m_phi_insn, m_last_bb->end_insn () };
804}
805
806inline void
807ebb_info::set_first_call_clobbers (ebb_call_clobbers_info *call_clobbers)
808{
809  m_first_call_clobbers = call_clobbers;
810}
811
812inline ebb_call_clobbers_info *
813ebb_info::first_call_clobbers () const
814{
815  return m_first_call_clobbers;
816}
817
818inline iterator_range<ebb_call_clobbers_iterator>
819ebb_info::call_clobbers () const
820{
821  return { m_first_call_clobbers, nullptr };
822}
823
824inline insn_change::insn_change (insn_info *insn)
825  : m_insn (insn),
826    new_defs (insn->defs ()),
827    new_uses (insn->uses ()),
828    move_range (insn),
829    new_cost (UNKNOWN_COST),
830    m_is_deletion (false)
831{
832}
833
834inline insn_change::insn_change (insn_info *insn, delete_action)
835  : m_insn (insn),
836    new_defs (),
837    new_uses (),
838    move_range (insn),
839    new_cost (0),
840    m_is_deletion (true)
841{
842}
843
844inline insn_is_changing_closure::
845insn_is_changing_closure (array_slice<insn_change *const> changes)
846  : m_changes (changes)
847{
848}
849
850inline bool
851insn_is_changing_closure::operator() (const insn_info *insn) const
852{
853  for (const insn_change *change : m_changes)
854    if (change->insn () == insn)
855      return true;
856  return false;
857}
858
859inline iterator_range<bb_iterator>
860function_info::bbs () const
861{
862  return { m_first_bb, nullptr };
863}
864
865inline iterator_range<reverse_bb_iterator>
866function_info::reverse_bbs () const
867{
868  return { m_last_bb, nullptr };
869}
870
871inline iterator_range<ebb_iterator>
872function_info::ebbs () const
873{
874  return { m_first_bb->ebb (), nullptr };
875}
876
877inline iterator_range<reverse_ebb_iterator>
878function_info::reverse_ebbs () const
879{
880  return { m_last_bb->ebb (), nullptr };
881}
882
883inline iterator_range<any_insn_iterator>
884function_info::all_insns () const
885{
886  return { m_first_insn, nullptr };
887}
888
889inline iterator_range<reverse_any_insn_iterator>
890function_info::reverse_all_insns () const
891{
892  return { m_last_insn, nullptr };
893}
894
895inline iterator_range<nondebug_insn_iterator>
896function_info::nondebug_insns () const
897{
898  return { m_first_insn, nullptr };
899}
900
901inline iterator_range<reverse_nondebug_insn_iterator>
902function_info::reverse_nondebug_insns () const
903{
904  return { m_last_insn, nullptr };
905}
906
907inline iterator_range<def_iterator>
908function_info::mem_defs () const
909{
910  return { m_defs[0], nullptr };
911}
912
913inline iterator_range<def_iterator>
914function_info::reg_defs (unsigned int regno) const
915{
916  return { m_defs[regno + 1], nullptr };
917}
918
919inline set_info *
920function_info::single_dominating_def (unsigned int regno) const
921{
922  if (set_info *set = safe_dyn_cast<set_info *> (m_defs[regno + 1]))
923    if (is_single_dominating_def (set))
924      return set;
925  return nullptr;
926}
927
928template<typename IgnorePredicate>
929bool
930function_info::add_regno_clobber (obstack_watermark &watermark,
931				  insn_change &change, unsigned int regno,
932				  IgnorePredicate ignore)
933{
934  // Check whether CHANGE already clobbers REGNO.
935  if (find_access (change.new_defs, regno))
936    return true;
937
938  // Get the closest position to INSN at which the new instruction
939  // could be placed.
940  insn_info *insn = change.move_range.clamp_insn_to_range (change.insn ());
941  def_array new_defs = insert_temp_clobber (watermark, insn, regno,
942					    change.new_defs);
943  if (!new_defs.is_valid ())
944    return false;
945
946  // Find a definition at or neighboring INSN.
947  insn_range_info move_range = change.move_range;
948  if (!restrict_movement_for_dead_range (move_range, regno, insn, ignore))
949    return false;
950
951  change.new_defs = new_defs;
952  change.move_range = move_range;
953  return true;
954}
955
956}
957