SRC's operator. */
dest = resolve_operand_for_swap_move_operator (dest);
src = src_op;
+ if (resolve_reg_p (src))
+ {
+ gcc_assert (GET_CODE (src) == CONCATN);
+ if (reg_overlap_mentioned_p (XVECEXP (dest, 0, 0),
+ XVECEXP (src, 0, 1)))
+ {
+ /* If there is overlap betwee the first half of the
+ destination and what will be stored to the second one,
+ use a temporary pseudo. See PR114211. */
+ rtx tem = gen_reg_rtx (GET_MODE (XVECEXP (src, 0, 1)));
+ emit_move_insn (tem, XVECEXP (src, 0, 1));
+ src = copy_rtx (src);
+ XVECEXP (src, 0, 1) = tem;
+ }
+ }
}
else if (resolve_reg_p (src_op))
{
--- /dev/null
+/* PR rtl-optimization/114211 */
+/* { dg-do run { target int128 } } */
+/* { dg-options "-O -fno-tree-coalesce-vars -Wno-psabi" } */
+
+typedef unsigned __int128 V __attribute__((__vector_size__ (16)));
+unsigned int u;
+V v;
+
+V
+foo (unsigned __int128 h)
+{
+ h = h << 64 | h >> 64;
+ h *= ~u;
+ return h + v;
+}
+
+int
+main ()
+{
+ V x = foo (1);
+ if (x[0] != (unsigned __int128) 0xffffffff << 64)
+ __builtin_abort ();
+}