From: Tamar Christina Date: Mon, 6 Dec 2021 10:15:15 +0000 (+0000) Subject: cse: Make sure duplicate elements are not entered into the equivalence set [PR103404] X-Git-Tag: upstream/12.2.0~2896 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c2c843849a3392654d1c2191bd9931c0fff1f8ce;p=platform%2Fupstream%2Fgcc.git 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 --git a/gcc/cse.c b/gcc/cse.c index c1c7d0c..dc5d5ae 100644 --- a/gcc/cse.c +++ b/gcc/cse.c @@ -4275,7 +4275,12 @@ find_sets_in_insn (rtx_insn *insn, vec *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 0000000..66f3364 --- /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);) + ; +} +