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.