https://gcc.gnu.org/g:e31a353f1e7c5fe24a6b9d881adabfeed99dc845
commit r16-3187-ge31a353f1e7c5fe24a6b9d881adabfeed99dc845 Author: Jeff Law <j...@ventanamicro.com> Date: Wed Aug 13 11:17:02 2025 -0600 [RISC-V][PR target/121160] Avoid bogus force_reg call When we canonicalize the comparison for a czero sequence we need to handle both integer and fp comparisons. Furthermore, within the integer space we want to make sure we promote any sub-word objects to a full word. All that is working fine. After promotion we then force the value into a register if it is not a register or constant already. The idea is not to have to special case subregs in subsequent code. This works fine except when we're presented with a floating point object that would be a subword. (subreg:SF (reg:SI)) on rv64 for example. So this tightens up that force_reg step. Bootstapped and regression tested on riscv64-linux-gnu and tested on riscv32-elf and riscv64-elf. Pushing to the trunk after pre-commit verifies no regressions. Jeff PR target/121160 gcc/ * config/riscv/riscv.cc (canonicalize_comparands); Tighten check for forcing value into a GPR. gcc/testsuite/ * gcc.target/riscv/pr121160.c: New test. Diff: --- gcc/config/riscv/riscv.cc | 4 +-- gcc/testsuite/gcc.target/riscv/pr121160.c | 60 +++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 4935367dd0e0..e394cac7d417 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -5444,9 +5444,9 @@ canonicalize_comparands (rtx_code code, rtx *op0, rtx *op1) /* We might have been handed back a SUBREG. Just to make things easy, force it into a REG. */ - if (!REG_P (*op0) && !CONST_INT_P (*op0)) + if (!REG_P (*op0) && !CONST_INT_P (*op0) && INTEGRAL_MODE_P (GET_MODE (*op0))) *op0 = force_reg (word_mode, *op0); - if (!REG_P (*op1) && !CONST_INT_P (*op1)) + if (!REG_P (*op1) && !CONST_INT_P (*op1) && INTEGRAL_MODE_P (GET_MODE (*op1))) *op1 = force_reg (word_mode, *op1); } diff --git a/gcc/testsuite/gcc.target/riscv/pr121160.c b/gcc/testsuite/gcc.target/riscv/pr121160.c new file mode 100644 index 000000000000..93cca8ad6f1c --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr121160.c @@ -0,0 +1,60 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gc_zicond -mabi=lp64d -ffast-math -O2" { target { rv64 } } } */ +/* { dg-options "-march=rv32gc_zicond -mabi=ilp32d -ffast-math -O2" { target { rv32 } } } */ + + +typedef long int ssize_t; +typedef float MagickRealType; +typedef unsigned short Quantum; +typedef unsigned long long MagickSizeType; +typedef struct _PixelPacket +{ + Quantum blue, green, red, opacity; +} PixelPacket; +static inline Quantum +ClampToQuantum (const MagickRealType value) +{ + if (value <= 0.0f) + return ((Quantum) 0); + if (value >= (MagickRealType) ((Quantum) 65535)) + return (((Quantum) 65535)); + return ((Quantum) (value + 0.5f)); +} + +static inline float +HalfToSinglePrecision (const unsigned short half) +{ + typedef union _SinglePrecision + { + unsigned int fixed_point; + float single_precision; + } SinglePrecision; + register unsigned int exponent, significand, sign_bit; + SinglePrecision map; + unsigned int value; + if (significand == 0) + value = sign_bit << 31; + else + { + while ((significand & 0x00000400) == 0) + { + significand <<= 1; + } + value = (sign_bit << 31) | (exponent << 23) | (significand << 13); + } + map.fixed_point = value; + return (map.single_precision); +} + +void +ImportBlueQuantum (const MagickSizeType number_pixels, + PixelPacket *restrict q) +{ + register ssize_t x; + unsigned short pixel; + { + for (x = 0; x < (ssize_t) number_pixels; x++) + q->blue = ClampToQuantum (HalfToSinglePrecision (pixel)); + } +} +