On Wed, May 27, 2026 at 4:57 PM Roger Sayle <[email protected]> wrote:
>
>
> Many thanks to Uros and Hongtao for the reviews/feedback.  I agree they
> are both correct; performing this optimization early during RTL expansion
> allows the results to be optimized by early RTL optimization passes, and
> performing this optimization late, as a (pair of) define_insn_and_split
> patterns, enables this optimization to catch cases where the CONST1_RTX
> is exposed by early RTL optimization passes.  The obvious solution is
> to do both.
>
> This patch has been tested on x86_64-pc-linux-gnu, first only performing
> this
> transformation during RTL expansion, then only performing this optimization
> during combine/split, confirming both approaches pass the new test cases,
> with no new failures, both with and without --target_board=unix{-m32}.
> Ok for mainline?
>
>
> 2026-05-27  Roger Sayle  <[email protected]>
>             Hongtao Liu  <[email protected]>
>             Uros Bizjak  <[email protected]>
>
> gcc/ChangeLog
>         * config/i386/i386.md (inv_insn): New define_code_attr.
>         * config/i386/sse.md (<plusminus><mode>3): Accept a CONST_VECTOR
>         as the second operand.  If the second operand is CONST1_RTX,
>         canonicalize to use CONSTM1_RTX instead.
>         (*add<mode>3_one): New define_insn_and_split to convert padd +1
>         to psub -1.
>         (*sub<mode>3_one): Likewise, a new define_insn_and_split to
>         convert psub +1 to padd -1.
>
> gcc/testsuite/ChangeLog
>         * gcc.target/i386/avx512f-simd-1.c: Tweak test case.
>         * gcc.target/i386/sse2-paddb-2.c: New test case.
>         * gcc.target/i386/sse2-paddd-2.c: Likewise.
>         * gcc.target/i386/sse2-paddw-2.c: Likewise.
>         * gcc.target/i386/sse2-psubb-2.c: Likewise.
>         * gcc.target/i386/sse2-psubd-2.c: Likewise.
>         * gcc.target/i386/sse2-psubw-2.c: Likewise.

+/* Split vector add 1 into vector sub -1.  */
+(define_insn_and_split "*add<mode>3_one"
+  [(set (match_operand:VI_AVX2 0 "register_operand")
+    (plus:VI_AVX2
+      (match_operand:VI_AVX2 1 "nonimmediate_operand")
+      (match_operand:VI_AVX2 2 "const1_operand")))]
+  "TARGET_SSE2 && ix86_pre_reload_split ()"
+  "#"
+  "&& 1"
+  [(set (match_dup 3) (match_dup 4))
+   (set (match_dup 0) (minus:VI_AVX2 (match_dup 1) (match_dup 3)))]
+{
+  operands[1] = force_reg (<MODE>mode, operands[1]);
+  operands[3] = gen_reg_rtx (<MODE>mode);
+  operands[4] = CONSTM1_RTX (<MODE>mode);
+})

Just use:
{
   operands [1] = force_reg (...);
   operands[3] = force_reg (<MODE>mode, CONSTM1_RTX (<MODE>mode));
}

in insn preparation statement and you will be able to emit a simple:

  [(set (match_dup 0) (minus:VI_AVX2 (match_dup 1) (match_dup 3)))]

+  [(set (match_dup 3) (match_dup 4))
+   (set (match_dup 0) (plus:VI_AVX2 (match_dup 3) (match_dup 1)))]
+{
+  operands[3] = gen_reg_rtx (<MODE>mode);
+  operands[4] = CONSTM1_RTX (<MODE>mode);
+})

Also here,

"operands[3] = force_reg (<MODE>mode, CONSTM1_RTX (<MODE>mode));"

OK with the above changes.

Thanks,
Uros.

Reply via email to