diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -4973,6 +4973,54 @@ // Other cases are autogenerated. break; } + case ISD::MUL: { + SDValue Op0 = N->getOperand(0); + SDValue Op1 = N->getOperand(1); + if (Op1.getOpcode() != ISD::Constant || Op1.getValueType() != MVT::i64) + break; + + int64_t Imm = cast(Op1)->getZExtValue(); + unsigned Shift = countTrailingZeros(Imm); + if (isInt<16>(Imm) || !Shift) + break; + + int64_t ImmSh = Imm >> Shift; + if (isInt<16>(ImmSh)) { + uint64_t SextImm = SignExtend64(ImmSh & 0xFFFF, 16); + SDValue SDImm = CurDAG->getTargetConstant(SextImm, dl, MVT::i64); + SDNode *MulNode = CurDAG->getMachineNode(PPC::MULLI8, dl, MVT::i64, + N->getOperand(0), SDImm); + CurDAG->SelectNodeTo(N, PPC::RLDICR, MVT::i64, SDValue(MulNode, 0), + getI32Imm(Shift, dl), getI32Imm(63 - Shift, dl)); + return; + } + if (isPowerOf2_64(ImmSh - 1)) { + // The multiplicand has exactly two bits set so we don't need a multiply. + unsigned Shift2 = countTrailingZeros(ImmSh - 1); + SDNode *ShNode = CurDAG->getMachineNode(PPC::RLDICR, dl, MVT::i64, Op0, + getI32Imm(Shift2, dl), + getI32Imm(63 - Shift2, dl)); + SDNode *AddNode = CurDAG->getMachineNode(PPC::ADD8, dl, MVT::i64, Op0, + SDValue(ShNode, 0)); + CurDAG->SelectNodeTo(N, PPC::RLDICR, MVT::i64, SDValue(AddNode, 0), + getI32Imm(Shift, dl), getI32Imm(63 - Shift, dl)); + return; + } + if (isPowerOf2_64(ImmSh + 1)) { + // The multiplicand is a contiguous sequence of bits. We don't need a + // multiply. + unsigned Shift2 = countTrailingZeros(ImmSh + 1); + SDNode *ShNode = CurDAG->getMachineNode(PPC::RLDICR, dl, MVT::i64, Op0, + getI32Imm(Shift2, dl), + getI32Imm(63 - Shift2, dl)); + SDNode *SubNode = CurDAG->getMachineNode(PPC::SUBF8, dl, MVT::i64, Op0, + SDValue(ShNode, 0)); + CurDAG->SelectNodeTo(N, PPC::RLDICR, MVT::i64, SDValue(SubNode, 0), + getI32Imm(Shift, dl), getI32Imm(63 - Shift, dl)); + return; + } + break; + } // FIXME: Remove this once the ANDI glue bug is fixed: case PPCISD::ANDI_rec_1_EQ_BIT: case PPCISD::ANDI_rec_1_GT_BIT: { diff --git a/llvm/test/CodeGen/PowerPC/mulli.ll b/llvm/test/CodeGen/PowerPC/mulli.ll --- a/llvm/test/CodeGen/PowerPC/mulli.ll +++ b/llvm/test/CodeGen/PowerPC/mulli.ll @@ -4,9 +4,8 @@ define i64 @test1(i64 %x) { ; CHECK-LABEL: test1: ; CHECK: # %bb.0: -; CHECK-NEXT: li 4, 625 -; CHECK-NEXT: sldi 4, 4, 36 -; CHECK-NEXT: mulld 3, 3, 4 +; CHECK-NEXT: mulli 3, 3, 625 +; CHECK-NEXT: sldi 3, 3, 36 ; CHECK-NEXT: blr %y = mul i64 %x, 42949672960000 ret i64 %y @@ -15,9 +14,8 @@ define i64 @test2(i64 %x) { ; CHECK-LABEL: test2: ; CHECK: # %bb.0: -; CHECK-NEXT: li 4, -625 -; CHECK-NEXT: sldi 4, 4, 36 -; CHECK-NEXT: mulld 3, 3, 4 +; CHECK-NEXT: mulli 3, 3, -625 +; CHECK-NEXT: sldi 3, 3, 36 ; CHECK-NEXT: blr %y = mul i64 %x, -42949672960000 ret i64 %y @@ -26,9 +24,8 @@ define i64 @test3(i64 %x) { ; CHECK-LABEL: test3: ; CHECK: # %bb.0: -; CHECK-NEXT: lis 4, 74 -; CHECK-NEXT: ori 4, 4, 16384 -; CHECK-NEXT: mulld 3, 3, 4 +; CHECK-NEXT: mulli 3, 3, 297 +; CHECK-NEXT: sldi 3, 3, 14 ; CHECK-NEXT: blr %y = mul i64 %x, 4866048 ret i64 %y @@ -37,9 +34,8 @@ define i64 @test4(i64 %x) { ; CHECK-LABEL: test4: ; CHECK: # %bb.0: -; CHECK-NEXT: lis 4, -75 -; CHECK-NEXT: ori 4, 4, 49152 -; CHECK-NEXT: mulld 3, 3, 4 +; CHECK-NEXT: mulli 3, 3, -297 +; CHECK-NEXT: sldi 3, 3, 14 ; CHECK-NEXT: blr %y = mul i64 %x, -4866048 ret i64 %y @@ -48,10 +44,9 @@ define i64 @test5(i64 %x) { ; CHECK-LABEL: test5: ; CHECK: # %bb.0: -; CHECK-NEXT: lis 4, 16 -; CHECK-NEXT: ori 4, 4, 1 -; CHECK-NEXT: sldi 4, 4, 12 -; CHECK-NEXT: mulld 3, 3, 4 +; CHECK-NEXT: sldi 4, 3, 20 +; CHECK-NEXT: add 3, 3, 4 +; CHECK-NEXT: sldi 3, 3, 12 ; CHECK-NEXT: blr %y = mul i64 %x, 4294971392 ret i64 %y @@ -68,3 +63,15 @@ %y = mul i64 %x, -4294971392 ret i64 %y } + +define i64 @test7(i64 %x) { +; CHECK-LABEL: test7: +; CHECK: # %bb.0: +; CHECK-NEXT: sldi 4, 3, 21 +; CHECK-NEXT: sub 3, 4, 3 +; CHECK-NEXT: sldi 3, 3, 13 +; CHECK-NEXT: blr + %y = mul i64 %x, 17179860992 + ret i64 %y +} +