diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc index 21b7eb484d0..9c68d360672 100644 --- a/gcc/simplify-rtx.cc +++ b/gcc/simplify-rtx.cc @@ -4860,6 +4860,17 @@ simplify_ashift: return simplify_gen_binary (VEC_SELECT, mode, XEXP (trueop0, 0), gen_rtx_PARALLEL (VOIDmode, vec)); } + /* (vec_concat: + (subreg_lowpart:N OP) + (vec_select:N OP P)) --> OP when P selects the high half + of the OP. */ + if (GET_CODE (trueop0) == SUBREG + && subreg_lowpart_p (trueop0) + && GET_CODE (trueop1) == VEC_SELECT + && SUBREG_REG (trueop0) == XEXP (trueop1, 0) + && !side_effects_p (XEXP (trueop1, 0)) + && vec_series_highpart_p (op1_mode, mode, XEXP (trueop1, 1))) + return XEXP (trueop1, 0); } return 0; diff --git a/gcc/testsuite/gcc.target/aarch64/simd/low-high-combine_1.c b/gcc/testsuite/gcc.target/aarch64/simd/low-high-combine_1.c new file mode 100644 index 00000000000..0b502d593f2 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/simd/low-high-combine_1.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-O" } */ +/* { dg-final { check-function-bodies "**" "" "" } } */ + +#include + +/* +** foo_le: { target aarch64_little_endian } +** ret +*/ + +int32x4_t +foo_le (int32x4_t a) +{ + return vcombine_s32 (vget_low_s32 (a), vget_high_s32 (a)); +} + +/* +** foo_be: { target aarch64_big_endian } +** ret +*/ + +int32x4_t +foo_be (int32x4_t a) +{ + return vcombine_s32 (vget_high_s32 (a), vget_low_s32 (a)); +} +