combine.c (simplify_shift_const_1): Split code to determine shift_mode into ...

* combine.c (simplify_shift_const_1): Split code to determine
	shift_mode into ...
	(try_widen_shift_mode): ... here.  Allow widening for ASHIFTRT if the
	new bits shifted in are identical to the old sign bit.

testsuite/
	* gcc.target/mips/octeon-exts-7.c: New test.
	* gcc.target/mips/octeon-exts-2.c: Revert previous change.
	* gcc.target/mips/octeon-exts-5.c: Likewise.

From-SVN: r149778
This commit is contained in:
Adam Nemet 2009-07-18 21:46:01 +00:00 committed by Adam Nemet
parent b95d6ac9ca
commit b641d7fca3
6 changed files with 72 additions and 21 deletions

View File

@ -1,3 +1,10 @@
2009-07-18 Adam Nemet <anemet@caviumnetworks.com>
* combine.c (simplify_shift_const_1): Split code to determine
shift_mode into ...
(try_widen_shift_mode): ... here. Allow widening for ASHIFTRT if the
new bits shifted in are identical to the old sign bit.
2009-07-18 Richard Guenther <rguenther@suse.de>
PR c/40787

View File

@ -8982,6 +8982,42 @@ merge_outer_ops (enum rtx_code *pop0, HOST_WIDE_INT *pconst0, enum rtx_code op1,
return 1;
}
/* A helper to simplify_shift_const_1 to determine the mode we can perform
the shift in. The original shift operation CODE is performed on OP in
ORIG_MODE. Return the wider mode MODE if we can perform the operation
in that mode. Return ORIG_MODE otherwise. */
static enum machine_mode
try_widen_shift_mode (enum rtx_code code, rtx op,
enum machine_mode orig_mode, enum machine_mode mode)
{
if (orig_mode == mode)
return mode;
gcc_assert (GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (orig_mode));
/* In general we can't perform in wider mode for right shift and rotate. */
switch (code)
{
case ASHIFTRT:
/* We can still widen if the bits brought in from the left are identical
to the sign bit of ORIG_MODE. */
if (num_sign_bit_copies (op, mode)
> (unsigned) (GET_MODE_BITSIZE (mode)
- GET_MODE_BITSIZE (orig_mode)))
return mode;
/* fall through */
case LSHIFTRT:
case ROTATE:
return orig_mode;
case ROTATERT:
gcc_unreachable ();
default:
return mode;
}
}
/* Simplify a shift of VAROP by COUNT bits. CODE says what kind of shift.
The result of the shift is RESULT_MODE. Return NULL_RTX if we cannot
simplify it. Otherwise, return a simplified value.
@ -9041,13 +9077,7 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
count = bitsize - count;
}
/* We need to determine what mode we will do the shift in. If the
shift is a right shift or a ROTATE, we must always do it in the mode
it was originally done in. Otherwise, we can do it in MODE, the
widest mode encountered. */
shift_mode
= (code == ASHIFTRT || code == LSHIFTRT || code == ROTATE
? result_mode : mode);
shift_mode = try_widen_shift_mode (code, varop, result_mode, mode);
/* Handle cases where the count is greater than the size of the mode
minus 1. For ASHIFT, use the size minus one as the count (this can
@ -9645,14 +9675,7 @@ simplify_shift_const_1 (enum rtx_code code, enum machine_mode result_mode,
break;
}
/* We need to determine what mode to do the shift in. If the shift is
a right shift or ROTATE, we must always do it in the mode it was
originally done in. Otherwise, we can do it in MODE, the widest mode
encountered. The code we care about is that of the shift that will
actually be done, not the shift that was originally requested. */
shift_mode
= (code == ASHIFTRT || code == LSHIFTRT || code == ROTATE
? result_mode : mode);
shift_mode = try_widen_shift_mode (code, varop, result_mode, mode);
/* We have now finished analyzing the shift. The result should be
a shift of type CODE with SHIFT_MODE shifting VAROP COUNT places. If

View File

@ -1,3 +1,9 @@
2009-07-18 Adam Nemet <anemet@caviumnetworks.com>
* gcc.target/mips/octeon-exts-7.c: New test.
* gcc.target/mips/octeon-exts-2.c: Revert previous change.
* gcc.target/mips/octeon-exts-5.c: Likewise.
2009-07-18 Richard Guenther <rguenther@suse.de>
PR testsuite/40798

View File

@ -1,7 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O -march=octeon -meb -dp" } */
/* Don't match exts in sign-extension. */
/* { dg-final { scan-assembler-times "\texts\t\[^\\n\]*extv" 4 } } */
/* { dg-options "-O -march=octeon -meb" } */
/* { dg-final { scan-assembler-times "\texts\t" 4 } } */
struct bar
{

View File

@ -1,8 +1,7 @@
/* -mel version of octeon-exts-2.c. */
/* { dg-do compile } */
/* { dg-options "-O -march=octeon -mel -dp" } */
/* Don't match exts in sign-extension. */
/* { dg-final { scan-assembler-times "\texts\t\[^\\n\]*extv" 4 } } */
/* { dg-options "-O -march=octeon -mel" } */
/* { dg-final { scan-assembler-times "\texts\t" 4 } } */
struct bar
{

View File

@ -0,0 +1,17 @@
/* Remove the redundant sign-extension after the sign-extraction. */
/* { dg-do compile } */
/* { dg-options "-O -march=octeon -mgp64" } */
/* { dg-final { scan-assembler-times "\texts\t" 1 } } */
/* { dg-final { scan-assembler-not "sll|sra" } } */
struct bar
{
long long a:18;
long long b:14;
};
NOMIPS16 int
f1 (struct bar *s)
{
return s->b;
}