summaryrefslogtreecommitdiff
path: root/gcc/combine.c
diff options
context:
space:
mode:
authorsegher <segher@138bc75d-0d04-0410-961f-82ee72b054a4>2016-11-23 14:33:13 +0000
committersegher <segher@138bc75d-0d04-0410-961f-82ee72b054a4>2016-11-23 14:33:13 +0000
commitc1acc1d41f0711ebaebb13aae05e47b669feb8fb (patch)
tree35a38cefb14ddb97781f6cba2e1483e9cc17ac3c /gcc/combine.c
parentca99c78703007760b5c46d3f27b5a9afe5ff3340 (diff)
downloadgcc-c1acc1d41f0711ebaebb13aae05e47b669feb8fb.tar.gz
combine: Convert subreg-of-lshiftrt to zero_extract properly (PR78390)
r242414, for PR77881, introduces some bugs (PR78390, PR78438, PR78477). It all has the same root cause: that patch makes combine convert every lowpart subreg of a logical shift right to a zero_extract. This cannot work at all if it is not a constant shift, and it has to be a bit more careful exactly which bits it extracts. PR target/77881 PR bootstrap/78390 PR target/78438 PR bootstrap/78477 * combine.c (make_compound_operation_int): Do not convert a subreg of a non-constant logical shift right to a zero_extract. Handle the case where some zero bits have been shifted into the range covered by that subreg. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@242757 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/combine.c')
-rw-r--r--gcc/combine.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/gcc/combine.c b/gcc/combine.c
index 93621bd02fb..ae25ef35ed9 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -8089,12 +8089,17 @@ make_compound_operation_int (machine_mode mode, rtx *x_ptr,
/* If the SUBREG is masking of a logical right shift,
make an extraction. */
if (GET_CODE (inner) == LSHIFTRT
+ && CONST_INT_P (XEXP (inner, 1))
&& GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (inner))
&& subreg_lowpart_p (x))
{
new_rtx = make_compound_operation (XEXP (inner, 0), next_code);
+ int width = GET_MODE_PRECISION (GET_MODE (inner))
+ - INTVAL (XEXP (inner, 1));
+ if (width > mode_width)
+ width = mode_width;
new_rtx = make_extraction (mode, new_rtx, 0, XEXP (inner, 1),
- mode_width, 1, 0, in_code == COMPARE);
+ width, 1, 0, in_code == COMPARE);
break;
}