Details
- Reviewers
spatel
Diff Detail
- Repository
- rG LLVM Github Monorepo
- Build Status
Buildable 42264 Build 42696: arc lint + arc unit
Event Timeline
What does this patch do with INT_MIN? Is there demonstrable benefit (code patterns in real world applications)?
Isn't abs(INT_MIN) undefined?
expensive div is removed:
_Z4fooai: # @_Z4fooai mov eax, edi mov ecx, edi neg ecx cmovl ecx, edi cdq idiv ecx ret _Z5fooari: # @_Z5fooari mov eax, edi sar eax, 31 or eax, 1 ret
GCC knows this trick too.
abs(INT_MIN) is only undefined if the sub 0, %x operation that SPF_ABS matched has the nsw flag set on it.
Isn't it sufficient to just check that the true/false values of the select are x and -x. The condition itself doesn't matter. x / (select c, x, -x) -> select c ? 1 : -1
Name: div abs %cmp = icmp slt i32 %x, 0 %sub = sub nsw i32 0, %x %cond = select i1 %cmp, i32 %sub, i32 %x %div = sdiv i32 %x, %cond => %div = select i1 %cmp, i32 -1, i32 1
Right.
llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | ||
---|---|---|
1115 | Taking this even farther. Can't we do X / (select C, A, X) -> select C, X / A, 1 I assume if A happens to be X or -X it would continue folding on its own when the new nodes are processed in the worklist |
Seems like we should maybe teach InstCombiner::FoldOpIntoSelect to handle cases where one of the select operands becomes a constant if we fold. But we might only call FoldOpIntoSelect when one of the operands of the binop is a constant today.
I think we also miss
x + (c ? -x : y) -> c ? 0 : x + y
x - (c ? x : y) -> c ? 0 : x - y
Also does InstSimplify know X / -X -> -1 when the neg has NSW?
I'm not sure if this does everything you want, but you probably should look at:
InstCombiner::SimplifySelectsFeedingBinaryOp()
Taking this even farther. Can't we do
X / (select C, A, X) -> select C, X / A, 1
I assume if A happens to be X or -X it would continue folding on its own when the new nodes are processed in the worklist