[gcc(refs/users/marxin/heads/marxin-gcc-benchmark-branch)] i386: Fix splitters that call extract_insn_cached [PR93611]

Martin Liska marxin@gcc.gnu.org
Mon Mar 30 10:51:43 GMT 2020


https://gcc.gnu.org/g:e7bec5d5edeaab404931bf599821c6c2a3023b47

commit e7bec5d5edeaab404931bf599821c6c2a3023b47
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Fri Feb 7 09:26:54 2020 +0100

    i386: Fix splitters that call extract_insn_cached [PR93611]
    
    The following testcase ICEs.  The generated split_insns starts
    with recog_data.insn = NULL and then tries to put various operands into
    recog_data.operand array and checks various splitter conditions.
    The problem is that some atom related tuning splitters indirectly call
    extract_insn_cached on the insn they are used in.  This can change
    recog_data.operand, but most likely it will just keep it as is, but
    sets recog_data.insn to the current instruction.  If that splitter doesn't
    match, we continue trying some other split conditions and modify
    recog_data.operand array again.  If even that doesn't find any usable
    splitter, we punt, but at that point recog_data.insn says that recog_data
    is valid for that particular instruction, even when recog_data.operand array
    can be anything.
    The safest thing would be to copy whole recog_data to a temporary object
    before doing the calls that can call extract_insn_cached and restore it
    afterwards, but it would be also very costly, recog_data has 1280 bytes.
    So, this patch just makes sure to clear recog_data.insn if it has changed
    during the extract_insn_cached call, which means if we extract_insn_cached
    later, we'll extract it properly, while if we call it say from some other
    context than splitter conditions, the insn is already cached, we don't reset
    the cache.
    
    2020-02-07  Jakub Jelinek  <jakub@redhat.com>
    
            PR target/93611
            * config/i386/i386.c (ix86_lea_outperforms): Make sure to clear
            recog_data.insn if distance_non_agu_define changed it.
    
            * gcc.target/i386/pr93611.c: New test.

Diff:
---
 gcc/ChangeLog                           | 6 ++++++
 gcc/config/i386/i386.c                  | 9 +++++++++
 gcc/testsuite/ChangeLog                 | 5 +++++
 gcc/testsuite/gcc.target/i386/pr93611.c | 5 +++++
 4 files changed, 25 insertions(+)

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9797dd4e81f..56090a9e0b6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2020-02-07  Jakub Jelinek  <jakub@redhat.com>
+
+	PR target/93611
+	* config/i386/i386.c (ix86_lea_outperforms): Make sure to clear
+	recog_data.insn if distance_non_agu_define changed it.
+
 2020-02-06  Michael Meissner  <meissner@linux.ibm.com>
 
 	PR target/93569
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index ffda3e8fd21..556ca82a2b3 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -14459,9 +14459,18 @@ ix86_lea_outperforms (rtx_insn *insn, unsigned int regno0, unsigned int regno1,
       return true;
     }
 
+  rtx_insn *rinsn = recog_data.insn;
+
   dist_define = distance_non_agu_define (regno1, regno2, insn);
   dist_use = distance_agu_use (regno0, insn);
 
+  /* distance_non_agu_define can call extract_insn_cached.  If this function
+     is called from define_split conditions, that can break insn splitting,
+     because split_insns works by clearing recog_data.insn and then modifying
+     recog_data.operand array and match the various split conditions.  */
+  if (recog_data.insn != rinsn)
+    recog_data.insn = NULL;
+
   if (dist_define < 0 || dist_define >= LEA_MAX_STALL)
     {
       /* If there is no non AGU operand definition, no AGU
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a6fbf5bec59..6be609acf3f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2020-02-07  Jakub Jelinek  <jakub@redhat.com>
+
+	PR target/93611
+	* gcc.target/i386/pr93611.c: New test.
+
 2020-02-06  David Malcolm  <dmalcolm@redhat.com>
 
 	PR analyzer/93375
diff --git a/gcc/testsuite/gcc.target/i386/pr93611.c b/gcc/testsuite/gcc.target/i386/pr93611.c
new file mode 100644
index 00000000000..2a0e816b1e4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr93611.c
@@ -0,0 +1,5 @@
+/* PR target/93611 */
+/* { dg-do compile } */
+/* { dg-options "-fira-algorithm=priority -O3 -mtune=bonnell" } */
+
+#include "../../gcc.dg/vect/pr58508.c"


More information about the Gcc-cvs mailing list