InstCombine: Combine mul with div.
authorDavid Majnemer <david.majnemer@gmail.com>
Sat, 16 Aug 2014 08:55:06 +0000 (08:55 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Sat, 16 Aug 2014 08:55:06 +0000 (08:55 +0000)
commitcb698b26a108b4aa42995d629fa72231eb238f24
tree9a9acdefd077d79571477b01581a7a143f35e442
parentf1aba61bb5b0655ac6c74a54764f50ca7a3d9d3d
InstCombine: Combine mul with div.

We can combne a mul with a div if one of the operands is a multiple of
the other:

%mul = mul nsw nuw %a, C1
%ret = udiv %mul, C2
  =>
%ret = mul nsw %a, (C1 / C2)

This can expose further optimization opportunities if we end up
multiplying or dividing by a power of 2.

Consider this small example:

define i32 @f(i32 %a) {
  %mul = mul nuw i32 %a, 14
  %div = udiv exact i32 %mul, 7
  ret i32 %div
}

which gets CodeGen'd to:

    imull       $14, %edi, %eax
    imulq       $613566757, %rax, %rcx
    shrq        $32, %rcx
    subl        %ecx, %eax
    shrl        %eax
    addl        %ecx, %eax
    shrl        $2, %eax
    retq

We can now transform this into:
define i32 @f(i32 %a) {
  %shl = shl nuw i32 %a, 1
  ret i32 %shl
}

which gets CodeGen'd to:

    leal        (%rdi,%rdi), %eax
    retq

This fixes PR20681.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215815 91177308-0d34-0410-b5e6-96231b3b80d8
lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
test/Transforms/InstCombine/div.ll