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 @@ -1328,6 +1328,43 @@ getI32Imm(Lo16)); ++InstCntDirect; } + + // Try to use 4 instructions to materialize the immediate which is "almost" a + // splat of a 32 bit immediate. + if (InstCntDirect > 4) { + uint32_t Hi16OfHi32 = (Hi_32(Imm) >> 16) & 0xffff; + uint32_t Lo16OfHi32 = Hi_32(Imm) & 0xffff; + uint32_t Hi16OfLo32 = (Lo_32(Imm) >> 16) & 0xffff; + uint32_t Lo16OfLo32 = Lo_32(Imm) & 0xffff; + + auto getSplat = [CurDAG, dl](uint32_t Hi16, uint32_t Lo16) { + auto getI32Imm = [CurDAG, dl](unsigned Imm) { + return CurDAG->getTargetConstant(Imm, dl, MVT::i32); + }; + SDNode *Result = + CurDAG->getMachineNode(PPC::LIS8, dl, MVT::i64, getI32Imm(Hi16)); + Result = CurDAG->getMachineNode(PPC::ORI8, dl, MVT::i64, + SDValue(Result, 0), getI32Imm(Lo16)); + SDValue Ops[] = {SDValue(Result, 0), SDValue(Result, 0), getI32Imm(32), + getI32Imm(0)}; + return CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops); + }; + + if (Hi16OfHi32 == Hi16OfLo32) { + InstCntDirect = 4; + Result = getSplat(Hi16OfHi32, Lo16OfHi32); + Result = CurDAG->getMachineNode( + PPC::ORI8, dl, MVT::i64, SDValue(Result, 0), + CurDAG->getTargetConstant(Lo16OfLo32, dl, MVT::i32)); + } else if (Lo16OfHi32 == Lo16OfLo32) { + InstCntDirect = 4; + Result = getSplat(Hi16OfHi32, Lo16OfHi32); + Result = CurDAG->getMachineNode( + PPC::ORIS8, dl, MVT::i64, SDValue(Result, 0), + CurDAG->getTargetConstant(Hi16OfLo32, dl, MVT::i32)); + } + } + if (InstCnt) *InstCnt = InstCntDirect; return Result; diff --git a/llvm/test/CodeGen/PowerPC/constants-i64.ll b/llvm/test/CodeGen/PowerPC/constants-i64.ll --- a/llvm/test/CodeGen/PowerPC/constants-i64.ll +++ b/llvm/test/CodeGen/PowerPC/constants-i64.ll @@ -380,8 +380,7 @@ ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: lis 3, -13105 ; CHECK-NEXT: ori 3, 3, 52479 -; CHECK-NEXT: rldic 3, 3, 32, 0 -; CHECK-NEXT: oris 3, 3, 52431 +; CHECK-NEXT: rldimi 3, 3, 32, 0 ; CHECK-NEXT: ori 3, 3, 291 ; CHECK-NEXT: blr entry: @@ -393,9 +392,8 @@ ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: lis 3, -13057 ; CHECK-NEXT: ori 3, 3, 52479 -; CHECK-NEXT: rldic 3, 3, 32, 0 +; CHECK-NEXT: rldimi 3, 3, 32, 0 ; CHECK-NEXT: oris 3, 3, 291 -; CHECK-NEXT: ori 3, 3, 52479 ; CHECK-NEXT: blr entry: ret i64 14771750698406366463 ;0xCCFFCCFF0123CCFF