Bug 40060 - [4.9 Regression] casts loose alignment info
Summary: [4.9 Regression] casts loose alignment info
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.5.0
: P2 normal
Target Milestone: 4.9.4
Assignee: Not yet assigned to anyone
Keywords: missed-optimization
: 43814 (view as bug list)
Depends on:
Reported: 2009-05-07 12:36 UTC by Michael Matz
Modified: 2015-06-26 20:05 UTC (History)
3 users (show)

See Also:
Known to work:
Known to fail:
Last reconfirmed: 2009-05-07 12:56:14


Note You need to log in before you can comment on or make changes to this bug.
Description Michael Matz 2009-05-07 12:36:02 UTC
These testcase on powerpc:
  gcc.target/powerpc/405-dlmzb-strlen-1.c scan-assembler dlmzb\\\\.  (-m32)
  gcc.target/powerpc/440-dlmzb-strlen-1.c scan-assembler dlmzb\\\\.  (-m32)
fail since expand from SSA.  That's because TER can't work around a frontend
deficiency anymore.  The code therein is:

size_t strlen8(const long long *s)
{ return strlen((const char *)s); }

the parameter is "long long *" to make the alignment known to the compiler.
There are of course other ways, but this is not what this report is about.
In any case the target type of *s is aligned(8).
The cast is there to be type-correct for strlen, but the destination type
of that cast simply is "const char *", where "char" of course is aligned(1).

For the middle-end the case to char* is not useless, hence we can't get
rid of it, so the pointer alignment as far as strlen is concerned is 1, which
is why the transformation doesn't happen anymore.  TER could work around this
in some case (single use of that temporary), but not always.  Now it doesn't
do that work-around in any case.

What IMO needs to happen is that the frontend construct a new type as destination type of the cast, as if the user had written:

typedef char alignedchar __attribute__((aligned(8)));
x = (const alignedchar *)s;

Unfortunately this can't be easily transformed into a testcase using __alignof__, because __alignof__((*(char*)s)) is already transformed by
the frontend looking through the casts.  That disregards that the same 
can't be done by the middle-end.
Comment 1 Richard Biener 2009-05-07 12:56:14 UTC
Comment 2 Andrew Pinski 2009-05-07 13:15:52 UTC
Actually a cast to a lower alignment is valid (to an bigger alignment is questionable if the pointer is not already aligned).
And this is a regression from the 4.4 as these testcases passed.  Really expand should look through NOPs.
Comment 3 Michael Matz 2009-05-07 13:28:58 UTC
How alignment is dealt with in was explained by Joseph in 
A conversion sequence implicitely maintains the largest found alignment.
Looking through casts would not be correct for the middle-end, as a different
frontend could very well use such conversions to implement what you suggested,
namely forcefully reducing alignment for whatever reason.  Looking through
the cast would deafeat that, it's really the frontend that needs to establish
the expected semantics here (retaining the large alignment through casts).

As usual with the problems exposed by the more limited TER it's not really
a regression.  Trivially modifying the testcase to have two uses of the same
cast would have made TER not work around the situation and you would have
ended up with the missed optimization already since introduction of tree-ssa
(and TER of course).
Comment 4 Richard Biener 2009-05-07 15:06:16 UTC
And if something should look through conversions it is get_pointer_alignment
which funnily has

  /* We rely on TER to compute accurate alignment information.  */
  if (!(optimize && flag_tree_ter))
    return 0;

eh.  That's probably trying to work around the alignment wrong-code bugs ... :/
Comment 5 Michael Matz 2009-05-07 15:13:14 UTC
Subject: Re:  [4.5 Regression] casts loose alignment

On Thu, 7 May 2009, rguenth at gcc dot gnu dot org wrote:

> And if something should look through conversions it is get_pointer_alignment

