https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89018
Bug ID: 89018
Summary: common subexpression present in both branches of
condition is not factored out
Product: gcc
Version: 9.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: wojciech_mula at poczta dot onet.pl
Target Milestone: ---
A common transformation used in a C condition expression is not detected and
code is duplicated. Below are a few examples:
---condition.c---
long transform(long);
long negative_max(long a, long b) {
return (a >= b) ? -a : -b;
}
long fun_max(long a, long b) {
return (a >= b) ? 47*a : 47*b;
}
long transform_max(long a, long b) {
return (a >= b) ? transform(a) : transform(b);
}
---eof---
In both branches a scalar value is a part of the same expression. So, it
would be more profitable when, for instance "(a >= b) ? -a : -b" would be
compiled as "-((a >= b) ? a : b))". Of course, a programmer might factor it
out, but in case of macros or auto-generated code such silly repetition
might occur.
Below is assembly code generated for x86 by a pretty fresh GCC 9.
BTW the jump instruction from `fun_max` and `transform_max` can
be replaced with a condition move.
$ gcc --version
gcc (GCC) 9.0.0 20190117 (experimental)
$ gcc -O3 -march=skylake -c -S condition.c && cat condition.s
negative_max:
movq %rdi, %rdx
movq %rsi, %rax
negq %rdx
negq %rax
cmpq %rsi, %rdi
cmovge %rdx, %rax
ret
fun_max:
cmpq %rsi, %rdi
jl .L6
imulq $47, %rdi, %rax
ret
.L6:
imulq $47, %rsi, %rax
ret
transform_max:
cmpq %rsi, %rdi
jge .L11
movq %rsi, %rdi
.L11:
jmp transform