public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-5801] cse: Make sure duplicate elements are not entered into the equivalence set [PR103404]
@ 2021-12-06 10:16 Tamar Christina
  0 siblings, 0 replies; only message in thread
From: Tamar Christina @ 2021-12-06 10:16 UTC (permalink / raw)
  To: gcc-cvs

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

commit r12-5801-gc2c843849a3392654d1c2191bd9931c0fff1f8ce
Author: Tamar Christina <tamar.christina@arm.com>
Date:   Mon Dec 6 10:15:15 2021 +0000

    cse: Make sure duplicate elements are not entered into the equivalence set [PR103404]
    
    CSE uses equivalence classes to keep track of expressions that all have the same
    values at the current point in the program.
    
    Normal equivalences through SETs only insert and perform lookups in this set but
    equivalence determined from comparisons, e.g.
    
    (insn 46 44 47 7 (set (reg:CCZ 17 flags)
            (compare:CCZ (reg:SI 105 [ iD.2893 ])
                (const_int 0 [0]))) "cse.c":18:22 7 {*cmpsi_ccno_1}
         (expr_list:REG_DEAD (reg:SI 105 [ iD.2893 ])
            (nil)))
    
    creates the equivalence EQ on (reg:SI 105 [ iD.2893 ]) and (const_int 0 [0]).
    
    This causes a merge to happen between the two equivalence sets denoted by
    (const_int 0 [0]) and (reg:SI 105 [ iD.2893 ]) respectively.
    
    The operation happens through merge_equiv_classes however this function has an
    invariant that the classes to be merge not contain any duplicates.  This is
    because it frees entries before merging.
    
    The given testcase when using the supplied flags trigger an ICE due to the
    equivalence set being
    
    (rr) p dump_class (class1)
    Equivalence chain for (reg:SI 105 [ iD.2893 ]):
    (reg:SI 105 [ iD.2893 ])
    $3 = void
    
    (rr) p dump_class (class2)
    Equivalence chain for (const_int 0 [0]):
    (const_int 0 [0])
    (reg:SI 97 [ _10 ])
    (reg:SI 97 [ _10 ])
    $4 = void
    
    This happens because the original INSN being recorded is
    
    (insn 18 17 24 2 (set (subreg:V1SI (reg:SI 97 [ _10 ]) 0)
            (const_vector:V1SI [
                    (const_int 0 [0])
                ])) "cse.c":11:9 1363 {*movv1si_internal}
         (expr_list:REG_UNUSED (reg:SI 97 [ _10 ])
            (nil)))
    
    and we end up generating two equivalences. the first one is simply that
    reg:SI 97 is 0.  The second one is that 0 can be extracted from the V1SI, so
    subreg (subreg:V1SI (reg:SI 97) 0) 0 == 0.  This nested subreg gets folded away
    to just reg:SI 97 and we re-insert the same equivalence.
    
    This patch changes it so that if the nunits of a subreg is 1 then don't generate
    a vec_select from the subreg as the subreg will be folded away and we get a dup.
    
    gcc/ChangeLog:
    
            PR rtl-optimization/103404
            * cse.c (find_sets_in_insn): Don't select elements out of a V1 mode
            subreg.
    
    gcc/testsuite/ChangeLog:
    
            PR rtl-optimization/103404
            * gcc.target/i386/pr103404.c: New test.

Diff:
---
 gcc/cse.c                                |  7 ++++++-
 gcc/testsuite/gcc.target/i386/pr103404.c | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/gcc/cse.c b/gcc/cse.c
index c1c7d0ca27b..dc5d5aed047 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -4275,7 +4275,12 @@ find_sets_in_insn (rtx_insn *insn, vec<struct set> *psets)
       else if (GET_CODE (SET_SRC (x)) == CALL)
 	;
       else if (GET_CODE (SET_SRC (x)) == CONST_VECTOR
-	       && GET_MODE_CLASS (GET_MODE (SET_SRC (x))) != MODE_VECTOR_BOOL)
+	       && GET_MODE_CLASS (GET_MODE (SET_SRC (x))) != MODE_VECTOR_BOOL
+	       /* Prevent duplicates from being generated if the type is a V1
+		  type and a subreg.  Folding this will result in the same
+		  element as folding x itself.  */
+	       && !(SUBREG_P (SET_DEST (x))
+		    && known_eq (GET_MODE_NUNITS (GET_MODE (SET_SRC (x))), 1)))
 	{
 	  /* First register the vector itself.  */
 	  add_to_set (psets, x);
diff --git a/gcc/testsuite/gcc.target/i386/pr103404.c b/gcc/testsuite/gcc.target/i386/pr103404.c
new file mode 100644
index 00000000000..66f33645301
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr103404.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Og -fcse-follow-jumps -fno-dce -fno-early-inlining -fgcse -fharden-conditional-branches -frerun-cse-after-loop -fno-tree-ccp -mavx5124fmaps -std=c99 -w" } */
+
+typedef unsigned __attribute__((__vector_size__ (4))) U;
+typedef unsigned __attribute__((__vector_size__ (16))) V;
+typedef unsigned __attribute__((__vector_size__ (64))) W;
+
+int x, y;
+
+V v;
+W w;
+
+inline
+int bar (U a)
+{
+  a |= x;
+  W k =
+    __builtin_shufflevector (v, 5 / a,
+			     2, 4, 0, 2, 4, 1, 0, 1,
+			     1, 2, 1, 3, 0, 4, 4, 0);
+  w = k;
+  y = 0;
+}
+
+int
+foo ()
+{
+  bar ((U){0xffffffff});
+  for (unsigned i; i < sizeof (foo);)
+    ;
+}
+


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-12-06 10:16 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-06 10:16 [gcc r12-5801] cse: Make sure duplicate elements are not entered into the equivalence set [PR103404] Tamar Christina

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).