From 0eb6b0f474ff13f5e98d2c26a3669fdd17b40dd4 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Sun, 2 Nov 2025 20:30:55 +0100 Subject: [PATCH] i386: Canonicalize (compare (minus (a b)) a) to (compare (a b)) [PR122518] SUB (a, b) underflows precisely when a < b. Convert (compare (minus (a b)) a) to (compare (a b)) to match *sub_3 pattern. PR target/122518 gcc/ChangeLog: * config/i386/i386.cc (ix86_canonicalize_comparison): Convert (compare (minus (a b)) a) to (compare (a b)) to match *sub_3 pattern. gcc/testsuite/ChangeLog: * gcc.target/i386/pr122518.c: New test. --- gcc/config/i386/i386.cc | 14 ++++++++++++++ gcc/testsuite/gcc.target/i386/pr122518.c | 15 +++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 gcc/testsuite/gcc.target/i386/pr122518.c diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index 587b2bd0c1d..6b6febc8870 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -598,6 +598,20 @@ ix86_canonicalize_comparison (int *code, rtx *op0, rtx *op1, } } + /* SUB (a, b) underflows precisely when a < b. Convert + (compare (minus (a b)) a) to (compare (a b)) + to match *sub_3 pattern. */ + if (!op0_preserve_value + && (*code == GTU || *code == LEU) + && GET_CODE (*op0) == MINUS + && rtx_equal_p (XEXP (*op0, 0), *op1)) + { + *op1 = XEXP (*op0, 1); + *op0 = XEXP (*op0, 0); + *code = (int) swap_condition ((enum rtx_code) *code); + return; + } + /* Swap operands of GTU comparison to canonicalize addcarry/subborrow comparison. */ if (!op0_preserve_value diff --git a/gcc/testsuite/gcc.target/i386/pr122518.c b/gcc/testsuite/gcc.target/i386/pr122518.c new file mode 100644 index 00000000000..2791889c45d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr122518.c @@ -0,0 +1,15 @@ +/* PR target/122518 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +inline unsigned min (unsigned a, unsigned b) +{ + return (a < b) ? a : b; +} + +unsigned uminsub (unsigned a, unsigned b) +{ + return min (a - b, a); +} + +/* { dg-final { scan-assembler-not "cmp" } } */ -- 2.47.3