int g(); int f(int a, int b) { if (a != b) return a - b; return g(); } This can be optimized to using the result of `a - b` to check for `a != b`. This is done by LLVM, but not by GCC. For example, on x86, LLVM generates this : f(int, int): sub edi, esi jne .LBB0_1 jmp g() .LBB0_1: mov eax, edi ret GCC generates this : f(int, int): cmp edi, esi je .L7 mov eax, edi sub eax, esi ret .L7: jmp g()
Shouldn't it be marked as target issue for x86?
(In reply to Hongtao.liu from comment #1) > Shouldn't it be marked as target issue for x86? Or you means that middle-end should transform code to int g(); int f(int a, int b) { int c = a - b; if (c) return c; return g(); }
Well, I don't actually know enough to be able to determine which would be optimal. Transformation to the example from the third comment would be suboptimal on some targets (say, I don't think AVR would like this for 64-bit numbers), while doing this as an x86 specific transformation would be missing on an optimization opportunity on plenty of other targets.
I guess it could be formulated as code-hoisting opportunity when we make a - b (or b - a) anticipated on the edges from the a != b compare. What's then missing is transforming int tem = a - b; if (a != b) ... into tem = a - b; if (tem != 0) but IIRC we essentially do the reverse transform via match.pd. Here the main issue is that the GIMPLE IL doesn't reflect what targets usually do, that is, flags registers are not modeled and instead we branch on the actual compare rather than its outcome and a subtract doesn't set flags. Eventually this is sth for RTL if-conversion though where those details are exposed.