Previously GEP of GEP with constant indices are only merged to the front (Second GEP is merged to the first one whenever possible). This patch expanded the optimization to also try merging to the direction under some constraints on GEP usage, if the first attempt failed.
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
I'm not a big fan of the "try to combine in both directions approach". It will still miss cases where neither direction works, but the GEPs can still be folded. Something like this should work for all constant GEPs: https://gist.github.com/nikic/8a1a82382468c88f19094d4b0a2f547c
@nikic
I will add converting constant GEP to i8* in the next patch. The existing merging functionality can handle GEP with not all constant indices, such as
%1 = gep {i32, i32, i32}, ptr %p, i64 %a, i32 1 %2 = gep i32, ptr %1, i64 1
Such expression cannot be convert to GEP of i8 without creating a complicated index expression, which is basically moving instruction selection to the front. It is unreasonable that merge only allows one direction but not the other, given use-def constraints satisfied.
@huangjd The not all constant case continues to be handled. If you mean the case where we have ((p + C) + x), then this should first be converted to ((p + x) + C` by the previously discussed transform to hoist constant GEPs, at which point the constant GEP is in the right position of this transform again. There is no need to additionally perform a swap at this point.
Added fallback if merging GEP of GEP with all constant indices fails on both directions, convert the expression into GEP of i8, using the sum of both GEP's offsets