X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FPowerPC%2FPPCISelDAGToDAG.cpp;h=d45c255d660fef2788fa6614636491715aac9c34;hb=f5da13367f88f06e3b585dc2263ab6e9ca6c4bf8;hp=40f10057d576825a1952d7ae063e8c6f77d99876;hpb=6da2f3268d12a9e64f2635dbb94b63e1c4142f59;p=oota-llvm.git diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 40f10057d57..d45c255d660 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "PPC.h" +#include "PPCPredicates.h" #include "PPCTargetMachine.h" #include "PPCISelLowering.h" #include "PPCHazardRecognizers.h" @@ -28,14 +29,13 @@ #include "llvm/Intrinsics.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/Visibility.h" -#include +#include "llvm/Support/Compiler.h" #include #include using namespace llvm; namespace { - Statistic<> FrameOff("ppc-codegen", "Number of frame idx offsets collapsed"); + Statistic FrameOff("ppc-codegen", "Number of frame idx offsets collapsed"); //===--------------------------------------------------------------------===// /// PPCDAGToDAGISel - PPC specific code to select PPC machine @@ -76,14 +76,25 @@ namespace { return CurDAG->getTargetConstant(Imm, PPCLowering.getPointerTy()); } + /// isRunOfOnes - Returns true iff Val consists of one contiguous run of 1s + /// with any number of 0s on either side. The 1s are allowed to wrap from + /// LSB to MSB, so 0x000FFF0, 0x0000FFFF, and 0xFF0000FF are all runs. + /// 0x0F0F0000 is not, since all 1s are not contiguous. + static bool isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME); + + + /// isRotateAndMask - Returns true if Mask and Shift can be folded into a + /// rotate and mask opcode and mask operation. + static bool isRotateAndMask(SDNode *N, unsigned Mask, bool IsShiftMask, + unsigned &SH, unsigned &MB, unsigned &ME); /// getGlobalBaseReg - insert code into the entry mbb to materialize the PIC /// base register. Return the virtual register that holds this value. - SDOperand getGlobalBaseReg(); + SDNode *getGlobalBaseReg(); // Select - Convert the specified operand from a target-independent to a // target-specific node if it hasn't already been changed. - SDNode *Select(SDOperand &Result, SDOperand Op); + SDNode *Select(SDOperand Op); SDNode *SelectBitfieldInsert(SDNode *N); @@ -93,22 +104,42 @@ namespace { /// SelectAddrImm - Returns true if the address N can be represented by /// a base register plus a signed 16-bit displacement [r+imm]. - bool SelectAddrImm(SDOperand N, SDOperand &Disp, SDOperand &Base); + bool SelectAddrImm(SDOperand Op, SDOperand N, SDOperand &Disp, + SDOperand &Base) { + return PPCLowering.SelectAddressRegImm(N, Disp, Base, *CurDAG); + } + + /// SelectAddrImmOffs - Return true if the operand is valid for a preinc + /// immediate field. Because preinc imms have already been validated, just + /// accept it. + bool SelectAddrImmOffs(SDOperand Op, SDOperand N, SDOperand &Out) const { + Out = N; + return true; + } /// SelectAddrIdx - Given the specified addressed, check to see if it can be /// represented as an indexed [r+r] operation. Returns false if it can /// be represented by [r+imm], which are preferred. - bool SelectAddrIdx(SDOperand N, SDOperand &Base, SDOperand &Index); + bool SelectAddrIdx(SDOperand Op, SDOperand N, SDOperand &Base, + SDOperand &Index) { + return PPCLowering.SelectAddressRegReg(N, Base, Index, *CurDAG); + } /// SelectAddrIdxOnly - Given the specified addressed, force it to be /// represented as an indexed [r+r] operation. - bool SelectAddrIdxOnly(SDOperand N, SDOperand &Base, SDOperand &Index); + bool SelectAddrIdxOnly(SDOperand Op, SDOperand N, SDOperand &Base, + SDOperand &Index) { + return PPCLowering.SelectAddressRegRegOnly(N, Base, Index, *CurDAG); + } /// SelectAddrImmShift - Returns true if the address N can be represented by /// a base register plus a signed 14-bit displacement [r+imm*4]. Suitable /// for use by STD and friends. - bool SelectAddrImmShift(SDOperand N, SDOperand &Disp, SDOperand &Base); - + bool SelectAddrImmShift(SDOperand Op, SDOperand N, SDOperand &Disp, + SDOperand &Base) { + return PPCLowering.SelectAddressRegImmShift(N, Disp, Base, *CurDAG); + } + /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for /// inline asm expressions. virtual bool SelectInlineAsmMemoryOperand(const SDOperand &Op, @@ -119,18 +150,18 @@ namespace { switch (ConstraintCode) { default: return true; case 'm': // memory - if (!SelectAddrIdx(Op, Op0, Op1)) - SelectAddrImm(Op, Op0, Op1); + if (!SelectAddrIdx(Op, Op, Op0, Op1)) + SelectAddrImm(Op, Op, Op0, Op1); break; case 'o': // offsetable - if (!SelectAddrImm(Op, Op0, Op1)) { + if (!SelectAddrImm(Op, Op, Op0, Op1)) { Op0 = Op; AddToISelQueue(Op0); // r+0. Op1 = getSmallIPtrImm(0); } break; case 'v': // not offsetable - SelectAddrIdxOnly(Op, Op0, Op1); + SelectAddrIdxOnly(Op, Op, Op0, Op1); break; } @@ -167,8 +198,6 @@ namespace { private: SDNode *SelectSETCC(SDOperand Op); - SDNode *MySelect_PPCbctrl(SDOperand N); - SDNode *MySelect_PPCcall(SDOperand N); }; } @@ -220,18 +249,18 @@ void PPCDAGToDAGISel::InsertVRSaveCode(Function &F) { unsigned InVRSAVE = RegMap->createVirtualRegister(&PPC::GPRCRegClass); unsigned UpdatedVRSAVE = RegMap->createVirtualRegister(&PPC::GPRCRegClass); + const TargetInstrInfo &TII = *TM.getInstrInfo(); MachineBasicBlock &EntryBB = *Fn.begin(); // Emit the following code into the entry block: // InVRSAVE = MFVRSAVE // UpdatedVRSAVE = UPDATE_VRSAVE InVRSAVE // MTVRSAVE UpdatedVRSAVE MachineBasicBlock::iterator IP = EntryBB.begin(); // Insert Point - BuildMI(EntryBB, IP, PPC::MFVRSAVE, 0, InVRSAVE); - BuildMI(EntryBB, IP, PPC::UPDATE_VRSAVE, 1, UpdatedVRSAVE).addReg(InVRSAVE); - BuildMI(EntryBB, IP, PPC::MTVRSAVE, 1).addReg(UpdatedVRSAVE); + BuildMI(EntryBB, IP, TII.get(PPC::MFVRSAVE), InVRSAVE); + BuildMI(EntryBB, IP, TII.get(PPC::UPDATE_VRSAVE), UpdatedVRSAVE).addReg(InVRSAVE); + BuildMI(EntryBB, IP, TII.get(PPC::MTVRSAVE)).addReg(UpdatedVRSAVE); // Find all return blocks, outputting a restore in each epilog. - const TargetInstrInfo &TII = *TM.getInstrInfo(); for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) { if (!BB->empty() && TII.isReturn(BB->back().getOpcode())) { IP = BB->end(); --IP; @@ -243,7 +272,7 @@ void PPCDAGToDAGISel::InsertVRSaveCode(Function &F) { IP = I2; // Emit: MTVRSAVE InVRSave - BuildMI(*BB, IP, PPC::MTVRSAVE, 1).addReg(InVRSAVE); + BuildMI(*BB, IP, TII.get(PPC::MTVRSAVE)).addReg(InVRSAVE); } } } @@ -252,22 +281,25 @@ void PPCDAGToDAGISel::InsertVRSaveCode(Function &F) { /// getGlobalBaseReg - Output the instructions required to put the /// base address to use for accessing globals into a register. /// -SDOperand PPCDAGToDAGISel::getGlobalBaseReg() { +SDNode *PPCDAGToDAGISel::getGlobalBaseReg() { if (!GlobalBaseReg) { + const TargetInstrInfo &TII = *TM.getInstrInfo(); // Insert the set of GlobalBaseReg into the first MBB of the function MachineBasicBlock &FirstMBB = BB->getParent()->front(); MachineBasicBlock::iterator MBBI = FirstMBB.begin(); SSARegMap *RegMap = BB->getParent()->getSSARegMap(); - if (PPCLowering.getPointerTy() == MVT::i32) + if (PPCLowering.getPointerTy() == MVT::i32) { GlobalBaseReg = RegMap->createVirtualRegister(PPC::GPRCRegisterClass); - else + BuildMI(FirstMBB, MBBI, TII.get(PPC::MovePCtoLR), PPC::LR); + BuildMI(FirstMBB, MBBI, TII.get(PPC::MFLR), GlobalBaseReg); + } else { GlobalBaseReg = RegMap->createVirtualRegister(PPC::G8RCRegisterClass); - - BuildMI(FirstMBB, MBBI, PPC::MovePCtoLR, 0, PPC::LR); - BuildMI(FirstMBB, MBBI, PPC::MFLR, 1, GlobalBaseReg); + BuildMI(FirstMBB, MBBI, TII.get(PPC::MovePCtoLR8), PPC::LR8); + BuildMI(FirstMBB, MBBI, TII.get(PPC::MFLR8), GlobalBaseReg); + } } - return CurDAG->getRegister(GlobalBaseReg, PPCLowering.getPointerTy()); + return CurDAG->getRegister(GlobalBaseReg, PPCLowering.getPointerTy()).Val; } /// isIntS16Immediate - This method tests to see if the node is either a 32-bit @@ -303,7 +335,7 @@ static bool isInt32Immediate(SDNode *N, unsigned &Imm) { /// isInt64Immediate - This method tests to see if the node is a 64-bit constant /// operand. If so Imm will receive the 64-bit value. static bool isInt64Immediate(SDNode *N, uint64_t &Imm) { - if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) { + if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i64) { Imm = cast(N)->getValue(); return true; } @@ -324,12 +356,7 @@ static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { return N->getOpcode() == Opc && isInt32Immediate(N->getOperand(1).Val, Imm); } - -// isRunOfOnes - Returns true iff Val consists of one contiguous run of 1s with -// any number of 0s on either side. The 1s are allowed to wrap from LSB to -// MSB, so 0x000FFF0, 0x0000FFFF, and 0xFF0000FF are all runs. 0x0F0F0000 is -// not, since all 1s are not contiguous. -static bool isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME) { +bool PPCDAGToDAGISel::isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME) { if (isShiftedMask_32(Val)) { // look for the first non-zero bit MB = CountLeadingZeros_32(Val); @@ -350,10 +377,9 @@ static bool isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME) { return false; } -// isRotateAndMask - Returns true if Mask and Shift can be folded into a rotate -// and mask opcode and mask operation. -static bool isRotateAndMask(SDNode *N, unsigned Mask, bool IsShiftMask, - unsigned &SH, unsigned &MB, unsigned &ME) { +bool PPCDAGToDAGISel::isRotateAndMask(SDNode *N, unsigned Mask, + bool IsShiftMask, unsigned &SH, + unsigned &MB, unsigned &ME) { // Don't even go down this path for i64, since different logic will be // necessary for rldicl/rldicr/rldimi. if (N->getValueType(0) != MVT::i32) @@ -378,6 +404,8 @@ static bool isRotateAndMask(SDNode *N, unsigned Mask, bool IsShiftMask, Indeterminant = ~(0xFFFFFFFFu >> Shift); // adjust for the left rotate Shift = 32 - Shift; + } else if (Opcode == ISD::ROTL) { + Indeterminant = 0; } else { return false; } @@ -457,237 +485,14 @@ SDNode *PPCDAGToDAGISel::SelectBitfieldInsert(SDNode *N) { AddToISelQueue(Tmp3); AddToISelQueue(Op1); SH &= 31; - return CurDAG->getTargetNode(PPC::RLWIMI, MVT::i32, Tmp3, Op1, - getI32Imm(SH), getI32Imm(MB), getI32Imm(ME)); + SDOperand Ops[] = { Tmp3, Op1, getI32Imm(SH), getI32Imm(MB), + getI32Imm(ME) }; + return CurDAG->getTargetNode(PPC::RLWIMI, MVT::i32, Ops, 5); } } return 0; } -/// SelectAddrImm - Returns true if the address N can be represented by -/// a base register plus a signed 16-bit displacement [r+imm]. -bool PPCDAGToDAGISel::SelectAddrImm(SDOperand N, SDOperand &Disp, - SDOperand &Base) { - // If this can be more profitably realized as r+r, fail. - if (SelectAddrIdx(N, Disp, Base)) - return false; - - if (N.getOpcode() == ISD::ADD) { - short imm = 0; - if (isIntS16Immediate(N.getOperand(1), imm)) { - Disp = getI32Imm((int)imm & 0xFFFF); - if (FrameIndexSDNode *FI = dyn_cast(N.getOperand(0))) { - Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType()); - } else { - Base = N.getOperand(0); - } - return true; // [r+i] - } else if (N.getOperand(1).getOpcode() == PPCISD::Lo) { - // Match LOAD (ADD (X, Lo(G))). - assert(!cast(N.getOperand(1).getOperand(1))->getValue() - && "Cannot handle constant offsets yet!"); - Disp = N.getOperand(1).getOperand(0); // The global address. - assert(Disp.getOpcode() == ISD::TargetGlobalAddress || - Disp.getOpcode() == ISD::TargetConstantPool || - Disp.getOpcode() == ISD::TargetJumpTable); - Base = N.getOperand(0); - return true; // [&g+r] - } - } else if (N.getOpcode() == ISD::OR) { - short imm = 0; - if (isIntS16Immediate(N.getOperand(1), imm)) { - // If this is an or of disjoint bitfields, we can codegen this as an add - // (for better address arithmetic) if the LHS and RHS of the OR are - // provably disjoint. - uint64_t LHSKnownZero, LHSKnownOne; - PPCLowering.ComputeMaskedBits(N.getOperand(0), ~0U, - LHSKnownZero, LHSKnownOne); - if ((LHSKnownZero|~(unsigned)imm) == ~0U) { - // If all of the bits are known zero on the LHS or RHS, the add won't - // carry. - Base = N.getOperand(0); - Disp = getI32Imm((int)imm & 0xFFFF); - return true; - } - } - } else if (ConstantSDNode *CN = dyn_cast(N)) { - // Loading from a constant address. - - // If this address fits entirely in a 16-bit sext immediate field, codegen - // this as "d, 0" - short Imm; - if (isIntS16Immediate(CN, Imm)) { - Disp = CurDAG->getTargetConstant(Imm, CN->getValueType(0)); - Base = CurDAG->getRegister(PPC::R0, CN->getValueType(0)); - return true; - } - - // FIXME: Handle small sext constant offsets in PPC64 mode also! - if (CN->getValueType(0) == MVT::i32) { - int Addr = (int)CN->getValue(); - - // Otherwise, break this down into an LIS + disp. - Disp = getI32Imm((short)Addr); - Base = CurDAG->getConstant(Addr - (signed short)Addr, MVT::i32); - return true; - } - } - - Disp = getSmallIPtrImm(0); - if (FrameIndexSDNode *FI = dyn_cast(N)) - Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType()); - else - Base = N; - return true; // [r+0] -} - -/// SelectAddrIdx - Given the specified addressed, check to see if it can be -/// represented as an indexed [r+r] operation. Returns false if it can -/// be represented by [r+imm], which are preferred. -bool PPCDAGToDAGISel::SelectAddrIdx(SDOperand N, SDOperand &Base, - SDOperand &Index) { - short imm = 0; - if (N.getOpcode() == ISD::ADD) { - if (isIntS16Immediate(N.getOperand(1), imm)) - return false; // r+i - if (N.getOperand(1).getOpcode() == PPCISD::Lo) - return false; // r+i - - Base = N.getOperand(0); - Index = N.getOperand(1); - return true; - } else if (N.getOpcode() == ISD::OR) { - if (isIntS16Immediate(N.getOperand(1), imm)) - return false; // r+i can fold it if we can. - - // If this is an or of disjoint bitfields, we can codegen this as an add - // (for better address arithmetic) if the LHS and RHS of the OR are provably - // disjoint. - uint64_t LHSKnownZero, LHSKnownOne; - uint64_t RHSKnownZero, RHSKnownOne; - PPCLowering.ComputeMaskedBits(N.getOperand(0), ~0U, - LHSKnownZero, LHSKnownOne); - - if (LHSKnownZero) { - PPCLowering.ComputeMaskedBits(N.getOperand(1), ~0U, - RHSKnownZero, RHSKnownOne); - // If all of the bits are known zero on the LHS or RHS, the add won't - // carry. - if ((LHSKnownZero | RHSKnownZero) == ~0U) { - Base = N.getOperand(0); - Index = N.getOperand(1); - return true; - } - } - } - - return false; -} - -/// SelectAddrIdxOnly - Given the specified addressed, force it to be -/// represented as an indexed [r+r] operation. -bool PPCDAGToDAGISel::SelectAddrIdxOnly(SDOperand N, SDOperand &Base, - SDOperand &Index) { - // Check to see if we can easily represent this as an [r+r] address. This - // will fail if it thinks that the address is more profitably represented as - // reg+imm, e.g. where imm = 0. - if (SelectAddrIdx(N, Base, Index)) - return true; - - // If the operand is an addition, always emit this as [r+r], since this is - // better (for code size, and execution, as the memop does the add for free) - // than emitting an explicit add. - if (N.getOpcode() == ISD::ADD) { - Base = N.getOperand(0); - Index = N.getOperand(1); - return true; - } - - // Otherwise, do it the hard way, using R0 as the base register. - Base = CurDAG->getRegister(PPC::R0, N.getValueType()); - Index = N; - return true; -} - -/// SelectAddrImmShift - Returns true if the address N can be represented by -/// a base register plus a signed 14-bit displacement [r+imm*4]. Suitable -/// for use by STD and friends. -bool PPCDAGToDAGISel::SelectAddrImmShift(SDOperand N, SDOperand &Disp, - SDOperand &Base) { - // If this can be more profitably realized as r+r, fail. - if (SelectAddrIdx(N, Disp, Base)) - return false; - - if (N.getOpcode() == ISD::ADD) { - short imm = 0; - if (isIntS16Immediate(N.getOperand(1), imm) && (imm & 3) == 0) { - Disp = getI32Imm(((int)imm & 0xFFFF) >> 2); - if (FrameIndexSDNode *FI = dyn_cast(N.getOperand(0))) { - Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType()); - } else { - Base = N.getOperand(0); - } - return true; // [r+i] - } else if (N.getOperand(1).getOpcode() == PPCISD::Lo) { - // Match LOAD (ADD (X, Lo(G))). - assert(!cast(N.getOperand(1).getOperand(1))->getValue() - && "Cannot handle constant offsets yet!"); - Disp = N.getOperand(1).getOperand(0); // The global address. - assert(Disp.getOpcode() == ISD::TargetGlobalAddress || - Disp.getOpcode() == ISD::TargetConstantPool || - Disp.getOpcode() == ISD::TargetJumpTable); - Base = N.getOperand(0); - return true; // [&g+r] - } - } else if (N.getOpcode() == ISD::OR) { - short imm = 0; - if (isIntS16Immediate(N.getOperand(1), imm) && (imm & 3) == 0) { - // If this is an or of disjoint bitfields, we can codegen this as an add - // (for better address arithmetic) if the LHS and RHS of the OR are - // provably disjoint. - uint64_t LHSKnownZero, LHSKnownOne; - PPCLowering.ComputeMaskedBits(N.getOperand(0), ~0U, - LHSKnownZero, LHSKnownOne); - if ((LHSKnownZero|~(unsigned)imm) == ~0U) { - // If all of the bits are known zero on the LHS or RHS, the add won't - // carry. - Base = N.getOperand(0); - Disp = getI32Imm(((int)imm & 0xFFFF) >> 2); - return true; - } - } - } else if (ConstantSDNode *CN = dyn_cast(N)) { - // Loading from a constant address. - - // If this address fits entirely in a 14-bit sext immediate field, codegen - // this as "d, 0" - short Imm; - if (isIntS16Immediate(CN, Imm)) { - Disp = getSmallIPtrImm((unsigned short)Imm >> 2); - Base = CurDAG->getRegister(PPC::R0, CN->getValueType(0)); - return true; - } - - // FIXME: Handle small sext constant offsets in PPC64 mode also! - if (CN->getValueType(0) == MVT::i32) { - int Addr = (int)CN->getValue(); - - // Otherwise, break this down into an LIS + disp. - Disp = getI32Imm((short)Addr >> 2); - Base = CurDAG->getConstant(Addr - (signed short)Addr, MVT::i32); - return true; - } - } - - Disp = getSmallIPtrImm(0); - if (FrameIndexSDNode *FI = dyn_cast(N)) - Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType()); - else - Base = N; - return true; // [r+0] -} - - /// SelectCC - Select a comparison of the specified values with the specified /// condition code, returning the CR# of the expression. SDOperand PPCDAGToDAGISel::SelectCC(SDOperand LHS, SDOperand RHS, @@ -698,7 +503,33 @@ SDOperand PPCDAGToDAGISel::SelectCC(SDOperand LHS, SDOperand RHS, if (LHS.getValueType() == MVT::i32) { unsigned Imm; - if (ISD::isUnsignedIntSetCC(CC)) { + if (CC == ISD::SETEQ || CC == ISD::SETNE) { + if (isInt32Immediate(RHS, Imm)) { + // SETEQ/SETNE comparison with 16-bit immediate, fold it. + if (isUInt16(Imm)) + return SDOperand(CurDAG->getTargetNode(PPC::CMPLWI, MVT::i32, LHS, + getI32Imm(Imm & 0xFFFF)), 0); + // If this is a 16-bit signed immediate, fold it. + if (isInt16(Imm)) + return SDOperand(CurDAG->getTargetNode(PPC::CMPWI, MVT::i32, LHS, + getI32Imm(Imm & 0xFFFF)), 0); + + // For non-equality comparisons, the default code would materialize the + // constant, then compare against it, like this: + // lis r2, 4660 + // ori r2, r2, 22136 + // cmpw cr0, r3, r2 + // Since we are just comparing for equality, we can emit this instead: + // xoris r0,r3,0x1234 + // cmplwi cr0,r0,0x5678 + // beq cr0,L6 + SDOperand Xor(CurDAG->getTargetNode(PPC::XORIS, MVT::i32, LHS, + getI32Imm(Imm >> 16)), 0); + return SDOperand(CurDAG->getTargetNode(PPC::CMPLWI, MVT::i32, Xor, + getI32Imm(Imm & 0xFFFF)), 0); + } + Opc = PPC::CMPLW; + } else if (ISD::isUnsignedIntSetCC(CC)) { if (isInt32Immediate(RHS, Imm) && isUInt16(Imm)) return SDOperand(CurDAG->getTargetNode(PPC::CMPLWI, MVT::i32, LHS, getI32Imm(Imm & 0xFFFF)), 0); @@ -713,7 +544,35 @@ SDOperand PPCDAGToDAGISel::SelectCC(SDOperand LHS, SDOperand RHS, } } else if (LHS.getValueType() == MVT::i64) { uint64_t Imm; - if (ISD::isUnsignedIntSetCC(CC)) { + if (CC == ISD::SETEQ || CC == ISD::SETNE) { + if (isInt64Immediate(RHS.Val, Imm)) { + // SETEQ/SETNE comparison with 16-bit immediate, fold it. + if (isUInt16(Imm)) + return SDOperand(CurDAG->getTargetNode(PPC::CMPLDI, MVT::i64, LHS, + getI32Imm(Imm & 0xFFFF)), 0); + // If this is a 16-bit signed immediate, fold it. + if (isInt16(Imm)) + return SDOperand(CurDAG->getTargetNode(PPC::CMPDI, MVT::i64, LHS, + getI32Imm(Imm & 0xFFFF)), 0); + + // For non-equality comparisons, the default code would materialize the + // constant, then compare against it, like this: + // lis r2, 4660 + // ori r2, r2, 22136 + // cmpd cr0, r3, r2 + // Since we are just comparing for equality, we can emit this instead: + // xoris r0,r3,0x1234 + // cmpldi cr0,r0,0x5678 + // beq cr0,L6 + if (isUInt32(Imm)) { + SDOperand Xor(CurDAG->getTargetNode(PPC::XORIS8, MVT::i64, LHS, + getI64Imm(Imm >> 16)), 0); + return SDOperand(CurDAG->getTargetNode(PPC::CMPLDI, MVT::i64, Xor, + getI64Imm(Imm & 0xFFFF)), 0); + } + } + Opc = PPC::CMPLD; + } else if (ISD::isUnsignedIntSetCC(CC)) { if (isInt64Immediate(RHS.Val, Imm) && isUInt16(Imm)) return SDOperand(CurDAG->getTargetNode(PPC::CMPLDI, MVT::i64, LHS, getI64Imm(Imm & 0xFFFF)), 0); @@ -722,7 +581,7 @@ SDOperand PPCDAGToDAGISel::SelectCC(SDOperand LHS, SDOperand RHS, short SImm; if (isIntS16Immediate(RHS, SImm)) return SDOperand(CurDAG->getTargetNode(PPC::CMPDI, MVT::i64, LHS, - getI64Imm((int)SImm & 0xFFFF)), + getI64Imm(SImm & 0xFFFF)), 0); Opc = PPC::CMPD; } @@ -736,34 +595,31 @@ SDOperand PPCDAGToDAGISel::SelectCC(SDOperand LHS, SDOperand RHS, return SDOperand(CurDAG->getTargetNode(Opc, MVT::i32, LHS, RHS), 0); } -/// getBCCForSetCC - Returns the PowerPC condition branch mnemonic corresponding -/// to Condition. -static unsigned getBCCForSetCC(ISD::CondCode CC) { +static PPC::Predicate getPredicateForSetCC(ISD::CondCode CC) { switch (CC) { default: assert(0 && "Unknown condition!"); abort(); case ISD::SETOEQ: // FIXME: This is incorrect see PR642. case ISD::SETUEQ: - case ISD::SETEQ: return PPC::BEQ; + case ISD::SETEQ: return PPC::PRED_EQ; case ISD::SETONE: // FIXME: This is incorrect see PR642. case ISD::SETUNE: - case ISD::SETNE: return PPC::BNE; + case ISD::SETNE: return PPC::PRED_NE; case ISD::SETOLT: // FIXME: This is incorrect see PR642. case ISD::SETULT: - case ISD::SETLT: return PPC::BLT; + case ISD::SETLT: return PPC::PRED_LT; case ISD::SETOLE: // FIXME: This is incorrect see PR642. case ISD::SETULE: - case ISD::SETLE: return PPC::BLE; + case ISD::SETLE: return PPC::PRED_LE; case ISD::SETOGT: // FIXME: This is incorrect see PR642. case ISD::SETUGT: - case ISD::SETGT: return PPC::BGT; + case ISD::SETGT: return PPC::PRED_GT; case ISD::SETOGE: // FIXME: This is incorrect see PR642. case ISD::SETUGE: - case ISD::SETGE: return PPC::BGE; + case ISD::SETGE: return PPC::PRED_GE; - case ISD::SETO: return PPC::BUN; - case ISD::SETUO: return PPC::BNU; + case ISD::SETO: return PPC::PRED_NU; + case ISD::SETUO: return PPC::PRED_UN; } - return 0; } /// getCRIdxForSetCC - Return the index of the condition register field @@ -809,26 +665,28 @@ SDNode *PPCDAGToDAGISel::SelectSETCC(SDOperand Op) { AddToISelQueue(Op); switch (CC) { default: break; - case ISD::SETEQ: + case ISD::SETEQ: { Op = SDOperand(CurDAG->getTargetNode(PPC::CNTLZW, MVT::i32, Op), 0); - return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Op, getI32Imm(27), - getI32Imm(5), getI32Imm(31)).Val; + SDOperand Ops[] = { Op, getI32Imm(27), getI32Imm(5), getI32Imm(31) }; + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); + } case ISD::SETNE: { SDOperand AD = SDOperand(CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, Op, getI32Imm(~0U)), 0); return CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, AD, Op, - AD.getValue(1)).Val; + AD.getValue(1)); + } + case ISD::SETLT: { + SDOperand Ops[] = { Op, getI32Imm(1), getI32Imm(31), getI32Imm(31) }; + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); } - case ISD::SETLT: - return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Op, getI32Imm(1), - getI32Imm(31), getI32Imm(31)).Val; case ISD::SETGT: { SDOperand T = SDOperand(CurDAG->getTargetNode(PPC::NEG, MVT::i32, Op), 0); T = SDOperand(CurDAG->getTargetNode(PPC::ANDC, MVT::i32, T, Op), 0); - return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, T, getI32Imm(1), - getI32Imm(31), getI32Imm(31)).Val; + SDOperand Ops[] = { T, getI32Imm(1), getI32Imm(31), getI32Imm(31) }; + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); } } } else if (Imm == ~0U) { // setcc op, -1 @@ -842,28 +700,28 @@ SDNode *PPCDAGToDAGISel::SelectSETCC(SDOperand Op) { return CurDAG->SelectNodeTo(N, PPC::ADDZE, MVT::i32, SDOperand(CurDAG->getTargetNode(PPC::LI, MVT::i32, getI32Imm(0)), 0), - Op.getValue(1)).Val; + Op.getValue(1)); case ISD::SETNE: { Op = SDOperand(CurDAG->getTargetNode(PPC::NOR, MVT::i32, Op, Op), 0); SDNode *AD = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, Op, getI32Imm(~0U)); return CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, SDOperand(AD, 0), - Op, SDOperand(AD, 1)).Val; + Op, SDOperand(AD, 1)); } case ISD::SETLT: { SDOperand AD = SDOperand(CurDAG->getTargetNode(PPC::ADDI, MVT::i32, Op, getI32Imm(1)), 0); SDOperand AN = SDOperand(CurDAG->getTargetNode(PPC::AND, MVT::i32, AD, Op), 0); - return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, AN, getI32Imm(1), - getI32Imm(31), getI32Imm(31)).Val; + SDOperand Ops[] = { AN, getI32Imm(1), getI32Imm(31), getI32Imm(31) }; + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); } - case ISD::SETGT: - Op = SDOperand(CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, Op, - getI32Imm(1), getI32Imm(31), - getI32Imm(31)), 0); + case ISD::SETGT: { + SDOperand Ops[] = { Op, getI32Imm(1), getI32Imm(31), getI32Imm(31) }; + Op = SDOperand(CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, Ops, 4), 0); return CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Op, - getI32Imm(1)).Val; + getI32Imm(1)); + } } } } @@ -886,36 +744,32 @@ SDNode *PPCDAGToDAGISel::SelectSETCC(SDOperand Op) { else IntCR = SDOperand(CurDAG->getTargetNode(PPC::MFCR, MVT::i32, CCReg), 0); + SDOperand Ops[] = { IntCR, getI32Imm((32-(3-Idx)) & 31), + getI32Imm(31), getI32Imm(31) }; if (!Inv) { - return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, IntCR, - getI32Imm((32-(3-Idx)) & 31), - getI32Imm(31), getI32Imm(31)).Val; + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); } else { SDOperand Tmp = - SDOperand(CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, IntCR, - getI32Imm((32-(3-Idx)) & 31), - getI32Imm(31),getI32Imm(31)), 0); - return CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Tmp, getI32Imm(1)).Val; + SDOperand(CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, Ops, 4), 0); + return CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Tmp, getI32Imm(1)); } } // Select - Convert the specified operand from a target-independent to a // target-specific node if it hasn't already been changed. -SDNode *PPCDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) { +SDNode *PPCDAGToDAGISel::Select(SDOperand Op) { SDNode *N = Op.Val; if (N->getOpcode() >= ISD::BUILTIN_OP_END && - N->getOpcode() < PPCISD::FIRST_NUMBER) { - Result = Op; + N->getOpcode() < PPCISD::FIRST_NUMBER) return NULL; // Already selected. - } switch (N->getOpcode()) { default: break; case ISD::SETCC: return SelectSETCC(Op); case PPCISD::GlobalBaseReg: - return getGlobalBaseReg().Val; + return getGlobalBaseReg(); case ISD::FrameIndex: { int FI = cast(N)->getIndex(); @@ -923,7 +777,7 @@ SDNode *PPCDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) { unsigned Opc = Op.getValueType() == MVT::i32 ? PPC::ADDI : PPC::ADDI8; if (N->hasOneUse()) return CurDAG->SelectNodeTo(N, Opc, Op.getValueType(), TFI, - getSmallIPtrImm(0)).Val; + getSmallIPtrImm(0)); return CurDAG->getTargetNode(Opc, Op.getValueType(), TFI, getSmallIPtrImm(0)); } @@ -954,7 +808,7 @@ SDNode *PPCDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) { CurDAG->getTargetNode(PPC::SRAWI, MVT::i32, MVT::Flag, N0, getI32Imm(Log2_32(Imm))); return CurDAG->SelectNodeTo(N, PPC::ADDZE, MVT::i32, - SDOperand(Op, 0), SDOperand(Op, 1)).Val; + SDOperand(Op, 0), SDOperand(Op, 1)); } else if ((signed)Imm < 0 && isPowerOf2_32(-Imm)) { SDNode *Op = CurDAG->getTargetNode(PPC::SRAWI, MVT::i32, MVT::Flag, @@ -963,38 +817,95 @@ SDNode *PPCDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) { SDOperand(CurDAG->getTargetNode(PPC::ADDZE, MVT::i32, SDOperand(Op, 0), SDOperand(Op, 1)), 0); - return CurDAG->SelectNodeTo(N, PPC::NEG, MVT::i32, PT).Val; + return CurDAG->SelectNodeTo(N, PPC::NEG, MVT::i32, PT); } } // Other cases are autogenerated. break; } + + case ISD::LOAD: { + // Handle preincrement loads. + LoadSDNode *LD = cast(Op); + MVT::ValueType LoadedVT = LD->getLoadedVT(); + + // Normal loads are handled by code generated from the .td file. + if (LD->getAddressingMode() != ISD::PRE_INC) + break; + + SDOperand Offset = LD->getOffset(); + if (isa(Offset) || + Offset.getOpcode() == ISD::TargetGlobalAddress) { + + unsigned Opcode; + bool isSExt = LD->getExtensionType() == ISD::SEXTLOAD; + if (LD->getValueType(0) != MVT::i64) { + // Handle PPC32 integer and normal FP loads. + assert(!isSExt || LoadedVT == MVT::i16 && "Invalid sext update load"); + switch (LoadedVT) { + default: assert(0 && "Invalid PPC load type!"); + case MVT::f64: Opcode = PPC::LFDU; break; + case MVT::f32: Opcode = PPC::LFSU; break; + case MVT::i32: Opcode = PPC::LWZU; break; + case MVT::i16: Opcode = isSExt ? PPC::LHAU : PPC::LHZU; break; + case MVT::i1: + case MVT::i8: Opcode = PPC::LBZU; break; + } + } else { + assert(LD->getValueType(0) == MVT::i64 && "Unknown load result type!"); + assert(!isSExt || LoadedVT == MVT::i16 && "Invalid sext update load"); + switch (LoadedVT) { + default: assert(0 && "Invalid PPC load type!"); + case MVT::i64: Opcode = PPC::LDU; break; + case MVT::i32: Opcode = PPC::LWZU8; break; + case MVT::i16: Opcode = isSExt ? PPC::LHAU8 : PPC::LHZU8; break; + case MVT::i1: + case MVT::i8: Opcode = PPC::LBZU8; break; + } + } + + SDOperand Chain = LD->getChain(); + SDOperand Base = LD->getBasePtr(); + AddToISelQueue(Chain); + AddToISelQueue(Base); + AddToISelQueue(Offset); + SDOperand Ops[] = { Offset, Base, Chain }; + // FIXME: PPC64 + return CurDAG->getTargetNode(Opcode, MVT::i32, MVT::i32, + MVT::Other, Ops, 3); + } else { + assert(0 && "R+R preindex loads not supported yet!"); + } + } + case ISD::AND: { - unsigned Imm, Imm2; + unsigned Imm, Imm2, SH, MB, ME; + // If this is an and of a value rotated between 0 and 31 bits and then and'd // with a mask, emit rlwinm if (isInt32Immediate(N->getOperand(1), Imm) && - (isShiftedMask_32(Imm) || isShiftedMask_32(~Imm))) { - SDOperand Val; - unsigned SH, MB, ME; - if (isRotateAndMask(N->getOperand(0).Val, Imm, false, SH, MB, ME)) { - Val = N->getOperand(0).getOperand(0); - AddToISelQueue(Val); - } else if (Imm == 0) { - // AND X, 0 -> 0, not "rlwinm 32". - AddToISelQueue(N->getOperand(1)); - ReplaceUses(SDOperand(N, 0), N->getOperand(1)); - return NULL; - } else { - Val = N->getOperand(0); - AddToISelQueue(Val); - isRunOfOnes(Imm, MB, ME); - SH = 0; - } - return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Val, - getI32Imm(SH), getI32Imm(MB), - getI32Imm(ME)).Val; + isRotateAndMask(N->getOperand(0).Val, Imm, false, SH, MB, ME)) { + SDOperand Val = N->getOperand(0).getOperand(0); + AddToISelQueue(Val); + SDOperand Ops[] = { Val, getI32Imm(SH), getI32Imm(MB), getI32Imm(ME) }; + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); + } + // If this is just a masked value where the input is not handled above, and + // is not a rotate-left (handled by a pattern in the .td file), emit rlwinm + if (isInt32Immediate(N->getOperand(1), Imm) && + isRunOfOnes(Imm, MB, ME) && + N->getOperand(0).getOpcode() != ISD::ROTL) { + SDOperand Val = N->getOperand(0); + AddToISelQueue(Val); + SDOperand Ops[] = { Val, getI32Imm(0), getI32Imm(MB), getI32Imm(ME) }; + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); + } + // AND X, 0 -> 0, not "rlwinm 32". + if (isInt32Immediate(N->getOperand(1), Imm) && (Imm == 0)) { + AddToISelQueue(N->getOperand(1)); + ReplaceUses(SDOperand(N, 0), N->getOperand(1)); + return NULL; } // ISD::OR doesn't get all the bitfield insertion fun. // (and (or x, c1), c2) where isRunOfOnes(~(c1^c2)) is a bitfield insert @@ -1006,10 +917,10 @@ SDNode *PPCDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) { if (isRunOfOnes(Imm, MB, ME)) { AddToISelQueue(N->getOperand(0).getOperand(0)); AddToISelQueue(N->getOperand(0).getOperand(1)); - return CurDAG->getTargetNode(PPC::RLWIMI, MVT::i32, - N->getOperand(0).getOperand(0), - N->getOperand(0).getOperand(1), - getI32Imm(0), getI32Imm(MB),getI32Imm(ME)); + SDOperand Ops[] = { N->getOperand(0).getOperand(0), + N->getOperand(0).getOperand(1), + getI32Imm(0), getI32Imm(MB),getI32Imm(ME) }; + return CurDAG->getTargetNode(PPC::RLWIMI, MVT::i32, Ops, 5); } } @@ -1028,10 +939,9 @@ SDNode *PPCDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) { if (isOpcWithIntImmediate(N->getOperand(0).Val, ISD::AND, Imm) && isRotateAndMask(N, Imm, true, SH, MB, ME)) { AddToISelQueue(N->getOperand(0).getOperand(0)); - return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, - N->getOperand(0).getOperand(0), - getI32Imm(SH), getI32Imm(MB), - getI32Imm(ME)).Val; + SDOperand Ops[] = { N->getOperand(0).getOperand(0), + getI32Imm(SH), getI32Imm(MB), getI32Imm(ME) }; + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); } // Other cases are autogenerated. @@ -1042,10 +952,9 @@ SDNode *PPCDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) { if (isOpcWithIntImmediate(N->getOperand(0).Val, ISD::AND, Imm) && isRotateAndMask(N, Imm, true, SH, MB, ME)) { AddToISelQueue(N->getOperand(0).getOperand(0)); - return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, - N->getOperand(0).getOperand(0), - getI32Imm(SH), getI32Imm(MB), - getI32Imm(ME)).Val; + SDOperand Ops[] = { N->getOperand(0).getOperand(0), + getI32Imm(SH), getI32Imm(MB), getI32Imm(ME) }; + return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); } // Other cases are autogenerated. @@ -1068,13 +977,12 @@ SDNode *PPCDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) { N->getOperand(0), getI32Imm(~0U)); return CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, SDOperand(Tmp, 0), N->getOperand(0), - SDOperand(Tmp, 1)).Val; + SDOperand(Tmp, 1)); } SDOperand CCReg = SelectCC(N->getOperand(0), N->getOperand(1), CC); - unsigned BROpc = getBCCForSetCC(CC); + unsigned BROpc = getPredicateForSetCC(CC); - bool isFP = MVT::isFloatingPoint(N->getValueType(0)); unsigned SelectCCOp; if (N->getValueType(0) == MVT::i32) SelectCCOp = PPC::SELECT_CC_I4; @@ -1089,17 +997,27 @@ SDNode *PPCDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) { AddToISelQueue(N->getOperand(2)); AddToISelQueue(N->getOperand(3)); - return CurDAG->SelectNodeTo(N, SelectCCOp, N->getValueType(0), CCReg, - N->getOperand(2), N->getOperand(3), - getI32Imm(BROpc)).Val; + SDOperand Ops[] = { CCReg, N->getOperand(2), N->getOperand(3), + getI32Imm(BROpc) }; + return CurDAG->SelectNodeTo(N, SelectCCOp, N->getValueType(0), Ops, 4); + } + case PPCISD::COND_BRANCH: { + AddToISelQueue(N->getOperand(0)); // Op #0 is the Chain. + // Op #1 is the PPC::PRED_* number. + // Op #2 is the CR# + // Op #3 is the Dest MBB + AddToISelQueue(N->getOperand(4)); // Op #4 is the Flag. + SDOperand Ops[] = { N->getOperand(1), N->getOperand(2), N->getOperand(3), + N->getOperand(0), N->getOperand(4) }; + return CurDAG->SelectNodeTo(N, PPC::BCC, MVT::Other, Ops, 5); } case ISD::BR_CC: { AddToISelQueue(N->getOperand(0)); ISD::CondCode CC = cast(N->getOperand(1))->get(); SDOperand CondCode = SelectCC(N->getOperand(2), N->getOperand(3), CC); - return CurDAG->SelectNodeTo(N, PPC::COND_BRANCH, MVT::Other, - CondCode, getI32Imm(getBCCForSetCC(CC)), - N->getOperand(4), N->getOperand(0)).Val; + SDOperand Ops[] = { getI32Imm(getPredicateForSetCC(CC)), CondCode, + N->getOperand(4), N->getOperand(0) }; + return CurDAG->SelectNodeTo(N, PPC::BCC, MVT::Other, Ops, 4); } case ISD::BRIND: { // FIXME: Should custom lower this. @@ -1110,153 +1028,14 @@ SDNode *PPCDAGToDAGISel::Select(SDOperand &Result, SDOperand Op) { unsigned Opc = Target.getValueType() == MVT::i32 ? PPC::MTCTR : PPC::MTCTR8; Chain = SDOperand(CurDAG->getTargetNode(Opc, MVT::Other, Target, Chain), 0); - return CurDAG->SelectNodeTo(N, PPC::BCTR, MVT::Other, Chain).Val; + return CurDAG->SelectNodeTo(N, PPC::BCTR, MVT::Other, Chain); } - // FIXME: These are manually selected because tblgen isn't handling varargs - // nodes correctly. - case PPCISD::BCTRL: return MySelect_PPCbctrl(Op); - case PPCISD::CALL: return MySelect_PPCcall(Op); } - return SelectCode(Result, Op); + return SelectCode(Op); } -// FIXME: This is manually selected because tblgen isn't handling varargs nodes -// correctly. -SDNode *PPCDAGToDAGISel::MySelect_PPCbctrl(SDOperand N) { - SDOperand Chain(0, 0); - - bool hasFlag = - N.getOperand(N.getNumOperands()-1).getValueType() == MVT::Flag; - - SmallVector Ops; - // Push varargs arguments, including optional flag. - for (unsigned i = 1, e = N.getNumOperands()-hasFlag; i != e; ++i) { - Chain = N.getOperand(i); - AddToISelQueue(Chain); - Ops.push_back(Chain); - } - - Chain = N.getOperand(0); - AddToISelQueue(Chain); - Ops.push_back(Chain); - - if (hasFlag) { - Chain = N.getOperand(N.getNumOperands()-1); - AddToISelQueue(Chain); - Ops.push_back(Chain); - } - - return CurDAG->getTargetNode(PPC::BCTRL, MVT::Other, MVT::Flag, - &Ops[0], Ops.size()); -} - -// FIXME: This is manually selected because tblgen isn't handling varargs nodes -// correctly. -SDNode *PPCDAGToDAGISel::MySelect_PPCcall(SDOperand N) { - SDOperand Chain(0, 0); - SDOperand N1(0, 0); - SDOperand Tmp0(0, 0); - SDNode *ResNode; - Chain = N.getOperand(0); - N1 = N.getOperand(1); - - // Pattern: (PPCcall:void (imm:i32):$func) - // Emits: (BLA:void (imm:i32):$func) - // Pattern complexity = 4 cost = 1 - if (N1.getOpcode() == ISD::Constant) { - unsigned Tmp0C = (unsigned)cast(N1)->getValue(); - - SmallVector Ops; - Ops.push_back(CurDAG->getTargetConstant(Tmp0C, MVT::i32)); - - bool hasFlag = - N.getOperand(N.getNumOperands()-1).getValueType() == MVT::Flag; - - // Push varargs arguments, not including optional flag. - for (unsigned i = 2, e = N.getNumOperands()-hasFlag; i != e; ++i) { - Chain = N.getOperand(i); - AddToISelQueue(Chain); - Ops.push_back(Chain); - } - Chain = N.getOperand(0); - AddToISelQueue(Chain); - Ops.push_back(Chain); - if (hasFlag) { - Chain = N.getOperand(N.getNumOperands()-1); - AddToISelQueue(Chain); - Ops.push_back(Chain); - } - return CurDAG->getTargetNode(PPC::BLA, MVT::Other, MVT::Flag, - &Ops[0], Ops.size()); - } - - // Pattern: (PPCcall:void (tglobaladdr:i32):$dst) - // Emits: (BL:void (tglobaladdr:i32):$dst) - // Pattern complexity = 4 cost = 1 - if (N1.getOpcode() == ISD::TargetGlobalAddress) { - SmallVector Ops; - Ops.push_back(N1); - - bool hasFlag = - N.getOperand(N.getNumOperands()-1).getValueType() == MVT::Flag; - - // Push varargs arguments, not including optional flag. - for (unsigned i = 2, e = N.getNumOperands()-hasFlag; i != e; ++i) { - Chain = N.getOperand(i); - AddToISelQueue(Chain); - Ops.push_back(Chain); - } - Chain = N.getOperand(0); - AddToISelQueue(Chain); - Ops.push_back(Chain); - if (hasFlag) { - Chain = N.getOperand(N.getNumOperands()-1); - AddToISelQueue(Chain); - Ops.push_back(Chain); - } - - return CurDAG->getTargetNode(PPC::BL, MVT::Other, MVT::Flag, - &Ops[0], Ops.size()); - } - - // Pattern: (PPCcall:void (texternalsym:i32):$dst) - // Emits: (BL:void (texternalsym:i32):$dst) - // Pattern complexity = 4 cost = 1 - if (N1.getOpcode() == ISD::TargetExternalSymbol) { - std::vector Ops; - Ops.push_back(N1); - - bool hasFlag = - N.getOperand(N.getNumOperands()-1).getValueType() == MVT::Flag; - - // Push varargs arguments, not including optional flag. - for (unsigned i = 2, e = N.getNumOperands()-hasFlag; i != e; ++i) { - Chain = N.getOperand(i); - AddToISelQueue(Chain); - Ops.push_back(Chain); - } - Chain = N.getOperand(0); - AddToISelQueue(Chain); - Ops.push_back(Chain); - if (hasFlag) { - Chain = N.getOperand(N.getNumOperands()-1); - AddToISelQueue(Chain); - Ops.push_back(Chain); - } - - return CurDAG->getTargetNode(PPC::BL, MVT::Other, MVT::Flag, - &Ops[0], Ops.size()); - } - std::cerr << "Cannot yet select: "; - N.Val->dump(CurDAG); - std::cerr << '\n'; - abort(); - - return NULL; -} - /// createPPCISelDag - This pass converts a legalized DAG into a /// PowerPC-specific DAG, ready for instruction scheduling.