[llvm] r304972 - This patch closes PR28513: an optimization of multiplication by different constants.

Eric Christopher via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 16 10:07:57 PDT 2017


Hi Andrew,

This isn't a great commit message. What was the issue and how did you fix
it? What's the difference? This probably should have gone up for re-review
after.

Also, relatedly, we're seeing failures in grub with this. We'll work on
getting a testcase, but can you please revert this in the meantime?

Thanks!

-eric

On Thu, Jun 8, 2017 at 3:20 AM Andrew V. Tischenko via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: avt77
> Date: Thu Jun  8 05:20:13 2017
> New Revision: 304972
>
> URL: http://llvm.org/viewvc/llvm-project?rev=304972&view=rev
> Log:
> This patch closes PR28513: an optimization of multiplication by different
> constants.
> The initial patch was rejected: I fixed the issue and re-apply it.
>
> Added:
>     llvm/trunk/test/CodeGen/X86/mul-constant-result.ll
> Modified:
>     llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
>     llvm/trunk/test/CodeGen/X86/mul-constant-i16.ll
>     llvm/trunk/test/CodeGen/X86/mul-constant-i32.ll
>     llvm/trunk/test/CodeGen/X86/mul-constant-i64.ll
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=304972&r1=304971&r2=304972&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Thu Jun  8 05:20:13 2017
> @@ -81,6 +81,12 @@ static cl::opt<int> ExperimentalPrefLoop
>               " of the loop header PC will be 0)."),
>      cl::Hidden);
>
> +static cl::opt<bool> MulConstantOptimization(
> +    "mul-constant-optimization", cl::init(true),
> +    cl::desc("Replace 'mul x, Const' with more effective instructions
> like "
> +             "SHIFT, LEA, etc."),
> +    cl::Hidden);
> +
>  /// Call this when the user attempts to do something unsupported, like
>  /// returning a double without SSE2 enabled on x86_64. This is not fatal,
> unlike
>  /// report_fatal_error, so calling code should attempt to recover without
> @@ -31031,6 +31037,77 @@ static SDValue reduceVMULWidth(SDNode *N
>    }
>  }
>
> +static SDValue combineMulSpecial(uint64_t MulAmt, SDNode *N, SelectionDAG
> &DAG,
> +                                 EVT VT, SDLoc DL) {
> +
> +  auto combineMulShlAddOrSub = [&](int Mult, int Shift, bool isAdd) {
> +    SDValue Result = DAG.getNode(X86ISD::MUL_IMM, DL, VT,
> N->getOperand(0),
> +                                 DAG.getConstant(Mult, DL, VT));
> +    Result = DAG.getNode(ISD::SHL, DL, VT, Result,
> +                         DAG.getConstant(Shift, DL, MVT::i8));
> +    Result = DAG.getNode(isAdd ? ISD::ADD : ISD::SUB, DL, VT, Result,
> +                         N->getOperand(0));
> +    return Result;
> +  };
> +
> +  auto combineMulMulAddOrSub = [&](bool isAdd) {
> +    SDValue Result = DAG.getNode(X86ISD::MUL_IMM, DL, VT,
> N->getOperand(0),
> +                                 DAG.getConstant(9, DL, VT));
> +    Result = DAG.getNode(ISD::MUL, DL, VT, Result, DAG.getConstant(3, DL,
> VT));
> +    Result = DAG.getNode(isAdd ? ISD::ADD : ISD::SUB, DL, VT, Result,
> +                         N->getOperand(0));
> +    return Result;
> +  };
> +
> +  switch (MulAmt) {
> +  default:
> +    break;
> +  case 11:
> +    // mul x, 11 => add ((shl (mul x, 5), 1), x)
> +    return combineMulShlAddOrSub(5, 1, /*isAdd*/ true);
> +  case 21:
> +    // mul x, 21 => add ((shl (mul x, 5), 2), x)
> +    return combineMulShlAddOrSub(5, 2, /*isAdd*/ true);
> +  case 22:
> +    // mul x, 22 => add (add ((shl (mul x, 5), 2), x), x)
> +    return DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0),
> +                       combineMulShlAddOrSub(5, 2, /*isAdd*/ true));
> +  case 19:
> +    // mul x, 19 => sub ((shl (mul x, 5), 2), x)
> +    return combineMulShlAddOrSub(5, 2, /*isAdd*/ false);
> +  case 13:
> +    // mul x, 13 => add ((shl (mul x, 3), 2), x)
> +    return combineMulShlAddOrSub(3, 2, /*isAdd*/ true);
> +  case 23:
> +    // mul x, 13 => sub ((shl (mul x, 3), 3), x)
> +    return combineMulShlAddOrSub(3, 3, /*isAdd*/ false);
> +  case 14:
> +    // mul x, 14 => add (add ((shl (mul x, 3), 2), x), x)
> +    return DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0),
> +                       combineMulShlAddOrSub(3, 2, /*isAdd*/ true));
> +  case 26:
> +    // mul x, 26 => sub ((mul (mul x, 9), 3), x)
> +    return combineMulMulAddOrSub(/*isAdd*/ false);
> +  case 28:
> +    // mul x, 28 => add ((mul (mul x, 9), 3), x)
> +    return combineMulMulAddOrSub(/*isAdd*/ true);
> +  case 29:
> +    // mul x, 29 => add (add ((mul (mul x, 9), 3), x), x)
> +    return DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0),
> +                       combineMulMulAddOrSub(/*isAdd*/ true));
> +  case 30:
> +    // mul x, 30 => sub (sub ((shl x, 5), x), x)
> +    return DAG.getNode(
> +        ISD::SUB, DL, VT,
> +        DAG.getNode(ISD::SUB, DL, VT,
> +                    DAG.getNode(ISD::SHL, DL, VT, N->getOperand(0),
> +                                DAG.getConstant(5, DL, MVT::i8)),
> +                    N->getOperand(0)),
> +        N->getOperand(0));
> +  }
> +  return SDValue();
> +}
> +
>  /// Optimize a single multiply with constant into two operations in order
> to
>  /// implement it with two cheaper instructions, e.g. LEA + SHL, LEA + LEA.
>  static SDValue combineMul(SDNode *N, SelectionDAG &DAG,
> @@ -31040,6 +31117,8 @@ static SDValue combineMul(SDNode *N, Sel
>    if (DCI.isBeforeLegalize() && VT.isVector())
>      return reduceVMULWidth(N, DAG, Subtarget);
>
> +  if (!MulConstantOptimization)
> +    return SDValue();
>    // An imul is usually smaller than the alternative sequence.
>    if (DAG.getMachineFunction().getFunction()->optForMinSize())
>      return SDValue();
> @@ -31095,7 +31174,8 @@ static SDValue combineMul(SDNode *N, Sel
>      else
>        NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, NewMul,
>                             DAG.getConstant(MulAmt2, DL, VT));
> -  }
> +  } else if (!Subtarget.slowLEA())
> +    NewMul = combineMulSpecial(MulAmt, N, DAG, VT, DL);
>
>    if (!NewMul) {
>      assert(MulAmt != 0 &&
>
> Modified: llvm/trunk/test/CodeGen/X86/mul-constant-i16.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/mul-constant-i16.ll?rev=304972&r1=304971&r2=304972&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/mul-constant-i16.ll (original)
> +++ llvm/trunk/test/CodeGen/X86/mul-constant-i16.ll Thu Jun  8 05:20:13
> 2017
> @@ -188,13 +188,16 @@ define i16 @test_mul_by_11(i16 %x) {
>  ; X86-LABEL: test_mul_by_11:
>  ; X86:       # BB#0:
>  ; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
> -; X86-NEXT:    imull $11, %eax, %eax
> +; X86-NEXT:    leal (%eax,%eax,4), %ecx
> +; X86-NEXT:    leal (%eax,%ecx,2), %eax
>  ; X86-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X86-NEXT:    retl
>  ;
>  ; X64-LABEL: test_mul_by_11:
>  ; X64:       # BB#0:
> -; X64-NEXT:    imull $11, %edi, %eax
> +; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-NEXT:    leal (%rdi,%rdi,4), %eax
> +; X64-NEXT:    leal (%rdi,%rax,2), %eax
>  ; X64-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X64-NEXT:    retq
>    %mul = mul nsw i16 %x, 11
> @@ -225,13 +228,16 @@ define i16 @test_mul_by_13(i16 %x) {
>  ; X86-LABEL: test_mul_by_13:
>  ; X86:       # BB#0:
>  ; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
> -; X86-NEXT:    imull $13, %eax, %eax
> +; X86-NEXT:    leal (%eax,%eax,2), %ecx
> +; X86-NEXT:    leal (%eax,%ecx,4), %eax
>  ; X86-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X86-NEXT:    retl
>  ;
>  ; X64-LABEL: test_mul_by_13:
>  ; X64:       # BB#0:
> -; X64-NEXT:    imull $13, %edi, %eax
> +; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-NEXT:    leal (%rdi,%rdi,2), %eax
> +; X64-NEXT:    leal (%rdi,%rax,4), %eax
>  ; X64-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X64-NEXT:    retq
>    %mul = mul nsw i16 %x, 13
> @@ -241,14 +247,19 @@ define i16 @test_mul_by_13(i16 %x) {
>  define i16 @test_mul_by_14(i16 %x) {
>  ; X86-LABEL: test_mul_by_14:
>  ; X86:       # BB#0:
> -; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
> -; X86-NEXT:    imull $14, %eax, %eax
> +; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %ecx
> +; X86-NEXT:    leal (%ecx,%ecx,2), %eax
> +; X86-NEXT:    leal (%ecx,%eax,4), %eax
> +; X86-NEXT:    addl %ecx, %eax
>  ; X86-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X86-NEXT:    retl
>  ;
>  ; X64-LABEL: test_mul_by_14:
>  ; X64:       # BB#0:
> -; X64-NEXT:    imull $14, %edi, %eax
> +; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-NEXT:    leal (%rdi,%rdi,2), %eax
> +; X64-NEXT:    leal (%rdi,%rax,4), %eax
> +; X64-NEXT:    addl %edi, %eax
>  ; X64-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X64-NEXT:    retq
>    %mul = mul nsw i16 %x, 14
> @@ -337,14 +348,19 @@ define i16 @test_mul_by_18(i16 %x) {
>  define i16 @test_mul_by_19(i16 %x) {
>  ; X86-LABEL: test_mul_by_19:
>  ; X86:       # BB#0:
> -; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
> -; X86-NEXT:    imull $19, %eax, %eax
> +; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %ecx
> +; X86-NEXT:    leal (%ecx,%ecx,4), %eax
> +; X86-NEXT:    shll $2, %eax
> +; X86-NEXT:    subl %ecx, %eax
>  ; X86-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X86-NEXT:    retl
>  ;
>  ; X64-LABEL: test_mul_by_19:
>  ; X64:       # BB#0:
> -; X64-NEXT:    imull $19, %edi, %eax
> +; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-NEXT:    leal (%rdi,%rdi,4), %eax
> +; X64-NEXT:    shll $2, %eax
> +; X64-NEXT:    subl %edi, %eax
>  ; X64-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X64-NEXT:    retq
>    %mul = mul nsw i16 %x, 19
> @@ -375,13 +391,16 @@ define i16 @test_mul_by_21(i16 %x) {
>  ; X86-LABEL: test_mul_by_21:
>  ; X86:       # BB#0:
>  ; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
> -; X86-NEXT:    imull $21, %eax, %eax
> +; X86-NEXT:    leal (%eax,%eax,4), %ecx
> +; X86-NEXT:    leal (%eax,%ecx,4), %eax
>  ; X86-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X86-NEXT:    retl
>  ;
>  ; X64-LABEL: test_mul_by_21:
>  ; X64:       # BB#0:
> -; X64-NEXT:    imull $21, %edi, %eax
> +; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-NEXT:    leal (%rdi,%rdi,4), %eax
> +; X64-NEXT:    leal (%rdi,%rax,4), %eax
>  ; X64-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X64-NEXT:    retq
>    %mul = mul nsw i16 %x, 21
> @@ -391,14 +410,19 @@ define i16 @test_mul_by_21(i16 %x) {
>  define i16 @test_mul_by_22(i16 %x) {
>  ; X86-LABEL: test_mul_by_22:
>  ; X86:       # BB#0:
> -; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
> -; X86-NEXT:    imull $22, %eax, %eax
> +; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %ecx
> +; X86-NEXT:    leal (%ecx,%ecx,4), %eax
> +; X86-NEXT:    leal (%ecx,%eax,4), %eax
> +; X86-NEXT:    addl %ecx, %eax
>  ; X86-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X86-NEXT:    retl
>  ;
>  ; X64-LABEL: test_mul_by_22:
>  ; X64:       # BB#0:
> -; X64-NEXT:    imull $22, %edi, %eax
> +; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-NEXT:    leal (%rdi,%rdi,4), %eax
> +; X64-NEXT:    leal (%rdi,%rax,4), %eax
> +; X64-NEXT:    addl %edi, %eax
>  ; X64-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X64-NEXT:    retq
>    %mul = mul nsw i16 %x, 22
> @@ -408,14 +432,19 @@ define i16 @test_mul_by_22(i16 %x) {
>  define i16 @test_mul_by_23(i16 %x) {
>  ; X86-LABEL: test_mul_by_23:
>  ; X86:       # BB#0:
> -; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
> -; X86-NEXT:    imull $23, %eax, %eax
> +; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %ecx
> +; X86-NEXT:    leal (%ecx,%ecx,2), %eax
> +; X86-NEXT:    shll $3, %eax
> +; X86-NEXT:    subl %ecx, %eax
>  ; X86-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X86-NEXT:    retl
>  ;
>  ; X64-LABEL: test_mul_by_23:
>  ; X64:       # BB#0:
> -; X64-NEXT:    imull $23, %edi, %eax
> +; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-NEXT:    leal (%rdi,%rdi,2), %eax
> +; X64-NEXT:    shll $3, %eax
> +; X64-NEXT:    subl %edi, %eax
>  ; X64-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X64-NEXT:    retq
>    %mul = mul nsw i16 %x, 23
> @@ -465,14 +494,19 @@ define i16 @test_mul_by_25(i16 %x) {
>  define i16 @test_mul_by_26(i16 %x) {
>  ; X86-LABEL: test_mul_by_26:
>  ; X86:       # BB#0:
> -; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
> -; X86-NEXT:    imull $26, %eax, %eax
> +; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %ecx
> +; X86-NEXT:    leal (%ecx,%ecx,8), %eax
> +; X86-NEXT:    leal (%eax,%eax,2), %eax
> +; X86-NEXT:    subl %ecx, %eax
>  ; X86-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X86-NEXT:    retl
>  ;
>  ; X64-LABEL: test_mul_by_26:
>  ; X64:       # BB#0:
> -; X64-NEXT:    imull $26, %edi, %eax
> +; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-NEXT:    leal (%rdi,%rdi,8), %eax
> +; X64-NEXT:    leal (%rax,%rax,2), %eax
> +; X64-NEXT:    subl %edi, %eax
>  ; X64-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X64-NEXT:    retq
>    %mul = mul nsw i16 %x, 26
> @@ -502,14 +536,19 @@ define i16 @test_mul_by_27(i16 %x) {
>  define i16 @test_mul_by_28(i16 %x) {
>  ; X86-LABEL: test_mul_by_28:
>  ; X86:       # BB#0:
> -; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
> -; X86-NEXT:    imull $28, %eax, %eax
> +; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %ecx
> +; X86-NEXT:    leal (%ecx,%ecx,8), %eax
> +; X86-NEXT:    leal (%eax,%eax,2), %eax
> +; X86-NEXT:    addl %ecx, %eax
>  ; X86-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X86-NEXT:    retl
>  ;
>  ; X64-LABEL: test_mul_by_28:
>  ; X64:       # BB#0:
> -; X64-NEXT:    imull $28, %edi, %eax
> +; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-NEXT:    leal (%rdi,%rdi,8), %eax
> +; X64-NEXT:    leal (%rax,%rax,2), %eax
> +; X64-NEXT:    addl %edi, %eax
>  ; X64-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X64-NEXT:    retq
>    %mul = mul nsw i16 %x, 28
> @@ -519,14 +558,21 @@ define i16 @test_mul_by_28(i16 %x) {
>  define i16 @test_mul_by_29(i16 %x) {
>  ; X86-LABEL: test_mul_by_29:
>  ; X86:       # BB#0:
> -; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
> -; X86-NEXT:    imull $29, %eax, %eax
> +; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %ecx
> +; X86-NEXT:    leal (%ecx,%ecx,8), %eax
> +; X86-NEXT:    leal (%eax,%eax,2), %eax
> +; X86-NEXT:    addl %ecx, %eax
> +; X86-NEXT:    addl %ecx, %eax
>  ; X86-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X86-NEXT:    retl
>  ;
>  ; X64-LABEL: test_mul_by_29:
>  ; X64:       # BB#0:
> -; X64-NEXT:    imull $29, %edi, %eax
> +; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-NEXT:    leal (%rdi,%rdi,8), %eax
> +; X64-NEXT:    leal (%rax,%rax,2), %eax
> +; X64-NEXT:    addl %edi, %eax
> +; X64-NEXT:    addl %edi, %eax
>  ; X64-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X64-NEXT:    retq
>    %mul = mul nsw i16 %x, 29
> @@ -536,14 +582,20 @@ define i16 @test_mul_by_29(i16 %x) {
>  define i16 @test_mul_by_30(i16 %x) {
>  ; X86-LABEL: test_mul_by_30:
>  ; X86:       # BB#0:
> -; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
> -; X86-NEXT:    imull $30, %eax, %eax
> +; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %ecx
> +; X86-NEXT:    movl %ecx, %eax
> +; X86-NEXT:    shll $5, %eax
> +; X86-NEXT:    subl %ecx, %eax
> +; X86-NEXT:    subl %ecx, %eax
>  ; X86-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X86-NEXT:    retl
>  ;
>  ; X64-LABEL: test_mul_by_30:
>  ; X64:       # BB#0:
> -; X64-NEXT:    imull $30, %edi, %eax
> +; X64-NEXT:    movl %edi, %eax
> +; X64-NEXT:    shll $5, %eax
> +; X64-NEXT:    subl %edi, %eax
> +; X64-NEXT:    subl %edi, %eax
>  ; X64-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
>  ; X64-NEXT:    retq
>    %mul = mul nsw i16 %x, 30
> @@ -587,3 +639,30 @@ define i16 @test_mul_by_32(i16 %x) {
>    %mul = mul nsw i16 %x, 32
>    ret i16 %mul
>  }
> +
> +; (x*9+42)*(x*5+2)
> +define i16 @test_mul_spec(i16 %x) nounwind {
> +; X86-LABEL: test_mul_spec:
> +; X86:       # BB#0:
> +; X86-NEXT:    movzwl {{[0-9]+}}(%esp), %eax
> +; X86-NEXT:    leal 42(%eax,%eax,8), %ecx
> +; X86-NEXT:    leal 2(%eax,%eax,4), %eax
> +; X86-NEXT:    imull %ecx, %eax
> +; X86-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
> +; X86-NEXT:    retl
> +;
> +; X64-LABEL: test_mul_spec:
> +; X64:       # BB#0:
> +; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-NEXT:    leal 42(%rdi,%rdi,8), %ecx
> +; X64-NEXT:    leal 2(%rdi,%rdi,4), %eax
> +; X64-NEXT:    imull %ecx, %eax
> +; X64-NEXT:    # kill: %AX<def> %AX<kill> %EAX<kill>
> +; X64-NEXT:    retq
> +  %mul = mul nsw i16 %x, 9
> +  %add = add nsw i16 %mul, 42
> +  %mul2 = mul nsw i16 %x, 5
> +  %add2 = add nsw i16 %mul2, 2
> +  %mul3 = mul nsw i16 %add, %add2
> +  ret i16 %mul3
> +}
>
> Modified: llvm/trunk/test/CodeGen/X86/mul-constant-i32.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/mul-constant-i32.ll?rev=304972&r1=304971&r2=304972&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/mul-constant-i32.ll (original)
> +++ llvm/trunk/test/CodeGen/X86/mul-constant-i32.ll Thu Jun  8 05:20:13
> 2017
> @@ -1,6 +1,12 @@
>  ; NOTE: Assertions have been autogenerated by
> utils/update_llc_test_checks.py
>  ; RUN: llc < %s -mtriple=i686-unknown | FileCheck %s --check-prefix=X86
> -; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s --check-prefix=X64
> +; RUN: llc < %s -mtriple=x86_64-unknown -print-schedule=true
> -mcpu=haswell| FileCheck %s --check-prefix=X64-HSW
> +; RUN: llc < %s -mtriple=x86_64-unknown -print-schedule=true
> -mcpu=btver2| FileCheck %s --check-prefix=X64-JAG
> +; RUN: llc < %s -mtriple=i686-unknown -mul-constant-optimization=false |
> FileCheck %s --check-prefix=X86-NOOPT
> +; RUN: llc < %s -mtriple=x86_64-unknown -mul-constant-optimization=false
> -print-schedule=true -mcpu=haswell| FileCheck %s --check-prefix=HSW-NOOPT
> +; RUN: llc < %s -mtriple=x86_64-unknown -mul-constant-optimization=false
> -print-schedule=true -mcpu=btver2| FileCheck %s --check-prefix=JAG-NOOPT
> +; RUN: llc < %s -mtriple=x86_64-unknown -print-schedule=true -mcpu=slm|
> FileCheck %s --check-prefix=X64-SLM
> +; RUN: llc < %s -mtriple=x86_64-unknown -mul-constant-optimization=false
> -print-schedule=true -mcpu=slm| FileCheck %s --check-prefix=SLM-NOOPT
>
>  define i32 @test_mul_by_1(i32 %x) {
>  ; X86-LABEL: test_mul_by_1:
> @@ -8,10 +14,40 @@ define i32 @test_mul_by_1(i32 %x) {
>  ; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_1:
> -; X64:       # BB#0:
> -; X64-NEXT:    movl %edi, %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_1:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    movl %edi, %eax # sched: [1:0.25]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_1:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    movl %edi, %eax # sched: [1:0.17]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_1:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    movl {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_1:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    movl %edi, %eax # sched: [1:0.25]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_1:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    movl %edi, %eax # sched: [1:0.17]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_1:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    movl %edi, %eax # sched: [1:0.50]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_1:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    movl %edi, %eax # sched: [1:0.50]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 1
>    ret i32 %mul
>  }
> @@ -23,11 +59,47 @@ define i32 @test_mul_by_2(i32 %x) {
>  ; X86-NEXT:    addl %eax, %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_2:
> -; X64:       # BB#0:
> -; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> -; X64-NEXT:    leal (%rdi,%rdi), %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_2:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (%rdi,%rdi), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_2:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (%rdi,%rdi), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_2:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    movl {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    addl %eax, %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_2:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; HSW-NOOPT-NEXT:    leal (%rdi,%rdi), %eax # sched: [1:0.50]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_2:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; JAG-NOOPT-NEXT:    leal (%rdi,%rdi), %eax # sched: [1:0.50]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_2:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-SLM-NEXT:    leal (%rdi,%rdi), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_2:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; SLM-NOOPT-NEXT:    leal (%rdi,%rdi), %eax # sched: [1:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 2
>    ret i32 %mul
>  }
> @@ -38,11 +110,46 @@ define i32 @test_mul_by_3(i32 %x) {
>  ; X86-NEXT:    imull $3, {{[0-9]+}}(%esp), %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_3:
> -; X64:       # BB#0:
> -; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> -; X64-NEXT:    leal (%rdi,%rdi,2), %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_3:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_3:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_3:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $3, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_3:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; HSW-NOOPT-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:0.50]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_3:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; JAG-NOOPT-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:0.50]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_3:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-SLM-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_3:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; SLM-NOOPT-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 3
>    ret i32 %mul
>  }
> @@ -54,11 +161,47 @@ define i32 @test_mul_by_4(i32 %x) {
>  ; X86-NEXT:    shll $2, %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_4:
> -; X64:       # BB#0:
> -; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> -; X64-NEXT:    leal (,%rdi,4), %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_4:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (,%rdi,4), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_4:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (,%rdi,4), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_4:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    movl {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    shll $2, %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_4:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; HSW-NOOPT-NEXT:    leal (,%rdi,4), %eax # sched: [1:0.50]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_4:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; JAG-NOOPT-NEXT:    leal (,%rdi,4), %eax # sched: [1:0.50]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_4:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-SLM-NEXT:    leal (,%rdi,4), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_4:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; SLM-NOOPT-NEXT:    leal (,%rdi,4), %eax # sched: [1:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 4
>    ret i32 %mul
>  }
> @@ -69,11 +212,46 @@ define i32 @test_mul_by_5(i32 %x) {
>  ; X86-NEXT:    imull $5, {{[0-9]+}}(%esp), %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_5:
> -; X64:       # BB#0:
> -; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> -; X64-NEXT:    leal (%rdi,%rdi,4), %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_5:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_5:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_5:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $5, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_5:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; HSW-NOOPT-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_5:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; JAG-NOOPT-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_5:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-SLM-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_5:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; SLM-NOOPT-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 5
>    ret i32 %mul
>  }
> @@ -86,12 +264,46 @@ define i32 @test_mul_by_6(i32 %x) {
>  ; X86-NEXT:    leal (%eax,%eax,2), %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_6:
> -; X64:       # BB#0:
> -; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> -; X64-NEXT:    addl %edi, %edi
> -; X64-NEXT:    leal (%rdi,%rdi,2), %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_6:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    addl %edi, %edi # sched: [1:0.25]
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_6:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    addl %edi, %edi # sched: [1:0.50]
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_6:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $6, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_6:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $6, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_6:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $6, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_6:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-SLM-NEXT:    addl %edi, %edi # sched: [1:0.50]
> +; X64-SLM-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_6:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $6, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 6
>    ret i32 %mul
>  }
> @@ -104,12 +316,46 @@ define i32 @test_mul_by_7(i32 %x) {
>  ; X86-NEXT:    subl %ecx, %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_7:
> -; X64:       # BB#0:
> -; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> -; X64-NEXT:    leal (,%rdi,8), %eax
> -; X64-NEXT:    subl %edi, %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_7:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (,%rdi,8), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    subl %edi, %eax # sched: [1:0.25]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_7:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (,%rdi,8), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    subl %edi, %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_7:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $7, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_7:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $7, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_7:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $7, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_7:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-SLM-NEXT:    leal (,%rdi,8), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    subl %edi, %eax # sched: [1:0.50]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_7:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $7, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 7
>    ret i32 %mul
>  }
> @@ -121,11 +367,47 @@ define i32 @test_mul_by_8(i32 %x) {
>  ; X86-NEXT:    shll $3, %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_8:
> -; X64:       # BB#0:
> -; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> -; X64-NEXT:    leal (,%rdi,8), %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_8:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (,%rdi,8), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_8:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (,%rdi,8), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_8:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    movl {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    shll $3, %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_8:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; HSW-NOOPT-NEXT:    leal (,%rdi,8), %eax # sched: [1:0.50]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_8:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; JAG-NOOPT-NEXT:    leal (,%rdi,8), %eax # sched: [1:0.50]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_8:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-SLM-NEXT:    leal (,%rdi,8), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_8:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; SLM-NOOPT-NEXT:    leal (,%rdi,8), %eax # sched: [1:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 8
>    ret i32 %mul
>  }
> @@ -136,11 +418,46 @@ define i32 @test_mul_by_9(i32 %x) {
>  ; X86-NEXT:    imull $9, {{[0-9]+}}(%esp), %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_9:
> -; X64:       # BB#0:
> -; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> -; X64-NEXT:    leal (%rdi,%rdi,8), %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_9:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_9:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_9:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $9, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_9:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; HSW-NOOPT-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:0.50]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_9:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; JAG-NOOPT-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:0.50]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_9:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-SLM-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_9:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; SLM-NOOPT-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 9
>    ret i32 %mul
>  }
> @@ -153,12 +470,46 @@ define i32 @test_mul_by_10(i32 %x) {
>  ; X86-NEXT:    leal (%eax,%eax,4), %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_10:
> -; X64:       # BB#0:
> -; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> -; X64-NEXT:    addl %edi, %edi
> -; X64-NEXT:    leal (%rdi,%rdi,4), %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_10:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    addl %edi, %edi # sched: [1:0.25]
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_10:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    addl %edi, %edi # sched: [1:0.50]
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_10:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $10, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_10:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $10, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_10:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $10, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_10:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-SLM-NEXT:    addl %edi, %edi # sched: [1:0.50]
> +; X64-SLM-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_10:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $10, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 10
>    ret i32 %mul
>  }
> @@ -166,13 +517,49 @@ define i32 @test_mul_by_10(i32 %x) {
>  define i32 @test_mul_by_11(i32 %x) {
>  ; X86-LABEL: test_mul_by_11:
>  ; X86:       # BB#0:
> -; X86-NEXT:    imull $11, {{[0-9]+}}(%esp), %eax
> +; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
> +; X86-NEXT:    leal (%eax,%eax,4), %ecx
> +; X86-NEXT:    leal (%eax,%ecx,2), %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_11:
> -; X64:       # BB#0:
> -; X64-NEXT:    imull $11, %edi, %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_11:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    leal (%rdi,%rax,2), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_11:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    leal (%rdi,%rax,2), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_11:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $11, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_11:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $11, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_11:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $11, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_11:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    imull $11, %edi, %eax # sched: [3:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_11:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $11, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 11
>    ret i32 %mul
>  }
> @@ -185,12 +572,46 @@ define i32 @test_mul_by_12(i32 %x) {
>  ; X86-NEXT:    leal (%eax,%eax,2), %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_12:
> -; X64:       # BB#0:
> -; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> -; X64-NEXT:    shll $2, %edi
> -; X64-NEXT:    leal (%rdi,%rdi,2), %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_12:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    shll $2, %edi # sched: [1:0.50]
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_12:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    shll $2, %edi # sched: [1:0.50]
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_12:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $12, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_12:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $12, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_12:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $12, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_12:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-SLM-NEXT:    shll $2, %edi # sched: [1:1.00]
> +; X64-SLM-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_12:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $12, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 12
>    ret i32 %mul
>  }
> @@ -198,13 +619,49 @@ define i32 @test_mul_by_12(i32 %x) {
>  define i32 @test_mul_by_13(i32 %x) {
>  ; X86-LABEL: test_mul_by_13:
>  ; X86:       # BB#0:
> -; X86-NEXT:    imull $13, {{[0-9]+}}(%esp), %eax
> +; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
> +; X86-NEXT:    leal (%eax,%eax,2), %ecx
> +; X86-NEXT:    leal (%eax,%ecx,4), %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_13:
> -; X64:       # BB#0:
> -; X64-NEXT:    imull $13, %edi, %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_13:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    leal (%rdi,%rax,4), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_13:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    leal (%rdi,%rax,4), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_13:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $13, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_13:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $13, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_13:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $13, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_13:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    imull $13, %edi, %eax # sched: [3:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_13:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $13, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 13
>    ret i32 %mul
>  }
> @@ -212,13 +669,52 @@ define i32 @test_mul_by_13(i32 %x) {
>  define i32 @test_mul_by_14(i32 %x) {
>  ; X86-LABEL: test_mul_by_14:
>  ; X86:       # BB#0:
> -; X86-NEXT:    imull $14, {{[0-9]+}}(%esp), %eax
> +; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
> +; X86-NEXT:    leal (%ecx,%ecx,2), %eax
> +; X86-NEXT:    leal (%ecx,%eax,4), %eax
> +; X86-NEXT:    addl %ecx, %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_14:
> -; X64:       # BB#0:
> -; X64-NEXT:    imull $14, %edi, %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_14:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    leal (%rdi,%rax,4), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    addl %edi, %eax # sched: [1:0.25]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_14:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    leal (%rdi,%rax,4), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    addl %edi, %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_14:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $14, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_14:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $14, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_14:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $14, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_14:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    imull $14, %edi, %eax # sched: [3:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_14:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $14, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 14
>    ret i32 %mul
>  }
> @@ -231,12 +727,46 @@ define i32 @test_mul_by_15(i32 %x) {
>  ; X86-NEXT:    leal (%eax,%eax,2), %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_15:
> -; X64:       # BB#0:
> -; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> -; X64-NEXT:    leal (%rdi,%rdi,4), %eax
> -; X64-NEXT:    leal (%rax,%rax,2), %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_15:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    leal (%rax,%rax,2), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_15:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    leal (%rax,%rax,2), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_15:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $15, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_15:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $15, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_15:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $15, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_15:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-SLM-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    leal (%rax,%rax,2), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_15:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $15, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 15
>    ret i32 %mul
>  }
> @@ -248,11 +778,47 @@ define i32 @test_mul_by_16(i32 %x) {
>  ; X86-NEXT:    shll $4, %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_16:
> -; X64:       # BB#0:
> -; X64-NEXT:    shll $4, %edi
> -; X64-NEXT:    movl %edi, %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_16:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    shll $4, %edi # sched: [1:0.50]
> +; X64-HSW-NEXT:    movl %edi, %eax # sched: [1:0.25]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_16:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    shll $4, %edi # sched: [1:0.50]
> +; X64-JAG-NEXT:    movl %edi, %eax # sched: [1:0.17]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_16:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    movl {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    shll $4, %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_16:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    shll $4, %edi # sched: [1:0.50]
> +; HSW-NOOPT-NEXT:    movl %edi, %eax # sched: [1:0.25]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_16:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    shll $4, %edi # sched: [1:0.50]
> +; JAG-NOOPT-NEXT:    movl %edi, %eax # sched: [1:0.17]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_16:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    shll $4, %edi # sched: [1:1.00]
> +; X64-SLM-NEXT:    movl %edi, %eax # sched: [1:0.50]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_16:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    shll $4, %edi # sched: [1:1.00]
> +; SLM-NOOPT-NEXT:    movl %edi, %eax # sched: [1:0.50]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 16
>    ret i32 %mul
>  }
> @@ -266,13 +832,49 @@ define i32 @test_mul_by_17(i32 %x) {
>  ; X86-NEXT:    addl %ecx, %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_17:
> -; X64:       # BB#0:
> -; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> -; X64-NEXT:    movl %edi, %eax
> -; X64-NEXT:    shll $4, %eax
> -; X64-NEXT:    leal (%rax,%rdi), %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_17:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    movl %edi, %eax # sched: [1:0.25]
> +; X64-HSW-NEXT:    shll $4, %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    leal (%rax,%rdi), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_17:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    movl %edi, %eax # sched: [1:0.17]
> +; X64-JAG-NEXT:    shll $4, %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    leal (%rax,%rdi), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_17:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $17, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_17:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $17, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_17:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $17, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_17:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-SLM-NEXT:    movl %edi, %eax # sched: [1:0.50]
> +; X64-SLM-NEXT:    shll $4, %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    leal (%rax,%rdi), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_17:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $17, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 17
>    ret i32 %mul
>  }
> @@ -285,12 +887,46 @@ define i32 @test_mul_by_18(i32 %x) {
>  ; X86-NEXT:    leal (%eax,%eax,8), %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_18:
> -; X64:       # BB#0:
> -; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> -; X64-NEXT:    addl %edi, %edi
> -; X64-NEXT:    leal (%rdi,%rdi,8), %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_18:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    addl %edi, %edi # sched: [1:0.25]
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_18:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    addl %edi, %edi # sched: [1:0.50]
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_18:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $18, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_18:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $18, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_18:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $18, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_18:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-SLM-NEXT:    addl %edi, %edi # sched: [1:0.50]
> +; X64-SLM-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_18:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $18, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 18
>    ret i32 %mul
>  }
> @@ -298,13 +934,52 @@ define i32 @test_mul_by_18(i32 %x) {
>  define i32 @test_mul_by_19(i32 %x) {
>  ; X86-LABEL: test_mul_by_19:
>  ; X86:       # BB#0:
> -; X86-NEXT:    imull $19, {{[0-9]+}}(%esp), %eax
> +; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
> +; X86-NEXT:    leal (%ecx,%ecx,4), %eax
> +; X86-NEXT:    shll $2, %eax
> +; X86-NEXT:    subl %ecx, %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_19:
> -; X64:       # BB#0:
> -; X64-NEXT:    imull $19, %edi, %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_19:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    shll $2, %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    subl %edi, %eax # sched: [1:0.25]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_19:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    shll $2, %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    subl %edi, %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_19:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $19, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_19:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $19, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_19:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $19, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_19:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    imull $19, %edi, %eax # sched: [3:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_19:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $19, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 19
>    ret i32 %mul
>  }
> @@ -317,12 +992,46 @@ define i32 @test_mul_by_20(i32 %x) {
>  ; X86-NEXT:    leal (%eax,%eax,4), %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_20:
> -; X64:       # BB#0:
> -; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> -; X64-NEXT:    shll $2, %edi
> -; X64-NEXT:    leal (%rdi,%rdi,4), %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_20:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    shll $2, %edi # sched: [1:0.50]
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_20:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    shll $2, %edi # sched: [1:0.50]
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_20:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $20, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_20:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $20, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_20:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $20, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_20:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-SLM-NEXT:    shll $2, %edi # sched: [1:1.00]
> +; X64-SLM-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_20:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $20, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 20
>    ret i32 %mul
>  }
> @@ -330,13 +1039,49 @@ define i32 @test_mul_by_20(i32 %x) {
>  define i32 @test_mul_by_21(i32 %x) {
>  ; X86-LABEL: test_mul_by_21:
>  ; X86:       # BB#0:
> -; X86-NEXT:    imull $21, {{[0-9]+}}(%esp), %eax
> +; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
> +; X86-NEXT:    leal (%eax,%eax,4), %ecx
> +; X86-NEXT:    leal (%eax,%ecx,4), %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_21:
> -; X64:       # BB#0:
> -; X64-NEXT:    imull $21, %edi, %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_21:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    leal (%rdi,%rax,4), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_21:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    leal (%rdi,%rax,4), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_21:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $21, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_21:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $21, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_21:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $21, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_21:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    imull $21, %edi, %eax # sched: [3:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_21:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $21, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 21
>    ret i32 %mul
>  }
> @@ -344,13 +1089,52 @@ define i32 @test_mul_by_21(i32 %x) {
>  define i32 @test_mul_by_22(i32 %x) {
>  ; X86-LABEL: test_mul_by_22:
>  ; X86:       # BB#0:
> -; X86-NEXT:    imull $22, {{[0-9]+}}(%esp), %eax
> +; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
> +; X86-NEXT:    leal (%ecx,%ecx,4), %eax
> +; X86-NEXT:    leal (%ecx,%eax,4), %eax
> +; X86-NEXT:    addl %ecx, %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_22:
> -; X64:       # BB#0:
> -; X64-NEXT:    imull $22, %edi, %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_22:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    leal (%rdi,%rax,4), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    addl %edi, %eax # sched: [1:0.25]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_22:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    leal (%rdi,%rax,4), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    addl %edi, %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_22:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $22, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_22:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $22, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_22:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $22, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_22:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    imull $22, %edi, %eax # sched: [3:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_22:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $22, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 22
>    ret i32 %mul
>  }
> @@ -358,13 +1142,52 @@ define i32 @test_mul_by_22(i32 %x) {
>  define i32 @test_mul_by_23(i32 %x) {
>  ; X86-LABEL: test_mul_by_23:
>  ; X86:       # BB#0:
> -; X86-NEXT:    imull $23, {{[0-9]+}}(%esp), %eax
> +; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
> +; X86-NEXT:    leal (%ecx,%ecx,2), %eax
> +; X86-NEXT:    shll $3, %eax
> +; X86-NEXT:    subl %ecx, %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_23:
> -; X64:       # BB#0:
> -; X64-NEXT:    imull $23, %edi, %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_23:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    shll $3, %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    subl %edi, %eax # sched: [1:0.25]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_23:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    shll $3, %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    subl %edi, %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_23:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $23, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_23:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $23, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_23:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $23, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_23:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    imull $23, %edi, %eax # sched: [3:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_23:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $23, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 23
>    ret i32 %mul
>  }
> @@ -377,12 +1200,46 @@ define i32 @test_mul_by_24(i32 %x) {
>  ; X86-NEXT:    leal (%eax,%eax,2), %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_24:
> -; X64:       # BB#0:
> -; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> -; X64-NEXT:    shll $3, %edi
> -; X64-NEXT:    leal (%rdi,%rdi,2), %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_24:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    shll $3, %edi # sched: [1:0.50]
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_24:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    shll $3, %edi # sched: [1:0.50]
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_24:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $24, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_24:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $24, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_24:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $24, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_24:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-SLM-NEXT:    shll $3, %edi # sched: [1:1.00]
> +; X64-SLM-NEXT:    leal (%rdi,%rdi,2), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_24:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $24, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 24
>    ret i32 %mul
>  }
> @@ -395,12 +1252,46 @@ define i32 @test_mul_by_25(i32 %x) {
>  ; X86-NEXT:    leal (%eax,%eax,4), %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_25:
> -; X64:       # BB#0:
> -; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> -; X64-NEXT:    leal (%rdi,%rdi,4), %eax
> -; X64-NEXT:    leal (%rax,%rax,4), %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_25:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    leal (%rax,%rax,4), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_25:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    leal (%rax,%rax,4), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_25:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $25, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_25:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $25, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_25:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $25, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_25:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-SLM-NEXT:    leal (%rdi,%rdi,4), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    leal (%rax,%rax,4), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_25:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $25, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 25
>    ret i32 %mul
>  }
> @@ -408,13 +1299,52 @@ define i32 @test_mul_by_25(i32 %x) {
>  define i32 @test_mul_by_26(i32 %x) {
>  ; X86-LABEL: test_mul_by_26:
>  ; X86:       # BB#0:
> -; X86-NEXT:    imull $26, {{[0-9]+}}(%esp), %eax
> +; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
> +; X86-NEXT:    leal (%ecx,%ecx,8), %eax
> +; X86-NEXT:    leal (%eax,%eax,2), %eax
> +; X86-NEXT:    subl %ecx, %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_26:
> -; X64:       # BB#0:
> -; X64-NEXT:    imull $26, %edi, %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_26:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    leal (%rax,%rax,2), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    subl %edi, %eax # sched: [1:0.25]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_26:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    leal (%rax,%rax,2), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    subl %edi, %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_26:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $26, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_26:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $26, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_26:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $26, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_26:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    imull $26, %edi, %eax # sched: [3:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_26:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $26, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 26
>    ret i32 %mul
>  }
> @@ -427,12 +1357,46 @@ define i32 @test_mul_by_27(i32 %x) {
>  ; X86-NEXT:    leal (%eax,%eax,2), %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_27:
> -; X64:       # BB#0:
> -; X64-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> -; X64-NEXT:    leal (%rdi,%rdi,8), %eax
> -; X64-NEXT:    leal (%rax,%rax,2), %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_27:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    leal (%rax,%rax,2), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_27:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    leal (%rax,%rax,2), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    retq # sched: [4:1.00]
> +;
> +; X86-NOOPT-LABEL: test_mul_by_27:
> +; X86-NOOPT:       # BB#0:
> +; X86-NOOPT-NEXT:    imull $27, {{[0-9]+}}(%esp), %eax
> +; X86-NOOPT-NEXT:    retl
> +;
> +; HSW-NOOPT-LABEL: test_mul_by_27:
> +; HSW-NOOPT:       # BB#0:
> +; HSW-NOOPT-NEXT:    imull $27, %edi, %eax # sched: [4:1.00]
> +; HSW-NOOPT-NEXT:    retq # sched: [1:1.00]
> +;
> +; JAG-NOOPT-LABEL: test_mul_by_27:
> +; JAG-NOOPT:       # BB#0:
> +; JAG-NOOPT-NEXT:    imull $27, %edi, %eax # sched: [3:1.00]
> +; JAG-NOOPT-NEXT:    retq # sched: [4:1.00]
> +;
> +; X64-SLM-LABEL: test_mul_by_27:
> +; X64-SLM:       # BB#0:
> +; X64-SLM-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-SLM-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    leal (%rax,%rax,2), %eax # sched: [1:1.00]
> +; X64-SLM-NEXT:    retq # sched: [4:1.00]
> +;
> +; SLM-NOOPT-LABEL: test_mul_by_27:
> +; SLM-NOOPT:       # BB#0:
> +; SLM-NOOPT-NEXT:    imull $27, %edi, %eax # sched: [3:1.00]
> +; SLM-NOOPT-NEXT:    retq # sched: [4:1.00]
>    %mul = mul nsw i32 %x, 27
>    ret i32 %mul
>  }
> @@ -440,13 +1404,52 @@ define i32 @test_mul_by_27(i32 %x) {
>  define i32 @test_mul_by_28(i32 %x) {
>  ; X86-LABEL: test_mul_by_28:
>  ; X86:       # BB#0:
> -; X86-NEXT:    imull $28, {{[0-9]+}}(%esp), %eax
> +; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
> +; X86-NEXT:    leal (%ecx,%ecx,8), %eax
> +; X86-NEXT:    leal (%eax,%eax,2), %eax
> +; X86-NEXT:    addl %ecx, %eax
>  ; X86-NEXT:    retl
>  ;
> -; X64-LABEL: test_mul_by_28:
> -; X64:       # BB#0:
> -; X64-NEXT:    imull $28, %edi, %eax
> -; X64-NEXT:    retq
> +; X64-HSW-LABEL: test_mul_by_28:
> +; X64-HSW:       # BB#0:
> +; X64-HSW-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-HSW-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    leal (%rax,%rax,2), %eax # sched: [1:0.50]
> +; X64-HSW-NEXT:    addl %edi, %eax # sched: [1:0.25]
> +; X64-HSW-NEXT:    retq # sched: [1:1.00]
> +;
> +; X64-JAG-LABEL: test_mul_by_28:
> +; X64-JAG:       # BB#0:
> +; X64-JAG-NEXT:    # kill: %EDI<def> %EDI<kill> %RDI<def>
> +; X64-JAG-NEXT:    leal (%rdi,%rdi,8), %eax # sched: [1:0.50]
> +; X64-JAG-NEXT:    leal (%rax,%rax,2), %eax # sched: [1:0.50]
> +; X64-JAG-NE
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170616/65f7343f/attachment-0001.html>


More information about the llvm-commits mailing list