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 --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));
+ }
+}
+