aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/config/riscv/riscv.cc63
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/base/pr112743-2.c52
2 files changed, 95 insertions, 20 deletions
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 2f8d391..58060b8 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -2605,41 +2605,64 @@ riscv_legitimize_move (machine_mode mode, rtx dest, rtx src)
unsigned int nunits = vmode_size > mode_size ? vmode_size / mode_size : 1;
scalar_mode smode = as_a<scalar_mode> (mode);
unsigned int index = SUBREG_BYTE (src).to_constant () / mode_size;
- unsigned int num = smode == DImode && !TARGET_VECTOR_ELEN_64 ? 2 : 1;
+ unsigned int num = known_eq (GET_MODE_SIZE (smode), 8)
+ && !TARGET_VECTOR_ELEN_64 ? 2 : 1;
+ bool need_int_reg_p = false;
if (num == 2)
{
/* If we want to extract 64bit value but ELEN < 64,
we use RVV vector mode with EEW = 32 to extract
the highpart and lowpart. */
+ need_int_reg_p = smode == DFmode;
smode = SImode;
nunits = nunits * 2;
}
- vmode = riscv_vector::get_vector_mode (smode, nunits).require ();
- rtx v = gen_lowpart (vmode, SUBREG_REG (src));
- for (unsigned int i = 0; i < num; i++)
+ if (riscv_vector::get_vector_mode (smode, nunits).exists (&vmode))
{
- rtx result;
- if (num == 1)
- result = dest;
- else if (i == 0)
- result = gen_lowpart (smode, dest);
- else
- result = gen_reg_rtx (smode);
- riscv_vector::emit_vec_extract (result, v, index + i);
+ rtx v = gen_lowpart (vmode, SUBREG_REG (src));
+ rtx int_reg = dest;
- if (i == 1)
+ if (need_int_reg_p)
{
- rtx tmp
- = expand_binop (Pmode, ashl_optab, gen_lowpart (Pmode, result),
- gen_int_mode (32, Pmode), NULL_RTX, 0,
- OPTAB_DIRECT);
- rtx tmp2 = expand_binop (Pmode, ior_optab, tmp, dest, NULL_RTX, 0,
- OPTAB_DIRECT);
- emit_move_insn (dest, tmp2);
+ int_reg = gen_reg_rtx (DImode);
+ emit_move_insn (int_reg, gen_lowpart (GET_MODE (int_reg), dest));
}
+
+ for (unsigned int i = 0; i < num; i++)
+ {
+ rtx result;
+ if (num == 1)
+ result = int_reg;
+ else if (i == 0)
+ result = gen_lowpart (smode, int_reg);
+ else
+ result = gen_reg_rtx (smode);
+
+ riscv_vector::emit_vec_extract (result, v, index + i);
+
+ if (i == 1)
+ {
+ rtx tmp = expand_binop (Pmode, ashl_optab,
+ gen_lowpart (Pmode, result),
+ gen_int_mode (32, Pmode), NULL_RTX, 0,
+ OPTAB_DIRECT);
+ rtx tmp2 = expand_binop (Pmode, ior_optab, tmp, int_reg,
+ NULL_RTX, 0,
+ OPTAB_DIRECT);
+ emit_move_insn (int_reg, tmp2);
+ }
+ }
+
+ if (need_int_reg_p)
+ emit_move_insn (dest, gen_lowpart (GET_MODE (dest), int_reg));
+ else
+ emit_move_insn (dest, int_reg);
}
+ else
+ gcc_unreachable ();
+
return true;
}
/* Expand
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr112743-2.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr112743-2.c
new file mode 100644
index 0000000..fdb35fd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr112743-2.c
@@ -0,0 +1,52 @@
+/* Test that we do not have ice when compile */
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zve32f_zvfh_zfh -mabi=lp64 -O2" } */
+
+#include <sys/types.h>
+
+union double_union
+{
+ double d;
+ __uint32_t i[2];
+};
+
+#define word0(x) (x.i[1])
+#define word1(x) (x.i[0])
+
+#define P 53
+#define Exp_shift 20
+#define Exp_msk1 ((__uint32_t)0x100000L)
+#define Exp_mask ((__uint32_t)0x7ff00000L)
+
+double ulp (double _x)
+{
+ union double_union x, a;
+ register int L;
+
+ x.d = _x;
+ L = (word0 (x) & Exp_mask) - (P - 1) * Exp_msk1;
+
+ if (L > 0)
+ {
+ L |= Exp_msk1 >> 4;
+ word0 (a) = L;
+ word1 (a) = 0;
+ }
+ else
+ {
+ L = -L >> Exp_shift;
+ if (L < Exp_shift)
+ {
+ word0 (a) = 0x80000 >> L;
+ word1 (a) = 0;
+ }
+ else
+ {
+ word0 (a) = 0;
+ L -= Exp_shift;
+ word1 (a) = L >= 31 ? 1 : 1 << (31 - L);
+ }
+ }
+
+ return a.d;
+}