diff --git a/gcc/config/i386/i386-features.cc b/gcc/config/i386/i386-features.cc index fd212262..4bf8bb3 100644 --- a/gcc/config/i386/i386-features.cc +++ b/gcc/config/i386/i386-features.cc @@ -1756,6 +1756,19 @@ pseudo_reg_set (rtx_insn *insn) return set; } +/* Return true if the register REG is defined in a single DEF chain. + If it is defined in more than one DEF chains, we may not be able + to convert it in all chains. */ + +static bool +single_def_chain_p (rtx reg) +{ + df_ref ref = DF_REG_DEF_CHAIN (REGNO (reg)); + if (!ref) + return false; + return DF_REF_NEXT_REG (ref) == nullptr; +} + /* Check if comparison INSN may be transformed into vector comparison. Currently we transform equality/inequality checks which look like: (set (reg:CCZ 17 flags) (compare:CCZ (reg:TI x) (reg:TI y))) */ @@ -1972,9 +1985,14 @@ timode_scalar_to_vector_candidate_p (rtx_insn *insn) && !TARGET_SSE_UNALIGNED_STORE_OPTIMAL) return false; + if (REG_P (dst) && !single_def_chain_p (dst)) + return false; + switch (GET_CODE (src)) { case REG: + return single_def_chain_p (src); + case CONST_WIDE_INT: return true; diff --git a/gcc/testsuite/gcc.target/i386/pr106933-1.c b/gcc/testsuite/gcc.target/i386/pr106933-1.c new file mode 100644 index 0000000..bcd9576 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr106933-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O2" } */ + +short int +bar (void); + +__int128 +empty (void) +{ +} + +__attribute__ ((simd)) int +foo (__int128 *p) +{ + int a = 0x80000000; + + *p = empty (); + + return *p == (a < bar ()); +} + diff --git a/gcc/testsuite/gcc.target/i386/pr106933-2.c b/gcc/testsuite/gcc.target/i386/pr106933-2.c new file mode 100644 index 0000000..ac7d07e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr106933-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-msse4 -Os" } */ + +__int128 n; + +__int128 +empty (void) +{ +} + +int +foo (void) +{ + n = empty (); + + return n == 0; +} diff --git a/gcc/testsuite/gcc.target/i386/pr106959-1.c b/gcc/testsuite/gcc.target/i386/pr106959-1.c new file mode 100644 index 0000000..4bac2a7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr106959-1.c @@ -0,0 +1,26 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-msse4 -O2 -fno-tree-loop-im --param max-combine-insns=2 -Wno-shift-count-overflow" } */ + +unsigned __int128 n; + +int +foo (int x) +{ + __int128 a = 0; + int b = !!(n * 2); + + while (x < 2) + { + if (a) + { + if (n) + n ^= 1; + else + x <<= 32; + } + + a = 1; + } + + return b; +} diff --git a/gcc/testsuite/gcc.target/i386/pr106959-2.c b/gcc/testsuite/gcc.target/i386/pr106959-2.c new file mode 100644 index 0000000..29f0c47 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr106959-2.c @@ -0,0 +1,26 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-msse4 -O2 -fno-tree-loop-im -Wno-shift-count-overflow" } */ + +unsigned __int128 n; + +int +foo (int x) +{ + __int128 a = 0; + int b = !!(n * 2); + + while (x < 2) + { + if (a) + { + if (n) + n ^= 1; + else + x <<= 32; + } + + a = 1; + } + + return b; +} diff --git a/gcc/testsuite/gcc.target/i386/pr106959-3.c b/gcc/testsuite/gcc.target/i386/pr106959-3.c new file mode 100644 index 0000000..0f58f13 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr106959-3.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O2 -fpeel-loops" } */ + +unsigned __int128 m; +int n; + +__attribute__ ((simd)) void +foo (int x) +{ + x = n ? n : (short int) x; + if (x) + m /= 2; +} +