aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/config/i386/i386-expand.cc86
-rw-r--r--gcc/config/i386/predicates.md7
-rw-r--r--gcc/config/i386/sse.md12
-rw-r--r--gcc/testsuite/gcc.target/i386/pr107546.c19
4 files changed, 113 insertions, 11 deletions
diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index 2e0d12c..9c92b07 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -4510,15 +4510,86 @@ ix86_expand_int_sse_cmp (rtx dest, enum rtx_code code, rtx cop0, rtx cop1,
case GTU:
break;
- case NE:
case LE:
case LEU:
+ /* x <= cst can be handled as x < cst + 1 unless there is
+ wrap around in cst + 1. */
+ if (GET_CODE (cop1) == CONST_VECTOR
+ && GET_MODE_INNER (mode) != TImode)
+ {
+ unsigned int n_elts = GET_MODE_NUNITS (mode), i;
+ machine_mode eltmode = GET_MODE_INNER (mode);
+ for (i = 0; i < n_elts; ++i)
+ {
+ rtx elt = CONST_VECTOR_ELT (cop1, i);
+ if (!CONST_INT_P (elt))
+ break;
+ if (code == GE)
+ {
+ /* For LE punt if some element is signed maximum. */
+ if ((INTVAL (elt) & (GET_MODE_MASK (eltmode) >> 1))
+ == (GET_MODE_MASK (eltmode) >> 1))
+ break;
+ }
+ /* For LEU punt if some element is unsigned maximum. */
+ else if (elt == constm1_rtx)
+ break;
+ }
+ if (i == n_elts)
+ {
+ rtvec v = rtvec_alloc (n_elts);
+ for (i = 0; i < n_elts; ++i)
+ RTVEC_ELT (v, i)
+ = GEN_INT (INTVAL (CONST_VECTOR_ELT (cop1, i)) + 1);
+ cop1 = gen_rtx_CONST_VECTOR (mode, v);
+ std::swap (cop0, cop1);
+ code = code == LE ? GT : GTU;
+ break;
+ }
+ }
+ /* FALLTHRU */
+ case NE:
code = reverse_condition (code);
*negate = true;
break;
case GE:
case GEU:
+ /* x >= cst can be handled as x > cst - 1 unless there is
+ wrap around in cst - 1. */
+ if (GET_CODE (cop1) == CONST_VECTOR
+ && GET_MODE_INNER (mode) != TImode)
+ {
+ unsigned int n_elts = GET_MODE_NUNITS (mode), i;
+ machine_mode eltmode = GET_MODE_INNER (mode);
+ for (i = 0; i < n_elts; ++i)
+ {
+ rtx elt = CONST_VECTOR_ELT (cop1, i);
+ if (!CONST_INT_P (elt))
+ break;
+ if (code == GE)
+ {
+ /* For GE punt if some element is signed minimum. */
+ if (INTVAL (elt) < 0
+ && ((INTVAL (elt) & (GET_MODE_MASK (eltmode) >> 1))
+ == 0))
+ break;
+ }
+ /* For GEU punt if some element is zero. */
+ else if (elt == const0_rtx)
+ break;
+ }
+ if (i == n_elts)
+ {
+ rtvec v = rtvec_alloc (n_elts);
+ for (i = 0; i < n_elts; ++i)
+ RTVEC_ELT (v, i)
+ = GEN_INT (INTVAL (CONST_VECTOR_ELT (cop1, i)) - 1);
+ cop1 = gen_rtx_CONST_VECTOR (mode, v);
+ code = code == GE ? GT : GTU;
+ break;
+ }
+ }
code = reverse_condition (code);
*negate = true;
/* FALLTHRU */
@@ -4556,6 +4627,11 @@ ix86_expand_int_sse_cmp (rtx dest, enum rtx_code code, rtx cop0, rtx cop1,
}
}
+ if (GET_CODE (cop0) == CONST_VECTOR)
+ cop0 = force_reg (mode, cop0);
+ else if (GET_CODE (cop1) == CONST_VECTOR)
+ cop1 = force_reg (mode, cop1);
+
rtx optrue = op_true ? op_true : CONSTM1_RTX (data_mode);
rtx opfalse = op_false ? op_false : CONST0_RTX (data_mode);
if (*negate)
@@ -4752,13 +4828,13 @@ ix86_expand_int_sse_cmp (rtx dest, enum rtx_code code, rtx cop0, rtx cop1,
if (*negate)
std::swap (op_true, op_false);
+ if (GET_CODE (cop1) == CONST_VECTOR)
+ cop1 = force_reg (mode, cop1);
+
/* Allow the comparison to be done in one mode, but the movcc to
happen in another mode. */
if (data_mode == mode)
- {
- x = ix86_expand_sse_cmp (dest, code, cop0, cop1,
- op_true, op_false);
- }
+ x = ix86_expand_sse_cmp (dest, code, cop0, cop1, op_true, op_false);
else
{
gcc_assert (GET_MODE_SIZE (data_mode) == GET_MODE_SIZE (mode));
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 2a3f072..f995503 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -1235,6 +1235,13 @@
(ior (match_operand 0 "register_operand")
(match_operand 0 "vector_memory_operand")))
+; Return true when OP is register_operand, vector_memory_operand
+; or const_vector.
+(define_predicate "vector_or_const_vector_operand"
+ (ior (match_operand 0 "register_operand")
+ (match_operand 0 "vector_memory_operand")
+ (match_code "const_vector")))
+
(define_predicate "bcst_mem_operand"
(and (match_code "vec_duplicate")
(and (match_test "TARGET_AVX512F")
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index fa93ae7..9a4fc01 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -4311,7 +4311,7 @@
[(set (match_operand:<sseintvecmode> 0 "register_operand")
(match_operator:<sseintvecmode> 1 ""
[(match_operand:VI_256 2 "register_operand")
- (match_operand:VI_256 3 "nonimmediate_operand")]))]
+ (match_operand:VI_256 3 "nonimmediate_or_const_vector_operand")]))]
"TARGET_AVX2"
{
bool ok = ix86_expand_int_vec_cmp (operands);
@@ -4323,7 +4323,7 @@
[(set (match_operand:<sseintvecmode> 0 "register_operand")
(match_operator:<sseintvecmode> 1 ""
[(match_operand:VI124_128 2 "register_operand")
- (match_operand:VI124_128 3 "vector_operand")]))]
+ (match_operand:VI124_128 3 "vector_or_const_vector_operand")]))]
"TARGET_SSE2"
{
bool ok = ix86_expand_int_vec_cmp (operands);
@@ -4335,7 +4335,7 @@
[(set (match_operand:V2DI 0 "register_operand")
(match_operator:V2DI 1 ""
[(match_operand:V2DI 2 "register_operand")
- (match_operand:V2DI 3 "vector_operand")]))]
+ (match_operand:V2DI 3 "vector_or_const_vector_operand")]))]
"TARGET_SSE4_2"
{
bool ok = ix86_expand_int_vec_cmp (operands);
@@ -4397,7 +4397,7 @@
[(set (match_operand:<sseintvecmode> 0 "register_operand")
(match_operator:<sseintvecmode> 1 ""
[(match_operand:VI_256 2 "register_operand")
- (match_operand:VI_256 3 "nonimmediate_operand")]))]
+ (match_operand:VI_256 3 "nonimmediate_or_const_vector_operand")]))]
"TARGET_AVX2"
{
bool ok = ix86_expand_int_vec_cmp (operands);
@@ -4409,7 +4409,7 @@
[(set (match_operand:<sseintvecmode> 0 "register_operand")
(match_operator:<sseintvecmode> 1 ""
[(match_operand:VI124_128 2 "register_operand")
- (match_operand:VI124_128 3 "vector_operand")]))]
+ (match_operand:VI124_128 3 "vector_or_const_vector_operand")]))]
"TARGET_SSE2"
{
bool ok = ix86_expand_int_vec_cmp (operands);
@@ -4421,7 +4421,7 @@
[(set (match_operand:V2DI 0 "register_operand")
(match_operator:V2DI 1 ""
[(match_operand:V2DI 2 "register_operand")
- (match_operand:V2DI 3 "vector_operand")]))]
+ (match_operand:V2DI 3 "vector_or_const_vector_operand")]))]
"TARGET_SSE4_2"
{
bool ok = ix86_expand_int_vec_cmp (operands);
diff --git a/gcc/testsuite/gcc.target/i386/pr107546.c b/gcc/testsuite/gcc.target/i386/pr107546.c
new file mode 100644
index 0000000..e5cf56d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr107546.c
@@ -0,0 +1,19 @@
+/* PR target/107546 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -mno-xop -mno-avx512f" } */
+/* { dg-final { scan-assembler-not "pcmpeqb\t" } } */
+/* { dg-final { scan-assembler-times "pcmpgtb\t" 2 } } */
+
+typedef signed char V __attribute__((vector_size(16)));
+
+V
+foo (V x)
+{
+ return x < 48;
+}
+
+V
+bar (V x)
+{
+ return x >= (V) { 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57 };
+}