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]

Extending simplify-rtx handling of SUBREG_PROMOTED_VAR_P


This isn't really stage 3 material, but since the patch is written
and tested, I thought I might as well post it anyway for comments.

While looking at the DSE patch that I posted earlier, I found a case
in which we had:

    (set (reg:SI foo) (sign_extend:SI (subreg/s:QI (reg:DI R))))

where the "/s" indicates that R is a sign-extension of a QImode value.
This is equivalent to:

    (set (reg:SI foo) (subreg/s:SI (reg:DI R)))

since R is also the sign extension of an SImode value (which is itself
an extension of a QImode value).  The transformation would be correct
even without the "/s" in the new subreg, but keeping it preserves more
information.

The patch adds code to handle this case.  In other words:

  - it generalises the existing SUBREG_PROMOTED_VAR_P handling to
    cope with cases where the extended value is not as wide as the
    fully-promoted value (but is still wider than the unpromoted
    value, because extensions are always widening operations).

  - it makes simplify_subreg keep the SUBREG_PROMOTED_VAR_P
    information in an input SUBREG, in cases where doing so
    is valid.

The CSiBE results for mipsisa64-elf at -Os (without the DSE patch) are:

Total                                          3605997  3605713 :   99.99%

which is wortwhile but hardly earth-shattering.  Bootstrapped &
regression-tested on x86_64-linux-gnu.  Also regression-tested on
mipsisa32-elf and mipsisa64-elf.

Richard


gcc/
	* simplify-rtx.c (simplify_unary_operation_1): Extend the handling
	of SUBREG_PROMOTED_VAR_P to cope with cases where the extended value
	is smaller than the original promoted value.
	(simplify_subreg): If OP is a SUBREG, try to preserve its
	SUBREG_PROMOTED_VAR_P information.

Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c	2007-10-27 09:25:22.000000000 +0100
+++ gcc/simplify-rtx.c	2007-10-27 09:32:58.000000000 +0100
@@ -859,8 +859,8 @@ simplify_unary_operation_1 (enum rtx_cod
       if (GET_CODE (op) == SUBREG
 	  && SUBREG_PROMOTED_VAR_P (op)
 	  && ! SUBREG_PROMOTED_UNSIGNED_P (op)
-	  && GET_MODE (XEXP (op, 0)) == mode)
-	return XEXP (op, 0);
+	  && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0))))
+	return gen_lowpart_common (mode, op);
 
 #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
       if (! POINTERS_EXTEND_UNSIGNED
@@ -881,8 +881,8 @@ simplify_unary_operation_1 (enum rtx_cod
       if (GET_CODE (op) == SUBREG
 	  && SUBREG_PROMOTED_VAR_P (op)
 	  && SUBREG_PROMOTED_UNSIGNED_P (op) > 0
-	  && GET_MODE (XEXP (op, 0)) == mode)
-	return XEXP (op, 0);
+	  && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0))))
+	return gen_lowpart_common (mode, op);
 
 #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
       if (POINTERS_EXTEND_UNSIGNED > 0
@@ -5001,7 +5001,21 @@ simplify_subreg (enum machine_mode outer
 	return newx;
       if (validate_subreg (outermode, innermostmode,
 			   SUBREG_REG (op), final_offset))
-        return gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset);
+	{
+	  newx = gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset);
+	  if (SUBREG_PROMOTED_VAR_P (op)
+	      && SUBREG_PROMOTED_UNSIGNED_P (op) >= 0
+	      && IN_RANGE (GET_MODE_SIZE (outermode),
+			   GET_MODE_SIZE (innermode),
+			   GET_MODE_SIZE (innermostmode))
+	      && subreg_lowpart_p (newx))
+	    {
+	      SUBREG_PROMOTED_VAR_P (newx) = 1;
+	      SUBREG_PROMOTED_UNSIGNED_SET
+		(newx, SUBREG_PROMOTED_UNSIGNED_P (op));
+	    }
+	  return newx;
+	}
       return NULL_RTX;
     }
 


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