LoongArch: Fix ICE and use simplify_gen_subreg instead of gen_rtx_SUBREG directly.
Checks
Commit Message
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.
Comments
Pushed to r14-6317.
在 2023/11/29 上午11:18, Jiahao Xu 写道:
> 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.
>
> diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
> index e8a2584ac97..69fcb0aa6fb 100644
> --- a/gcc/config/loongarch/loongarch.cc
> +++ b/gcc/config/loongarch/loongarch.cc
> @@ -8799,13 +8799,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
> @@ -9584,8 +9584,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)));
>
> @@ -9614,8 +9614,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} */
> @@ -9661,9 +9661,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)));
> @@ -9695,9 +9696,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);
> @@ -9722,8 +9724,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,
> @@ -9767,9 +9769,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)));
> @@ -9801,10 +9804,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);
>
> @@ -9913,9 +9917,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
> @@ -9948,10 +9954,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
> @@ -10071,12 +10079,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:
> @@ -10162,7 +10170,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)));
> }
> @@ -11252,7 +11260,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);
> }
> @@ -11269,7 +11279,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);
> }
> @@ -11288,7 +11300,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 00000000000..d696d4182bb
> --- /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 00000000000..955d98552eb
> --- /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"
@@ -8799,13 +8799,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
@@ -9584,8 +9584,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)));
@@ -9614,8 +9614,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} */
@@ -9661,9 +9661,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)));
@@ -9695,9 +9696,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);
@@ -9722,8 +9724,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,
@@ -9767,9 +9769,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)));
@@ -9801,10 +9804,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);
@@ -9913,9 +9917,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
@@ -9948,10 +9954,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
@@ -10071,12 +10079,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:
@@ -10162,7 +10170,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)));
}
@@ -11252,7 +11260,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);
}
@@ -11269,7 +11279,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);
}
@@ -11288,7 +11300,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));
}
}
new file mode 100644
@@ -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;
+ }
+}
new file mode 100644
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlasx" } */
+
+#include "pr112476-3.c"