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 @@ -1325,6 +1325,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 @@ -375,4 +375,28 @@ ret i64 11174473921 } +define i64 @imm19() #0 { +; CHECK-LABEL: imm19: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lis 3, 13107 +; CHECK-NEXT: ori 3, 3, 13107 +; CHECK-NEXT: rldic 3, 3, 34, 0 +; CHECK-NEXT: ori 3, 3, 52428 +; CHECK-NEXT: blr +entry: + ret i64 14757395255531719884 ;0xCCCCCCCC0000CCCC +} + +define i64 @imm20() #0 { +; CHECK-LABEL: imm20: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: lis 3, -13057 +; CHECK-NEXT: ori 3, 3, 52479 +; CHECK-NEXT: rldimi 3, 3, 32, 0 +; CHECK-NEXT: oris 3, 3, 291 +; CHECK-NEXT: blr +entry: + ret i64 14771750698406366463 ;0xCCFFCCFF0123CCFF +} + attributes #0 = { nounwind readnone }