Yes, this is actually used in the ppc testcase to get hold of the 
pointer alignment of the mem buffer.  The conservatively typed cast is 
confusing it then, and as explained we aren't allowed to look through it 
(and if we were we would have to use the _lowest_ not largest alignment in 
the those conversion sequence).
Comment 6 Richard Biener 2010-01-14 16:57:46 UTC
Note that with the current middle-end setup we cannot really ever derive
anything about alignment when just seeing a pointer type.  We only can
ever derive alignment information when having access to the pointed-to
decl or when encountering an actual dereference of a pointer (though as
with this middle-end problem I'm sure we have bugs where the alignment
of the access is not that of the type of the dereferenced pointer).

Thus get_pointer_alignment is overly optimistic.

We could establish some C rules in the middle-end namely that pointer
function arguments have proper alignment, likewise passing a pointer
to a function is as good as a dereference of it.  But as other people
have noted we simply need to propagate alignment information
somewhere and the frontends need a way to communicate constraints to
the middle-end.

The operand scanner could set a flag in the SSA names pointer information
whether it is dereferenced or passed as function argument, points-to
information can constrain alignment based on the pointed-to objects
(but never can derive larger alignment than the pointed-to types).
Comment 7 Richard Biener 2010-04-06 11:20:11 UTC
GCC 4.5.0 is being released.  Deferring to 4.5.1.
Comment 8 Richard Biener 2010-07-31 09:29:27 UTC
GCC 4.5.1 is being released, adjusting target milestone.
Comment 9 Richard Biener 2010-12-16 13:03:20 UTC
GCC 4.5.2 is being released, adjusting target milestone.
Comment 10 Sean McGovern 2010-12-20 19:02:02 UTC
Any desire to reconfirm this on powerpc-darwin-*?
Comment 11 Richard Biener 2011-04-28 14:51:35 UTC
GCC 4.5.3 is being released, adjusting target milestone.
Comment 12 Richard Biener 2012-01-16 14:01:18 UTC
Since 4.6

"For the middle-end the case to char* is not useless, ..."

is no longer true.

  /* We rely on TER to compute accurate alignment information.  */
  if (!(optimize && flag_tree_ter))
    return 0;

was also fixed in a conservative way (we do not assume any alignment
for that long long * argument).

There is a duplicate PR for this, PR43814, I suppose the original PPC
testcases still fail.
Comment 13 Richard Biener 2012-01-16 14:01:48 UTC
*** Bug 43814 has been marked as a duplicate of this bug. ***
Comment 14 Dominique d'Humieres 2012-01-22 16:42:36 UTC
Still failing on trunk r183385!-(see http://gcc.gnu.org/ml/gcc-testresults/2012-01/msg02085.html ).
Comment 15 vries 2012-01-24 10:36:53 UTC
(In reply to comment #13)
> *** Bug 43814 has been marked as a duplicate of this bug. ***

I submitted a patch for PR43814 ( http://gcc.gnu.org/ml/gcc-patches/2011-12/msg00571.html ). That patch works for that PR, since the test-case has a dereference to derive alignment info from, but it doesn't work for this PR, since gcc.target/powerpc/405-dlmzb-strlen-1.c doesn't contain such a dereference.
Comment 16 Richard Biener 2012-07-02 11:37:01 UTC
The 4.5 branch is being closed, adjusting target milestone.
Comment 17 Jakub Jelinek 2013-04-12 15:16:04 UTC
GCC 4.6.4 has been released and the branch has been closed.
Comment 18 Richard Biener 2014-06-12 13:42:41 UTC
The 4.7 branch is being closed, moving target milestone to 4.8.4.
Comment 19 Jakub Jelinek 2014-12-19 13:25:35 UTC
GCC 4.8.4 has been released.
Comment 20 Aldy Hernandez 2015-03-11 20:19:14 UTC
The testcases were deemed invalid and changed on mainline by r219061, and thus no longer fail.  Can we close this PR, remove the GCC 5 regression tag, or is perhaps another similar testcase (??) still exhibiting a regression?

See discussion here:
Comment 21 Richard Biener 2015-06-23 08:14:56 UTC
The gcc-4_8-branch is being closed, re-targeting regressions to 4.9.3.
Comment 22 Jakub Jelinek 2015-06-26 19:52:22 UTC
GCC 4.9.3 has been released.