[PATCH] Allow all 1s of integer as standard SSE constants
Uros Bizjak
ubizjak@gmail.com
Thu Apr 21 07:37:00 GMT 2016
On Wed, Apr 20, 2016 at 9:53 PM, H.J. Lu <hongjiu.lu@intel.com> wrote:
> 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.
>
> Tested on Linux/x86-64. OK for master?
No.
This patch should use "isa" attribute instead of adding even more
similar patterns. Also, please leave MEM_P checks, the rare C->m move
can be easily resolved by IRA.
Also, the mode checks should be in the predicate,
standard_sse_constant_p just validates if the constant is allowed by
ISA.
Uros.
> BTW, it will be used to fix
>
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70155
>
>
> H.J.
> ---
> * 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. Pass mode to standard_sse_constant_opcode.
> (*movoi_internal_avx): Disabled for TARGET_AVX2. Check
> register_operand instead of MEM_P.
> (*movoi_internal_avx2): New pattern.
> (*movti_internal_sse): Likewise.
> (*movti_internal): Renamed to ...
> (*movti_internal_sse2): This. Require SSE2. Use BC instead of
> C in constraint. Check register_operand instead of MEM_P in
> 32-bit mode.
> ---
> gcc/config/i386/i386-protos.h | 2 +-
> gcc/config/i386/i386.c | 27 ++++++++---
> gcc/config/i386/i386.md | 104 ++++++++++++++++++++++++++++++++++++++++--
> 3 files changed, 121 insertions(+), 12 deletions(-)
>
> diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
> index ff47bc1..cf54189 100644
> --- a/gcc/config/i386/i386-protos.h
> +++ b/gcc/config/i386/i386-protos.h
> @@ -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);
> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> index 6379313..dd951c2 100644
> --- a/gcc/config/i386/i386.c
> +++ b/gcc/config/i386/i386.c
> @@ -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
> diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> index babd0a4..75227aa 100644
> --- a/gcc/config/i386/i386.md
> +++ b/gcc/config/i386/i386.md
> @@ -1971,8 +1971,10 @@
>
> (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]))"
> + (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)
> {
> @@ -1996,7 +1998,10 @@
> (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]))"
> + "TARGET_AVX
> + && !TARGET_AVX2
> + && (register_operand (operands[0], OImode)
> + || register_operand (operands[1], OImode))"
> {
> switch (get_attr_type (insn))
> {
> @@ -2042,10 +2047,62 @@
> ]
> (const_string "OI")))])
>
> -(define_insn "*movti_internal"
> +(define_insn "*movoi_internal_avx2"
> + [(set (match_operand:OI 0 "nonimmediate_operand" "=v,v ,m")
> + (match_operand:OI 1 "nonimmediate_or_sse_const_operand" "BC,vm,v"))]
> + "TARGET_AVX2
> + && (register_operand (operands[0], OImode)
> + || register_operand (operands[1], OImode))"
> +{
> + switch (get_attr_type (insn))
> + {
> + case TYPE_SSELOG1:
> + return standard_sse_constant_opcode (insn, operands[1]);
> +
> + case TYPE_SSEMOV:
> + if (misaligned_operand (operands[0], OImode)
> + || misaligned_operand (operands[1], OImode))
> + {
> + if (get_attr_mode (insn) == MODE_V8SF)
> + return "vmovups\t{%1, %0|%0, %1}";
> + else if (get_attr_mode (insn) == MODE_XI)
> + return "vmovdqu32\t{%1, %0|%0, %1}";
> + else
> + return "vmovdqu\t{%1, %0|%0, %1}";
> + }
> + else
> + {
> + if (get_attr_mode (insn) == MODE_V8SF)
> + return "vmovaps\t{%1, %0|%0, %1}";
> + else if (get_attr_mode (insn) == MODE_XI)
> + return "vmovdqa32\t{%1, %0|%0, %1}";
> + else
> + return "vmovdqa\t{%1, %0|%0, %1}";
> + }
> +
> + default:
> + gcc_unreachable ();
> + }
> +}
> + [(set_attr "type" "sselog1,ssemov,ssemov")
> + (set_attr "prefix" "vex")
> + (set (attr "mode")
> + (cond [(ior (match_operand 0 "ext_sse_reg_operand")
> + (match_operand 1 "ext_sse_reg_operand"))
> + (const_string "XI")
> + (match_test "TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL")
> + (const_string "V8SF")
> + (and (eq_attr "alternative" "2")
> + (match_test "TARGET_SSE_TYPELESS_STORES"))
> + (const_string "V8SF")
> + ]
> + (const_string "OI")))])
> +
> +(define_insn "*movti_internal_sse"
> [(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)
> + && !TARGET_SSE2
> && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
> {
> switch (get_attr_type (insn))
> @@ -2061,6 +2118,45 @@
> to stack may result in unaligned memory access. */
> if (misaligned_operand (operands[0], TImode)
> || misaligned_operand (operands[1], TImode))
> + return "%vmovups\t{%1, %0|%0, %1}";
> + else
> + return "%vmovaps\t{%1, %0|%0, %1}";
> +
> + default:
> + gcc_unreachable ();
> + }
> +}
> + [(set_attr "isa" "x64,x64,*,*,*")
> + (set_attr "type" "multi,multi,sselog1,ssemov,ssemov")
> + (set_attr "prefix" "orig")
> + (set (attr "mode")
> + (cond [(eq_attr "alternative" "0,1")
> + (const_string "DI")]
> + (const_string "TI")))])
> +
> +(define_insn "*movti_internal_sse2"
> + [(set (match_operand:TI 0 "nonimmediate_operand" "=!r ,o ,v, v ,m")
> + (match_operand:TI 1 "general_operand" "riFo,re,BC,vm,v"))]
> + "TARGET_SSE2
> + && ((TARGET_64BIT
> + && !(MEM_P (operands[0]) && MEM_P (operands[1])))
> + || (!TARGET_64BIT
> + && (register_operand (operands[0], TImode)
> + || register_operand (operands[1], TImode))))"
> +{
> + switch (get_attr_type (insn))
> + {
> + case TYPE_MULTI:
> + return "#";
> +
> + case TYPE_SSELOG1:
> + return standard_sse_constant_opcode (insn, operands[1]);
> +
> + case TYPE_SSEMOV:
> + /* TDmode values are passed as TImode on the stack. Moving them
> + to stack may result in unaligned memory access. */
> + if (misaligned_operand (operands[0], TImode)
> + || misaligned_operand (operands[1], TImode))
> {
> if (get_attr_mode (insn) == MODE_V4SF)
> return "%vmovups\t{%1, %0|%0, %1}";
> --
> 2.5.5
>
More information about the Gcc-patches
mailing list