Message ID | 1454538638.3232.125.camel@ubuntu-sellcey |
---|---|
State | New |
Headers | show |
On Feb 3, 2016, at 2:30 PM, Steve Ellcey <sellcey@imgtec.com> wrote:
> Here is a new patch for PR target/68273.
So this doesn’t fix aarch64, c6x, epiphany, ia64, iq2000, rs6000, rx, sparc, tilegx, tilepro or xtensa.
:-( That’s one of the problems by having each port copy and paste swaths of code from other ports to express the same thing instead of ports sharing just one copy of code. My port is also broken in the same way (currently).
I’m curious why the caller of the hook can’t grab the main variant, if it wants. If it did this, then all the ports are fixed wrt this issue.
> So this doesn’t fix aarch64, c6x, epiphany, ia64, iq2000, rs6000, rx, sparc, > tilegx, tilepro or xtensa. > :-( That’s one of the problems by having each port copy and paste swaths of > :code from other ports to express the same thing instead of ports sharing > :just one copy of code. My port is also broken in the same way > :(currently). Yes, fixing a compiler bug by changing the ABI is a no-no, and the argument of the compatibility with LLVM has IMO little merit since it's a GCC extension. > I’m curious why the caller of the hook can’t grab the main variant, if it > wants. If it did this, then all the ports are fixed wrt this issue. Or just fix PRE wrt the alignment discrepancy, which looks a lot safer to me. It's not because this works on x86 that this is necessarily correct for all the other architectures, especially the strict-alignment architectures.
On Thu, Feb 4, 2016 at 12:09 PM, Eric Botcazou <ebotcazou@adacore.com> wrote: >> So this doesn’t fix aarch64, c6x, epiphany, ia64, iq2000, rs6000, rx, sparc, >> tilegx, tilepro or xtensa. >> :-( That’s one of the problems by having each port copy and paste swaths of >> :code from other ports to express the same thing instead of ports sharing >> :just one copy of code. My port is also broken in the same way >> :(currently). > > Yes, fixing a compiler bug by changing the ABI is a no-no, and the argument of > the compatibility with LLVM has IMO little merit since it's a GCC extension. True, but the compiler bug is in the backends - it just now gets exposed more easily (read: w/o user intervention). >> I’m curious why the caller of the hook can’t grab the main variant, if it >> wants. If it did this, then all the ports are fixed wrt this issue. > > Or just fix PRE wrt the alignment discrepancy, which looks a lot safer to me. > It's not because this works on x86 that this is necessarily correct for all > the other architectures, especially the strict-alignment architectures. Doesn't "fix" the same issue popping up in other passes. Richard. > -- > Eric Botcazou
On Thu, 2016-02-04 at 12:09 +0100, Eric Botcazou wrote: > > So this doesn’t fix aarch64, c6x, epiphany, ia64, iq2000, rs6000, rx, sparc, > > tilegx, tilepro or xtensa. > > :-( That’s one of the problems by having each port copy and paste swaths of > > :code from other ports to express the same thing instead of ports sharing > > :just one copy of code. My port is also broken in the same way > > :(currently). > > Yes, fixing a compiler bug by changing the ABI is a no-no, and the argument of > the compatibility with LLVM has IMO little merit since it's a GCC extension. But it is a GCC extension that is implemented in LLVM. It's just implemented differently there. We either have to change GCC, change LLVM, or live with the difference. In any of these cases I wonder if we should change GCC so that the code below generates warnings. If the two types are going to get passed differently we shouldn't allow calls with one type to call a function expecting the other type to happen with no warning or error. Currently this code does not warn even with -Wall. typedef int alignedint __attribute__((aligned(8))); extern void foo (alignedint a); extern void bar (int); int a; alignedint b; int main() { foo(a); bar(b); } Steve Ellcey sellcey@imgtec.com
Richard Biener <richard.guenther@gmail.com> writes: > On Thu, Feb 4, 2016 at 12:09 PM, Eric Botcazou <ebotcazou@adacore.com> wrote: >>> So this doesn’t fix aarch64, c6x, epiphany, ia64, iq2000, rs6000, rx, sparc, >>> tilegx, tilepro or xtensa. >>> :-( That’s one of the problems by having each port copy and paste swaths of >>> :code from other ports to express the same thing instead of ports sharing >>> :just one copy of code. My port is also broken in the same way >>> :(currently). >> >> Yes, fixing a compiler bug by changing the ABI is a no-no, and the argument of >> the compatibility with LLVM has IMO little merit since it's a GCC extension. > > True, but the compiler bug is in the backends - it just now gets > exposed more easily > (read: w/o user intervention). I'm still not convinced it's a backend/target bug though. It seems like a similar situation to floats being promoted to doubles and chars to ints when passed to unprototyped functions or varargs. In those situations it's up to the hook to decide what type the value actually gets passed as. Passing an overaligned int as a plain int is pretty similar and isn't something that each target should need to check individually. Thanks, Richard
On February 4, 2016 9:28:22 PM GMT+01:00, Richard Sandiford <rdsandiford@googlemail.com> wrote: >Richard Biener <richard.guenther@gmail.com> writes: >> On Thu, Feb 4, 2016 at 12:09 PM, Eric Botcazou ><ebotcazou@adacore.com> wrote: >>>> So this doesn’t fix aarch64, c6x, epiphany, ia64, iq2000, rs6000, >rx, sparc, >>>> tilegx, tilepro or xtensa. >>>> :-( That’s one of the problems by having each port copy and paste >swaths of >>>> :code from other ports to express the same thing instead of ports >sharing >>>> :just one copy of code. My port is also broken in the same way >>>> :(currently). >>> >>> Yes, fixing a compiler bug by changing the ABI is a no-no, and the >argument of >>> the compatibility with LLVM has IMO little merit since it's a GCC >extension. >> >> True, but the compiler bug is in the backends - it just now gets >> exposed more easily >> (read: w/o user intervention). > >I'm still not convinced it's a backend/target bug though. It seems >like a similar situation to floats being promoted to doubles and >chars to ints when passed to unprototyped functions or varargs. >In those situations it's up to the hook to decide what type the >value actually gets passed as. Passing an overaligned int as a >plain int is pretty similar and isn't something that each target >should need to check individually. I agree here. BUT we are still effectively changing the ABI of each affected target then without actually knowing we do. I'd happily do such change in the middle-end if we identified all affected targets and verified the changes impact. That's a lot of work and thus having active targets follow the "arm way" of fixing the issue in the target is very reasonable in my opinion and the only thing I'd accept at this stage. Richard. >Thanks, >Richard
> True, but the compiler bug is in the backends - it just now gets > exposed more easily (read: w/o user intervention). As far as I can see there are no problematic types in the source code, i.e. it's plain ANSI C, so we shouldn't be creating types with non-canonical alignment from that. > Doesn't "fix" the same issue popping up in other passes. Which pass does the alignment promotion? Maybe it's the one to be fixed.
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 697abc2..4aa215f 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -5644,7 +5644,10 @@ mips_function_arg_boundary (machine_mode mode, const_tree type) { unsigned int alignment; - alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode); + alignment = type + ? TYPE_ALIGN (TYPE_MAIN_VARIANT (type)) + : GET_MODE_ALIGNMENT (mode); + if (alignment < PARM_BOUNDARY) alignment = PARM_BOUNDARY; if (alignment > STACK_BOUNDARY) 2016-02-03 Steve Ellcey <sellcey@imgtec.com> PR target/68273 * gcc.c-torture/execute/pr68273-1.c: New test. * gcc.c-torture/execute/pr68273-2.c: New test. diff --git a/gcc/testsuite/gcc.c-torture/execute/pr68273-1.c b/gcc/testsuite/gcc.c-torture/execute/pr68273-1.c index e69de29..3ce07c6 100644 --- a/gcc/testsuite/gcc.c-torture/execute/pr68273-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/pr68273-1.c @@ -0,0 +1,74 @@ +/* Make sure that the alignment attribute on an argument passed by + value does not affect the calling convention and what registers + arguments are passed in. */ + +extern void exit (int); +extern void abort (void); + +typedef int alignedint __attribute__((aligned(8))); + +int __attribute__((noinline)) +foo1 (int a, alignedint b) +{ return a + b; } + +int __attribute__((noinline)) +foo2 (int a, int b) +{ + return a + b; +} + +int __attribute__((noinline)) +bar1 (alignedint x) +{ + return foo1 (1, x); +} + +int __attribute__((noinline)) +bar2 (alignedint x) +{ + return foo1 (1, (alignedint) 99); +} + +int __attribute__((noinline)) +bar3 (alignedint x) +{ + return foo1 (1, x + (alignedint) 1); +} + +alignedint q = 77; + +int __attribute__((noinline)) +bar4 (alignedint x) +{ + return foo1 (1, q); +} + + +int __attribute__((noinline)) +bar5 (alignedint x) +{ + return foo2 (1, x); +} + +int __attribute__((noinline)) +use_arg_regs (int i, int j, int k) +{ + return i+j-k; +} + +int main() +{ + if (use_arg_regs (999, 999, 999) != 999) abort (); + if (foo1 (19,13) != 32) abort (); + if (use_arg_regs (999, 999, 999) != 999) abort (); + if (bar1 (-33) != -32) abort (); + if (use_arg_regs (999, 999, 999) != 999) abort (); + if (bar2 (1) != 100) abort (); + if (use_arg_regs (999, 999, 999) != 999) abort (); + if (bar3 (17) != 19) abort (); + if (use_arg_regs (999, 999, 999) != 999) abort (); + if (bar4 (-33) != 78) abort (); + if (use_arg_regs (999, 999, 999) != 999) abort (); + if (bar5 (-84) != -83) abort (); + exit (0); +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr68273-2.c b/gcc/testsuite/gcc.c-torture/execute/pr68273-2.c index e69de29..1661be9 100644 --- a/gcc/testsuite/gcc.c-torture/execute/pr68273-2.c +++ b/gcc/testsuite/gcc.c-torture/execute/pr68273-2.c @@ -0,0 +1,109 @@ +/* Make sure that the alignment attribute on an argument passed by + value does not affect the calling convention and what registers + arguments are passed in. */ + +extern void exit (int); +extern void abort (void); + +typedef struct s { + char c; + char d; +} t1; +typedef t1 t1_aligned8 __attribute__((aligned(8))); +typedef t1 t1_aligned16 __attribute__((aligned(16))); +typedef t1 t1_aligned32 __attribute__((aligned(32))); + +int bar1(int a, t1 b) +{ + return a + b.c + b.d; +} + +int bar2(int a, t1_aligned8 b) +{ + return a + b.c + b.d; +} + +int bar3(int a, t1_aligned16 b) +{ + return a + b.c + b.d; +} + +int bar4(int a, t1_aligned32 b) +{ + return a + b.c + b.d; +} + +#define FOODEF(n,m,type) \ +int __attribute__((noinline)) \ +foo##n (int i, type b) \ + { \ + return bar##m (i, b); \ + } + +FOODEF(1, 1, t1) +FOODEF(2, 1, t1_aligned8) +FOODEF(3, 1, t1_aligned16) +FOODEF(4, 1, t1_aligned32) +FOODEF(5, 2, t1) +FOODEF(6, 2, t1_aligned8) +FOODEF(7, 2, t1_aligned16) +FOODEF(8, 2, t1_aligned32) +FOODEF(9, 3, t1) +FOODEF(10, 3, t1_aligned8) +FOODEF(11, 3, t1_aligned16) +FOODEF(12, 3, t1_aligned32) +FOODEF(13, 4, t1) +FOODEF(14, 4, t1_aligned8) +FOODEF(15, 4, t1_aligned16) +FOODEF(16, 4, t1_aligned32) + +int __attribute__((noinline)) +use_arg_regs (int i, int j, int k) +{ + return i+j-k; +} + +#define FOOCALL(i) \ + c = i*11 + 39; \ + x1.c = i + 5; \ + x1.d = i*2 + 3; \ + x2.c = x1.c + 1; \ + x2.d = x1.d + 1; \ + x3.c = x2.c + 1; \ + x3.d = x2.d + 1; \ + x4.c = x3.c + 1; \ + x4.d = x3.d + 1; \ + if (use_arg_regs (999,999,999) != 999) abort (); \ + if (foo##i (c, x1) != c + x1.c + x1.d) abort (); \ + if (use_arg_regs (999,999,999) != 999) abort (); \ + if (foo##i (c, x2) != c + x2.c + x2.d) abort (); \ + if (use_arg_regs (999,999,999) != 999) abort (); \ + if (foo##i (c, x3) != c + x3.c + x3.d) abort (); \ + if (use_arg_regs (999,999,999) != 999) abort (); \ + if (foo##i (c, x4) != c + x4.c + x4.d) abort (); + +int main() +{ + int c; + t1 x1; + t1_aligned8 x2; + t1_aligned16 x3; + t1_aligned32 x4; + FOOCALL(1); + FOOCALL(2); + FOOCALL(3); + FOOCALL(4); + FOOCALL(5); + FOOCALL(6); + FOOCALL(7); + FOOCALL(8); + FOOCALL(9); + FOOCALL(10); + FOOCALL(11); + FOOCALL(12); + FOOCALL(13); + FOOCALL(14); + FOOCALL(15); + FOOCALL(16); + exit (0); +}