Hi,

The attached patch eliminates moves of the form

        set( (reg:DI n) vec_select:DI ( (reg:V2DI n) (parallel [const 0]))))

i.e. eliminates lower lane moves between src and dst where src and dst are the same register and this causes rtl to instead use the destination register in the required mode.

Also, if my understanding of Big-Endian is correct, this should be safe for big-endian targets as well.

I've bootstrapped this on x64_64, regressed on aarch64-none-elf, aarch64_be-none-elf.

OK for trunk?

Thanks,
Tejas Belagod
ARM.

2013-11-06  Tejas Belagod  <tejas.bela...@arm.com>

gcc/
        * rtlanal.c (set_noop_p): Return nonzero in case of redundant vec_select
        for same src and dst.
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 9769b69..3e434cd 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -1180,6 +1180,25 @@ set_noop_p (const_rtx set)
       dst = SUBREG_REG (dst);
     }
 
+  /* This is big-endian-safe because the elements are kept in target
+     memory order.  So, for eg. PARALLEL element value of 2 is the same in
+     either endian-ness.  */
+  if (GET_CODE (src) == VEC_SELECT
+      && REG_P (XEXP (src, 0)) && REG_P (dst)
+      && REGNO (XEXP (src, 0)) == REGNO (dst))
+    {
+      rtx par = XEXP (src, 1);
+      int i;
+
+      for (i = 0; i < XVECLEN (par, 0); i++)
+       {
+         rtx tem = XVECEXP (par, 0, i);
+         if (!CONST_INT_P (tem) || INTVAL (tem) != i)
+           return 0;
+       }
+      return 1;
+    }
+
   return (REG_P (src) && REG_P (dst)
          && REGNO (src) == REGNO (dst));
 }

Reply via email to