diff --git a/gcc/combine.cc b/gcc/combine.cc index 0106092e456..5aa0ec5c45a 100644 --- a/gcc/combine.cc +++ b/gcc/combine.cc @@ -5631,6 +5631,28 @@ maybe_swap_commutative_operands (rtx x) SUBST (XEXP (x, 0), XEXP (x, 1)); SUBST (XEXP (x, 1), temp); } + + unsigned n_elts = 0; + if (GET_CODE (x) == VEC_MERGE + && CONST_INT_P (XEXP (x, 2)) + && GET_MODE_NUNITS (GET_MODE (x)).is_constant (&n_elts) + && (swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)) + /* Two operands have same precedence, then + first bit of mask select first operand. */ + || (!swap_commutative_operands_p (XEXP (x, 1), XEXP (x, 0)) + && !(UINTVAL (XEXP (x, 2)) & 1)))) + { + rtx temp = XEXP (x, 0); + unsigned HOST_WIDE_INT sel = UINTVAL (XEXP (x, 2)); + unsigned HOST_WIDE_INT mask = HOST_WIDE_INT_1U; + if (n_elts == HOST_BITS_PER_WIDE_INT) + mask = -1; + else + mask = (HOST_WIDE_INT_1U << n_elts) - 1; + SUBST (XEXP (x, 0), XEXP (x, 1)); + SUBST (XEXP (x, 1), temp); + SUBST (XEXP (x, 2), GEN_INT (~sel & mask)); + } } /* Simplify X, a piece of RTL. We just operate on the expression at the diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 37e537733c9..8ebce31ba78 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -8224,6 +8224,13 @@ second operand. If a machine only supports a constant as the second operand, only patterns that match a constant in the second operand need be supplied. +@cindex @code{vec_merge}, canonicalization of +@item +For the @code{vec_merge} with constant mask(the third operand), the first +and the second operand can be exchanged by inverting the mask. In such cases, +a constant is always made the second operand, otherwise the least significant +bit of the mask is always set(select the first operand first). + @item For associative operators, a sequence of operators will always chain to the left; for instance, only the left operand of an integer @code{plus}