https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117688

Alexey Merzlyakov <alexey.merzlyakov at samsung dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |alexey.merzlyakov at samsung 
dot c
                   |                            |om

--- Comment #4 from Alexey Merzlyakov <alexey.merzlyakov at samsung dot com> ---
Indeed, the problem is not related to the latest change I've made: it caused
many fallouts that time, which were fixed shortly. When I've locally disapplied
the change, it did not take any effect on this issue.

Bisect shows that problem appeared in master since
https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=e21a8d9ec63464b2c8301f882a3a04ac59b01fcd
adding SAT_SUB optimization pattern into match.pd, which is actually made in
the test from the ticket's header. However, this patch only uncovers the issue,
which seems to be laying in another place.

The srai-xori-and <-> andi difference in generated code if pass x as foo()'s
argument could be de-optimized by disabling forward propagation in RTL
(-fno-forward-propagate). However if disable fwprop, the test still fails, so
most probably this difference is also caused by optimization of what was
initially wrong before.

Generated codes between foo() and foo2() from the second test (with disabled
fwprop) are almost the same. It was noted only the one difference, that foo()
contains:

  lui     a5,%hi(x)
  lbu     a5,%lo(x)(a5)

while foo2() just uses a0 instead.
Additionally, if insert the printing "x" routine into foo(), e.g.:

  __attribute__ ((noipa)) void
  foo ()
  {
    int8_t minus;
    bool overflow = __builtin_sub_overflow (x, y, &minus);
    result = overflow ? (x < 0 ? 0x80 : 0x7f) : minus;
    printf("x = %i\n", x);
  }

the test became to be passed. The difference between printing and non-printing
cases is just in signed/unsigned loads from memory:

  lui     a5,%hi(x)
  lbu     a5,%lo(x)(a5)
vs
  lui     a4,%hi(x)
  lb      a1,%lo(x)(a4) <- for printf-case 

(changing lbu -> to lb in assembler and then compiling it to executable, also
causes test to pass)

In printf-case, expand-rtl generates sign-extend RTX for "x.0_1 = x" GIMPLE:

  (insn 8 7 0 (set (reg:DI 134 [ x.0_1 ])
        (sign_extend:DI (mem/c:QI (lo_sum:DI (reg:DI 138)
                    (symbol_ref:DI ("x") [flags 0x86]  <var_decl 0x7105f9bc08e8
x>)) [0 x+0 S1 A8]))) "/app/example.cpp":11:42 -1
     (nil))

while for nonprintf-case, it generates zero-extend for "iftmp.2_5 = .SAT_SUB
(x.0_1, y.1_2)" GIMPLE ("x.0_1 = x" is in the list of replaceable expressions
for that case, and RTX is not separately generated for it):

  (insn 12 11 13 (set (reg:DI 141)
        (zero_extend:DI (mem/c:QI (lo_sum:DI (reg:DI 137)
                    (symbol_ref:DI ("x") [flags 0x86]  <var_decl 0x7f9fd25c08e8
x>)) [0 x+0 S1 A8]))) -1
     (nil))

Not sure whether it might be related to incorrect SAT_SUB internal function
implementation for RISC-V or something else in expand. But this behavior seems
strange to me, since we are relying on "x" sign bit during further SAT_SUB
call.

Reply via email to