Jeff Law via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
> On 11/13/20 1:19 AM, Richard Sandiford via Gcc-patches wrote:
>> In some cases, it can be convenient to roll back the changes that
>> have been made by validate_change to see how things looked before,
>> then reroll the changes.  For example, this makes it possible
>> to defer calculating the cost of an instruction until we know that
>> the result is actually needed.  It can also make dumps easier to read.
>>
>> This patch adds a couple of helper functions for doing that.
>>
>> gcc/
>>      * recog.h (temporarily_undo_changes, redo_changes): Declare.
>>      * recog.c (swap_change, temporarily_undo_changes): New functions.
>>      (redo_changes): Likewise.
> OK...  But...
> +
>> +/* Temporarily undo all the changes numbered NUM and up, with a view
>> +   to reapplying them later.  The next call to the changes machinery
>> +   must be:
>> +
>> +      redo_changes (NUM)
>> +
>> +   otherwise things will end up in an invalid state.  */
> It'd be nice if we had state validation in the other routines. Somebody
> is likely to mess this up at some point...

Yeah, good point, can definitely see myself doing that. :-)

Here's the version I committed, with temporarily_undone_changes tracking
what has been undone.

Thanks,
Richard


gcc/
        * recog.h (temporarily_undo_changes, redo_changes): Declare.
        * recog.c (temporarily_undone_changes): New variable.
        (validate_change_1, confirm_change_group): Check that it's zero.
        (cancel_changes): Likewise.
        (swap_change, temporarily_undo_changes): New functions.
        (redo_changes): Likewise.
---
 gcc/recog.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 gcc/recog.h |  2 ++
 2 files changed, 50 insertions(+)

diff --git a/gcc/recog.c b/gcc/recog.c
index 65125b8f0d1..cee481f4fa0 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -193,6 +193,7 @@ static change_t *changes;
 static int changes_allocated;
 
 static int num_changes = 0;
+static int temporarily_undone_changes = 0;
 
 /* Validate a proposed change to OBJECT.  LOC is the location in the rtl
    at which NEW_RTX will be placed.  If NEW_LEN is >= 0, XVECLEN (NEW_RTX, 0)
@@ -218,6 +219,7 @@ static bool
 validate_change_1 (rtx object, rtx *loc, rtx new_rtx, bool in_group,
                   bool unshare, int new_len = -1)
 {
+  gcc_assert (temporarily_undone_changes == 0);
   rtx old = *loc;
 
   /* Single-element parallels aren't valid and won't match anything.
@@ -506,6 +508,7 @@ confirm_change_group (void)
   int i;
   rtx last_object = NULL;
 
+  gcc_assert (temporarily_undone_changes == 0);
   for (i = 0; i < num_changes; i++)
     {
       rtx object = changes[i].object;
@@ -561,6 +564,7 @@ num_validated_changes (void)
 void
 cancel_changes (int num)
 {
+  gcc_assert (temporarily_undone_changes == 0);
   int i;
 
   /* Back out all the changes.  Do this in the opposite order in which
@@ -577,6 +581,50 @@ cancel_changes (int num)
   num_changes = num;
 }
 
+/* Swap the status of change NUM from being applied to not being applied,
+   or vice versa.  */
+
+static void
+swap_change (int num)
+{
+  if (changes[num].old_len >= 0)
+    std::swap (XVECLEN (*changes[num].loc, 0), changes[num].old_len);
+  else
+    std::swap (*changes[num].loc, changes[num].old);
+  if (changes[num].object && !MEM_P (changes[num].object))
+    std::swap (INSN_CODE (changes[num].object), changes[num].old_code);
+}
+
+/* Temporarily undo all the changes numbered NUM and up, with a view
+   to reapplying them later.  The next call to the changes machinery
+   must be:
+
+      redo_changes (NUM)
+
+   otherwise things will end up in an invalid state.  */
+
+void
+temporarily_undo_changes (int num)
+{
+  gcc_assert (temporarily_undone_changes == 0 && num <= num_changes);
+  for (int i = num_changes - 1; i >= num; i--)
+    swap_change (i);
+  temporarily_undone_changes = num_changes - num;
+}
+
+/* Redo the changes that were temporarily undone by:
+
+      temporarily_undo_changes (NUM).  */
+
+void
+redo_changes (int num)
+{
+  gcc_assert (temporarily_undone_changes == num_changes - num);
+  for (int i = num; i < num_changes; ++i)
+    swap_change (i);
+  temporarily_undone_changes = 0;
+}
+
 /* Reduce conditional compilation elsewhere.  */
 /* A subroutine of validate_replace_rtx_1 that tries to simplify the resulting
    rtx.  */
diff --git a/gcc/recog.h b/gcc/recog.h
index e152e2bb591..facf36e7c08 100644
--- a/gcc/recog.h
+++ b/gcc/recog.h
@@ -96,6 +96,8 @@ extern void confirm_change_group (void);
 extern int apply_change_group (void);
 extern int num_validated_changes (void);
 extern void cancel_changes (int);
+extern void temporarily_undo_changes (int);
+extern void redo_changes (int);
 extern int constrain_operands (int, alternative_mask);
 extern int constrain_operands_cached (rtx_insn *, int);
 extern int memory_address_addr_space_p (machine_mode, rtx, addr_space_t);

Reply via email to