aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Law <jlaw@ventanamicro.com>2025-08-13 11:17:02 -0600
committerJeff Law <jlaw@ventanamicro.com>2025-08-13 11:17:52 -0600
commite31a353f1e7c5fe24a6b9d881adabfeed99dc845 (patch)
treed47dcf942b2d51a548bf7b50ce6d6a7d1f4103ab
parent11f7d5648c42cd2ef6f0841cde6292b94831e7b6 (diff)
downloadgcc-e31a353f1e7c5fe24a6b9d881adabfeed99dc845.zip
gcc-e31a353f1e7c5fe24a6b9d881adabfeed99dc845.tar.gz
gcc-e31a353f1e7c5fe24a6b9d881adabfeed99dc845.tar.bz2
[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.
-rw-r--r--gcc/config/riscv/riscv.cc4
-rw-r--r--gcc/testsuite/gcc.target/riscv/pr121160.c60
2 files changed, 62 insertions, 2 deletions
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 4935367..e394cac7 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 0000000..93cca8a
--- /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));
+ }
+}
+