aboutsummaryrefslogtreecommitdiff
path: root/gcc/combine.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2013-05-03 13:19:51 +0000
committerJakub Jelinek <jakub@redhat.com>2013-05-03 13:19:51 +0000
commit0a91ddea3f1f9ec24436fcaf5a0d4b1db5da4ca9 (patch)
treeeebd3cd0571e56327e0f4974188185004d9abd66 /gcc/combine.c
parente8fa6d72c34e7cea30a8179e7ae08a8ddcf8e2d3 (diff)
PR rtl-optimization/57130
* combine.c (make_compound_operation) <case SUBREG>: Pass SET instead of COMPARE as in_code to the recursive call if needed. * gcc.c-torture/execute/pr57130.c: New test. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/gcc-4_8-branch@198581 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/combine.c')
-rw-r--r--gcc/combine.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/gcc/combine.c b/gcc/combine.c
index acb74216589..a589cfadb42 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -7703,8 +7703,24 @@ make_compound_operation (rtx x, enum rtx_code in_code)
what it originally did, do this SUBREG as a force_to_mode. */
{
rtx inner = SUBREG_REG (x), simplified;
-
- tem = make_compound_operation (inner, in_code);
+ enum rtx_code subreg_code = in_code;
+
+ /* If in_code is COMPARE, it isn't always safe to pass it through
+ to the recursive make_compound_operation call. */
+ if (subreg_code == COMPARE
+ && (!subreg_lowpart_p (x)
+ || GET_CODE (inner) == SUBREG
+ /* (subreg:SI (and:DI (reg:DI) (const_int 0x800000000)) 0)
+ is (const_int 0), rather than
+ (subreg:SI (lshiftrt:DI (reg:DI) (const_int 35)) 0). */
+ || (GET_CODE (inner) == AND
+ && CONST_INT_P (XEXP (inner, 1))
+ && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (inner))
+ && exact_log2 (UINTVAL (XEXP (inner, 1)))
+ >= GET_MODE_BITSIZE (mode))))
+ subreg_code = SET;
+
+ tem = make_compound_operation (inner, subreg_code);
simplified
= simplify_subreg (mode, tem, GET_MODE (inner), SUBREG_BYTE (x));