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.