aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2016-11-16 10:21:22 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2016-11-16 10:21:22 +0000
commit024f701ca1dc69ff3d6a3d0ec727debc224018f0 (patch)
tree52508ae9bd9955501846133b59b4d7f9e41e762a /gcc/expr.c
parent0e0af68921530695ddfd86780a0d955674ef239f (diff)
downloadgcc-024f701ca1dc69ff3d6a3d0ec727debc224018f0.zip
gcc-024f701ca1dc69ff3d6a3d0ec727debc224018f0.tar.gz
gcc-024f701ca1dc69ff3d6a3d0ec727debc224018f0.tar.bz2
Optimise CONCAT handling in emit_group_load
The CONCAT handling in emit_group_load chooses between doing an extraction from a single component or forcing the whole thing to memory and extracting from there. The condition for the former (more efficient) option was: if ((bytepos == 0 && bytelen == slen0) || (bytepos != 0 && bytepos + bytelen <= slen)) On the one hand this seems dangerous, since the second line allows bit ranges that start in the first component and leak into the second. On the other hand it seems strange to allow references that start after the first byte of the second component but not those that start after the first byte of the first component. This led to a pessimisation of things like gcc.dg/builtins-54.c for hppa64-hp-hpux11.23. This patch simply checks whether the reference is contained within a single component. It also makes sure that we do an extraction on anything that doesn't span the whole component (even if it's constant). gcc/ 2016-11-15 Richard Sandiford <richard.sandiford@arm.com> Alan Hayward <alan.hayward@arm.com> David Sherwood <david.sherwood@arm.com> * expr.c (emit_group_load_1): Tighten check for whether an access involves only one operand of a CONCAT. Use extract_bit_field for constants if the bit range does span the whole operand. Co-Authored-By: Alan Hayward <alan.hayward@arm.com> Co-Authored-By: David Sherwood <david.sherwood@arm.com> From-SVN: r242477
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index 0b0946d..985c2b3 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -2175,19 +2175,22 @@ emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
{
unsigned int slen = GET_MODE_SIZE (GET_MODE (src));
unsigned int slen0 = GET_MODE_SIZE (GET_MODE (XEXP (src, 0)));
+ unsigned int elt = bytepos / slen0;
+ unsigned int subpos = bytepos % slen0;
- if ((bytepos == 0 && bytelen == slen0)
- || (bytepos != 0 && bytepos + bytelen <= slen))
+ if (subpos + bytelen <= slen0)
{
/* The following assumes that the concatenated objects all
have the same size. In this case, a simple calculation
can be used to determine the object and the bit field
to be extracted. */
- tmps[i] = XEXP (src, bytepos / slen0);
- if (! CONSTANT_P (tmps[i])
- && (!REG_P (tmps[i]) || GET_MODE (tmps[i]) != mode))
+ tmps[i] = XEXP (src, elt);
+ if (subpos != 0
+ || subpos + bytelen != slen0
+ || (!CONSTANT_P (tmps[i])
+ && (!REG_P (tmps[i]) || GET_MODE (tmps[i]) != mode)))
tmps[i] = extract_bit_field (tmps[i], bytelen * BITS_PER_UNIT,
- (bytepos % slen0) * BITS_PER_UNIT,
+ subpos * BITS_PER_UNIT,
1, NULL_RTX, mode, mode, false);
}
else