Hi all,

The following rtx pattern will be transformed into the second one,
which makes the compiler unable to remove the redundant zero_extend operation.


(set (zero_extract:SI (reg/i:SI 0 x0)
                      (const_int 8 [0x8])
                  (const_int 0 [0]))
    (and:SI (reg:SI 1 x1 [ y ])
        (const_int 255 [0xff])))
------------------->>>>>>>>>>>>>>>>
(set (zero_extract:SI (reg/i:SI 0 x0)
                      (const_int 8 [0x8])
                  (const_int 0 [0]))
     (zero_extend:SI (reg:QI 1 x1 [ y ])))

This patch add the code to handle the second case as well.

for example, for the following short code excerpt

int f5(int x, int y)
{
        return (x & ~0xff) | (y & 0xff);
}

original code-gen is:
        uxtb    w1, w1
        bfi     w0, w1, 0, 8
        ret
new code-gen is:
        bfi    w0, w1, 0, 8
        ret

x86-64 bootstraps Okay, aarch64-none-elf regression test Okay.
Okay for trunk?

Regards,
Renlin Li

gcc/ChangeLog:

2015-02-13  Renlin Li  <renlin...@arm.com>

    * combine.c (make_field_assignment): Add code to remove redundant
    ZERO_EXTEND operation.
diff --git a/gcc/combine.c b/gcc/combine.c
index f779117..759e07c 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -9311,6 +9311,31 @@ make_field_assignment (rtx x)
 	}
     }
 
+  /* If DEST is already a field assignment, i.e. ZERO_EXTRACT, and the
+     SRC is an ZERO_EXTEND with all bits of that field set, then we can discard
+     the ZERO_EXTEND.  */
+  if (GET_CODE (dest) == ZERO_EXTRACT
+      && CONST_INT_P (XEXP (dest, 1))
+      && CONST_INT_P (XEXP (dest, 2))
+      && GET_CODE (src) == ZERO_EXTEND
+      && REG_P (XEXP (src, 0)))
+    {
+      unsigned int regno = REGNO (XEXP (src, 0));
+      unsigned int inner_size = GET_MODE_BITSIZE (GET_MODE (XEXP (src, 0)));
+      mode = GET_MODE (src);
+
+      HOST_WIDE_INT width = INTVAL (XEXP (dest, 1));
+      HOST_WIDE_INT lsb = INTVAL (XEXP (dest, 2));
+      /* Complete overlap.  We can remove the source ZERO_EXTEND.  */
+      if (width == inner_size
+	  && (regno < FIRST_PSEUDO_REGISTER)
+	  && HARD_REGNO_MODE_OK (regno, mode))
+      {
+	rtx reg = gen_rtx_REG (mode, regno);
+	return gen_rtx_SET (VOIDmode, dest, reg);
+      }
+    }
+
   /* The other case we handle is assignments into a constant-position
      field.  They look like (ior/xor (and DEST C1) OTHER).  If C1 represents
      a mask that has all one bits except for a group of zero bits and

Reply via email to