Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -78,6 +78,12 @@ " of the loop header PC will be 0)."), cl::Hidden); +static cl::opt MulConstantOptimization( + "mul-constant-optimization", cl::init(true), + cl::desc("Replace 'mul x, Const' with more effective instructions like " + "SHIFT, LEA, etc."), + cl::Hidden); + X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM, const X86Subtarget &STI) : TargetLowering(TM), Subtarget(STI) { @@ -30939,6 +30945,8 @@ static SDValue combineMul(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, const X86Subtarget &Subtarget) { + if (!MulConstantOptimization) + return SDValue(); EVT VT = N->getValueType(0); if (DCI.isBeforeLegalize() && VT.isVector()) return reduceVMULWidth(N, DAG, Subtarget); @@ -30998,6 +31006,112 @@ else NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, NewMul, DAG.getConstant(MulAmt2, DL, VT)); + } else { + switch (MulAmt) { + default: + break; + case 11: + // mul x, 11 => add ((mul (mul x, 5), 2), x) + NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, N->getOperand(0), + DAG.getConstant(5, DL, VT)); + NewMul = DAG.getNode(ISD::SHL, DL, VT, NewMul, + DAG.getConstant(1, DL, MVT::i8)); + NewMul = DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0), NewMul); + break; + case 21: + // mul x, 21 => add ((mul (mul x, 5), 4), x) + NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, N->getOperand(0), + DAG.getConstant(5, DL, VT)); + NewMul = DAG.getNode(ISD::SHL, DL, VT, NewMul, + DAG.getConstant(2, DL, MVT::i8)); + NewMul = DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0), NewMul); + break; + case 22: + // mul x, 22 => add (add ((mul (mul x, 5), 4), x), x) + NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, N->getOperand(0), + DAG.getConstant(5, DL, VT)); + NewMul = DAG.getNode(ISD::SHL, DL, VT, NewMul, + DAG.getConstant(2, DL, MVT::i8)); + NewMul = DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0), NewMul); + NewMul = DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0), NewMul); + break; + case 19: + // mul x, 19 => sub ((mul (mul x, 5), 4), x) + NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, N->getOperand(0), + DAG.getConstant(5, DL, VT)); + NewMul = DAG.getNode(ISD::SHL, DL, VT, NewMul, + DAG.getConstant(2, DL, MVT::i8)); + NewMul = DAG.getNode(ISD::SUB, DL, VT, N->getOperand(0), NewMul); + break; + case 13: + // mul x, 13 => add ((mul (mul x, 3), 4), x) + NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, N->getOperand(0), + DAG.getConstant(3, DL, VT)); + NewMul = DAG.getNode(ISD::SHL, DL, VT, NewMul, + DAG.getConstant(2, DL, MVT::i8)); + NewMul = DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0), NewMul); + break; + case 23: + // mul x, 13 => sub ((mul (mul x, 3), 8), x) + NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, N->getOperand(0), + DAG.getConstant(3, DL, VT)); + NewMul = DAG.getNode(ISD::SHL, DL, VT, NewMul, + DAG.getConstant(3, DL, MVT::i8)); + NewMul = DAG.getNode(ISD::SUB, DL, VT, NewMul, N->getOperand(0)); + break; + case 14: + // mul x, 14 => add (add ((mul (mul x, 3), 4), x), x) + NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, N->getOperand(0), + DAG.getConstant(3, DL, VT)); + NewMul = DAG.getNode(ISD::SHL, DL, VT, NewMul, + DAG.getConstant(2, DL, MVT::i8)); + NewMul = DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0), NewMul); + NewMul = DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0), NewMul); + break; + case 26: + // mul x, 26 => sub ((mul (mul x, 9), 3), x) + NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, N->getOperand(0), + DAG.getConstant(9, DL, VT)); + NewMul = + DAG.getNode(ISD::MUL, DL, VT, NewMul, DAG.getConstant(3, DL, VT)); + NewMul = DAG.getNode(ISD::SUB, DL, VT, N->getOperand(0), NewMul); + break; + case 28: + // mul x, 28 => add ((mul (mul x, 9), 3), x) + NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, N->getOperand(0), + DAG.getConstant(9, DL, VT)); + NewMul = + DAG.getNode(ISD::MUL, DL, VT, NewMul, DAG.getConstant(3, DL, VT)); + NewMul = DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0), NewMul); + break; + case 29: + // mul x, 29 => add (add ((mul (mul x, 9), 3), x), x) + NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, N->getOperand(0), + DAG.getConstant(9, DL, VT)); + NewMul = + DAG.getNode(ISD::MUL, DL, VT, NewMul, DAG.getConstant(3, DL, VT)); + NewMul = DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0), NewMul); + NewMul = DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0), NewMul); + break; + case 30: { + // mul x, 30 => add (add (add ((mul (mul x, 9), 3), x), x), x) + // mul x, 30 => sub (sub ((mul x, 32), x), x) + NewMul = DAG.getNode(ISD::SHL, DL, VT, N->getOperand(0), + DAG.getConstant(5, DL, MVT::i8)); + NewMul = DAG.getNode(ISD::SUB, DL, VT, N->getOperand(0), NewMul); + NewMul = DAG.getNode(ISD::SUB, DL, VT, N->getOperand(0), NewMul); + /* + NewMul = DAG.getNode(X86ISD::MUL_IMM, DL, VT, + N->getOperand(0), DAG.getConstant(9, DL, VT)); + NewMul = DAG.getNode(ISD::MUL, DL, VT, NewMul, + DAG.getConstant(3, DL, VT)); + NewMul = DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0), NewMul); + NewMul = DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0), NewMul); + NewMul = DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0), NewMul); + */ + break; + } + } } if (!NewMul) { Index: test/CodeGen/X86/mul-constant-i16.ll =================================================================== --- test/CodeGen/X86/mul-constant-i16.ll +++ test/CodeGen/X86/mul-constant-i16.ll @@ -188,13 +188,16 @@ ; 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 %AX %EAX ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_11: ; X64: # BB#0: -; X64-NEXT: imull $11, %edi, %eax +; X64-NEXT: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,4), %eax +; X64-NEXT: leal (%rdi,%rax,2), %eax ; X64-NEXT: # kill: %AX %AX %EAX ; X64-NEXT: retq %mul = mul nsw i16 %x, 11 @@ -225,13 +228,16 @@ ; 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 %AX %EAX ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_13: ; X64: # BB#0: -; X64-NEXT: imull $13, %edi, %eax +; X64-NEXT: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,2), %eax +; X64-NEXT: leal (%rdi,%rax,4), %eax ; X64-NEXT: # kill: %AX %AX %EAX ; X64-NEXT: retq %mul = mul nsw i16 %x, 13 @@ -241,14 +247,19 @@ 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 %AX %EAX ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_14: ; X64: # BB#0: -; X64-NEXT: imull $14, %edi, %eax +; X64-NEXT: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,2), %eax +; X64-NEXT: leal (%rdi,%rax,4), %eax +; X64-NEXT: addl %edi, %eax ; X64-NEXT: # kill: %AX %AX %EAX ; X64-NEXT: retq %mul = mul nsw i16 %x, 14 @@ -338,14 +349,19 @@ ; X86-LABEL: test_mul_by_19: ; X86: # BB#0: ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax -; X86-NEXT: imull $19, %eax, %eax +; X86-NEXT: leal (%eax,%eax,4), %ecx +; X86-NEXT: shll $2, %ecx +; X86-NEXT: subl %ecx, %eax ; X86-NEXT: # kill: %AX %AX %EAX ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_19: ; X64: # BB#0: -; X64-NEXT: imull $19, %edi, %eax -; X64-NEXT: # kill: %AX %AX %EAX +; X64-NEXT: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,4), %eax +; X64-NEXT: shll $2, %eax +; X64-NEXT: subl %eax, %edi +; X64-NEXT: movl %edi, %eax ; X64-NEXT: retq %mul = mul nsw i16 %x, 19 ret i16 %mul @@ -375,13 +391,16 @@ ; 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 %AX %EAX ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_21: ; X64: # BB#0: -; X64-NEXT: imull $21, %edi, %eax +; X64-NEXT: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,4), %eax +; X64-NEXT: leal (%rdi,%rax,4), %eax ; X64-NEXT: # kill: %AX %AX %EAX ; X64-NEXT: retq %mul = mul nsw i16 %x, 21 @@ -391,14 +410,19 @@ 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 %AX %EAX ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_22: ; X64: # BB#0: -; X64-NEXT: imull $22, %edi, %eax +; X64-NEXT: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,4), %eax +; X64-NEXT: leal (%rdi,%rax,4), %eax +; X64-NEXT: addl %edi, %eax ; X64-NEXT: # kill: %AX %AX %EAX ; X64-NEXT: retq %mul = mul nsw i16 %x, 22 @@ -408,14 +432,19 @@ 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 %AX %EAX ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_23: ; X64: # BB#0: -; X64-NEXT: imull $23, %edi, %eax +; X64-NEXT: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,2), %eax +; X64-NEXT: shll $3, %eax +; X64-NEXT: subl %edi, %eax ; X64-NEXT: # kill: %AX %AX %EAX ; X64-NEXT: retq %mul = mul nsw i16 %x, 23 @@ -466,14 +495,19 @@ ; X86-LABEL: test_mul_by_26: ; X86: # BB#0: ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax -; X86-NEXT: imull $26, %eax, %eax +; X86-NEXT: leal (%eax,%eax,8), %ecx +; X86-NEXT: leal (%ecx,%ecx,2), %ecx +; X86-NEXT: subl %ecx, %eax ; X86-NEXT: # kill: %AX %AX %EAX ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_26: ; X64: # BB#0: -; X64-NEXT: imull $26, %edi, %eax -; X64-NEXT: # kill: %AX %AX %EAX +; X64-NEXT: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,8), %eax +; X64-NEXT: leal (%rax,%rax,2), %eax +; X64-NEXT: subl %eax, %edi +; X64-NEXT: movl %edi, %eax ; X64-NEXT: retq %mul = mul nsw i16 %x, 26 ret i16 %mul @@ -502,14 +536,19 @@ 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 %AX %EAX ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_28: ; X64: # BB#0: -; X64-NEXT: imull $28, %edi, %eax +; X64-NEXT: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,8), %eax +; X64-NEXT: leal (%rax,%rax,2), %eax +; X64-NEXT: addl %edi, %eax ; X64-NEXT: # kill: %AX %AX %EAX ; X64-NEXT: retq %mul = mul nsw i16 %x, 28 @@ -519,14 +558,21 @@ 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 %AX %EAX ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_29: ; X64: # BB#0: -; X64-NEXT: imull $29, %edi, %eax +; X64-NEXT: # kill: %EDI %EDI %RDI +; 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 %AX %EAX ; X64-NEXT: retq %mul = mul nsw i16 %x, 29 @@ -537,14 +583,22 @@ ; X86-LABEL: test_mul_by_30: ; X86: # BB#0: ; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax -; X86-NEXT: imull $30, %eax, %eax +; X86-NEXT: movl %eax, %ecx +; X86-NEXT: shll $5, %ecx +; X86-NEXT: movl %eax, %edx +; X86-NEXT: subl %ecx, %edx +; X86-NEXT: subl %edx, %eax ; X86-NEXT: # kill: %AX %AX %EAX ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_30: ; X64: # BB#0: -; X64-NEXT: imull $30, %edi, %eax -; X64-NEXT: # kill: %AX %AX %EAX +; X64-NEXT: movl %edi, %eax +; X64-NEXT: shll $5, %eax +; X64-NEXT: movl %edi, %ecx +; X64-NEXT: subl %eax, %ecx +; X64-NEXT: subl %ecx, %edi +; X64-NEXT: movl %edi, %eax ; X64-NEXT: retq %mul = mul nsw i16 %x, 30 ret i16 %mul Index: test/CodeGen/X86/mul-constant-i32.ll =================================================================== --- test/CodeGen/X86/mul-constant-i32.ll +++ test/CodeGen/X86/mul-constant-i32.ll @@ -166,12 +166,16 @@ 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: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,4), %eax +; X64-NEXT: leal (%rdi,%rax,2), %eax ; X64-NEXT: retq %mul = mul nsw i32 %x, 11 ret i32 %mul @@ -198,12 +202,16 @@ 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: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,2), %eax +; X64-NEXT: leal (%rdi,%rax,4), %eax ; X64-NEXT: retq %mul = mul nsw i32 %x, 13 ret i32 %mul @@ -212,12 +220,18 @@ 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: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,2), %eax +; X64-NEXT: leal (%rdi,%rax,4), %eax +; X64-NEXT: addl %edi, %eax ; X64-NEXT: retq %mul = mul nsw i32 %x, 14 ret i32 %mul @@ -298,12 +312,19 @@ 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), %eax +; X86-NEXT: leal (%eax,%eax,4), %ecx +; X86-NEXT: shll $2, %ecx +; 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: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,4), %eax +; X64-NEXT: shll $2, %eax +; X64-NEXT: subl %eax, %edi +; X64-NEXT: movl %edi, %eax ; X64-NEXT: retq %mul = mul nsw i32 %x, 19 ret i32 %mul @@ -330,12 +351,16 @@ 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: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,4), %eax +; X64-NEXT: leal (%rdi,%rax,4), %eax ; X64-NEXT: retq %mul = mul nsw i32 %x, 21 ret i32 %mul @@ -344,12 +369,18 @@ 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: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,4), %eax +; X64-NEXT: leal (%rdi,%rax,4), %eax +; X64-NEXT: addl %edi, %eax ; X64-NEXT: retq %mul = mul nsw i32 %x, 22 ret i32 %mul @@ -358,12 +389,18 @@ 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: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,2), %eax +; X64-NEXT: shll $3, %eax +; X64-NEXT: subl %edi, %eax ; X64-NEXT: retq %mul = mul nsw i32 %x, 23 ret i32 %mul @@ -408,12 +445,19 @@ 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), %eax +; X86-NEXT: leal (%eax,%eax,8), %ecx +; X86-NEXT: leal (%ecx,%ecx,2), %ecx +; 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: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,8), %eax +; X64-NEXT: leal (%rax,%rax,2), %eax +; X64-NEXT: subl %eax, %edi +; X64-NEXT: movl %edi, %eax ; X64-NEXT: retq %mul = mul nsw i32 %x, 26 ret i32 %mul @@ -440,12 +484,18 @@ 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: # kill: %EDI %EDI %RDI +; X64-NEXT: leal (%rdi,%rdi,8), %eax +; X64-NEXT: leal (%rax,%rax,2), %eax +; X64-NEXT: addl %edi, %eax ; X64-NEXT: retq %mul = mul nsw i32 %x, 28 ret i32 %mul @@ -454,12 +504,20 @@ define i32 @test_mul_by_29(i32 %x) { ; X86-LABEL: test_mul_by_29: ; X86: # BB#0: -; X86-NEXT: imull $29, {{[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: addl %ecx, %eax ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_29: ; X64: # BB#0: -; X64-NEXT: imull $29, %edi, %eax +; X64-NEXT: # kill: %EDI %EDI %RDI +; 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: retq %mul = mul nsw i32 %x, 29 ret i32 %mul @@ -468,12 +526,22 @@ define i32 @test_mul_by_30(i32 %x) { ; X86-LABEL: test_mul_by_30: ; X86: # BB#0: -; X86-NEXT: imull $30, {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: movl %eax, %ecx +; X86-NEXT: shll $5, %ecx +; X86-NEXT: movl %eax, %edx +; X86-NEXT: subl %ecx, %edx +; X86-NEXT: subl %edx, %eax ; 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: movl %edi, %ecx +; X64-NEXT: subl %eax, %ecx +; X64-NEXT: subl %ecx, %edi +; X64-NEXT: movl %edi, %eax ; X64-NEXT: retq %mul = mul nsw i32 %x, 30 ret i32 %mul Index: test/CodeGen/X86/mul-constant-i64.ll =================================================================== --- test/CodeGen/X86/mul-constant-i64.ll +++ test/CodeGen/X86/mul-constant-i64.ll @@ -180,15 +180,18 @@ define i64 @test_mul_by_11(i64 %x) { ; X86-LABEL: test_mul_by_11: ; X86: # BB#0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: leal (%eax,%eax,4), %ecx +; X86-NEXT: leal (%eax,%ecx,2), %ecx ; X86-NEXT: movl $11, %eax ; X86-NEXT: mull {{[0-9]+}}(%esp) -; X86-NEXT: imull $11, {{[0-9]+}}(%esp), %ecx ; X86-NEXT: addl %ecx, %edx ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_11: ; X64: # BB#0: -; X64-NEXT: imulq $11, %rdi, %rax +; X64-NEXT: leaq (%rdi,%rdi,4), %rax +; X64-NEXT: leaq (%rdi,%rax,2), %rax ; X64-NEXT: retq %mul = mul nsw i64 %x, 11 ret i64 %mul @@ -216,15 +219,18 @@ define i64 @test_mul_by_13(i64 %x) { ; X86-LABEL: test_mul_by_13: ; X86: # BB#0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: leal (%eax,%eax,2), %ecx +; X86-NEXT: leal (%eax,%ecx,4), %ecx ; X86-NEXT: movl $13, %eax ; X86-NEXT: mull {{[0-9]+}}(%esp) -; X86-NEXT: imull $13, {{[0-9]+}}(%esp), %ecx ; X86-NEXT: addl %ecx, %edx ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_13: ; X64: # BB#0: -; X64-NEXT: imulq $13, %rdi, %rax +; X64-NEXT: leaq (%rdi,%rdi,2), %rax +; X64-NEXT: leaq (%rdi,%rax,4), %rax ; X64-NEXT: retq %mul = mul nsw i64 %x, 13 ret i64 %mul @@ -233,15 +239,20 @@ define i64 @test_mul_by_14(i64 %x) { ; X86-LABEL: test_mul_by_14: ; X86: # BB#0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: leal (%eax,%eax,2), %ecx +; X86-NEXT: leal (%eax,%ecx,4), %ecx +; X86-NEXT: addl %eax, %ecx ; X86-NEXT: movl $14, %eax ; X86-NEXT: mull {{[0-9]+}}(%esp) -; X86-NEXT: imull $14, {{[0-9]+}}(%esp), %ecx ; X86-NEXT: addl %ecx, %edx ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_14: ; X64: # BB#0: -; X64-NEXT: imulq $14, %rdi, %rax +; X64-NEXT: leaq (%rdi,%rdi,2), %rax +; X64-NEXT: leaq (%rdi,%rax,4), %rax +; X64-NEXT: addq %rdi, %rax ; X64-NEXT: retq %mul = mul nsw i64 %x, 14 ret i64 %mul @@ -329,15 +340,21 @@ define i64 @test_mul_by_19(i64 %x) { ; X86-LABEL: test_mul_by_19: ; X86: # BB#0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: leal (%ecx,%ecx,4), %eax +; X86-NEXT: shll $2, %eax +; X86-NEXT: subl %eax, %ecx ; X86-NEXT: movl $19, %eax ; X86-NEXT: mull {{[0-9]+}}(%esp) -; X86-NEXT: imull $19, {{[0-9]+}}(%esp), %ecx ; X86-NEXT: addl %ecx, %edx ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_19: ; X64: # BB#0: -; X64-NEXT: imulq $19, %rdi, %rax +; X64-NEXT: leaq (%rdi,%rdi,4), %rax +; X64-NEXT: shlq $2, %rax +; X64-NEXT: subq %rax, %rdi +; X64-NEXT: movq %rdi, %rax ; X64-NEXT: retq %mul = mul nsw i64 %x, 19 ret i64 %mul @@ -365,15 +382,18 @@ define i64 @test_mul_by_21(i64 %x) { ; X86-LABEL: test_mul_by_21: ; X86: # BB#0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: leal (%eax,%eax,4), %ecx +; X86-NEXT: leal (%eax,%ecx,4), %ecx ; X86-NEXT: movl $21, %eax ; X86-NEXT: mull {{[0-9]+}}(%esp) -; X86-NEXT: imull $21, {{[0-9]+}}(%esp), %ecx ; X86-NEXT: addl %ecx, %edx ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_21: ; X64: # BB#0: -; X64-NEXT: imulq $21, %rdi, %rax +; X64-NEXT: leaq (%rdi,%rdi,4), %rax +; X64-NEXT: leaq (%rdi,%rax,4), %rax ; X64-NEXT: retq %mul = mul nsw i64 %x, 21 ret i64 %mul @@ -382,15 +402,20 @@ define i64 @test_mul_by_22(i64 %x) { ; X86-LABEL: test_mul_by_22: ; X86: # BB#0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: leal (%eax,%eax,4), %ecx +; X86-NEXT: leal (%eax,%ecx,4), %ecx +; X86-NEXT: addl %eax, %ecx ; X86-NEXT: movl $22, %eax ; X86-NEXT: mull {{[0-9]+}}(%esp) -; X86-NEXT: imull $22, {{[0-9]+}}(%esp), %ecx ; X86-NEXT: addl %ecx, %edx ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_22: ; X64: # BB#0: -; X64-NEXT: imulq $22, %rdi, %rax +; X64-NEXT: leaq (%rdi,%rdi,4), %rax +; X64-NEXT: leaq (%rdi,%rax,4), %rax +; X64-NEXT: addq %rdi, %rax ; X64-NEXT: retq %mul = mul nsw i64 %x, 22 ret i64 %mul @@ -399,15 +424,20 @@ define i64 @test_mul_by_23(i64 %x) { ; X86-LABEL: test_mul_by_23: ; X86: # BB#0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: leal (%eax,%eax,2), %ecx +; X86-NEXT: shll $3, %ecx +; X86-NEXT: subl %eax, %ecx ; X86-NEXT: movl $23, %eax ; X86-NEXT: mull {{[0-9]+}}(%esp) -; X86-NEXT: imull $23, {{[0-9]+}}(%esp), %ecx ; X86-NEXT: addl %ecx, %edx ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_23: ; X64: # BB#0: -; X64-NEXT: imulq $23, %rdi, %rax +; X64-NEXT: leaq (%rdi,%rdi,2), %rax +; X64-NEXT: shlq $3, %rax +; X64-NEXT: subq %rdi, %rax ; X64-NEXT: retq %mul = mul nsw i64 %x, 23 ret i64 %mul @@ -455,15 +485,21 @@ define i64 @test_mul_by_26(i64 %x) { ; X86-LABEL: test_mul_by_26: ; X86: # BB#0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: leal (%ecx,%ecx,8), %eax +; X86-NEXT: leal (%eax,%eax,2), %eax +; X86-NEXT: subl %eax, %ecx ; X86-NEXT: movl $26, %eax ; X86-NEXT: mull {{[0-9]+}}(%esp) -; X86-NEXT: imull $26, {{[0-9]+}}(%esp), %ecx ; X86-NEXT: addl %ecx, %edx ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_26: ; X64: # BB#0: -; X64-NEXT: imulq $26, %rdi, %rax +; X64-NEXT: leaq (%rdi,%rdi,8), %rax +; X64-NEXT: leaq (%rax,%rax,2), %rax +; X64-NEXT: subq %rax, %rdi +; X64-NEXT: movq %rdi, %rax ; X64-NEXT: retq %mul = mul nsw i64 %x, 26 ret i64 %mul @@ -492,15 +528,20 @@ define i64 @test_mul_by_28(i64 %x) { ; X86-LABEL: test_mul_by_28: ; X86: # BB#0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: leal (%eax,%eax,8), %ecx +; X86-NEXT: leal (%ecx,%ecx,2), %ecx +; X86-NEXT: addl %eax, %ecx ; X86-NEXT: movl $28, %eax ; X86-NEXT: mull {{[0-9]+}}(%esp) -; X86-NEXT: imull $28, {{[0-9]+}}(%esp), %ecx ; X86-NEXT: addl %ecx, %edx ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_28: ; X64: # BB#0: -; X64-NEXT: imulq $28, %rdi, %rax +; X64-NEXT: leaq (%rdi,%rdi,8), %rax +; X64-NEXT: leaq (%rax,%rax,2), %rax +; X64-NEXT: addq %rdi, %rax ; X64-NEXT: retq %mul = mul nsw i64 %x, 28 ret i64 %mul @@ -509,15 +550,22 @@ define i64 @test_mul_by_29(i64 %x) { ; X86-LABEL: test_mul_by_29: ; X86: # BB#0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %eax +; X86-NEXT: leal (%eax,%eax,8), %ecx +; X86-NEXT: leal (%ecx,%ecx,2), %ecx +; X86-NEXT: addl %eax, %ecx +; X86-NEXT: addl %eax, %ecx ; X86-NEXT: movl $29, %eax ; X86-NEXT: mull {{[0-9]+}}(%esp) -; X86-NEXT: imull $29, {{[0-9]+}}(%esp), %ecx ; X86-NEXT: addl %ecx, %edx ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_29: ; X64: # BB#0: -; X64-NEXT: imulq $29, %rdi, %rax +; X64-NEXT: leaq (%rdi,%rdi,8), %rax +; X64-NEXT: leaq (%rax,%rax,2), %rax +; X64-NEXT: addq %rdi, %rax +; X64-NEXT: addq %rdi, %rax ; X64-NEXT: retq %mul = mul nsw i64 %x, 29 ret i64 %mul @@ -526,15 +574,21 @@ define i64 @test_mul_by_30(i64 %x) { ; X86-LABEL: test_mul_by_30: ; X86: # BB#0: +; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: shll $5, %ecx ; X86-NEXT: movl $30, %eax ; X86-NEXT: mull {{[0-9]+}}(%esp) -; X86-NEXT: imull $30, {{[0-9]+}}(%esp), %ecx ; X86-NEXT: addl %ecx, %edx ; X86-NEXT: retl ; ; X64-LABEL: test_mul_by_30: ; X64: # BB#0: -; X64-NEXT: imulq $30, %rdi, %rax +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: shlq $5, %rax +; X64-NEXT: movq %rdi, %rcx +; X64-NEXT: subq %rax, %rcx +; X64-NEXT: subq %rcx, %rdi +; X64-NEXT: movq %rdi, %rax ; X64-NEXT: retq %mul = mul nsw i64 %x, 30 ret i64 %mul