Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -28869,22 +28869,39 @@ } if (!NewMul) { - assert(MulAmt != 0 && MulAmt != (VT == MVT::i64 ? UINT64_MAX : UINT32_MAX) - && "Both cases that could cause potential overflows should have " - "already been handled."); - if (isPowerOf2_64(MulAmt - 1)) - // (mul x, 2^N + 1) => (add (shl x, N), x) - NewMul = DAG.getNode(ISD::ADD, DL, VT, N->getOperand(0), - DAG.getNode(ISD::SHL, DL, VT, N->getOperand(0), - DAG.getConstant(Log2_64(MulAmt - 1), DL, - MVT::i8))); - - else if (isPowerOf2_64(MulAmt + 1)) - // (mul x, 2^N - 1) => (sub (shl x, N), x) - NewMul = DAG.getNode(ISD::SUB, DL, VT, DAG.getNode(ISD::SHL, DL, VT, - N->getOperand(0), - DAG.getConstant(Log2_64(MulAmt + 1), - DL, MVT::i8)), N->getOperand(0)); + assert(MulAmt != 0 && + MulAmt != (VT == MVT::i64 ? UINT64_MAX : UINT32_MAX) && + "Both cases that could cause potential overflows should have " + "already been handled."); + int64_t SignMulAmt = C->getSExtValue(); + if ((SignMulAmt != INT64_MIN) && (SignMulAmt != INT64_MAX) && + (SignMulAmt != -INT64_MAX)) { + int NumSign = SignMulAmt > 0 ? 1 : -1; + if (isPowerOf2_64(NumSign * SignMulAmt - 1)) { + // (mul x, 2^N + 1) => (add (shl x, N), x) + NewMul = DAG.getNode( + ISD::ADD, DL, VT, N->getOperand(0), + DAG.getNode(ISD::SHL, DL, VT, N->getOperand(0), + DAG.getConstant(Log2_64(NumSign * SignMulAmt - 1), DL, + MVT::i8))); + // To negate, subtract the number from zero + if (NumSign == -1) + NewMul = + DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), NewMul); + } else if (isPowerOf2_64(NumSign * SignMulAmt + 1)) { + // (mul x, 2^N - 1) => (sub (shl x, N), x) + NewMul = DAG.getNode( + ISD::SUB, DL, VT, + DAG.getNode(ISD::SHL, DL, VT, N->getOperand(0), + DAG.getConstant(Log2_64(NumSign * SignMulAmt + 1), DL, + MVT::i8)), + N->getOperand(0)); + // To negate, subtract the number from zero + if (NumSign == -1) + NewMul = + DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT), NewMul); + } + } } if (NewMul) Index: test/CodeGen/X86/imul.ll =================================================================== --- test/CodeGen/X86/imul.ll +++ test/CodeGen/X86/imul.ll @@ -171,3 +171,97 @@ %mul = mul i64 %A, 18446744073709551615 ret i64 %mul } + +define i32 @test(i32 %a) { +entry: + %tmp3 = mul i32 %a, 31 +; CHECK-LABEL: test: +; CHECK-NOT: imul +; CHECK: shll +; CHECK-NEXT: sub + ret i32 %tmp3 +} + +define i32 @test1(i32 %a) { +entry: + %tmp3 = mul i32 %a, -31 +; CHECK-LABEL: test1: +; CHECK-NOT: imul +; CHECK: shll +; CHECK-NEXT: sub +; CHECK-NEXT: negl + ret i32 %tmp3 +} + + +define i32 @test2(i32 %a) { +entry: + %tmp3 = mul i32 %a, 33 +; CHECK-LABEL: test2: +; CHECK-NOT: imul +; CHECK: shll +; CHECK-NEXT: leal + ret i32 %tmp3 +} + +define i32 @test3(i32 %a) { +entry: + %tmp3 = mul i32 %a, -33 +; CHECK-LABEL: test3: +; CHECK-NOT: imul +; CHECK: shll +; CHECK-NEXT: leal +; CHECK-NEXT: negl + ret i32 %tmp3 +} + +define i64 @test4(i64 %a) { +entry: + %tmp3 = mul i64 %a, 31 +; CHECK-LABEL: test4: +; CHECK-NOT: imul +; CHECK: shlq +; CHECK-NEXT: sub + ret i64 %tmp3 +} + +define i64 @test5(i64 %a) { +entry: + %tmp3 = mul i64 %a, -31 +; CHECK-LABEL: test5: +; CHECK-NOT: imul +; CHECK: shlq +; CHECK-NEXT: sub +; CHECK-NEXT: negq + ret i64 %tmp3 +} + + +define i64 @test6(i64 %a) { +entry: + %tmp3 = mul i64 %a, 33 +; CHECK-LABEL: test6: +; CHECK-NOT: imul +; CHECK: shlq +; CHECK-NEXT: leaq + ret i64 %tmp3 +} + +define i64 @test7(i64 %a) { +entry: + %tmp3 = mul i64 %a, -33 +; CHECK-LABEL: test7: +; CHECK-NOT: imul +; CHECK: shlq +; CHECK-NEXT: leaq +; CHECK-NEXT: negq + ret i64 %tmp3 +} + +define i64 @testOverflow(i64 %a) { +entry: + %tmp3 = mul i64 %a, 9223372036854775807 +; CHECK-LABEL: testOverflow: +; CHECK-NOT: shl + ret i64 %tmp3 +}