https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128449
Bug ID: 128449
Summary: Improve gimple select across sequences that differ
only in signedness
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Keywords: missed-optimization
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: law at gcc dot gnu.org
Blocks: 26163
Target Milestone: ---
Target: riscv
Imagine this code in gimple:
;; basic block 3, loop depth 0
;; pred: 2
_2 = f_13(D) + _18;
_3 = _2 * mf_14(D);
_4 = _3 >> 16;
_16 = (short int) _4;
goto <bb 5>; [100.00%]
;; succ: 5
;; basic block 4, loop depth 0
;; pred: 2
_6 = f_13(D) - _18;
_7 = _6 * mf_14(D);
_8 = _7 >> 16;
_9 = (unsigned short) _8;
_10 = -_9;
_15 = (short int) _10;
;; succ: 5
;; basic block 5, loop depth 0
;; pred: 3
;; 4
# _11 = PHI <_16(3), _15(4)>
A bit of work shows that _16 and _15 only differ in signs. Furthermore, the
RTL if-converter is going to turn that into straightline code with two
multiplies!
sub a5,a1,a0 # 47 [c=4 l=4] subdi3
mul t0,a5,a2 # 48 [c=16 l=4] muldi3
add a1,a1,a0 # 43 [c=4 l=4] *adddi3/0
slti a0,a0,1 # 53 [c=4 l=4] *sle_didi
mul t1,a1,a2 # 45 [c=16 l=4] muldi3
sraiw t2,t0,16 # 49 [c=8 l=4] ashrsi3_extend
negw a2,t2 # 50 [c=8 l=4] negsi2_extended
sext.h a3,a2 # 51 [c=4 l=4] *extendhidi2_bitmanip/0
czero.eqz a4,a3,a0 # 54 [c=4 l=4] *czero.eqz.didi
sraiw a6,t1,16 # 46 [c=12 l=4] *lshrsi3_extend_2
czero.nez a7,a6,a0 # 55 [c=4 l=4] *czero.nez.didi
add a0,a7,a4 # 38 [c=4 l=4] *adddi3/0
That's probably still better than taking a branch mispredict, but it'd be more
profitable if we just did a single multiply. A quick looksie at the RTL
confirmed my suspicion that this could be quite painful to try and capture in
ifcvt.c But the gimple might be more feasible. It's about 19m instructions in
x264. Small, but with the multiply in there, it's going to have an outsized
impact.
short
f (short x, int f, int mf)
{
if (x > 0)
return (f + x) * mf >> 16;
else
return -((f - x) * mf >> 16);
}
Note the bigger versions of quant get vectorized and thus don't suffer from
this problem on modern designs.
Referenced Bugs:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=26163
[Bug 26163] [meta-bug] missed optimization in SPEC (2026, 2k17, 2k and 2k6 and
95)