This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] In DSE optimize replace_read even if a constant store needs shifting (PR middle-end/37135)


Hi!

union U
{
  struct
  {
    unsigned f1 : 4;
    unsigned f2 : 4;
    unsigned f3 : 4;
    unsigned f4 : 4;
    unsigned f5 : 4;
    unsigned f6 : 4;
    unsigned f7 : 4;
    unsigned f8 : 4;
  } f;
  unsigned g;
} u;

const union U def = { .f = { .f1 = 6, .f2 = 4, .f3 = 2, .f4 = 11,
                             .f5 = 3, .f6 = 5, .f7 = 0, .f8 = 5 } };

void fn1 (void)
{
  u = def;
}

void fn3 (union U *);
void fn2 (void)
{
  union U v = def;
  fn3 (&v);
}

is optimized into 4 stores (doing just one store is something I'll try
to address later on separately) on x86_64-linux or i386-linux at -O2,
but not at -Os, eventhough it is clearly much shorter (and faster).

The problem is in replace_read optimization.  When shift != 0,
find_shift_sequence computes the cost of shifting the value down
and at -Os figures that it is too expensive and thus doesn't perform
this optimization.  But, when we know store_info->rhs is CONSTANT_P
(in this case const0_rtx), this cost computation fails to account
that LSHIFTRT of a constant can be optimized into a constant.
At -O2 find_shift_sequence considers it cheap enough and combine
fixes it up (though, for dse2 nothing would do that).

The following patch just tries to simplify extraction from a constant
and if that results in a constant and a SET with that constant on the RHS
is cheap enough, returns that directly.

This patch thus transforms PR37135 into a dup of PR22141.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

OT, I believe read_rtx is wrong for PDP-endian, guess it should bail out:

   access_size = shift + GET_MODE_SIZE (read_mode);
+  if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
+    return false;

(or it could only bail out if access_size doesn't fit into a word
and shift isn't a multiple of wordsize).

2008-11-24  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/37135
	* dse.c (find_shift_sequence): Optimize extraction from a constant.

--- gcc/dse.c.jj	2008-10-23 13:21:40.000000000 +0200
+++ gcc/dse.c	2008-11-24 11:46:05.000000000 +0100
@@ -1447,6 +1447,29 @@ find_shift_sequence (int access_size,
       rtx target, new_reg, shift_seq, insn, new_lhs;
       int cost;
 
+      /* If a constant was stored into memory, try to simplify it here,
+	 otherwise the cost of the shift might preclude this optimization
+	 e.g. at -Os, even when no actual shift will be needed.  */
+      if (CONSTANT_P (store_info->rhs))
+	{
+	  unsigned int byte = subreg_lowpart_offset (new_mode, store_mode);
+	  rtx ret = simplify_subreg (new_mode, store_info->rhs, store_mode,
+				     byte);
+	  if (ret && CONSTANT_P (ret))
+	    {
+	      ret = simplify_const_binary_operation (LSHIFTRT, new_mode,
+						     ret, GEN_INT (shift));
+	      if (ret && CONSTANT_P (ret))
+		{
+		  byte = subreg_lowpart_offset (read_mode, new_mode);
+		  ret = simplify_subreg (read_mode, ret, new_mode, byte);
+		  if (ret && CONSTANT_P (ret)
+		      && rtx_cost (ret, SET, speed) <= COSTS_N_INSNS (1))
+		    return ret;
+		}
+	    }
+	}
+
       /* Try a wider mode if truncating the store mode to NEW_MODE
 	 requires a real instruction.  */
       if (GET_MODE_BITSIZE (new_mode) < GET_MODE_BITSIZE (store_mode)

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]