llvm / llvm/llvm-project

[InstCombine] Bad codegen for gep(p, select cond, 0, const) over select(cond, p, gep p, const)

Open
#220,596 2 comments 0 reactions 0 assignees View on GitHub
llvm:instcombine missed-optimization
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

gep(p, select cond, 0, const) tends to result in worse codegen than select(cond, p, gep p, const). InstCombine currently canonicalizes in the other direction. Not sure if we should prefer to canonicalize src->tgt or handle this in SelectionDAG.

```c++
struct U {long x[4]; }; U *src(U *u, unsigned x) { return x ? u - 1 : u; }
```

```llvm
define ptr @src(ptr %0, i32 %1) {
%3 = icmp eq i32 %1, 0
%4 = select i1 %3, i64 0, i64 -32
%5 = getelementptr inbounds i8, ptr %0, i64 %4
ret ptr %5
}
define ptr @tgt(ptr %0, i32 %1) {
%3 = icmp eq i32 %1, 0
%4 = getelementptr inbounds i8, ptr %0, i64 -32
%5 = select i1 %3, ptr %0, ptr %4
ret ptr %5
}
```

```asm
src: # @src
xor eax, eax
test esi, esi
sete al
shl eax, 5
lea rax, [rax + rdi - 32]
ret
tgt: # @tgt
lea rax, [rdi - 32]
test esi, esi
cmove rax, rdi
ret

src: // @src
mov x8, #-32 // =0xffffffffffffffe0
cmp w1, #0
csel x8, xzr, x8, eq
add x0, x0, x8
ret
tgt: // @tgt
sub x8, x0, #32
cmp w1, #0
csel x0, x0, x8, eq
ret
```

https://alive2.llvm.org/ce/z/8C7vQu

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the src and tgt examples for x86 and AArch64, then compare the InstCombine canonicalization with the SelectionDAG alternative. Use the provided LLVM IR and Alive2 link to verify equivalence; done means choosing and implementing a direction that produces the better codegen without breaking the transformation.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.