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 @@ -4963,6 +4963,32 @@ // Other cases are autogenerated. break; } + case ISD::MUL: { + SDValue Op1 = N->getOperand(1); + if (Op1.getOpcode() != ISD::Constant || Op1.getValueType() != MVT::i64) + break; + + // If the multiplier fits int16, we can handle it with mulli. + int64_t Imm = cast(Op1)->getZExtValue(); + unsigned Shift = countTrailingZeros(Imm); + if (isInt<16>(Imm) || !Shift) + break; + + // If the shifted value fits int16, we can do this transformation: + // (mul X, c1 << c2) -> (rldicr (mulli X, c1) c2). We do this in ISEL due to + // DAGCombiner prefers (shl (mul X, c1), c2) -> (mul X, c1 << c2). + uint64_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 @@ -96,9 +92,8 @@ ; CHECK-NEXT: sldi 4, 3, 12 ; CHECK-NEXT: sldi 5, 3, 32 ; CHECK-NEXT: add 4, 5, 4 -; CHECK-NEXT: li 5, 8193 -; CHECK-NEXT: sldi 5, 5, 19 -; 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