From 57c811f25e0735e744d255b3d66a86dbb131749c Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Sun, 6 Mar 2016 06:40:31 -0800
Subject: [PATCH] Allow all 1s of integer as standard SSE constants
Since all 1s in TImode is standard SSE2 constants, all 1s in OImode is
standard AVX2 constants and all 1s in XImode is standard AVX512F constants,
pass mode to standard_sse_constant_p and standard_sse_constant_opcode
to check if all 1s is available for target.
* config/i386/i386-protos.h (standard_sse_constant_p): Take
machine_mode with VOIDmode as default.
* config/i386/i386.c (standard_sse_constant_p): Get mode if
it is VOIDmode. Return 2 for all 1s of integer in supported
modes.
(ix86_expand_vector_move): Pass mode to standard_sse_constant_p.
* config/i386/i386.md (*movxi_internal_avx512f): Replace
vector_move_operand with nonimmediate_or_sse_const_operand and
use BC instead of C in constraint. Check register_operand
instead of MEM_P.
(*movoi_internal_avx): Add a "BC" alternative for AVX2. Check
register_operand instead of MEM_P.
(*movti_internal): Add a "BC" alternative for SSE2. Check
register_operand instead of MEM_P for SSE.
---
gcc/config/i386/i386-protos.h | 2 +-
gcc/config/i386/i386.c | 27 ++++++++++++++++++++-------
gcc/config/i386/i386.md | 39 ++++++++++++++++++++++++---------------
3 files changed, 45 insertions(+), 23 deletions(-)
@@ -50,7 +50,7 @@ extern bool ix86_using_red_zone (void);
extern int standard_80387_constant_p (rtx);
extern const char *standard_80387_constant_opcode (rtx);
extern rtx standard_80387_constant_rtx (int);
-extern int standard_sse_constant_p (rtx);
+extern int standard_sse_constant_p (rtx, machine_mode = VOIDmode);
extern const char *standard_sse_constant_opcode (rtx_insn *, rtx);
extern bool symbolic_reference_mentioned_p (rtx);
extern bool extended_reg_mentioned_p (rtx);
@@ -10766,18 +10766,31 @@ standard_80387_constant_rtx (int idx)
in supported SSE/AVX vector mode. */
int
-standard_sse_constant_p (rtx x)
+standard_sse_constant_p (rtx x, machine_mode mode)
{
- machine_mode mode;
-
if (!TARGET_SSE)
return 0;
- mode = GET_MODE (x);
-
+ if (mode == VOIDmode)
+ mode = GET_MODE (x);
+
if (x == const0_rtx || x == CONST0_RTX (mode))
return 1;
- if (vector_all_ones_operand (x, mode))
+ if (CONST_INT_P (x))
+ {
+ /* If mode != VOIDmode, standard_sse_constant_p must be called:
+ 1. On TImode with SSE2.
+ 2. On OImode with AVX2.
+ 3. On XImode with AVX512F.
+ */
+ if ((HOST_WIDE_INT) INTVAL (x) == HOST_WIDE_INT_M1
+ && (mode == VOIDmode
+ || (mode == TImode && TARGET_SSE2)
+ || (mode == OImode && TARGET_AVX2)
+ || (mode == XImode && TARGET_AVX512F)))
+ return 2;
+ }
+ else if (vector_all_ones_operand (x, mode))
switch (mode)
{
case V16QImode:
@@ -18758,7 +18771,7 @@ ix86_expand_vector_move (machine_mode mode, rtx operands[])
&& (CONSTANT_P (op1)
|| (SUBREG_P (op1)
&& CONSTANT_P (SUBREG_REG (op1))))
- && !standard_sse_constant_p (op1))
+ && !standard_sse_constant_p (op1, mode))
op1 = validize_mem (force_const_mem (mode, op1));
/* We need to check memory alignment for SSE mode since attribute
@@ -1970,9 +1970,11 @@
(set_attr "length_immediate" "1")])
(define_insn "*movxi_internal_avx512f"
- [(set (match_operand:XI 0 "nonimmediate_operand" "=v,v ,m")
- (match_operand:XI 1 "vector_move_operand" "C ,vm,v"))]
- "TARGET_AVX512F && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ [(set (match_operand:XI 0 "nonimmediate_operand" "=v,v ,m")
+ (match_operand:XI 1 "nonimmediate_or_sse_const_operand" "BC,vm,v"))]
+ "TARGET_AVX512F
+ && (register_operand (operands[0], XImode)
+ || register_operand (operands[1], XImode))"
{
switch (which_alternative)
{
@@ -1994,9 +1996,11 @@
(set_attr "mode" "XI")])
(define_insn "*movoi_internal_avx"
- [(set (match_operand:OI 0 "nonimmediate_operand" "=v,v ,m")
- (match_operand:OI 1 "vector_move_operand" "C ,vm,v"))]
- "TARGET_AVX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ [(set (match_operand:OI 0 "nonimmediate_operand" "=v,v,v ,m")
+ (match_operand:OI 1 "nonimmediate_or_sse_const_operand" "BC,C,vm,v"))]
+ "TARGET_AVX
+ && (register_operand (operands[0], OImode)
+ || register_operand (operands[1], OImode))"
{
switch (get_attr_type (insn))
{
@@ -2028,7 +2032,8 @@
gcc_unreachable ();
}
}
- [(set_attr "type" "sselog1,ssemov,ssemov")
+ [(set_attr "isa" "avx2,*,*,*")
+ (set_attr "type" "sselog1,sselog1,ssemov,ssemov")
(set_attr "prefix" "vex")
(set (attr "mode")
(cond [(ior (match_operand 0 "ext_sse_reg_operand")
@@ -2036,17 +2041,21 @@
(const_string "XI")
(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
(const_string "V8SF")
- (and (eq_attr "alternative" "2")
+ (and (eq_attr "alternative" "3")
(match_test "TARGET_SSE_TYPELESS_STORES"))
(const_string "V8SF")
]
(const_string "OI")))])
(define_insn "*movti_internal"
- [(set (match_operand:TI 0 "nonimmediate_operand" "=!r ,o ,v,v ,m")
- (match_operand:TI 1 "general_operand" "riFo,re,C,vm,v"))]
- "(TARGET_64BIT || TARGET_SSE)
- && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=!r ,o ,v ,v,v ,m")
+ (match_operand:TI 1 "general_operand" "riFo,re,BC,C,vm,v"))]
+ "(TARGET_64BIT
+ && !(MEM_P (operands[0]) && MEM_P (operands[1])))
+ || (TARGET_SSE
+ && nonimmediate_or_sse_const_operand (operands[1], TImode)
+ && (register_operand (operands[0], TImode)
+ || register_operand (operands[1], TImode)))"
{
switch (get_attr_type (insn))
{
@@ -2083,8 +2092,8 @@
gcc_unreachable ();
}
}
- [(set_attr "isa" "x64,x64,*,*,*")
- (set_attr "type" "multi,multi,sselog1,ssemov,ssemov")
+ [(set_attr "isa" "x64,x64,sse2,*,*,*")
+ (set_attr "type" "multi,multi,sselog1,sselog1,ssemov,ssemov")
(set (attr "prefix")
(if_then_else (eq_attr "type" "sselog1,ssemov")
(const_string "maybe_vex")
@@ -2098,7 +2107,7 @@
(ior (not (match_test "TARGET_SSE2"))
(match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL"))
(const_string "V4SF")
- (and (eq_attr "alternative" "4")
+ (and (eq_attr "alternative" "5")
(match_test "TARGET_SSE_TYPELESS_STORES"))
(const_string "V4SF")
(match_test "TARGET_AVX")
--
2.5.5