https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87535
Bug ID: 87535
Summary: multiple attribute assume_aligned interpreted
inconsistently
Product: gcc
Version: 9.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: middle-end
Assignee: unassigned at gcc dot gnu.org
Reporter: msebor at gcc dot gnu.org
Target Milestone: ---
The example below shows that attribute assume_aligned is interpreted
inconsistently between apparently equivalent declarations of the same function.
When two such attributes are specified on the same declaration the one
specified last wins. When the same pair are specified on distinct declarations
of the same function, the first one wins.
Clang treats both forms consistently, but honors the attribute that was
specified last. I think it's debatable whether that's preferable to honoring
the most restrictive one as specified for _Alignas by C11. I'm leaning toward
going with the C11 approach to minimize surprises due to an inconsistency.
$ cat c.c && gcc -O2 -S -Wall -fdump-tree-optimized=/dev/stdout c.c
__attribute ((assume_aligned (8), // ignored
assume_aligned (32))) // overrdides prior attribute
char* f (void);
void f1 (void)
{
char *p = f ();
if ((__INTPTR_TYPE__)p & 31) // folded to false
__builtin_abort ();
}
__attribute ((assume_aligned (8))) // overrides subsequent attribute
void* g (void);
__attribute ((assume_aligned (32))) // attribute ignored
void* g (void);
void g1 (void)
{
void *p = g ();
if ((__INTPTR_TYPE__)p & 31) // not folded
__builtin_abort ();
}
;; Function f1 (f1, funcdef_no=0, decl_uid=1908, cgraph_uid=1, symbol_order=0)
f1 ()
{
<bb 2> [local count: 1073741824]:
f (); [tail call]
return;
}
;; Function g1 (g1, funcdef_no=1, decl_uid=1916, cgraph_uid=2, symbol_order=1)
g1 ()
{
void * p;
long int p.1_1;
long int _2;
<bb 2> [local count: 1073741824]:
p_5 = g ();
p.1_1 = (long int) p_5;
_2 = p.1_1 & 31;
if (_2 != 0)
goto <bb 3>; [0.00%]
else
goto <bb 4>; [99.96%]
<bb 3> [count: 0]:
__builtin_abort ();
<bb 4> [local count: 1073312328]:
return;
}