https://gcc.gnu.org/g:38f93a682a024fa67197aafe4a48b5e1495b3ca9
commit 38f93a682a024fa67197aafe4a48b5e1495b3ca9 Author: Michael Meissner <[email protected]> Date: Mon Oct 26 00:38:29 2026 -0400 Add saturate subtract support This patch adds support for saturating subtract instructions that might be added to a future PowerPC.r I think I had originally submitted patches that added a new built-in function to generate the subfus and subdus instructions. Segher suggested that instead of generating a built-in function, that I should just having GCC automatically recognize cases where a saturating subtract could be generated. This patch generates the saturating subtract instructions in the appropriate context. 2026-10-25 Michael Meissner <[email protected]> gcc/ * config/rs6000/rs6000.md (gtu_geu): New code iterator. (subfus<mode>3_<code>): New insns. gcc/testsuite/ * gcc.target/powerpc/saturate-subtract-1.c: New test. * gcc.target/powerpc/saturate-subtract-2.c: Likewise. Diff: --- gcc/config/rs6000/rs6000.md | 14 ++++++++ .../gcc.target/powerpc/saturate-subtract-1.c | 39 +++++++++++++++++++++ .../gcc.target/powerpc/saturate-subtract-2.c | 40 ++++++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 166a03bc6e91..9144b894bf56 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -2503,6 +2503,20 @@ "" ) +;; Saturating subtract +(define_code_iterator gtu_geu [gtu geu]) + +(define_insn "*subfus<mode>3_<code>" + [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") + (if_then_else:GPR (gtu_geu (match_operand:GPR 1 "gpc_reg_operand" "r") + (match_operand:GPR 2 "gpc_reg_operand" "r")) + (minus:GPR (match_dup 1) + (match_dup 2)) + (const_int 0)))] + "TARGET_FUTURE" + "sub<wd>us %0,%1,%2" + [(set_attr "type" "add")]) + (define_insn "@neg<mode>2" [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))] diff --git a/gcc/testsuite/gcc.target/powerpc/saturate-subtract-1.c b/gcc/testsuite/gcc.target/powerpc/saturate-subtract-1.c new file mode 100644 index 000000000000..608c67f33f0b --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/saturate-subtract-1.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-mdejagnu-cpu=future -O2" } */ +/* { dg-require-effective-target powerpc_future_assemble_ok } */ + +/* Check that saturating subtract (subfus) is generated. Check that all + combinations of >, >=, <, and <= are optimized. */ + +#ifndef TYPE +#define TYPE unsigned int +#endif + +void +saturated_subtract_gt (TYPE a, TYPE b, TYPE *p) +{ + *p = (a > b) ? a - b : 0; +} + +void +saturated_subtract_ge (TYPE a, TYPE b, TYPE *p) +{ + *p = (a >= b) ? a - b : 0; +} + +void +saturated_subtract_lt (TYPE a, TYPE b, TYPE *p) +{ + *p = (a < b) ? 0 : a - b; +} + +void +saturated_subtract_le (TYPE a, TYPE b, TYPE *p) +{ + *p = (a <= b) ? 0 : a - b; +} + +/* { dg-final { scan-assembler-times {\msubwus\M} 4 } } */ +/* { dg-final { scan-assembler-not {\mcmplw\M} } } */ +/* { dg-final { scan-assembler-not {\misel\M} } } */ +/* { dg-final { scan-assembler-not {\msubf\M} } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/saturate-subtract-2.c b/gcc/testsuite/gcc.target/powerpc/saturate-subtract-2.c new file mode 100644 index 000000000000..d84c674fe2cf --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/saturate-subtract-2.c @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_future_assemble_ok } */ +/* { dg-require-effective-target lp64 } */ +/* { dg-options "-mdejagnu-cpu=future -O2" } */ + +/* Check that saturating subtract (subfus) is generated. Check that all + combinations of >, >=, <, and <= are optimized. */ + +#ifndef TYPE +#define TYPE unsigned long long +#endif + +void +saturated_subtract_gt (TYPE a, TYPE b, TYPE *p) +{ + *p = (a > b) ? a - b : 0; +} + +void +saturated_subtract_ge (TYPE a, TYPE b, TYPE *p) +{ + *p = (a >= b) ? a - b : 0; +} + +void +saturated_subtract_lt (TYPE a, TYPE b, TYPE *p) +{ + *p = (a < b) ? 0 : a - b; +} + +void +saturated_subtract_le (TYPE a, TYPE b, TYPE *p) +{ + *p = (a <= b) ? 0 : a - b; +} + +/* { dg-final { scan-assembler-times {\msubdus\M} 4 } } */ +/* { dg-final { scan-assembler-not {\mcmpld\M} } } */ +/* { dg-final { scan-assembler-not {\misel\M} } } */ +/* { dg-final { scan-assembler-not {\msubf\M} } } */
