diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index d45c255d660..08cceecb5b0 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -766,6 +766,81 @@ SDNode *PPCDAGToDAGISel::Select(SDOperand Op) { switch (N->getOpcode()) { default: break; + + case ISD::Constant: { + if (N->getValueType(0) == MVT::i64) { + // Get 64 bit value. + int64_t Imm = cast(N)->getValue(); + // Assume no remaining bits. + unsigned Remainder = 0; + // Assume no shift required. + unsigned Shift = 0; + + // If it can't be represented as a 32 bit value. + if (!isInt32(Imm)) { + Shift = CountTrailingZeros_64(Imm); + int64_t ImmSh = static_cast(Imm) >> Shift; + + // If the shifted value fits 32 bits. + if (isInt32(ImmSh)) { + // Go with the shifted value. + Imm = ImmSh; + } else { + // Still stuck with a 64 bit value. + Remainder = Imm; + Shift = 32; + Imm >>= 32; + } + } + + // Intermediate operand. + SDNode *Result; + + // Handle first 32 bits. + unsigned Lo = Imm & 0xFFFF; + unsigned Hi = (Imm >> 16) & 0xFFFF; + + // Simple value. + if (isInt16(Imm)) { + // Just the Lo bits. + Result = CurDAG->getTargetNode(PPC::LI8, MVT::i64, getI32Imm(Lo)); + } else if (Lo) { + // Handle the Hi bits. + unsigned OpC = Hi ? PPC::LIS8 : PPC::LI8; + Result = CurDAG->getTargetNode(OpC, MVT::i64, getI32Imm(Hi)); + // And Lo bits. + Result = CurDAG->getTargetNode(PPC::ORI8, MVT::i64, + SDOperand(Result, 0), getI32Imm(Lo)); + } else { + // Just the Hi bits. + Result = CurDAG->getTargetNode(PPC::LIS8, MVT::i64, getI32Imm(Hi)); + } + + // If no shift, we're done. + if (!Shift) return Result; + + // Shift for next step if the upper 32-bits were not zero. + if (Imm) { + Result = CurDAG->getTargetNode(PPC::RLDICR, MVT::i64, + SDOperand(Result, 0), + getI32Imm(Shift), getI32Imm(63 - Shift)); + } + + // Add in the last bits as required. + if ((Hi = (Remainder >> 16) & 0xFFFF)) { + Result = CurDAG->getTargetNode(PPC::ORIS8, MVT::i64, + SDOperand(Result, 0), getI32Imm(Hi)); + } + if ((Lo = Remainder & 0xFFFF)) { + Result = CurDAG->getTargetNode(PPC::ORI8, MVT::i64, + SDOperand(Result, 0), getI32Imm(Lo)); + } + + return Result; + } + break; + } + case ISD::SETCC: return SelectSETCC(Op); case PPCISD::GlobalBaseReg: diff --git a/lib/Target/PowerPC/PPCInstr64Bit.td b/lib/Target/PowerPC/PPCInstr64Bit.td index f47e92f3dcd..56d02cc146c 100644 --- a/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/lib/Target/PowerPC/PPCInstr64Bit.td @@ -474,48 +474,6 @@ def FCTIDZ : XForm_26<63, 815, (ops F8RC:$frD, F8RC:$frB), // Instruction Patterns // -// Immediate support. -// Handled above: -// sext(0x0000_0000_0000_FFFF, i8) -> li imm -// sext(0x0000_0000_FFFF_0000, i16) -> lis imm>>16 - -// sext(0x0000_0000_FFFF_FFFF, i16) -> lis + ori -def sext_0x0000_0000_FFFF_FFFF_i16 : PatLeaf<(imm), [{ - return N->getValue() == (uint64_t)(int32_t)N->getValue(); -}]>; -def : Pat<(i64 sext_0x0000_0000_FFFF_FFFF_i16:$imm), - (ORI8 (LIS8 (HI16 imm:$imm)), (LO16 imm:$imm))>; - -// zext(0x0000_0000_FFFF_7FFF, i16) -> oris (li lo16(imm)), imm>>16 -def zext_0x0000_0000_FFFF_7FFF_i16 : PatLeaf<(imm), [{ - return (N->getValue() & 0xFFFFFFFF00008000ULL) == 0; -}]>; -def : Pat<(i64 zext_0x0000_0000_FFFF_7FFF_i16:$imm), - (ORIS8 (LI8 (LO16 imm:$imm)), (HI16 imm:$imm))>; - -// zext(0x0000_0000_FFFF_FFFF, i16) -> oris (ori (li 0), lo16(imm)), imm>>16 -def zext_0x0000_0000_FFFF_FFFF_i16 : PatLeaf<(imm), [{ - return (N->getValue() & 0xFFFFFFFF00000000ULL) == 0; -}]>; -def : Pat<(i64 zext_0x0000_0000_FFFF_FFFF_i16:$imm), - (ORIS8 (ORI8 (LI8 0), (LO16 imm:$imm)), (HI16 imm:$imm))>; - -// FIXME: Handle smart forms where the top 32-bits are set. Right now, stuff -// like 0xABCD0123BCDE0000 hits the case below, which produces ORI R, R, 0's! - -// Fully general (and most expensive: 6 instructions!) immediate pattern. -def : Pat<(i64 imm:$imm), - (ORI8 - (ORIS8 - (RLDICR - (ORI8 - (LIS8 (HI48_64 imm:$imm)), - (HI32_48 imm:$imm)), - 32, 31), - (HI16 imm:$imm)), - (LO16 imm:$imm))>; - - // Extensions and truncates to/from 32-bit regs. def : Pat<(i64 (zext GPRC:$in)), (RLDICL (OR4To8 GPRC:$in, GPRC:$in), 0, 32)>;