Bug 110795 - Bad code gen for vector compare booleans
Summary: Bad code gen for vector compare booleans
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 13.1.1
: P3 normal
Target Milestone: ---
Assignee: Kewen Lin
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2023-07-24 22:20 UTC by Steven Munroe
Modified: 2023-07-28 14:42 UTC (History)
7 users (show)

See Also:
Host:
Target: powerpc
Build:
Known to work:
Known to fail: 6.4.1
Last reconfirmed: 2023-07-27 00:00:00


Attachments
Test examples for vector code combinining vector compare combined with logical or. functions vec_cmp33 and vec_divduw generate correct code while vec_divduw_V1 generates bad code. (1.48 KB, text/x-csrc)
2023-07-24 22:20 UTC, Steven Munroe
Details
Main and unit-test. When compiled and linked with vec_divide.c will verify if the divide code is correct or not. (1.15 KB, text/x-csrc)
2023-07-24 22:25 UTC, Steven Munroe
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Steven Munroe 2023-07-24 22:20:03 UTC
Created attachment 55626 [details]
Test examples for vector code combinining vector compare combined with logical or. functions vec_cmp33 and vec_divduw generate correct code while vec_divduw_V1 generates bad code.

Combining a vec_cmplt and vec_cmpge with vector logical OR misscompiles.
For example:
  // Capture the carry t as a bool using signed compare
  t = vec_cmplt ((vi32_t) x, zeros);
  ge = vec_cmpge (x, z);
  // Combine t with (x >= z) for 33-bit compare
  t  = vec_or (ge, t);

This seems to work for the minimized example above but fails when used in the more complex loop of the example vec_divduw_V1. At -O3 the compiler elides any code generated for vec_cmplt.

With this bug the function vec_divduw_V1 (Vector_Divide double (words by) unsigned word) fails the unit test.
Comment 1 Steven Munroe 2023-07-24 22:25:23 UTC
Created attachment 55627 [details]
Main and unit-test. When compiled and linked with vec_divide.c will verify if the divide code is correct or not.
Comment 2 Steven Munroe 2023-07-24 22:31:00 UTC
Also fails with gcc11/12. Also fails with Advance Toolchain 10.0 GCC 6.4.1.

It might fail for all version between GCC 6 and 13.
Comment 3 Kewen Lin 2023-07-27 02:52:07 UTC
I'll have a look first.
Comment 4 Kewen Lin 2023-07-27 06:57:18 UTC
I think this is a test case issue, with the below patch to the provided test case, it can pass the associate testing:

$ diff -Nuar vec_divide.c.orig vec_divide.c
--- vec_divide.c.orig   2023-07-27 01:42:20.723440140 -0500
+++ vec_divide.c        2023-07-27 01:42:33.383375622 -0500
@@ -113,7 +113,7 @@
       // Then  the compiler should merge the NOT with OR as ORC
       ge = vec_cmpge (x, z);
       // Combine t with (x >= z) for 33-bit compare
-      t  = vec_or (ge, t);
+      ge  = vec_or (ge, t);

       /* if (x >= z) x = x - z ; y++ */
       xt = vec_sub (x, z);


It tries to "deconstruct ((t || x) >= z) as (t || (x >= z))", but adopts *ge* rather than *t* as the selector for the following vec_sel, it's unexpected and the testing passed once it gets fixed. I also tried with -O2 and -Ofast with -mcpu=power10, all passed.

Please reopen it if the above is just a typo and the underlying issue is covered.
Comment 5 Steven Munroe 2023-07-28 14:42:40 UTC
Thanks, sorry I missed the obvious.