Bug 93843 - [10 Regression] wrong code at -O3 on x86_64-linux-gnu
Summary: [10 Regression] wrong code at -O3 on x86_64-linux-gnu
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 10.0
: P1 normal
Target Milestone: 10.0
Assignee: Richard Sandiford
URL:
Keywords: wrong-code
: 93919 (view as bug list)
Depends on:
Blocks: 93919
  Show dependency treegraph
 
Reported: 2020-02-20 06:07 UTC by Qirun Zhang
Modified: 2020-02-27 19:56 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work: 9.2.0
Known to fail: 10.0
Last reconfirmed: 2020-02-20 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Qirun Zhang 2020-02-20 06:07:26 UTC
A recent regression. Gcc-9 works fine.

Bisection points to g:6271dd984d7f920d4fb17ad37af6a1f8e6b796dc

$ gcc-trunk -v
gcc version 10.0.1 20200219 (experimental) [master revision 665c5bad168:533e82edecf:51faf07cef9293af544bfacc7d0b320ab90d7d60] (GCC)


$ gcc-trunk -O3 abc.c ; ./a.out
4
0

$ gcc-9 -O3 abc.c ; ./a.out
4
4

$ gcc-trunk  abc.c ; ./a.out
4
4

$ cat abc.c
int printf(const char *, ...);
char a, e;
struct {
  short b;
  short c;
} d;
int f;
int main() {
  short *g = &d.c, *h = &d.b;
  e = 4 - a;
  *h = *g = e;
  for (; f < 2; f++)
    printf("%d\n", d.c);
}
Comment 1 Martin Liška 2020-02-20 08:20:45 UTC
Nice catch. Actually started with -fno-common with r10-4742-g9b75f56d4b7951c6.
Comment 2 Jakub Jelinek 2020-02-24 10:56:19 UTC
Adjusted testcase:
char a;
struct S { short b, c; } d;

__attribute__((noipa)) void
foo (int x)
{
  if (x != 4)
    __builtin_abort ();
}

int
main ()
{
  short *g = &d.c, *h = &d.b;
  char e = 4 - a;
  int f;
  *h = *g = e;
  for (f = 0; f < 2; f++)
    foo (d.c);
  return 0;
}
Comment 3 Jakub Jelinek 2020-02-24 11:24:35 UTC
The problem is that we have a signed char -> short int cast and vectorizable_conversion on that sees vectype_in a 2xQI with HImode TYPE_MODE and
vectype_out a 2xHI with SImode TYPE_MODE.  As both vector types have 2 units, modifier is NONE and we create a NOP_EXPR from the 2xQI vector to 2xHI vector where we actually need to sign-extend both vector elements.
The big question is whether this is something valid (I'd hope not); if yes, we'd need to tweak the expansion so that it emits something that actually does the extensions, if not, we need to punt or handle it some different way in vectorizable_conversion.  Because right now, we actually emit just a scalar sign-extension, which means the first element contains both original elements and second element just 0 or -1 depending on the sign of the original second element.
Comment 4 Richard Biener 2020-02-24 12:54:56 UTC
IIRC Richard made this valid but maybe didn't expect targets to advertise
support for it (how do we check this?)
Comment 5 Matthias Kretz (Vir) 2020-02-25 10:45:38 UTC
Simpler variant. I couldn't come up with a better barrier to force the last line to load from out than inline asm.

char in[2] = {2, 2};
short out[2] = {};

int
main()
{
  for (int i = 0; i < 2; ++i)
    out[i] = in[i];
  asm("":::"memory");
  if (out[0] != 2) __builtin_abort();
}
Comment 6 Andrew Pinski 2020-02-25 11:15:22 UTC
(In reply to Matthias Kretz (Vir) from comment #5)
> Simpler variant. I couldn't come up with a better barrier to force the last
> line to load from out than inline asm.
> 
> char in[2] = {2, 2};
> short out[2] = {};
> 
> int
> main()
> {
>   for (int i = 0; i < 2; ++i)
>     out[i] = in[i];
>   asm("":::"memory");
>   if (out[0] != 2) __builtin_abort();
> }

__atomic_signal_fence (__ATOMIC_RELAXED)  If you don't want to use inline-asm directly (it should translate to the same thing internally though).
Comment 7 Matthias Kretz (Vir) 2020-02-25 14:40:36 UTC
This one exhibits the issue without -ftree-vectorize (`-O1` suffices) (cf. https://godbolt.org/z/Swx-jW):

using M [[gnu::vector_size(2)]] = char;
using MM [[gnu::vector_size(4)]] = short;

MM
cvt(M x)
{
  return MM{short(x[0]), short(x[1])};
}
Comment 8 Richard Sandiford 2020-02-25 19:22:18 UTC
Testing a patch.
Comment 9 GCC Commits 2020-02-26 12:48:04 UTC
The master branch has been updated by Richard Sandiford <rsandifo@gcc.gnu.org>:

https://gcc.gnu.org/g:b6268016bf46dd63227dcbb73d13c30a3b4b9d2a

commit r10-6863-gb6268016bf46dd63227dcbb73d13c30a3b4b9d2a
Author: Richard Sandiford <richard.sandiford@arm.com>
Date:   Tue Feb 25 19:20:58 2020 +0000

    optabs: Don't use scalar conversions for vectors [PR93843]
    
    In this PR we had a conversion between two integer vectors that
    both had scalar integer modes.  We then tried to implement the
    conversion using the scalar optab for those modes, instead of
    doing the conversion elementwise.
    
    I wondered about letting through scalar modes for single-element
    vectors, but I don't have any evidence that that's useful/necessary,
    so it seemed better to keep things simple.
    
    2020-02-26  Richard Sandiford  <richard.sandiford@arm.com>
    
    gcc/
    	PR middle-end/93843
    	* optabs-tree.c (supportable_convert_operation): Reject types with
    	scalar modes.
    
    gcc/testsuite/
    	PR middle-end/93843
    	* gcc.dg/vect/pr93843-1.c: New test.
    	* gcc.dg/vect/pr93843-2.c: Likewise.
Comment 10 Richard Sandiford 2020-02-26 12:50:56 UTC
Fixed.
Comment 11 Matthias Kretz (Vir) 2020-02-27 19:56:15 UTC
*** Bug 93919 has been marked as a duplicate of this bug. ***