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 @@ -4975,6 +4975,30 @@ // Other cases are autogenerated. break; } + case ISD::MUL: { + 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; + + // If the shifted value fits 16 bits, we can transform the multiplication to + // "mulli + rldicr". + 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; + } + 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 @@ -97,12 +93,11 @@ ; CHECK-LABEL: test9: ; CHECK: # %bb.0: ; CHECK-NEXT: lis 4, 16 -; CHECK-NEXT: li 5, 8193 ; CHECK-NEXT: ori 4, 4, 1 -; CHECK-NEXT: sldi 5, 5, 19 ; CHECK-NEXT: sldi 4, 4, 12 ; CHECK-NEXT: mulld 4, 3, 4 -; CHECK-NEXT: mulld 3, 3, 5 +; CHECK-NEXT: mulli 3, 3, 8193 +; CHECK-NEXT: sldi 3, 3, 19 ; CHECK-NEXT: sub 3, 4, 3 ; CHECK-NEXT: blr %y = mul i64 %x, 4294971392