319 lines
12 KiB
Diff
319 lines
12 KiB
Diff
|
|
From 87396b4550eeb097cdbe73fb19c84059ba6bb85e Mon Sep 17 00:00:00 2001
|
||
|
|
From: Jiahao Xu <xujiahao@loongson.cn>
|
||
|
|
Date: Wed, 29 Nov 2023 11:18:00 +0800
|
||
|
|
Subject: [PATCH 065/188] LoongArch: Fix ICE and use simplify_gen_subreg
|
||
|
|
instead of gen_rtx_SUBREG directly.
|
||
|
|
|
||
|
|
loongarch_expand_vec_cond_mask_expr generates 'subreg's of 'subreg's, which are not supported
|
||
|
|
in gcc, it causes an ICE:
|
||
|
|
|
||
|
|
ice.c:55:1: error: unrecognizable insn:
|
||
|
|
55 | }
|
||
|
|
| ^
|
||
|
|
(insn 63 62 64 8 (set (reg:V4DI 278)
|
||
|
|
(subreg:V4DI (subreg:V4DF (reg:V4DI 273 [ vect__53.26 ]) 0) 0)) -1
|
||
|
|
(nil))
|
||
|
|
during RTL pass: vregs
|
||
|
|
ice.c:55:1: internal compiler error: in extract_insn, at recog.cc:2804
|
||
|
|
|
||
|
|
Last time, Ruoyao has fixed a similar ICE:
|
||
|
|
https://gcc.gnu.org/pipermail/gcc-patches/2023-November/636156.html
|
||
|
|
|
||
|
|
This patch fixes ICE and use simplify_gen_subreg instead of gen_rtx_SUBREG as much as possible
|
||
|
|
to avoid the same ice happening again.
|
||
|
|
|
||
|
|
gcc/ChangeLog:
|
||
|
|
|
||
|
|
* config/loongarch/loongarch.cc (loongarch_try_expand_lsx_vshuf_const): Use
|
||
|
|
simplify_gen_subreg instead of gen_rtx_SUBREG.
|
||
|
|
(loongarch_expand_vec_perm_const_2): Ditto.
|
||
|
|
(loongarch_expand_vec_cond_expr): Ditto.
|
||
|
|
|
||
|
|
gcc/testsuite/ChangeLog:
|
||
|
|
|
||
|
|
* gcc.target/loongarch/pr112476-3.c: New test.
|
||
|
|
* gcc.target/loongarch/pr112476-4.c: New test.
|
||
|
|
---
|
||
|
|
gcc/config/loongarch/loongarch.cc | 79 +++++++++++--------
|
||
|
|
.../gcc.target/loongarch/pr112476-3.c | 58 ++++++++++++++
|
||
|
|
.../gcc.target/loongarch/pr112476-4.c | 4 +
|
||
|
|
3 files changed, 108 insertions(+), 33 deletions(-)
|
||
|
|
create mode 100644 gcc/testsuite/gcc.target/loongarch/pr112476-3.c
|
||
|
|
create mode 100644 gcc/testsuite/gcc.target/loongarch/pr112476-4.c
|
||
|
|
|
||
|
|
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
|
||
|
|
index d64777179..4a3a7a246 100644
|
||
|
|
--- a/gcc/config/loongarch/loongarch.cc
|
||
|
|
+++ b/gcc/config/loongarch/loongarch.cc
|
||
|
|
@@ -8824,13 +8824,13 @@ loongarch_try_expand_lsx_vshuf_const (struct expand_vec_perm_d *d)
|
||
|
|
if (d->vmode == E_V2DFmode)
|
||
|
|
{
|
||
|
|
sel = gen_rtx_CONST_VECTOR (E_V2DImode, gen_rtvec_v (d->nelt, rperm));
|
||
|
|
- tmp = gen_rtx_SUBREG (E_V2DImode, d->target, 0);
|
||
|
|
+ tmp = simplify_gen_subreg (E_V2DImode, d->target, d->vmode, 0);
|
||
|
|
emit_move_insn (tmp, sel);
|
||
|
|
}
|
||
|
|
else if (d->vmode == E_V4SFmode)
|
||
|
|
{
|
||
|
|
sel = gen_rtx_CONST_VECTOR (E_V4SImode, gen_rtvec_v (d->nelt, rperm));
|
||
|
|
- tmp = gen_rtx_SUBREG (E_V4SImode, d->target, 0);
|
||
|
|
+ tmp = simplify_gen_subreg (E_V4SImode, d->target, d->vmode, 0);
|
||
|
|
emit_move_insn (tmp, sel);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
@@ -9614,8 +9614,8 @@ loongarch_expand_vec_perm_const_2 (struct expand_vec_perm_d *d)
|
||
|
|
/* Adjust op1 for selecting correct value in high 128bit of target
|
||
|
|
register.
|
||
|
|
op1: E_V4DImode, { 4, 5, 6, 7 } -> { 2, 3, 4, 5 }. */
|
||
|
|
- rtx conv_op1 = gen_rtx_SUBREG (E_V4DImode, op1_alt, 0);
|
||
|
|
- rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, d->op0, 0);
|
||
|
|
+ rtx conv_op1 = simplify_gen_subreg (E_V4DImode, op1_alt, d->vmode, 0);
|
||
|
|
+ rtx conv_op0 = simplify_gen_subreg (E_V4DImode, d->op0, d->vmode, 0);
|
||
|
|
emit_insn (gen_lasx_xvpermi_q_v4di (conv_op1, conv_op1,
|
||
|
|
conv_op0, GEN_INT (0x21)));
|
||
|
|
|
||
|
|
@@ -9644,8 +9644,8 @@ loongarch_expand_vec_perm_const_2 (struct expand_vec_perm_d *d)
|
||
|
|
emit_move_insn (op0_alt, d->op0);
|
||
|
|
|
||
|
|
/* Generate subreg for fitting into insn gen function. */
|
||
|
|
- rtx conv_op1 = gen_rtx_SUBREG (E_V4DImode, op1_alt, 0);
|
||
|
|
- rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, op0_alt, 0);
|
||
|
|
+ rtx conv_op1 = simplify_gen_subreg (E_V4DImode, op1_alt, d->vmode, 0);
|
||
|
|
+ rtx conv_op0 = simplify_gen_subreg (E_V4DImode, op0_alt, d->vmode, 0);
|
||
|
|
|
||
|
|
/* Adjust op value in temp register.
|
||
|
|
op0 = {0,1,2,3}, op1 = {4,5,0,1} */
|
||
|
|
@@ -9691,9 +9691,10 @@ loongarch_expand_vec_perm_const_2 (struct expand_vec_perm_d *d)
|
||
|
|
emit_move_insn (op1_alt, d->op1);
|
||
|
|
emit_move_insn (op0_alt, d->op0);
|
||
|
|
|
||
|
|
- rtx conv_op1 = gen_rtx_SUBREG (E_V4DImode, op1_alt, 0);
|
||
|
|
- rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, op0_alt, 0);
|
||
|
|
- rtx conv_target = gen_rtx_SUBREG (E_V4DImode, d->target, 0);
|
||
|
|
+ rtx conv_op1 = simplify_gen_subreg (E_V4DImode, op1_alt, d->vmode, 0);
|
||
|
|
+ rtx conv_op0 = simplify_gen_subreg (E_V4DImode, op0_alt, d->vmode, 0);
|
||
|
|
+ rtx conv_target = simplify_gen_subreg (E_V4DImode, d->target,
|
||
|
|
+ d->vmode, 0);
|
||
|
|
|
||
|
|
emit_insn (gen_lasx_xvpermi_q_v4di (conv_op1, conv_op1,
|
||
|
|
conv_op0, GEN_INT (0x02)));
|
||
|
|
@@ -9725,9 +9726,10 @@ loongarch_expand_vec_perm_const_2 (struct expand_vec_perm_d *d)
|
||
|
|
Selector sample: E_V4DImode, { 0, 1, 4 ,5 } */
|
||
|
|
if (!d->testing_p)
|
||
|
|
{
|
||
|
|
- rtx conv_op1 = gen_rtx_SUBREG (E_V4DImode, d->op1, 0);
|
||
|
|
- rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, d->op0, 0);
|
||
|
|
- rtx conv_target = gen_rtx_SUBREG (E_V4DImode, d->target, 0);
|
||
|
|
+ rtx conv_op1 = simplify_gen_subreg (E_V4DImode, d->op1, d->vmode, 0);
|
||
|
|
+ rtx conv_op0 = simplify_gen_subreg (E_V4DImode, d->op0, d->vmode, 0);
|
||
|
|
+ rtx conv_target = simplify_gen_subreg (E_V4DImode, d->target,
|
||
|
|
+ d->vmode, 0);
|
||
|
|
|
||
|
|
/* We can achieve the expectation by using sinple xvpermi.q insn. */
|
||
|
|
emit_move_insn (conv_target, conv_op1);
|
||
|
|
@@ -9752,8 +9754,8 @@ loongarch_expand_vec_perm_const_2 (struct expand_vec_perm_d *d)
|
||
|
|
emit_move_insn (op1_alt, d->op1);
|
||
|
|
emit_move_insn (op0_alt, d->op0);
|
||
|
|
|
||
|
|
- rtx conv_op1 = gen_rtx_SUBREG (E_V4DImode, op1_alt, 0);
|
||
|
|
- rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, op0_alt, 0);
|
||
|
|
+ rtx conv_op1 = simplify_gen_subreg (E_V4DImode, op1_alt, d->vmode, 0);
|
||
|
|
+ rtx conv_op0 = simplify_gen_subreg (E_V4DImode, op0_alt, d->vmode, 0);
|
||
|
|
/* Adjust op value in temp regiter.
|
||
|
|
op0 = { 0, 1, 2, 3 }, op1 = { 6, 7, 2, 3 } */
|
||
|
|
emit_insn (gen_lasx_xvpermi_q_v4di (conv_op1, conv_op1,
|
||
|
|
@@ -9797,9 +9799,10 @@ loongarch_expand_vec_perm_const_2 (struct expand_vec_perm_d *d)
|
||
|
|
emit_move_insn (op1_alt, d->op1);
|
||
|
|
emit_move_insn (op0_alt, d->op0);
|
||
|
|
|
||
|
|
- rtx conv_op1 = gen_rtx_SUBREG (E_V4DImode, op1_alt, 0);
|
||
|
|
- rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, op0_alt, 0);
|
||
|
|
- rtx conv_target = gen_rtx_SUBREG (E_V4DImode, d->target, 0);
|
||
|
|
+ rtx conv_op1 = simplify_gen_subreg (E_V4DImode, op1_alt, d->vmode, 0);
|
||
|
|
+ rtx conv_op0 = simplify_gen_subreg (E_V4DImode, op0_alt, d->vmode, 0);
|
||
|
|
+ rtx conv_target = simplify_gen_subreg (E_V4DImode, d->target,
|
||
|
|
+ d->vmode, 0);
|
||
|
|
|
||
|
|
emit_insn (gen_lasx_xvpermi_q_v4di (conv_op1, conv_op1,
|
||
|
|
conv_op0, GEN_INT (0x13)));
|
||
|
|
@@ -9831,10 +9834,11 @@ loongarch_expand_vec_perm_const_2 (struct expand_vec_perm_d *d)
|
||
|
|
Selector sample:E_V8SImode, { 2, 2, 2, 2, 2, 2, 2, 2 } */
|
||
|
|
if (!d->testing_p)
|
||
|
|
{
|
||
|
|
- rtx conv_op1 = gen_rtx_SUBREG (E_V4DImode, d->op1, 0);
|
||
|
|
- rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, d->op0, 0);
|
||
|
|
+ rtx conv_op1 = simplify_gen_subreg (E_V4DImode, d->op1, d->vmode, 0);
|
||
|
|
+ rtx conv_op0 = simplify_gen_subreg (E_V4DImode, d->op0, d->vmode, 0);
|
||
|
|
rtx temp_reg = gen_reg_rtx (d->vmode);
|
||
|
|
- rtx conv_temp = gen_rtx_SUBREG (E_V4DImode, temp_reg, 0);
|
||
|
|
+ rtx conv_temp = simplify_gen_subreg (E_V4DImode, temp_reg,
|
||
|
|
+ d->vmode, 0);
|
||
|
|
|
||
|
|
emit_move_insn (temp_reg, d->op0);
|
||
|
|
|
||
|
|
@@ -9943,9 +9947,11 @@ loongarch_expand_vec_perm_const_2 (struct expand_vec_perm_d *d)
|
||
|
|
emit_move_insn (op0_alt, d->op0);
|
||
|
|
emit_move_insn (op1_alt, d->op1);
|
||
|
|
|
||
|
|
- rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, d->op0, 0);
|
||
|
|
- rtx conv_op0a = gen_rtx_SUBREG (E_V4DImode, op0_alt, 0);
|
||
|
|
- rtx conv_op1a = gen_rtx_SUBREG (E_V4DImode, op1_alt, 0);
|
||
|
|
+ rtx conv_op0 = simplify_gen_subreg (E_V4DImode, d->op0, d->vmode, 0);
|
||
|
|
+ rtx conv_op0a = simplify_gen_subreg (E_V4DImode, op0_alt,
|
||
|
|
+ d->vmode, 0);
|
||
|
|
+ rtx conv_op1a = simplify_gen_subreg (E_V4DImode, op1_alt,
|
||
|
|
+ d->vmode, 0);
|
||
|
|
|
||
|
|
/* Duplicate op0's low 128bit in op0, then duplicate high 128bit
|
||
|
|
in op1. After this, xvshuf.* insn's selector argument can
|
||
|
|
@@ -9978,10 +9984,12 @@ loongarch_expand_vec_perm_const_2 (struct expand_vec_perm_d *d)
|
||
|
|
emit_move_insn (op0_alt, d->op0);
|
||
|
|
emit_move_insn (op1_alt, d->op1);
|
||
|
|
|
||
|
|
- rtx conv_op0a = gen_rtx_SUBREG (E_V4DImode, op0_alt, 0);
|
||
|
|
- rtx conv_op1a = gen_rtx_SUBREG (E_V4DImode, op1_alt, 0);
|
||
|
|
- rtx conv_op0 = gen_rtx_SUBREG (E_V4DImode, d->op0, 0);
|
||
|
|
- rtx conv_op1 = gen_rtx_SUBREG (E_V4DImode, d->op1, 0);
|
||
|
|
+ rtx conv_op0a = simplify_gen_subreg (E_V4DImode, op0_alt,
|
||
|
|
+ d->vmode, 0);
|
||
|
|
+ rtx conv_op1a = simplify_gen_subreg (E_V4DImode, op1_alt,
|
||
|
|
+ d->vmode, 0);
|
||
|
|
+ rtx conv_op0 = simplify_gen_subreg (E_V4DImode, d->op0, d->vmode, 0);
|
||
|
|
+ rtx conv_op1 = simplify_gen_subreg (E_V4DImode, d->op1, d->vmode, 0);
|
||
|
|
|
||
|
|
/* Reorganize op0's hi/lo 128bit and op1's hi/lo 128bit, to make sure
|
||
|
|
that selector's low 128bit can access all op0's elements, and
|
||
|
|
@@ -10101,12 +10109,12 @@ loongarch_expand_vec_perm_const_2 (struct expand_vec_perm_d *d)
|
||
|
|
{
|
||
|
|
case E_V4DFmode:
|
||
|
|
sel = gen_rtx_CONST_VECTOR (E_V4DImode, gen_rtvec_v (d->nelt, rperm));
|
||
|
|
- tmp = gen_rtx_SUBREG (E_V4DImode, d->target, 0);
|
||
|
|
+ tmp = simplify_gen_subreg (E_V4DImode, d->target, d->vmode, 0);
|
||
|
|
emit_move_insn (tmp, sel);
|
||
|
|
break;
|
||
|
|
case E_V8SFmode:
|
||
|
|
sel = gen_rtx_CONST_VECTOR (E_V8SImode, gen_rtvec_v (d->nelt, rperm));
|
||
|
|
- tmp = gen_rtx_SUBREG (E_V8SImode, d->target, 0);
|
||
|
|
+ tmp = simplify_gen_subreg (E_V8SImode, d->target, d->vmode, 0);
|
||
|
|
emit_move_insn (tmp, sel);
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
@@ -10192,7 +10200,7 @@ loongarch_expand_vec_perm_const_2 (struct expand_vec_perm_d *d)
|
||
|
|
64bit in target vector register. */
|
||
|
|
else if (extract_ev_od)
|
||
|
|
{
|
||
|
|
- rtx converted = gen_rtx_SUBREG (E_V4DImode, d->target, 0);
|
||
|
|
+ rtx converted = simplify_gen_subreg (E_V4DImode, d->target, d->vmode, 0);
|
||
|
|
emit_insn (gen_lasx_xvpermi_d_v4di (converted, converted,
|
||
|
|
GEN_INT (0xD8)));
|
||
|
|
}
|
||
|
|
@@ -11279,7 +11287,9 @@ loongarch_expand_vec_cond_expr (machine_mode mode, machine_mode vimode,
|
||
|
|
if (mode != vimode)
|
||
|
|
{
|
||
|
|
xop1 = gen_reg_rtx (vimode);
|
||
|
|
- emit_move_insn (xop1, gen_rtx_SUBREG (vimode, operands[1], 0));
|
||
|
|
+ emit_move_insn (xop1,
|
||
|
|
+ simplify_gen_subreg (vimode, operands[1],
|
||
|
|
+ mode, 0));
|
||
|
|
}
|
||
|
|
emit_move_insn (src1, xop1);
|
||
|
|
}
|
||
|
|
@@ -11296,7 +11306,9 @@ loongarch_expand_vec_cond_expr (machine_mode mode, machine_mode vimode,
|
||
|
|
if (mode != vimode)
|
||
|
|
{
|
||
|
|
xop2 = gen_reg_rtx (vimode);
|
||
|
|
- emit_move_insn (xop2, gen_rtx_SUBREG (vimode, operands[2], 0));
|
||
|
|
+ emit_move_insn (xop2,
|
||
|
|
+ simplify_gen_subreg (vimode, operands[2],
|
||
|
|
+ mode, 0));
|
||
|
|
}
|
||
|
|
emit_move_insn (src2, xop2);
|
||
|
|
}
|
||
|
|
@@ -11315,7 +11327,8 @@ loongarch_expand_vec_cond_expr (machine_mode mode, machine_mode vimode,
|
||
|
|
gen_rtx_AND (vimode, mask, src1));
|
||
|
|
/* The result is placed back to a register with the mask. */
|
||
|
|
emit_insn (gen_rtx_SET (mask, bsel));
|
||
|
|
- emit_move_insn (operands[0], gen_rtx_SUBREG (mode, mask, 0));
|
||
|
|
+ emit_move_insn (operands[0],
|
||
|
|
+ simplify_gen_subreg (mode, mask, vimode, 0));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
diff --git a/gcc/testsuite/gcc.target/loongarch/pr112476-3.c b/gcc/testsuite/gcc.target/loongarch/pr112476-3.c
|
||
|
|
new file mode 100644
|
||
|
|
index 000000000..d696d4182
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/gcc/testsuite/gcc.target/loongarch/pr112476-3.c
|
||
|
|
@@ -0,0 +1,58 @@
|
||
|
|
+/* { dg-do compile } */
|
||
|
|
+/* { dg-options "-O3 -mlsx" } */
|
||
|
|
+
|
||
|
|
+#include <stdint.h>
|
||
|
|
+
|
||
|
|
+typedef int8_t orc_int8;
|
||
|
|
+typedef int16_t orc_int16;
|
||
|
|
+typedef int32_t orc_int32;
|
||
|
|
+typedef int64_t orc_int64;
|
||
|
|
+
|
||
|
|
+typedef union
|
||
|
|
+{
|
||
|
|
+ orc_int32 i;
|
||
|
|
+ float f;
|
||
|
|
+ orc_int16 x2[2];
|
||
|
|
+ orc_int8 x4[4];
|
||
|
|
+} orc_union32;
|
||
|
|
+typedef union
|
||
|
|
+{
|
||
|
|
+ orc_int64 i;
|
||
|
|
+ double f;
|
||
|
|
+ orc_int32 x2[2];
|
||
|
|
+ float x2f[2];
|
||
|
|
+ orc_int16 x4[4];
|
||
|
|
+} orc_union64;
|
||
|
|
+
|
||
|
|
+void
|
||
|
|
+audio_orc_s32_to_double (double * restrict d1,
|
||
|
|
+ const signed int * restrict s1, int n)
|
||
|
|
+{
|
||
|
|
+ int i;
|
||
|
|
+ orc_union64 *restrict ptr0;
|
||
|
|
+ const orc_union32 *restrict ptr4;
|
||
|
|
+ orc_union32 var33;
|
||
|
|
+ orc_union64 var34;
|
||
|
|
+ orc_union64 var35;
|
||
|
|
+ orc_union64 var36;
|
||
|
|
+
|
||
|
|
+ ptr0 = (orc_union64 *) d1;
|
||
|
|
+ ptr4 = (orc_union32 *) s1;
|
||
|
|
+
|
||
|
|
+ var34.i = 0x41e0000000000000UL;
|
||
|
|
+
|
||
|
|
+ for (i = 0; i < n; i++) {
|
||
|
|
+ var33 = ptr4[i];
|
||
|
|
+ var36.f = var33.i;
|
||
|
|
+ {
|
||
|
|
+ orc_union64 _src1;
|
||
|
|
+ orc_union64 _src2;
|
||
|
|
+ orc_union64 _dest1;
|
||
|
|
+ _src1.i = ((var36.i) & ((((var36.i)&0x7ff0000000000000UL) == 0) ? 0xfff0000000000000UL : 0xffffffffffffffffUL));
|
||
|
|
+ _src2.i = ((var34.i) & ((((var34.i)&0x7ff0000000000000UL) == 0) ? 0xfff0000000000000UL : 0xffffffffffffffffUL));
|
||
|
|
+ _dest1.f = _src1.f / _src2.f;
|
||
|
|
+ var35.i = ((_dest1.i) & ((((_dest1.i)&0x7ff0000000000000UL) == 0) ? 0xfff0000000000000UL : 0xffffffffffffffffUL));
|
||
|
|
+ }
|
||
|
|
+ ptr0[i] = var35;
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
diff --git a/gcc/testsuite/gcc.target/loongarch/pr112476-4.c b/gcc/testsuite/gcc.target/loongarch/pr112476-4.c
|
||
|
|
new file mode 100644
|
||
|
|
index 000000000..955d98552
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/gcc/testsuite/gcc.target/loongarch/pr112476-4.c
|
||
|
|
@@ -0,0 +1,4 @@
|
||
|
|
+/* { dg-do compile } */
|
||
|
|
+/* { dg-options "-O3 -mlasx" } */
|
||
|
|
+
|
||
|
|
+#include "pr112476-3.c"
|
||
|
|
--
|
||
|
|
2.43.0
|
||
|
|
|