From 6f3b9546629e5c0d1eabbf94aabff74a04df33e9 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 14 Oct 2005 23:59:06 +0000 Subject: Rename PPC32*.h to PPC*.h This completes the grand PPC file renaming llvm-svn: 23745 --- llvm/lib/Target/PowerPC/PPC32CodeEmitter.cpp | 264 ---- llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp | 1890 ------------------------- llvm/lib/Target/PowerPC/PPC32InstrInfo.cpp | 111 -- llvm/lib/Target/PowerPC/PPC32InstrInfo.h | 61 - llvm/lib/Target/PowerPC/PPC32JITInfo.cpp | 243 ---- llvm/lib/Target/PowerPC/PPC32RegisterInfo.cpp | 346 ----- llvm/lib/Target/PowerPC/PPC32RegisterInfo.h | 64 - llvm/lib/Target/PowerPC/PPC32Relocations.h | 58 - llvm/lib/Target/PowerPC/PPC32TargetMachine.h | 74 - llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 2 +- llvm/lib/Target/PowerPC/PPCBranchSelector.cpp | 2 +- llvm/lib/Target/PowerPC/PPCCodeEmitter.cpp | 264 ++++ llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 4 +- llvm/lib/Target/PowerPC/PPCISelLowering.cpp | 4 +- llvm/lib/Target/PowerPC/PPCISelPattern.cpp | 1889 ++++++++++++++++++++++++ llvm/lib/Target/PowerPC/PPCInstrInfo.cpp | 111 ++ llvm/lib/Target/PowerPC/PPCInstrInfo.h | 61 + llvm/lib/Target/PowerPC/PPCJITInfo.cpp | 243 ++++ llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp | 346 +++++ llvm/lib/Target/PowerPC/PPCRegisterInfo.h | 64 + llvm/lib/Target/PowerPC/PPCRelocations.h | 58 + llvm/lib/Target/PowerPC/PPCTargetMachine.cpp | 2 +- llvm/lib/Target/PowerPC/PPCTargetMachine.h | 74 + 23 files changed, 3117 insertions(+), 3118 deletions(-) delete mode 100644 llvm/lib/Target/PowerPC/PPC32CodeEmitter.cpp delete mode 100644 llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp delete mode 100644 llvm/lib/Target/PowerPC/PPC32InstrInfo.cpp delete mode 100644 llvm/lib/Target/PowerPC/PPC32InstrInfo.h delete mode 100644 llvm/lib/Target/PowerPC/PPC32JITInfo.cpp delete mode 100644 llvm/lib/Target/PowerPC/PPC32RegisterInfo.cpp delete mode 100644 llvm/lib/Target/PowerPC/PPC32RegisterInfo.h delete mode 100644 llvm/lib/Target/PowerPC/PPC32Relocations.h delete mode 100644 llvm/lib/Target/PowerPC/PPC32TargetMachine.h create mode 100644 llvm/lib/Target/PowerPC/PPCCodeEmitter.cpp create mode 100644 llvm/lib/Target/PowerPC/PPCISelPattern.cpp create mode 100644 llvm/lib/Target/PowerPC/PPCInstrInfo.cpp create mode 100644 llvm/lib/Target/PowerPC/PPCInstrInfo.h create mode 100644 llvm/lib/Target/PowerPC/PPCJITInfo.cpp create mode 100644 llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp create mode 100644 llvm/lib/Target/PowerPC/PPCRegisterInfo.h create mode 100644 llvm/lib/Target/PowerPC/PPCRelocations.h create mode 100644 llvm/lib/Target/PowerPC/PPCTargetMachine.h (limited to 'llvm/lib/Target/PowerPC') diff --git a/llvm/lib/Target/PowerPC/PPC32CodeEmitter.cpp b/llvm/lib/Target/PowerPC/PPC32CodeEmitter.cpp deleted file mode 100644 index ad7ff492f3f..00000000000 --- a/llvm/lib/Target/PowerPC/PPC32CodeEmitter.cpp +++ /dev/null @@ -1,264 +0,0 @@ -//===-- PPCCodeEmitter.cpp - JIT Code Emitter for PowerPC32 -----*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the PowerPC 32-bit CodeEmitter and associated machinery to -// JIT-compile bytecode to native PowerPC. -// -//===----------------------------------------------------------------------===// - -#include "PPC32TargetMachine.h" -#include "PPC32Relocations.h" -#include "PPC.h" -#include "llvm/Module.h" -#include "llvm/CodeGen/MachineCodeEmitter.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/Support/Debug.h" -using namespace llvm; - -namespace { - class PPCCodeEmitter : public MachineFunctionPass { - TargetMachine &TM; - MachineCodeEmitter &MCE; - - // Tracks which instruction references which BasicBlock - std::vector > BBRefs; - // Tracks where each BasicBlock starts - std::map BBLocations; - - /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr - /// - int getMachineOpValue(MachineInstr &MI, MachineOperand &MO); - - public: - PPCCodeEmitter(TargetMachine &T, MachineCodeEmitter &M) - : TM(T), MCE(M) {} - - const char *getPassName() const { return "PowerPC Machine Code Emitter"; } - - /// runOnMachineFunction - emits the given MachineFunction to memory - /// - bool runOnMachineFunction(MachineFunction &MF); - - /// emitBasicBlock - emits the given MachineBasicBlock to memory - /// - void emitBasicBlock(MachineBasicBlock &MBB); - - /// emitWord - write a 32-bit word to memory at the current PC - /// - void emitWord(unsigned w) { MCE.emitWord(w); } - - /// getValueBit - return the particular bit of Val - /// - unsigned getValueBit(int64_t Val, unsigned bit) { return (Val >> bit) & 1; } - - /// getBinaryCodeForInstr - This function, generated by the - /// CodeEmitterGenerator using TableGen, produces the binary encoding for - /// machine instructions. - /// - unsigned getBinaryCodeForInstr(MachineInstr &MI); - }; -} - -/// addPassesToEmitMachineCode - Add passes to the specified pass manager to get -/// machine code emitted. This uses a MachineCodeEmitter object to handle -/// actually outputting the machine code and resolving things like the address -/// of functions. This method should returns true if machine code emission is -/// not supported. -/// -bool PPC32TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM, - MachineCodeEmitter &MCE) { - // Machine code emitter pass for PowerPC - PM.add(new PPCCodeEmitter(*this, MCE)); - // Delete machine code for this function after emitting it - PM.add(createMachineCodeDeleter()); - return false; -} - -bool PPCCodeEmitter::runOnMachineFunction(MachineFunction &MF) { - MCE.startFunction(MF); - MCE.emitConstantPool(MF.getConstantPool()); - for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB) - emitBasicBlock(*BB); - MCE.finishFunction(MF); - - // Resolve branches to BasicBlocks for the entire function - for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) { - intptr_t Location = BBLocations[BBRefs[i].first]; - unsigned *Ref = BBRefs[i].second; - DEBUG(std::cerr << "Fixup @ " << (void*)Ref << " to " << (void*)Location - << "\n"); - unsigned Instr = *Ref; - intptr_t BranchTargetDisp = (Location - (intptr_t)Ref) >> 2; - - switch (Instr >> 26) { - default: assert(0 && "Unknown branch user!"); - case 18: // This is B or BL - *Ref |= (BranchTargetDisp & ((1 << 24)-1)) << 2; - break; - case 16: // This is BLT,BLE,BEQ,BGE,BGT,BNE, or other bcx instruction - *Ref |= (BranchTargetDisp & ((1 << 14)-1)) << 2; - break; - } - } - BBRefs.clear(); - BBLocations.clear(); - - return false; -} - -void PPCCodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) { - assert(!PICEnabled && "CodeEmitter does not support PIC!"); - BBLocations[&MBB] = MCE.getCurrentPCValue(); - for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I){ - MachineInstr &MI = *I; - unsigned Opcode = MI.getOpcode(); - switch (MI.getOpcode()) { - default: - emitWord(getBinaryCodeForInstr(*I)); - break; - case PPC::IMPLICIT_DEF_GPR: - case PPC::IMPLICIT_DEF_F8: - case PPC::IMPLICIT_DEF_F4: - break; // pseudo opcode, no side effects - case PPC::MovePCtoLR: - assert(0 && "CodeEmitter does not support MovePCtoLR instruction"); - break; - } - } -} - -static unsigned enumRegToMachineReg(unsigned enumReg) { - switch (enumReg) { - case PPC::R0 : case PPC::F0 : case PPC::CR0: return 0; - case PPC::R1 : case PPC::F1 : case PPC::CR1: return 1; - case PPC::R2 : case PPC::F2 : case PPC::CR2: return 2; - case PPC::R3 : case PPC::F3 : case PPC::CR3: return 3; - case PPC::R4 : case PPC::F4 : case PPC::CR4: return 4; - case PPC::R5 : case PPC::F5 : case PPC::CR5: return 5; - case PPC::R6 : case PPC::F6 : case PPC::CR6: return 6; - case PPC::R7 : case PPC::F7 : case PPC::CR7: return 7; - case PPC::R8 : case PPC::F8 : return 8; - case PPC::R9 : case PPC::F9 : return 9; - case PPC::R10: case PPC::F10: return 10; - case PPC::R11: case PPC::F11: return 11; - case PPC::R12: case PPC::F12: return 12; - case PPC::R13: case PPC::F13: return 13; - case PPC::R14: case PPC::F14: return 14; - case PPC::R15: case PPC::F15: return 15; - case PPC::R16: case PPC::F16: return 16; - case PPC::R17: case PPC::F17: return 17; - case PPC::R18: case PPC::F18: return 18; - case PPC::R19: case PPC::F19: return 19; - case PPC::R20: case PPC::F20: return 20; - case PPC::R21: case PPC::F21: return 21; - case PPC::R22: case PPC::F22: return 22; - case PPC::R23: case PPC::F23: return 23; - case PPC::R24: case PPC::F24: return 24; - case PPC::R25: case PPC::F25: return 25; - case PPC::R26: case PPC::F26: return 26; - case PPC::R27: case PPC::F27: return 27; - case PPC::R28: case PPC::F28: return 28; - case PPC::R29: case PPC::F29: return 29; - case PPC::R30: case PPC::F30: return 30; - case PPC::R31: case PPC::F31: return 31; - default: - std::cerr << "Unhandled reg in enumRegToRealReg!\n"; - abort(); - } -} - -int PPCCodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) { - - int rv = 0; // Return value; defaults to 0 for unhandled cases - // or things that get fixed up later by the JIT. - if (MO.isRegister()) { - rv = enumRegToMachineReg(MO.getReg()); - - // Special encoding for MTCRF and MFOCRF, which uses a bit mask for the - // register, not the register number directly. - if ((MI.getOpcode() == PPC::MTCRF || MI.getOpcode() == PPC::MFOCRF) && - (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7)) { - rv = 0x80 >> rv; - } - } else if (MO.isImmediate()) { - rv = MO.getImmedValue(); - } else if (MO.isGlobalAddress() || MO.isExternalSymbol()) { - bool isExternal = MO.isExternalSymbol() || - MO.getGlobal()->hasWeakLinkage() || - MO.getGlobal()->isExternal(); - unsigned Reloc = 0; - if (MI.getOpcode() == PPC::CALLpcrel) - Reloc = PPC::reloc_pcrel_bx; - else { - switch (MI.getOpcode()) { - default: MI.dump(); assert(0 && "Unknown instruction for relocation!"); - case PPC::LIS: - if (isExternal) - Reloc = PPC::reloc_absolute_ptr_high; // Pointer to stub - else - Reloc = PPC::reloc_absolute_high; // Pointer to symbol - break; - case PPC::LA: - assert(!isExternal && "Something in the ISEL changed\n"); - Reloc = PPC::reloc_absolute_low; - break; - case PPC::LBZ: - case PPC::LHA: - case PPC::LHZ: - case PPC::LWZ: - case PPC::LFS: - case PPC::LFD: - case PPC::STB: - case PPC::STH: - case PPC::STW: - case PPC::STFS: - case PPC::STFD: - if (isExternal) - Reloc = PPC::reloc_absolute_ptr_low; - else - Reloc = PPC::reloc_absolute_low; - break; - } - } - if (MO.isGlobalAddress()) - MCE.addRelocation(MachineRelocation(MCE.getCurrentPCOffset(), - Reloc, MO.getGlobal(), 0)); - else - MCE.addRelocation(MachineRelocation(MCE.getCurrentPCOffset(), - Reloc, MO.getSymbolName(), 0)); - } else if (MO.isMachineBasicBlock()) { - unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue(); - BBRefs.push_back(std::make_pair(MO.getMachineBasicBlock(), CurrPC)); - } else if (MO.isConstantPoolIndex()) { - unsigned index = MO.getConstantPoolIndex(); - unsigned Opcode = MI.getOpcode(); - rv = MCE.getConstantPoolEntryAddress(index); - if (Opcode == PPC::LIS) { - // lis wants hi16(addr) - if ((short)rv < 0) rv += 1 << 16; - rv >>= 16; - } else if (Opcode == PPC::LWZ || Opcode == PPC::LA || - Opcode == PPC::LFS || Opcode == PPC::LFD) { - // These load opcodes want lo16(addr) - rv &= 0xffff; - } else { - assert(0 && "Unknown constant pool using instruction!"); - } - } else { - std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n"; - abort(); - } - - return rv; -} - -#include "PPCGenCodeEmitter.inc" - diff --git a/llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp b/llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp deleted file mode 100644 index a1f6b1c3c0a..00000000000 --- a/llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp +++ /dev/null @@ -1,1890 +0,0 @@ -//===-- PPC32ISelPattern.cpp - A pattern matching inst selector for PPC32 -===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by Nate Begeman and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a pattern matching instruction selector for 32 bit PowerPC. -// Magic number generation for integer divide from the PowerPC Compiler Writer's -// Guide, section 3.2.3.5 -// -//===----------------------------------------------------------------------===// - -#include "PPC.h" -#include "PPCInstrBuilder.h" -#include "PPC32InstrInfo.h" -#include "PPC32TargetMachine.h" -#include "PPC32ISelLowering.h" -#include "llvm/Constants.h" -#include "llvm/Function.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/CodeGen/SelectionDAGISel.h" -#include "llvm/CodeGen/SSARegMap.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/ADT/Statistic.h" -#include -#include -using namespace llvm; - -namespace { -Statistic<> Recorded("ppc-codegen", "Number of recording ops emitted"); -Statistic<> FusedFP ("ppc-codegen", "Number of fused fp operations"); -Statistic<> FrameOff("ppc-codegen", "Number of frame idx offsets collapsed"); - -//===--------------------------------------------------------------------===// -// ISel - PPC32 specific code to select PPC32 machine instructions for -// SelectionDAG operations. -//===--------------------------------------------------------------------===// - -class ISel : public SelectionDAGISel { - PPC32TargetLowering PPC32Lowering; - SelectionDAG *ISelDAG; // Hack to support us having a dag->dag transform - // for sdiv and udiv until it is put into the future - // dag combiner. - - /// ExprMap - As shared expressions are codegen'd, we keep track of which - /// vreg the value is produced in, so we only emit one copy of each compiled - /// tree. - std::map ExprMap; - - unsigned GlobalBaseReg; - bool GlobalBaseInitialized; - bool RecordSuccess; -public: - ISel(TargetMachine &TM) : SelectionDAGISel(PPC32Lowering), PPC32Lowering(TM), - ISelDAG(0) {} - - /// runOnFunction - Override this function in order to reset our per-function - /// variables. - virtual bool runOnFunction(Function &Fn) { - // Make sure we re-emit a set of the global base reg if necessary - GlobalBaseInitialized = false; - return SelectionDAGISel::runOnFunction(Fn); - } - - /// InstructionSelectBasicBlock - This callback is invoked by - /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. - virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) { - DEBUG(BB->dump()); - // Codegen the basic block. - ISelDAG = &DAG; - Select(DAG.getRoot()); - - // Clear state used for selection. - ExprMap.clear(); - ISelDAG = 0; - } - - // convenience functions for virtual register creation - inline unsigned MakeIntReg() { - return RegMap->createVirtualRegister(PPC32::GPRCRegisterClass); - } - - // dag -> dag expanders for integer divide by constant - SDOperand BuildSDIVSequence(SDOperand N); - SDOperand BuildUDIVSequence(SDOperand N); - - unsigned getGlobalBaseReg(); - void MoveCRtoGPR(unsigned CCReg, ISD::CondCode CC, unsigned Result); - bool SelectBitfieldInsert(SDOperand OR, unsigned Result); - unsigned FoldIfWideZeroExtend(SDOperand N); - unsigned SelectCC(SDOperand LHS, SDOperand RHS, ISD::CondCode CC); - bool SelectIntImmediateExpr(SDOperand N, unsigned Result, - unsigned OCHi, unsigned OCLo, - bool IsArithmetic = false, bool Negate = false); - unsigned SelectExpr(SDOperand N, bool Recording=false); - void Select(SDOperand N); - - unsigned SelectAddr(SDOperand N, unsigned& Reg, int& offset); - void SelectBranchCC(SDOperand N); - - virtual const char *getPassName() const { - return "PowerPC Pattern Instruction Selection"; - } -}; - -// 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) { - if (isShiftedMask_32(Val)) { - // look for the first non-zero bit - MB = CountLeadingZeros_32(Val); - // look for the first zero bit after the run of ones - ME = CountLeadingZeros_32((Val - 1) ^ Val); - return true; - } else if (isShiftedMask_32(Val = ~Val)) { // invert mask - // effectively look for the first zero bit - ME = CountLeadingZeros_32(Val) - 1; - // effectively look for the first one bit after the run of zeros - MB = CountLeadingZeros_32((Val - 1) ^ Val) + 1; - return true; - } - // no run present - return false; -} - -// isRotateAndMask - Returns true if Mask and Shift can be folded in to a rotate -// and mask opcode and mask operation. -static bool isRotateAndMask(unsigned Opcode, unsigned Shift, unsigned Mask, - bool IsShiftMask, - unsigned &SH, unsigned &MB, unsigned &ME) { - if (Shift > 31) return false; - unsigned Indeterminant = ~0; // bit mask marking indeterminant results - - if (Opcode == ISD::SHL) { // shift left - // apply shift to mask if it comes first - if (IsShiftMask) Mask = Mask << Shift; - // determine which bits are made indeterminant by shift - Indeterminant = ~(0xFFFFFFFFu << Shift); - } else if (Opcode == ISD::SRA || Opcode == ISD::SRL) { // shift rights - // apply shift to mask if it comes first - if (IsShiftMask) Mask = Mask >> Shift; - // determine which bits are made indeterminant by shift - Indeterminant = ~(0xFFFFFFFFu >> Shift); - // adjust for the left rotate - Shift = 32 - Shift; - } - - // if the mask doesn't intersect any Indeterminant bits - if (Mask && !(Mask & Indeterminant)) { - SH = Shift; - // make sure the mask is still a mask (wrap arounds may not be) - return isRunOfOnes(Mask, MB, ME); - } - - // can't do it - return false; -} - -// isIntImmediate - This method tests to see if a constant operand. -// If so Imm will receive the 32 bit value. -static bool isIntImmediate(SDOperand N, unsigned& Imm) { - // test for constant - if (ConstantSDNode *CN = dyn_cast(N)) { - // retrieve value - Imm = (unsigned)CN->getValue(); - // passes muster - return true; - } - // not a constant - return false; -} - -// isOpcWithIntImmediate - This method tests to see if the node is a specific -// opcode and that it has a immediate integer right operand. -// If so Imm will receive the 32 bit value. -static bool isOpcWithIntImmediate(SDOperand N, unsigned Opc, unsigned& Imm) { - return N.getOpcode() == Opc && isIntImmediate(N.getOperand(1), Imm); -} - -// isOprShiftImm - Returns true if the specified operand is a shift opcode with -// a immediate shift count less than 32. -static bool isOprShiftImm(SDOperand N, unsigned& Opc, unsigned& SH) { - Opc = N.getOpcode(); - return (Opc == ISD::SHL || Opc == ISD::SRL || Opc == ISD::SRA) && - isIntImmediate(N.getOperand(1), SH) && SH < 32; -} - -// isOprNot - Returns true if the specified operand is an xor with immediate -1. -static bool isOprNot(SDOperand N) { - unsigned Imm; - return isOpcWithIntImmediate(N, ISD::XOR, Imm) && (signed)Imm == -1; -} - -// Immediate constant composers. -// Lo16 - grabs the lo 16 bits from a 32 bit constant. -// Hi16 - grabs the hi 16 bits from a 32 bit constant. -// HA16 - computes the hi bits required if the lo bits are add/subtracted in -// arithmethically. -static unsigned Lo16(unsigned x) { return x & 0x0000FFFF; } -static unsigned Hi16(unsigned x) { return Lo16(x >> 16); } -static unsigned HA16(unsigned x) { return Hi16((signed)x - (signed short)x); } - -/// NodeHasRecordingVariant - If SelectExpr can always produce code for -/// NodeOpcode that also sets CR0 as a side effect, return true. Otherwise, -/// return false. -static bool NodeHasRecordingVariant(unsigned NodeOpcode) { - switch(NodeOpcode) { - default: return false; - case ISD::AND: - case ISD::OR: - return true; - } -} - -/// getBCCForSetCC - Returns the PowerPC condition branch mnemonic corresponding -/// to Condition. -static unsigned getBCCForSetCC(ISD::CondCode CC) { - switch (CC) { - default: assert(0 && "Unknown condition!"); abort(); - case ISD::SETEQ: return PPC::BEQ; - case ISD::SETNE: return PPC::BNE; - case ISD::SETULT: - case ISD::SETLT: return PPC::BLT; - case ISD::SETULE: - case ISD::SETLE: return PPC::BLE; - case ISD::SETUGT: - case ISD::SETGT: return PPC::BGT; - case ISD::SETUGE: - case ISD::SETGE: return PPC::BGE; - } - return 0; -} - -/// getCRIdxForSetCC - Return the index of the condition register field -/// associated with the SetCC condition, and whether or not the field is -/// treated as inverted. That is, lt = 0; ge = 0 inverted. -static unsigned getCRIdxForSetCC(ISD::CondCode CC, bool& Inv) { - switch (CC) { - default: assert(0 && "Unknown condition!"); abort(); - case ISD::SETULT: - case ISD::SETLT: Inv = false; return 0; - case ISD::SETUGE: - case ISD::SETGE: Inv = true; return 0; - case ISD::SETUGT: - case ISD::SETGT: Inv = false; return 1; - case ISD::SETULE: - case ISD::SETLE: Inv = true; return 1; - case ISD::SETEQ: Inv = false; return 2; - case ISD::SETNE: Inv = true; return 2; - } - return 0; -} - -/// IndexedOpForOp - Return the indexed variant for each of the PowerPC load -/// and store immediate instructions. -static unsigned IndexedOpForOp(unsigned Opcode) { - switch(Opcode) { - default: assert(0 && "Unknown opcode!"); abort(); - case PPC::LBZ: return PPC::LBZX; case PPC::STB: return PPC::STBX; - case PPC::LHZ: return PPC::LHZX; case PPC::STH: return PPC::STHX; - case PPC::LHA: return PPC::LHAX; case PPC::STW: return PPC::STWX; - case PPC::LWZ: return PPC::LWZX; case PPC::STFS: return PPC::STFSX; - case PPC::LFS: return PPC::LFSX; case PPC::STFD: return PPC::STFDX; - case PPC::LFD: return PPC::LFDX; - } - return 0; -} - -// Structure used to return the necessary information to codegen an SDIV as -// a multiply. -struct ms { - int m; // magic number - int s; // shift amount -}; - -struct mu { - unsigned int m; // magic number - int a; // add indicator - int s; // shift amount -}; - -/// magic - calculate the magic numbers required to codegen an integer sdiv as -/// a sequence of multiply and shifts. Requires that the divisor not be 0, 1, -/// or -1. -static struct ms magic(int d) { - int p; - unsigned int ad, anc, delta, q1, r1, q2, r2, t; - const unsigned int two31 = 0x80000000U; - struct ms mag; - - ad = abs(d); - t = two31 + ((unsigned int)d >> 31); - anc = t - 1 - t%ad; // absolute value of nc - p = 31; // initialize p - q1 = two31/anc; // initialize q1 = 2p/abs(nc) - r1 = two31 - q1*anc; // initialize r1 = rem(2p,abs(nc)) - q2 = two31/ad; // initialize q2 = 2p/abs(d) - r2 = two31 - q2*ad; // initialize r2 = rem(2p,abs(d)) - do { - p = p + 1; - q1 = 2*q1; // update q1 = 2p/abs(nc) - r1 = 2*r1; // update r1 = rem(2p/abs(nc)) - if (r1 >= anc) { // must be unsigned comparison - q1 = q1 + 1; - r1 = r1 - anc; - } - q2 = 2*q2; // update q2 = 2p/abs(d) - r2 = 2*r2; // update r2 = rem(2p/abs(d)) - if (r2 >= ad) { // must be unsigned comparison - q2 = q2 + 1; - r2 = r2 - ad; - } - delta = ad - r2; - } while (q1 < delta || (q1 == delta && r1 == 0)); - - mag.m = q2 + 1; - if (d < 0) mag.m = -mag.m; // resulting magic number - mag.s = p - 32; // resulting shift - return mag; -} - -/// magicu - calculate the magic numbers required to codegen an integer udiv as -/// a sequence of multiply, add and shifts. Requires that the divisor not be 0. -static struct mu magicu(unsigned d) -{ - int p; - unsigned int nc, delta, q1, r1, q2, r2; - struct mu magu; - magu.a = 0; // initialize "add" indicator - nc = - 1 - (-d)%d; - p = 31; // initialize p - q1 = 0x80000000/nc; // initialize q1 = 2p/nc - r1 = 0x80000000 - q1*nc; // initialize r1 = rem(2p,nc) - q2 = 0x7FFFFFFF/d; // initialize q2 = (2p-1)/d - r2 = 0x7FFFFFFF - q2*d; // initialize r2 = rem((2p-1),d) - do { - p = p + 1; - if (r1 >= nc - r1 ) { - q1 = 2*q1 + 1; // update q1 - r1 = 2*r1 - nc; // update r1 - } - else { - q1 = 2*q1; // update q1 - r1 = 2*r1; // update r1 - } - if (r2 + 1 >= d - r2) { - if (q2 >= 0x7FFFFFFF) magu.a = 1; - q2 = 2*q2 + 1; // update q2 - r2 = 2*r2 + 1 - d; // update r2 - } - else { - if (q2 >= 0x80000000) magu.a = 1; - q2 = 2*q2; // update q2 - r2 = 2*r2 + 1; // update r2 - } - delta = d - 1 - r2; - } while (p < 64 && (q1 < delta || (q1 == delta && r1 == 0))); - magu.m = q2 + 1; // resulting magic number - magu.s = p - 32; // resulting shift - return magu; -} -} - -/// BuildSDIVSequence - Given an ISD::SDIV node expressing a divide by constant, -/// return a DAG expression to select that will generate the same value by -/// multiplying by a magic number. See: -/// -SDOperand ISel::BuildSDIVSequence(SDOperand N) { - int d = (int)cast(N.getOperand(1))->getSignExtended(); - ms magics = magic(d); - // Multiply the numerator (operand 0) by the magic value - SDOperand Q = ISelDAG->getNode(ISD::MULHS, MVT::i32, N.getOperand(0), - ISelDAG->getConstant(magics.m, MVT::i32)); - // If d > 0 and m < 0, add the numerator - if (d > 0 && magics.m < 0) - Q = ISelDAG->getNode(ISD::ADD, MVT::i32, Q, N.getOperand(0)); - // If d < 0 and m > 0, subtract the numerator. - if (d < 0 && magics.m > 0) - Q = ISelDAG->getNode(ISD::SUB, MVT::i32, Q, N.getOperand(0)); - // Shift right algebraic if shift value is nonzero - if (magics.s > 0) - Q = ISelDAG->getNode(ISD::SRA, MVT::i32, Q, - ISelDAG->getConstant(magics.s, MVT::i32)); - // Extract the sign bit and add it to the quotient - SDOperand T = - ISelDAG->getNode(ISD::SRL, MVT::i32, Q, ISelDAG->getConstant(31, MVT::i32)); - return ISelDAG->getNode(ISD::ADD, MVT::i32, Q, T); -} - -/// BuildUDIVSequence - Given an ISD::UDIV node expressing a divide by constant, -/// return a DAG expression to select that will generate the same value by -/// multiplying by a magic number. See: -/// -SDOperand ISel::BuildUDIVSequence(SDOperand N) { - unsigned d = - (unsigned)cast(N.getOperand(1))->getSignExtended(); - mu magics = magicu(d); - // Multiply the numerator (operand 0) by the magic value - SDOperand Q = ISelDAG->getNode(ISD::MULHU, MVT::i32, N.getOperand(0), - ISelDAG->getConstant(magics.m, MVT::i32)); - if (magics.a == 0) { - Q = ISelDAG->getNode(ISD::SRL, MVT::i32, Q, - ISelDAG->getConstant(magics.s, MVT::i32)); - } else { - SDOperand NPQ = ISelDAG->getNode(ISD::SUB, MVT::i32, N.getOperand(0), Q); - NPQ = ISelDAG->getNode(ISD::SRL, MVT::i32, NPQ, - ISelDAG->getConstant(1, MVT::i32)); - NPQ = ISelDAG->getNode(ISD::ADD, MVT::i32, NPQ, Q); - Q = ISelDAG->getNode(ISD::SRL, MVT::i32, NPQ, - ISelDAG->getConstant(magics.s-1, MVT::i32)); - } - return Q; -} - -/// getGlobalBaseReg - Output the instructions required to put the -/// base address to use for accessing globals into a register. -/// -unsigned ISel::getGlobalBaseReg() { - if (!GlobalBaseInitialized) { - // Insert the set of GlobalBaseReg into the first MBB of the function - MachineBasicBlock &FirstMBB = BB->getParent()->front(); - MachineBasicBlock::iterator MBBI = FirstMBB.begin(); - GlobalBaseReg = MakeIntReg(); - BuildMI(FirstMBB, MBBI, PPC::MovePCtoLR, 0, PPC::LR); - BuildMI(FirstMBB, MBBI, PPC::MFLR, 1, GlobalBaseReg); - GlobalBaseInitialized = true; - } - return GlobalBaseReg; -} - -/// MoveCRtoGPR - Move CCReg[Idx] to the least significant bit of Result. If -/// Inv is true, then invert the result. -void ISel::MoveCRtoGPR(unsigned CCReg, ISD::CondCode CC, unsigned Result){ - bool Inv; - unsigned IntCR = MakeIntReg(); - unsigned Idx = getCRIdxForSetCC(CC, Inv); - BuildMI(BB, PPC::MCRF, 1, PPC::CR7).addReg(CCReg); - bool GPOpt = - TLI.getTargetMachine().getSubtarget().isGigaProcessor(); - if (GPOpt) - BuildMI(BB, PPC::MFOCRF, 1, IntCR).addReg(PPC::CR7); - else - BuildMI(BB, PPC::MFCR, 0, IntCR); - if (Inv) { - unsigned Tmp1 = MakeIntReg(); - BuildMI(BB, PPC::RLWINM, 4, Tmp1).addReg(IntCR).addImm(32-(3-Idx)) - .addImm(31).addImm(31); - BuildMI(BB, PPC::XORI, 2, Result).addReg(Tmp1).addImm(1); - } else { - BuildMI(BB, PPC::RLWINM, 4, Result).addReg(IntCR).addImm(32-(3-Idx)) - .addImm(31).addImm(31); - } -} - -/// SelectBitfieldInsert - turn an or of two masked values into -/// the rotate left word immediate then mask insert (rlwimi) instruction. -/// Returns true on success, false if the caller still needs to select OR. -/// -/// Patterns matched: -/// 1. or shl, and 5. or and, and -/// 2. or and, shl 6. or shl, shr -/// 3. or shr, and 7. or shr, shl -/// 4. or and, shr -bool ISel::SelectBitfieldInsert(SDOperand OR, unsigned Result) { - bool IsRotate = false; - unsigned TgtMask = 0xFFFFFFFF, InsMask = 0xFFFFFFFF, Amount = 0; - unsigned Value; - - SDOperand Op0 = OR.getOperand(0); - SDOperand Op1 = OR.getOperand(1); - - unsigned Op0Opc = Op0.getOpcode(); - unsigned Op1Opc = Op1.getOpcode(); - - // Verify that we have the correct opcodes - if (ISD::SHL != Op0Opc && ISD::SRL != Op0Opc && ISD::AND != Op0Opc) - return false; - if (ISD::SHL != Op1Opc && ISD::SRL != Op1Opc && ISD::AND != Op1Opc) - return false; - - // Generate Mask value for Target - if (isIntImmediate(Op0.getOperand(1), Value)) { - switch(Op0Opc) { - case ISD::SHL: TgtMask <<= Value; break; - case ISD::SRL: TgtMask >>= Value; break; - case ISD::AND: TgtMask &= Value; break; - } - } else { - return false; - } - - // Generate Mask value for Insert - if (isIntImmediate(Op1.getOperand(1), Value)) { - switch(Op1Opc) { - case ISD::SHL: - Amount = Value; - InsMask <<= Amount; - if (Op0Opc == ISD::SRL) IsRotate = true; - break; - case ISD::SRL: - Amount = Value; - InsMask >>= Amount; - Amount = 32-Amount; - if (Op0Opc == ISD::SHL) IsRotate = true; - break; - case ISD::AND: - InsMask &= Value; - break; - } - } else { - return false; - } - - unsigned Tmp3 = 0; - - // If both of the inputs are ANDs and one of them has a logical shift by - // constant as its input, make that the inserted value so that we can combine - // the shift into the rotate part of the rlwimi instruction - if (Op0Opc == ISD::AND && Op1Opc == ISD::AND) { - if (Op1.getOperand(0).getOpcode() == ISD::SHL || - Op1.getOperand(0).getOpcode() == ISD::SRL) { - if (isIntImmediate(Op1.getOperand(0).getOperand(1), Value)) { - Amount = Op1.getOperand(0).getOpcode() == ISD::SHL ? - Value : 32 - Value; - Tmp3 = SelectExpr(Op1.getOperand(0).getOperand(0)); - } - } else if (Op0.getOperand(0).getOpcode() == ISD::SHL || - Op0.getOperand(0).getOpcode() == ISD::SRL) { - if (isIntImmediate(Op0.getOperand(0).getOperand(1), Value)) { - std::swap(Op0, Op1); - std::swap(TgtMask, InsMask); - Amount = Op1.getOperand(0).getOpcode() == ISD::SHL ? - Value : 32 - Value; - Tmp3 = SelectExpr(Op1.getOperand(0).getOperand(0)); - } - } - } - - // Verify that the Target mask and Insert mask together form a full word mask - // and that the Insert mask is a run of set bits (which implies both are runs - // of set bits). Given that, Select the arguments and generate the rlwimi - // instruction. - unsigned MB, ME; - if (((TgtMask & InsMask) == 0) && isRunOfOnes(InsMask, MB, ME)) { - unsigned Tmp1, Tmp2; - bool fullMask = (TgtMask ^ InsMask) == 0xFFFFFFFF; - // Check for rotlwi / rotrwi here, a special case of bitfield insert - // where both bitfield halves are sourced from the same value. - if (IsRotate && fullMask && - OR.getOperand(0).getOperand(0) == OR.getOperand(1).getOperand(0)) { - Tmp1 = SelectExpr(OR.getOperand(0).getOperand(0)); - BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp1).addImm(Amount) - .addImm(0).addImm(31); - return true; - } - if (Op0Opc == ISD::AND && fullMask) - Tmp1 = SelectExpr(Op0.getOperand(0)); - else - Tmp1 = SelectExpr(Op0); - Tmp2 = Tmp3 ? Tmp3 : SelectExpr(Op1.getOperand(0)); - BuildMI(BB, PPC::RLWIMI, 5, Result).addReg(Tmp1).addReg(Tmp2) - .addImm(Amount).addImm(MB).addImm(ME); - return true; - } - return false; -} - -/// FoldIfWideZeroExtend - 32 bit PowerPC implicit masks shift amounts to the -/// low six bits. If the shift amount is an ISD::AND node with a mask that is -/// wider than the implicit mask, then we can get rid of the AND and let the -/// shift do the mask. -unsigned ISel::FoldIfWideZeroExtend(SDOperand N) { - unsigned C; - if (isOpcWithIntImmediate(N, ISD::AND, C) && isMask_32(C) && C > 63) - return SelectExpr(N.getOperand(0)); - else - return SelectExpr(N); -} - -unsigned ISel::SelectCC(SDOperand LHS, SDOperand RHS, ISD::CondCode CC) { - unsigned Result, Tmp1, Tmp2; - bool AlreadySelected = false; - - // Allocate a condition register for this expression - Result = RegMap->createVirtualRegister(PPC32::CRRCRegisterClass); - - // Use U to determine whether the SETCC immediate range is signed or not. - bool U = ISD::isUnsignedIntSetCC(CC); - if (isIntImmediate(RHS, Tmp2) && - ((U && isUInt16(Tmp2)) || (!U && isInt16(Tmp2)))) { - Tmp2 = Lo16(Tmp2); - // For comparisons against zero, we can implicity set CR0 if a recording - // variant (e.g. 'or.' instead of 'or') of the instruction that defines - // operand zero of the SetCC node is available. - if (Tmp2 == 0 && - NodeHasRecordingVariant(LHS.getOpcode()) && LHS.Val->hasOneUse()) { - RecordSuccess = false; - Tmp1 = SelectExpr(LHS, true); - if (RecordSuccess) { - ++Recorded; - BuildMI(BB, PPC::MCRF, 1, Result).addReg(PPC::CR0); - return Result; - } - AlreadySelected = true; - } - // If we could not implicitly set CR0, then emit a compare immediate - // instead. - if (!AlreadySelected) Tmp1 = SelectExpr(LHS); - if (U) - BuildMI(BB, PPC::CMPLWI, 2, Result).addReg(Tmp1).addImm(Tmp2); - else - BuildMI(BB, PPC::CMPWI, 2, Result).addReg(Tmp1).addSImm(Tmp2); - } else { - unsigned CompareOpc; - if (MVT::isInteger(LHS.getValueType())) - CompareOpc = U ? PPC::CMPLW : PPC::CMPW; - else if (LHS.getValueType() == MVT::f32) - CompareOpc = PPC::FCMPUS; - else - CompareOpc = PPC::FCMPUD; - Tmp1 = SelectExpr(LHS); - Tmp2 = SelectExpr(RHS); - BuildMI(BB, CompareOpc, 2, Result).addReg(Tmp1).addReg(Tmp2); - } - return Result; -} - -/// Check to see if the load is a constant offset from a base register. -unsigned ISel::SelectAddr(SDOperand N, unsigned& Reg, int& offset) -{ - unsigned imm = 0, opcode = N.getOpcode(); - if (N.getOpcode() == ISD::ADD) { - bool isFrame = N.getOperand(0).getOpcode() == ISD::FrameIndex; - if (isIntImmediate(N.getOperand(1), imm) && isInt16(imm)) { - offset = Lo16(imm); - if (isFrame) { - ++FrameOff; - Reg = cast(N.getOperand(0))->getIndex(); - return 1; - } else { - Reg = SelectExpr(N.getOperand(0)); - return 0; - } - } else { - Reg = SelectExpr(N.getOperand(0)); - offset = SelectExpr(N.getOperand(1)); - return 2; - } - } - // Now check if we're dealing with a global, and whether or not we should emit - // an optimized load or store for statics. - if(GlobalAddressSDNode *GN = dyn_cast(N)) { - GlobalValue *GV = GN->getGlobal(); - if (!GV->hasWeakLinkage() && !GV->isExternal()) { - unsigned GlobalHi = MakeIntReg(); - if (PICEnabled) - BuildMI(BB, PPC::ADDIS, 2, GlobalHi).addReg(getGlobalBaseReg()) - .addGlobalAddress(GV); - else - BuildMI(BB, PPC::LIS, 1, GlobalHi).addGlobalAddress(GV); - Reg = GlobalHi; - offset = 0; - return 3; - } - } - Reg = SelectExpr(N); - offset = 0; - return 0; -} - -void ISel::SelectBranchCC(SDOperand N) -{ - MachineBasicBlock *Dest = - cast(N.getOperand(4))->getBasicBlock(); - - Select(N.getOperand(0)); //chain - ISD::CondCode CC = cast(N.getOperand(1))->get(); - unsigned CCReg = SelectCC(N.getOperand(2), N.getOperand(3), CC); - unsigned Opc = getBCCForSetCC(CC); - - // If this is a two way branch, then grab the fallthrough basic block argument - // and build a PowerPC branch pseudo-op, suitable for long branch conversion - // if necessary by the branch selection pass. Otherwise, emit a standard - // conditional branch. - if (N.getOpcode() == ISD::BRTWOWAY_CC) { - MachineBasicBlock *Fallthrough = - cast(N.getOperand(5))->getBasicBlock(); - BuildMI(BB, PPC::COND_BRANCH, 4).addReg(CCReg).addImm(Opc) - .addMBB(Dest).addMBB(Fallthrough); - BuildMI(BB, PPC::B, 1).addMBB(Fallthrough); - } else { - // Iterate to the next basic block - ilist::iterator It = BB; - ++It; - - // If the fallthrough path is off the end of the function, which would be - // undefined behavior, set it to be the same as the current block because - // we have nothing better to set it to, and leaving it alone will cause the - // PowerPC Branch Selection pass to crash. - if (It == BB->getParent()->end()) It = Dest; - BuildMI(BB, PPC::COND_BRANCH, 4).addReg(CCReg).addImm(Opc) - .addMBB(Dest).addMBB(It); - } - return; -} - -// SelectIntImmediateExpr - Choose code for opcodes with immediate value. -bool ISel::SelectIntImmediateExpr(SDOperand N, unsigned Result, - unsigned OCHi, unsigned OCLo, - bool IsArithmetic, bool Negate) { - // check constant - ConstantSDNode *CN = dyn_cast(N.getOperand(1)); - // exit if not a constant - if (!CN) return false; - // extract immediate - unsigned C = (unsigned)CN->getValue(); - // negate if required (ISD::SUB) - if (Negate) C = -C; - // get the hi and lo portions of constant - unsigned Hi = IsArithmetic ? HA16(C) : Hi16(C); - unsigned Lo = Lo16(C); - // assume no intermediate result from lo instruction (same as final result) - unsigned Tmp = Result; - // check if two instructions are needed - if (Hi && Lo) { - // exit if usage indicates it would be better to load immediate into a - // register - if (CN->use_size() > 2) return false; - // need intermediate result for two instructions - Tmp = MakeIntReg(); - } - // get first operand - unsigned Opr0 = SelectExpr(N.getOperand(0)); - // is a lo instruction needed - if (Lo) { - // generate instruction for lo portion - BuildMI(BB, OCLo, 2, Tmp).addReg(Opr0).addImm(Lo); - // need to switch out first operand for hi instruction - Opr0 = Tmp; - } - // is a hi instruction needed - if (Hi) { - // generate instruction for hi portion - BuildMI(BB, OCHi, 2, Result).addReg(Opr0).addImm(Hi); - } - return true; -} - -unsigned ISel::SelectExpr(SDOperand N, bool Recording) { - unsigned Result; - unsigned Tmp1, Tmp2, Tmp3; - unsigned Opc = 0; - unsigned opcode = N.getOpcode(); - - SDNode *Node = N.Val; - MVT::ValueType DestType = N.getValueType(); - - if (Node->getOpcode() == ISD::CopyFromReg) { - unsigned Reg = cast(Node->getOperand(1))->getReg(); - // Just use the specified register as our input. - if (MRegisterInfo::isVirtualRegister(Reg) || Reg == PPC::R1) - return Reg; - } - - unsigned &Reg = ExprMap[N]; - if (Reg) return Reg; - - switch (N.getOpcode()) { - default: - Reg = Result = (N.getValueType() != MVT::Other) ? - MakeReg(N.getValueType()) : 1; - break; - case ISD::AssertSext: - case ISD::AssertZext: - // Don't allocate a vreg for these nodes. - return Reg = SelectExpr(N.getOperand(0)); - case ISD::TAILCALL: - case ISD::CALL: - // If this is a call instruction, make sure to prepare ALL of the result - // values as well as the chain. - if (Node->getNumValues() == 1) - Reg = Result = 1; // Void call, just a chain. - else { - Result = MakeReg(Node->getValueType(0)); - ExprMap[N.getValue(0)] = Result; - for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i) - ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i)); - ExprMap[SDOperand(Node, Node->getNumValues()-1)] = 1; - } - break; - case ISD::ADD_PARTS: - case ISD::SUB_PARTS: - Result = MakeReg(Node->getValueType(0)); - ExprMap[N.getValue(0)] = Result; - for (unsigned i = 1, e = N.Val->getNumValues(); i != e; ++i) - ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i)); - break; - } - - switch (opcode) { - default: - Node->dump(); std::cerr << '\n'; - assert(0 && "Node not handled!\n"); - case PPCISD::FSEL: - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1)); - Tmp3 = SelectExpr(N.getOperand(2)); - - // Extend the comparison to 64-bits if needed. - if (N.getOperand(0).getValueType() == MVT::f32) { - unsigned Tmp1New = MakeReg(MVT::f64); - BuildMI(BB, PPC::FMRSD, 1, Tmp1New).addReg(Tmp1); - Tmp1 = Tmp1New; - } - - Opc = N.Val->getValueType(0) == MVT::f32 ? PPC::FSELS : PPC::FSELD; - BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3); - return Result; - case PPCISD::FCFID: - Tmp1 = SelectExpr(N.getOperand(0)); - BuildMI(BB, PPC::FCFID, 1, Result).addReg(Tmp1); - return Result; - case PPCISD::FCTIDZ: - Tmp1 = SelectExpr(N.getOperand(0)); - BuildMI(BB, PPC::FCTIDZ, 1, Result).addReg(Tmp1); - return Result; - case PPCISD::FCTIWZ: - Tmp1 = SelectExpr(N.getOperand(0)); - BuildMI(BB, PPC::FCTIWZ, 1, Result).addReg(Tmp1); - return Result; - case ISD::UNDEF: - if (Node->getValueType(0) == MVT::i32) - BuildMI(BB, PPC::IMPLICIT_DEF_GPR, 0, Result); - else if (Node->getValueType(0) == MVT::f32) - BuildMI(BB, PPC::IMPLICIT_DEF_F4, 0, Result); - else - BuildMI(BB, PPC::IMPLICIT_DEF_F8, 0, Result); - return Result; - case ISD::DYNAMIC_STACKALLOC: - // Generate both result values. FIXME: Need a better commment here? - if (Result != 1) - ExprMap[N.getValue(1)] = 1; - else - Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); - - // FIXME: We are currently ignoring the requested alignment for handling - // greater than the stack alignment. This will need to be revisited at some - // point. Align = N.getOperand(2); - if (!isa(N.getOperand(2)) || - cast(N.getOperand(2))->getValue() != 0) { - std::cerr << "Cannot allocate stack object with greater alignment than" - << " the stack alignment yet!"; - abort(); - } - Select(N.getOperand(0)); - Tmp1 = SelectExpr(N.getOperand(1)); - // Subtract size from stack pointer, thereby allocating some space. - BuildMI(BB, PPC::SUBF, 2, PPC::R1).addReg(Tmp1).addReg(PPC::R1); - // Put a pointer to the space into the result register by copying the SP - BuildMI(BB, PPC::OR, 2, Result).addReg(PPC::R1).addReg(PPC::R1); - return Result; - - case ISD::ConstantPool: - Tmp1 = BB->getParent()->getConstantPool()-> - getConstantPoolIndex(cast(N)->get()); - Tmp2 = MakeIntReg(); - if (PICEnabled) - BuildMI(BB, PPC::ADDIS, 2, Tmp2).addReg(getGlobalBaseReg()) - .addConstantPoolIndex(Tmp1); - else - BuildMI(BB, PPC::LIS, 1, Tmp2).addConstantPoolIndex(Tmp1); - BuildMI(BB, PPC::LA, 2, Result).addReg(Tmp2).addConstantPoolIndex(Tmp1); - return Result; - - case ISD::FrameIndex: - Tmp1 = cast(N)->getIndex(); - addFrameReference(BuildMI(BB, PPC::ADDI, 2, Result), (int)Tmp1, 0, false); - return Result; - - case ISD::GlobalAddress: { - GlobalValue *GV = cast(N)->getGlobal(); - Tmp1 = MakeIntReg(); - if (PICEnabled) - BuildMI(BB, PPC::ADDIS, 2, Tmp1).addReg(getGlobalBaseReg()) - .addGlobalAddress(GV); - else - BuildMI(BB, PPC::LIS, 1, Tmp1).addGlobalAddress(GV); - if (GV->hasWeakLinkage() || GV->isExternal()) { - BuildMI(BB, PPC::LWZ, 2, Result).addGlobalAddress(GV).addReg(Tmp1); - } else { - BuildMI(BB, PPC::LA, 2, Result).addReg(Tmp1).addGlobalAddress(GV); - } - return Result; - } - - case ISD::LOAD: - case ISD::EXTLOAD: - case ISD::ZEXTLOAD: - case ISD::SEXTLOAD: { - MVT::ValueType TypeBeingLoaded = (ISD::LOAD == opcode) ? - Node->getValueType(0) : cast(Node->getOperand(3))->getVT(); - bool sext = (ISD::SEXTLOAD == opcode); - - // Make sure we generate both values. - if (Result != 1) - ExprMap[N.getValue(1)] = 1; // Generate the token - else - Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); - - SDOperand Chain = N.getOperand(0); - SDOperand Address = N.getOperand(1); - Select(Chain); - - switch (TypeBeingLoaded) { - default: Node->dump(); assert(0 && "Cannot load this type!"); - case MVT::i1: Opc = PPC::LBZ; break; - case MVT::i8: Opc = PPC::LBZ; break; - case MVT::i16: Opc = sext ? PPC::LHA : PPC::LHZ; break; - case MVT::i32: Opc = PPC::LWZ; break; - case MVT::f32: Opc = PPC::LFS; break; - case MVT::f64: Opc = PPC::LFD; break; - } - - if (ConstantPoolSDNode *CP = dyn_cast(Address)) { - Tmp1 = MakeIntReg(); - unsigned CPI = BB->getParent()->getConstantPool()-> - getConstantPoolIndex(CP->get()); - if (PICEnabled) - BuildMI(BB, PPC::ADDIS, 2, Tmp1).addReg(getGlobalBaseReg()) - .addConstantPoolIndex(CPI); - else - BuildMI(BB, PPC::LIS, 1, Tmp1).addConstantPoolIndex(CPI); - BuildMI(BB, Opc, 2, Result).addConstantPoolIndex(CPI).addReg(Tmp1); - } else if (Address.getOpcode() == ISD::FrameIndex) { - Tmp1 = cast(Address)->getIndex(); - addFrameReference(BuildMI(BB, Opc, 2, Result), (int)Tmp1); - } else { - int offset; - switch(SelectAddr(Address, Tmp1, offset)) { - default: assert(0 && "Unhandled return value from SelectAddr"); - case 0: // imm offset, no frame, no index - BuildMI(BB, Opc, 2, Result).addSImm(offset).addReg(Tmp1); - break; - case 1: // imm offset + frame index - addFrameReference(BuildMI(BB, Opc, 2, Result), (int)Tmp1, offset); - break; - case 2: // base+index addressing - Opc = IndexedOpForOp(Opc); - BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(offset); - break; - case 3: { - GlobalAddressSDNode *GN = cast(Address); - GlobalValue *GV = GN->getGlobal(); - BuildMI(BB, Opc, 2, Result).addGlobalAddress(GV).addReg(Tmp1); - } - } - } - return Result; - } - - case ISD::TAILCALL: - case ISD::CALL: { - unsigned GPR_idx = 0, FPR_idx = 0; - static const unsigned GPR[] = { - PPC::R3, PPC::R4, PPC::R5, PPC::R6, - PPC::R7, PPC::R8, PPC::R9, PPC::R10, - }; - static const unsigned FPR[] = { - PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, - PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13 - }; - - // Lower the chain for this call. - Select(N.getOperand(0)); - ExprMap[N.getValue(Node->getNumValues()-1)] = 1; - - MachineInstr *CallMI; - // Emit the correct call instruction based on the type of symbol called. - if (GlobalAddressSDNode *GASD = - dyn_cast(N.getOperand(1))) { - CallMI = BuildMI(PPC::CALLpcrel, 1).addGlobalAddress(GASD->getGlobal(), - true); - } else if (ExternalSymbolSDNode *ESSDN = - dyn_cast(N.getOperand(1))) { - CallMI = BuildMI(PPC::CALLpcrel, 1).addExternalSymbol(ESSDN->getSymbol(), - true); - } else { - Tmp1 = SelectExpr(N.getOperand(1)); - BuildMI(BB, PPC::MTCTR, 1).addReg(Tmp1); - BuildMI(BB, PPC::OR, 2, PPC::R12).addReg(Tmp1).addReg(Tmp1); - CallMI = BuildMI(PPC::CALLindirect, 3).addImm(20).addImm(0) - .addReg(PPC::R12); - } - - // Load the register args to virtual regs - std::vector ArgVR; - for(int i = 2, e = Node->getNumOperands(); i < e; ++i) - ArgVR.push_back(SelectExpr(N.getOperand(i))); - - // Copy the virtual registers into the appropriate argument register - for(int i = 0, e = ArgVR.size(); i < e; ++i) { - switch(N.getOperand(i+2).getValueType()) { - default: Node->dump(); assert(0 && "Unknown value type for call"); - case MVT::i32: - assert(GPR_idx < 8 && "Too many int args"); - if (N.getOperand(i+2).getOpcode() != ISD::UNDEF) { - BuildMI(BB, PPC::OR,2,GPR[GPR_idx]).addReg(ArgVR[i]).addReg(ArgVR[i]); - CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use); - } - ++GPR_idx; - break; - case MVT::f64: - case MVT::f32: - assert(FPR_idx < 13 && "Too many fp args"); - BuildMI(BB, N.getOperand(i+2).getValueType() == MVT::f32 ? PPC::FMRS : - PPC::FMRD, 1, FPR[FPR_idx]).addReg(ArgVR[i]); - CallMI->addRegOperand(FPR[FPR_idx], MachineOperand::Use); - ++FPR_idx; - break; - } - } - - // Put the call instruction in the correct place in the MachineBasicBlock - BB->push_back(CallMI); - - switch (Node->getValueType(0)) { - default: assert(0 && "Unknown value type for call result!"); - case MVT::Other: return 1; - case MVT::i32: - if (Node->getValueType(1) == MVT::i32) { - BuildMI(BB, PPC::OR, 2, Result+1).addReg(PPC::R3).addReg(PPC::R3); - BuildMI(BB, PPC::OR, 2, Result).addReg(PPC::R4).addReg(PPC::R4); - } else { - BuildMI(BB, PPC::OR, 2, Result).addReg(PPC::R3).addReg(PPC::R3); - } - break; - case MVT::f32: - BuildMI(BB, PPC::FMRS, 1, Result).addReg(PPC::F1); - break; - case MVT::f64: - BuildMI(BB, PPC::FMRD, 1, Result).addReg(PPC::F1); - break; - } - return Result+N.ResNo; - } - - case ISD::SIGN_EXTEND_INREG: - Tmp1 = SelectExpr(N.getOperand(0)); - switch(cast(Node->getOperand(1))->getVT()) { - default: Node->dump(); assert(0 && "Unhandled SIGN_EXTEND type"); break; - case MVT::i16: - BuildMI(BB, PPC::EXTSH, 1, Result).addReg(Tmp1); - break; - case MVT::i8: - BuildMI(BB, PPC::EXTSB, 1, Result).addReg(Tmp1); - break; - } - return Result; - - case ISD::CopyFromReg: - DestType = N.getValue(0).getValueType(); - if (Result == 1) - Result = ExprMap[N.getValue(0)] = MakeReg(DestType); - else - ExprMap[N.getValue(1)] = 1; - Tmp1 = dyn_cast(Node->getOperand(1))->getReg(); - if (MVT::isInteger(DestType)) - BuildMI(BB, PPC::OR, 2, Result).addReg(Tmp1).addReg(Tmp1); - else if (DestType == MVT::f32) - BuildMI(BB, PPC::FMRS, 1, Result).addReg(Tmp1); - else - BuildMI(BB, PPC::FMRD, 1, Result).addReg(Tmp1); - return Result; - - case ISD::SHL: - if (isIntImmediate(N.getOperand(1), Tmp2)) { - unsigned SH, MB, ME; - if (isOpcWithIntImmediate(N.getOperand(0), ISD::AND, Tmp3) && - isRotateAndMask(ISD::SHL, Tmp2, Tmp3, true, SH, MB, ME)) { - Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); - BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp1).addImm(SH) - .addImm(MB).addImm(ME); - return Result; - } - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 &= 0x1F; - BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp1).addImm(Tmp2).addImm(0) - .addImm(31-Tmp2); - } else { - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = FoldIfWideZeroExtend(N.getOperand(1)); - BuildMI(BB, PPC::SLW, 2, Result).addReg(Tmp1).addReg(Tmp2); - } - return Result; - - case ISD::SRL: - if (isIntImmediate(N.getOperand(1), Tmp2)) { - unsigned SH, MB, ME; - if (isOpcWithIntImmediate(N.getOperand(0), ISD::AND, Tmp3) && - isRotateAndMask(ISD::SRL, Tmp2, Tmp3, true, SH, MB, ME)) { - Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); - BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp1).addImm(SH & 0x1F) - .addImm(MB).addImm(ME); - return Result; - } - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 &= 0x1F; - BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp1).addImm((32-Tmp2) & 0x1F) - .addImm(Tmp2).addImm(31); - } else { - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = FoldIfWideZeroExtend(N.getOperand(1)); - BuildMI(BB, PPC::SRW, 2, Result).addReg(Tmp1).addReg(Tmp2); - } - return Result; - - case ISD::SRA: - if (isIntImmediate(N.getOperand(1), Tmp2)) { - unsigned SH, MB, ME; - if (isOpcWithIntImmediate(N.getOperand(0), ISD::AND, Tmp3) && - isRotateAndMask(ISD::SRA, Tmp2, Tmp3, true, SH, MB, ME)) { - Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); - BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp1).addImm(SH) - .addImm(MB).addImm(ME); - return Result; - } - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 &= 0x1F; - BuildMI(BB, PPC::SRAWI, 2, Result).addReg(Tmp1).addImm(Tmp2); - } else { - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = FoldIfWideZeroExtend(N.getOperand(1)); - BuildMI(BB, PPC::SRAW, 2, Result).addReg(Tmp1).addReg(Tmp2); - } - return Result; - - case ISD::CTLZ: - Tmp1 = SelectExpr(N.getOperand(0)); - BuildMI(BB, PPC::CNTLZW, 1, Result).addReg(Tmp1); - return Result; - - case ISD::ADD: - if (SelectIntImmediateExpr(N, Result, PPC::ADDIS, PPC::ADDI, true)) - return Result; - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1)); - BuildMI(BB, PPC::ADD, 2, Result).addReg(Tmp1).addReg(Tmp2); - return Result; - - case ISD::FADD: - if (!NoExcessFPPrecision && N.getOperand(0).getOpcode() == ISD::FMUL && - N.getOperand(0).Val->hasOneUse()) { - ++FusedFP; // Statistic - Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(0).getOperand(1)); - Tmp3 = SelectExpr(N.getOperand(1)); - Opc = DestType == MVT::f64 ? PPC::FMADD : PPC::FMADDS; - BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3); - return Result; - } - if (!NoExcessFPPrecision && N.getOperand(1).getOpcode() == ISD::FMUL && - N.getOperand(1).Val->hasOneUse()) { - ++FusedFP; // Statistic - Tmp1 = SelectExpr(N.getOperand(1).getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1).getOperand(1)); - Tmp3 = SelectExpr(N.getOperand(0)); - Opc = DestType == MVT::f64 ? PPC::FMADD : PPC::FMADDS; - BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3); - return Result; - } - Opc = DestType == MVT::f64 ? PPC::FADD : PPC::FADDS; - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1)); - BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); - return Result; - - case ISD::AND: - if (isIntImmediate(N.getOperand(1), Tmp2)) { - if (isShiftedMask_32(Tmp2) || isShiftedMask_32(~Tmp2)) { - unsigned SH, MB, ME; - Opc = Recording ? PPC::RLWINMo : PPC::RLWINM; - unsigned OprOpc; - if (isOprShiftImm(N.getOperand(0), OprOpc, Tmp3) && - isRotateAndMask(OprOpc, Tmp3, Tmp2, false, SH, MB, ME)) { - Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); - } else { - Tmp1 = SelectExpr(N.getOperand(0)); - isRunOfOnes(Tmp2, MB, ME); - SH = 0; - } - BuildMI(BB, Opc, 4, Result).addReg(Tmp1).addImm(SH) - .addImm(MB).addImm(ME); - RecordSuccess = true; - return Result; - } else if (isUInt16(Tmp2)) { - Tmp2 = Lo16(Tmp2); - Tmp1 = SelectExpr(N.getOperand(0)); - BuildMI(BB, PPC::ANDIo, 2, Result).addReg(Tmp1).addImm(Tmp2); - RecordSuccess = true; - return Result; - } else if (isUInt16(Tmp2)) { - Tmp2 = Hi16(Tmp2); - Tmp1 = SelectExpr(N.getOperand(0)); - BuildMI(BB, PPC::ANDISo, 2, Result).addReg(Tmp1).addImm(Tmp2); - RecordSuccess = true; - return Result; - } - } - if (isOprNot(N.getOperand(1))) { - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1).getOperand(0)); - BuildMI(BB, PPC::ANDC, 2, Result).addReg(Tmp1).addReg(Tmp2); - RecordSuccess = false; - return Result; - } - if (isOprNot(N.getOperand(0))) { - Tmp1 = SelectExpr(N.getOperand(1)); - Tmp2 = SelectExpr(N.getOperand(0).getOperand(0)); - BuildMI(BB, PPC::ANDC, 2, Result).addReg(Tmp1).addReg(Tmp2); - RecordSuccess = false; - return Result; - } - // emit a regular and - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1)); - Opc = Recording ? PPC::ANDo : PPC::AND; - BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); - RecordSuccess = true; - return Result; - - case ISD::OR: - if (SelectBitfieldInsert(N, Result)) - return Result; - if (SelectIntImmediateExpr(N, Result, PPC::ORIS, PPC::ORI)) - return Result; - if (isOprNot(N.getOperand(1))) { - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1).getOperand(0)); - BuildMI(BB, PPC::ORC, 2, Result).addReg(Tmp1).addReg(Tmp2); - RecordSuccess = false; - return Result; - } - if (isOprNot(N.getOperand(0))) { - Tmp1 = SelectExpr(N.getOperand(1)); - Tmp2 = SelectExpr(N.getOperand(0).getOperand(0)); - BuildMI(BB, PPC::ORC, 2, Result).addReg(Tmp1).addReg(Tmp2); - RecordSuccess = false; - return Result; - } - // emit regular or - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1)); - Opc = Recording ? PPC::ORo : PPC::OR; - RecordSuccess = true; - BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); - return Result; - - case ISD::XOR: { - // Check for EQV: xor, (xor a, -1), b - if (isOprNot(N.getOperand(0))) { - Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1)); - BuildMI(BB, PPC::EQV, 2, Result).addReg(Tmp1).addReg(Tmp2); - return Result; - } - // Check for NOT, NOR, EQV, and NAND: xor (copy, or, xor, and), -1 - if (isOprNot(N)) { - switch(N.getOperand(0).getOpcode()) { - case ISD::OR: - Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(0).getOperand(1)); - BuildMI(BB, PPC::NOR, 2, Result).addReg(Tmp1).addReg(Tmp2); - break; - case ISD::AND: - Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(0).getOperand(1)); - BuildMI(BB, PPC::NAND, 2, Result).addReg(Tmp1).addReg(Tmp2); - break; - case ISD::XOR: - Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(0).getOperand(1)); - BuildMI(BB, PPC::EQV, 2, Result).addReg(Tmp1).addReg(Tmp2); - break; - default: - Tmp1 = SelectExpr(N.getOperand(0)); - BuildMI(BB, PPC::NOR, 2, Result).addReg(Tmp1).addReg(Tmp1); - break; - } - return Result; - } - if (SelectIntImmediateExpr(N, Result, PPC::XORIS, PPC::XORI)) - return Result; - // emit regular xor - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1)); - BuildMI(BB, PPC::XOR, 2, Result).addReg(Tmp1).addReg(Tmp2); - return Result; - } - - case ISD::FSUB: - if (!NoExcessFPPrecision && N.getOperand(0).getOpcode() == ISD::FMUL && - N.getOperand(0).Val->hasOneUse()) { - ++FusedFP; // Statistic - Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(0).getOperand(1)); - Tmp3 = SelectExpr(N.getOperand(1)); - Opc = DestType == MVT::f64 ? PPC::FMSUB : PPC::FMSUBS; - BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3); - return Result; - } - if (!NoExcessFPPrecision && N.getOperand(1).getOpcode() == ISD::FMUL && - N.getOperand(1).Val->hasOneUse()) { - ++FusedFP; // Statistic - Tmp1 = SelectExpr(N.getOperand(1).getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1).getOperand(1)); - Tmp3 = SelectExpr(N.getOperand(0)); - Opc = DestType == MVT::f64 ? PPC::FNMSUB : PPC::FNMSUBS; - BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3); - return Result; - } - Opc = DestType == MVT::f64 ? PPC::FSUB : PPC::FSUBS; - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1)); - BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); - return Result; - case ISD::SUB: - if (isIntImmediate(N.getOperand(0), Tmp1) && isInt16(Tmp1)) { - Tmp1 = Lo16(Tmp1); - Tmp2 = SelectExpr(N.getOperand(1)); - if (0 == Tmp1) - BuildMI(BB, PPC::NEG, 1, Result).addReg(Tmp2); - else - BuildMI(BB, PPC::SUBFIC, 2, Result).addReg(Tmp2).addSImm(Tmp1); - return Result; - } - if (SelectIntImmediateExpr(N, Result, PPC::ADDIS, PPC::ADDI, true, true)) - return Result; - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1)); - BuildMI(BB, PPC::SUBF, 2, Result).addReg(Tmp2).addReg(Tmp1); - return Result; - - case ISD::FMUL: - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1)); - BuildMI(BB, DestType == MVT::f32 ? PPC::FMULS : PPC::FMUL, 2, - Result).addReg(Tmp1).addReg(Tmp2); - return Result; - - case ISD::MUL: - Tmp1 = SelectExpr(N.getOperand(0)); - if (isIntImmediate(N.getOperand(1), Tmp2) && isInt16(Tmp2)) { - Tmp2 = Lo16(Tmp2); - BuildMI(BB, PPC::MULLI, 2, Result).addReg(Tmp1).addSImm(Tmp2); - } else { - Tmp2 = SelectExpr(N.getOperand(1)); - BuildMI(BB, PPC::MULLW, 2, Result).addReg(Tmp1).addReg(Tmp2); - } - return Result; - - case ISD::MULHS: - case ISD::MULHU: - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1)); - Opc = (ISD::MULHU == opcode) ? PPC::MULHWU : PPC::MULHW; - BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); - return Result; - - case ISD::FDIV: - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1)); - switch (DestType) { - default: assert(0 && "Unknown type to ISD::FDIV"); break; - case MVT::f32: Opc = PPC::FDIVS; break; - case MVT::f64: Opc = PPC::FDIV; break; - } - BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); - return Result; - - case ISD::SDIV: - if (isIntImmediate(N.getOperand(1), Tmp3)) { - if ((signed)Tmp3 > 0 && isPowerOf2_32(Tmp3)) { - Tmp3 = Log2_32(Tmp3); - Tmp1 = MakeIntReg(); - Tmp2 = SelectExpr(N.getOperand(0)); - BuildMI(BB, PPC::SRAWI, 2, Tmp1).addReg(Tmp2).addImm(Tmp3); - BuildMI(BB, PPC::ADDZE, 1, Result).addReg(Tmp1); - return Result; - } else if ((signed)Tmp3 < 0 && isPowerOf2_32(-Tmp3)) { - Tmp3 = Log2_32(-Tmp3); - Tmp2 = SelectExpr(N.getOperand(0)); - Tmp1 = MakeIntReg(); - unsigned Tmp4 = MakeIntReg(); - BuildMI(BB, PPC::SRAWI, 2, Tmp1).addReg(Tmp2).addImm(Tmp3); - BuildMI(BB, PPC::ADDZE, 1, Tmp4).addReg(Tmp1); - BuildMI(BB, PPC::NEG, 1, Result).addReg(Tmp4); - return Result; - } else if (Tmp3) { - ExprMap.erase(N); - return SelectExpr(BuildSDIVSequence(N)); - } - } - // fall thru - case ISD::UDIV: - // If this is a divide by constant, we can emit code using some magic - // constants to implement it as a multiply instead. - if (isIntImmediate(N.getOperand(1), Tmp3) && Tmp3) { - ExprMap.erase(N); - return SelectExpr(BuildUDIVSequence(N)); - } - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1)); - Opc = (ISD::UDIV == opcode) ? PPC::DIVWU : PPC::DIVW; break; - BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); - return Result; - - case ISD::ADD_PARTS: - case ISD::SUB_PARTS: { - assert(N.getNumOperands() == 4 && N.getValueType() == MVT::i32 && - "Not an i64 add/sub!"); - unsigned Tmp4 = 0; - Tmp1 = SelectExpr(N.getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(1)); - - if (N.getOpcode() == ISD::ADD_PARTS) { - bool ME = false, ZE = false; - if (isIntImmediate(N.getOperand(3), Tmp3)) { - ME = (signed)Tmp3 == -1; - ZE = Tmp3 == 0; - } - - if (!ZE && !ME) - Tmp4 = SelectExpr(N.getOperand(3)); - - if (isIntImmediate(N.getOperand(2), Tmp3) && - ((signed)Tmp3 >= -32768 || (signed)Tmp3 < 32768)) { - // Codegen the low 32 bits of the add. Interestingly, there is no - // shifted form of add immediate carrying. - BuildMI(BB, PPC::ADDIC, 2, Result).addReg(Tmp1).addSImm(Tmp3); - } else { - Tmp3 = SelectExpr(N.getOperand(2)); - BuildMI(BB, PPC::ADDC, 2, Result).addReg(Tmp1).addReg(Tmp3); - } - - // Codegen the high 32 bits, adding zero, minus one, or the full value - // along with the carry flag produced by addc/addic to tmp2. - if (ZE) { - BuildMI(BB, PPC::ADDZE, 1, Result+1).addReg(Tmp2); - } else if (ME) { - BuildMI(BB, PPC::ADDME, 1, Result+1).addReg(Tmp2); - } else { - BuildMI(BB, PPC::ADDE, 2, Result+1).addReg(Tmp2).addReg(Tmp4); - } - } else { - Tmp3 = SelectExpr(N.getOperand(2)); - Tmp4 = SelectExpr(N.getOperand(3)); - BuildMI(BB, PPC::SUBFC, 2, Result).addReg(Tmp3).addReg(Tmp1); - BuildMI(BB, PPC::SUBFE, 2, Result+1).addReg(Tmp4).addReg(Tmp2); - } - return Result+N.ResNo; - } - - case ISD::SETCC: { - ISD::CondCode CC = cast(Node->getOperand(2))->get(); - if (isIntImmediate(Node->getOperand(1), Tmp3)) { - // We can codegen setcc op, imm very efficiently compared to a brcond. - // Check for those cases here. - // setcc op, 0 - if (Tmp3 == 0) { - Tmp1 = SelectExpr(Node->getOperand(0)); - switch (CC) { - default: Node->dump(); assert(0 && "Unhandled SetCC condition");abort(); - case ISD::SETEQ: - Tmp2 = MakeIntReg(); - BuildMI(BB, PPC::CNTLZW, 1, Tmp2).addReg(Tmp1); - BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp2).addImm(27) - .addImm(5).addImm(31); - break; - case ISD::SETNE: - Tmp2 = MakeIntReg(); - BuildMI(BB, PPC::ADDIC, 2, Tmp2).addReg(Tmp1).addSImm(-1); - BuildMI(BB, PPC::SUBFE, 2, Result).addReg(Tmp2).addReg(Tmp1); - break; - case ISD::SETLT: - BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp1).addImm(1) - .addImm(31).addImm(31); - break; - case ISD::SETGT: - Tmp2 = MakeIntReg(); - Tmp3 = MakeIntReg(); - BuildMI(BB, PPC::NEG, 2, Tmp2).addReg(Tmp1); - BuildMI(BB, PPC::ANDC, 2, Tmp3).addReg(Tmp2).addReg(Tmp1); - BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp3).addImm(1) - .addImm(31).addImm(31); - break; - } - return Result; - } else if (Tmp3 == ~0U) { // setcc op, -1 - Tmp1 = SelectExpr(Node->getOperand(0)); - switch (CC) { - default: assert(0 && "Unhandled SetCC condition"); abort(); - case ISD::SETEQ: - Tmp2 = MakeIntReg(); - Tmp3 = MakeIntReg(); - BuildMI(BB, PPC::ADDIC, 2, Tmp2).addReg(Tmp1).addSImm(1); - BuildMI(BB, PPC::LI, 1, Tmp3).addSImm(0); - BuildMI(BB, PPC::ADDZE, 1, Result).addReg(Tmp3); - break; - case ISD::SETNE: - Tmp2 = MakeIntReg(); - Tmp3 = MakeIntReg(); - BuildMI(BB, PPC::NOR, 2, Tmp2).addReg(Tmp1).addReg(Tmp1); - BuildMI(BB, PPC::ADDIC, 2, Tmp3).addReg(Tmp2).addSImm(-1); - BuildMI(BB, PPC::SUBFE, 2, Result).addReg(Tmp3).addReg(Tmp2); - break; - case ISD::SETLT: - Tmp2 = MakeIntReg(); - Tmp3 = MakeIntReg(); - BuildMI(BB, PPC::ADDI, 2, Tmp2).addReg(Tmp1).addSImm(1); - BuildMI(BB, PPC::AND, 2, Tmp3).addReg(Tmp2).addReg(Tmp1); - BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp3).addImm(1) - .addImm(31).addImm(31); - break; - case ISD::SETGT: - Tmp2 = MakeIntReg(); - BuildMI(BB, PPC::RLWINM, 4, Tmp2).addReg(Tmp1).addImm(1) - .addImm(31).addImm(31); - BuildMI(BB, PPC::XORI, 2, Result).addReg(Tmp2).addImm(1); - break; - } - return Result; - } - } - - unsigned CCReg = SelectCC(N.getOperand(0), N.getOperand(1), CC); - MoveCRtoGPR(CCReg, CC, Result); - return Result; - } - - case ISD::SELECT_CC: { - ISD::CondCode CC = cast(N.getOperand(4))->get(); - - // handle the setcc cases here. select_cc lhs, 0, 1, 0, cc - ConstantSDNode *N1C = dyn_cast(N.getOperand(1)); - ConstantSDNode *N2C = dyn_cast(N.getOperand(2)); - ConstantSDNode *N3C = dyn_cast(N.getOperand(3)); - if (N1C && N2C && N3C && N1C->isNullValue() && N3C->isNullValue() && - N2C->getValue() == 1ULL && CC == ISD::SETNE) { - Tmp1 = SelectExpr(Node->getOperand(0)); - Tmp2 = MakeIntReg(); - BuildMI(BB, PPC::ADDIC, 2, Tmp2).addReg(Tmp1).addSImm(-1); - BuildMI(BB, PPC::SUBFE, 2, Result).addReg(Tmp2).addReg(Tmp1); - return Result; - } - - // If the False value only has one use, we can generate better code by - // selecting it in the fallthrough basic block rather than here, which - // increases register pressure. - unsigned TrueValue = SelectExpr(N.getOperand(2)); - unsigned FalseValue; - - // If the false value is simple enough, evaluate it inline in the false - // block. - if (N.getOperand(3).Val->hasOneUse() && - (isa(N.getOperand(3)) || - isa(N.getOperand(3)))) - FalseValue = 0; - else - FalseValue = SelectExpr(N.getOperand(3)); - unsigned CCReg = SelectCC(N.getOperand(0), N.getOperand(1), CC); - Opc = getBCCForSetCC(CC); - - // Create an iterator with which to insert the MBB for copying the false - // value and the MBB to hold the PHI instruction for this SetCC. - MachineBasicBlock *thisMBB = BB; - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - ilist::iterator It = BB; - ++It; - - // thisMBB: - // ... - // TrueVal = ... - // cmpTY ccX, r1, r2 - // bCC copy1MBB - // fallthrough --> copy0MBB - MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB); - MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB); - BuildMI(BB, Opc, 2).addReg(CCReg).addMBB(sinkMBB); - MachineFunction *F = BB->getParent(); - F->getBasicBlockList().insert(It, copy0MBB); - F->getBasicBlockList().insert(It, sinkMBB); - // Update machine-CFG edges - BB->addSuccessor(copy0MBB); - BB->addSuccessor(sinkMBB); - - // copy0MBB: - // %FalseValue = ... - // # fallthrough to sinkMBB - BB = copy0MBB; - - // If the false value is simple enough, evaluate it here, to avoid it being - // evaluated on the true edge. - if (FalseValue == 0) - FalseValue = SelectExpr(N.getOperand(3)); - - // Update machine-CFG edges - BB->addSuccessor(sinkMBB); - - // sinkMBB: - // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] - // ... - BB = sinkMBB; - BuildMI(BB, PPC::PHI, 4, Result).addReg(FalseValue) - .addMBB(copy0MBB).addReg(TrueValue).addMBB(thisMBB); - return Result; - } - - case ISD::Constant: { - assert(N.getValueType() == MVT::i32 && - "Only i32 constants are legal on this target!"); - unsigned v = (unsigned)cast(N)->getValue(); - if (isInt16(v)) { - BuildMI(BB, PPC::LI, 1, Result).addSImm(Lo16(v)); - } else { - unsigned Hi = Hi16(v); - unsigned Lo = Lo16(v); - if (Lo) { - Tmp1 = MakeIntReg(); - BuildMI(BB, PPC::LIS, 1, Tmp1).addSImm(Hi); - BuildMI(BB, PPC::ORI, 2, Result).addReg(Tmp1).addImm(Lo); - } else { - BuildMI(BB, PPC::LIS, 1, Result).addSImm(Hi); - } - } - return Result; - } - - case ISD::FNEG: - if (!NoExcessFPPrecision && - ISD::FADD == N.getOperand(0).getOpcode() && - N.getOperand(0).Val->hasOneUse() && - ISD::FMUL == N.getOperand(0).getOperand(0).getOpcode() && - N.getOperand(0).getOperand(0).Val->hasOneUse()) { - ++FusedFP; // Statistic - Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(1)); - Tmp3 = SelectExpr(N.getOperand(0).getOperand(1)); - Opc = DestType == MVT::f64 ? PPC::FNMADD : PPC::FNMADDS; - BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3); - } else if (!NoExcessFPPrecision && - ISD::FADD == N.getOperand(0).getOpcode() && - N.getOperand(0).Val->hasOneUse() && - ISD::FMUL == N.getOperand(0).getOperand(1).getOpcode() && - N.getOperand(0).getOperand(1).Val->hasOneUse()) { - ++FusedFP; // Statistic - Tmp1 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(0)); - Tmp2 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(1)); - Tmp3 = SelectExpr(N.getOperand(0).getOperand(0)); - Opc = DestType == MVT::f64 ? PPC::FNMADD : PPC::FNMADDS; - BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3); - } else if (ISD::FABS == N.getOperand(0).getOpcode()) { - Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); - if (N.getOperand(0).getValueType() == MVT::f32) - BuildMI(BB, PPC::FNABSS, 1, Result).addReg(Tmp1); - else - BuildMI(BB, PPC::FNABSD, 1, Result).addReg(Tmp1); - - } else { - Tmp1 = SelectExpr(N.getOperand(0)); - if (N.getOperand(0).getValueType() == MVT::f32) - BuildMI(BB, PPC::FNEGS, 1, Result).addReg(Tmp1); - else - BuildMI(BB, PPC::FNEGD, 1, Result).addReg(Tmp1); - } - return Result; - - case ISD::FABS: - Tmp1 = SelectExpr(N.getOperand(0)); - if (N.getOperand(0).getValueType() == MVT::f32) - BuildMI(BB, PPC::FABSS, 1, Result).addReg(Tmp1); - else - BuildMI(BB, PPC::FABSD, 1, Result).addReg(Tmp1); - return Result; - - case ISD::FSQRT: - Tmp1 = SelectExpr(N.getOperand(0)); - Opc = DestType == MVT::f64 ? PPC::FSQRT : PPC::FSQRTS; - BuildMI(BB, Opc, 1, Result).addReg(Tmp1); - return Result; - - case ISD::FP_ROUND: - assert (DestType == MVT::f32 && - N.getOperand(0).getValueType() == MVT::f64 && - "only f64 to f32 conversion supported here"); - Tmp1 = SelectExpr(N.getOperand(0)); - BuildMI(BB, PPC::FRSP, 1, Result).addReg(Tmp1); - return Result; - - case ISD::FP_EXTEND: - assert (DestType == MVT::f64 && - N.getOperand(0).getValueType() == MVT::f32 && - "only f32 to f64 conversion supported here"); - Tmp1 = SelectExpr(N.getOperand(0)); - BuildMI(BB, PPC::FMRSD, 1, Result).addReg(Tmp1); - return Result; - } - return 0; -} - -void ISel::Select(SDOperand N) { - unsigned Tmp1, Tmp2, Tmp3, Opc; - unsigned opcode = N.getOpcode(); - - if (!ExprMap.insert(std::make_pair(N, 1)).second) - return; // Already selected. - - SDNode *Node = N.Val; - - switch (Node->getOpcode()) { - default: - Node->dump(); std::cerr << "\n"; - assert(0 && "Node not handled yet!"); - case ISD::EntryToken: return; // Noop - case ISD::TokenFactor: - for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) - Select(Node->getOperand(i)); - return; - case ISD::CALLSEQ_START: - case ISD::CALLSEQ_END: - Select(N.getOperand(0)); - Tmp1 = cast(N.getOperand(1))->getValue(); - Opc = N.getOpcode() == ISD::CALLSEQ_START ? PPC::ADJCALLSTACKDOWN : - PPC::ADJCALLSTACKUP; - BuildMI(BB, Opc, 1).addImm(Tmp1); - return; - case ISD::BR: { - MachineBasicBlock *Dest = - cast(N.getOperand(1))->getBasicBlock(); - Select(N.getOperand(0)); - BuildMI(BB, PPC::B, 1).addMBB(Dest); - return; - } - case ISD::BR_CC: - case ISD::BRTWOWAY_CC: - SelectBranchCC(N); - return; - case ISD::CopyToReg: - Select(N.getOperand(0)); - Tmp1 = SelectExpr(N.getOperand(2)); - Tmp2 = cast(N.getOperand(1))->getReg(); - - if (Tmp1 != Tmp2) { - if (N.getOperand(2).getValueType() == MVT::f64) - BuildMI(BB, PPC::FMRD, 1, Tmp2).addReg(Tmp1); - else if (N.getOperand(2).getValueType() == MVT::f32) - BuildMI(BB, PPC::FMRS, 1, Tmp2).addReg(Tmp1); - else - BuildMI(BB, PPC::OR, 2, Tmp2).addReg(Tmp1).addReg(Tmp1); - } - return; - case ISD::ImplicitDef: - Select(N.getOperand(0)); - Tmp1 = cast(N.getOperand(1))->getReg(); - if (N.getOperand(1).getValueType() == MVT::i32) - BuildMI(BB, PPC::IMPLICIT_DEF_GPR, 0, Tmp1); - else if (N.getOperand(1).getValueType() == MVT::f32) - BuildMI(BB, PPC::IMPLICIT_DEF_F4, 0, Tmp1); - else - BuildMI(BB, PPC::IMPLICIT_DEF_F8, 0, Tmp1); - return; - case ISD::RET: - switch (N.getNumOperands()) { - default: - assert(0 && "Unknown return instruction!"); - case 3: - assert(N.getOperand(1).getValueType() == MVT::i32 && - N.getOperand(2).getValueType() == MVT::i32 && - "Unknown two-register value!"); - Select(N.getOperand(0)); - Tmp1 = SelectExpr(N.getOperand(1)); - Tmp2 = SelectExpr(N.getOperand(2)); - BuildMI(BB, PPC::OR, 2, PPC::R3).addReg(Tmp2).addReg(Tmp2); - BuildMI(BB, PPC::OR, 2, PPC::R4).addReg(Tmp1).addReg(Tmp1); - break; - case 2: - Select(N.getOperand(0)); - Tmp1 = SelectExpr(N.getOperand(1)); - switch (N.getOperand(1).getValueType()) { - default: - assert(0 && "Unknown return type!"); - case MVT::f64: - BuildMI(BB, PPC::FMRD, 1, PPC::F1).addReg(Tmp1); - break; - case MVT::f32: - BuildMI(BB, PPC::FMRS, 1, PPC::F1).addReg(Tmp1); - break; - case MVT::i32: - BuildMI(BB, PPC::OR, 2, PPC::R3).addReg(Tmp1).addReg(Tmp1); - break; - } - case 1: - Select(N.getOperand(0)); - break; - } - BuildMI(BB, PPC::BLR, 0); // Just emit a 'ret' instruction - return; - case ISD::TRUNCSTORE: - case ISD::STORE: { - SDOperand Chain = N.getOperand(0); - SDOperand Value = N.getOperand(1); - SDOperand Address = N.getOperand(2); - Select(Chain); - - Tmp1 = SelectExpr(Value); //value - - if (opcode == ISD::STORE) { - switch(Value.getValueType()) { - default: assert(0 && "unknown Type in store"); - case MVT::i32: Opc = PPC::STW; break; - case MVT::f64: Opc = PPC::STFD; break; - case MVT::f32: Opc = PPC::STFS; break; - } - } else { //ISD::TRUNCSTORE - switch(cast(Node->getOperand(4))->getVT()) { - default: assert(0 && "unknown Type in store"); - case MVT::i8: Opc = PPC::STB; break; - case MVT::i16: Opc = PPC::STH; break; - } - } - - if(Address.getOpcode() == ISD::FrameIndex) { - Tmp2 = cast(Address)->getIndex(); - addFrameReference(BuildMI(BB, Opc, 3).addReg(Tmp1), (int)Tmp2); - } else { - int offset; - switch(SelectAddr(Address, Tmp2, offset)) { - default: assert(0 && "Unhandled return value from SelectAddr"); - case 0: // imm offset, no frame, no index - BuildMI(BB, Opc, 3).addReg(Tmp1).addSImm(offset).addReg(Tmp2); - break; - case 1: // imm offset + frame index - addFrameReference(BuildMI(BB, Opc, 3).addReg(Tmp1), (int)Tmp2, offset); - break; - case 2: // base+index addressing - Opc = IndexedOpForOp(Opc); - BuildMI(BB, Opc, 3).addReg(Tmp1).addReg(Tmp2).addReg(offset); - break; - case 3: { - GlobalAddressSDNode *GN = cast(Address); - GlobalValue *GV = GN->getGlobal(); - BuildMI(BB, Opc, 3).addReg(Tmp1).addGlobalAddress(GV).addReg(Tmp2); - } - } - } - return; - } - case ISD::EXTLOAD: - case ISD::SEXTLOAD: - case ISD::ZEXTLOAD: - case ISD::LOAD: - case ISD::CopyFromReg: - case ISD::TAILCALL: - case ISD::CALL: - case ISD::DYNAMIC_STACKALLOC: - ExprMap.erase(N); - SelectExpr(N); - return; - } - assert(0 && "Should not be reached!"); -} - - -/// createPPC32PatternInstructionSelector - This pass converts an LLVM function -/// into a machine code representation using pattern matching and a machine -/// description file. -/// -FunctionPass *llvm::createPPC32ISelPattern(TargetMachine &TM) { - return new ISel(TM); -} - diff --git a/llvm/lib/Target/PowerPC/PPC32InstrInfo.cpp b/llvm/lib/Target/PowerPC/PPC32InstrInfo.cpp deleted file mode 100644 index 46f8a72fe03..00000000000 --- a/llvm/lib/Target/PowerPC/PPC32InstrInfo.cpp +++ /dev/null @@ -1,111 +0,0 @@ -//===- PPC32InstrInfo.cpp - PowerPC32 Instruction Information ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the PowerPC implementation of the TargetInstrInfo class. -// -//===----------------------------------------------------------------------===// - -#include "PPC32InstrInfo.h" -#include "PPCGenInstrInfo.inc" -#include "PPC.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include -using namespace llvm; - -PPC32InstrInfo::PPC32InstrInfo() - : TargetInstrInfo(PPCInsts, sizeof(PPCInsts)/sizeof(PPCInsts[0])) {} - -bool PPC32InstrInfo::isMoveInstr(const MachineInstr& MI, - unsigned& sourceReg, - unsigned& destReg) const { - MachineOpCode oc = MI.getOpcode(); - if (oc == PPC::OR) { // or r1, r2, r2 - assert(MI.getNumOperands() == 3 && - MI.getOperand(0).isRegister() && - MI.getOperand(1).isRegister() && - MI.getOperand(2).isRegister() && - "invalid PPC OR instruction!"); - if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) { - sourceReg = MI.getOperand(1).getReg(); - destReg = MI.getOperand(0).getReg(); - return true; - } - } else if (oc == PPC::ADDI) { // addi r1, r2, 0 - assert(MI.getNumOperands() == 3 && - MI.getOperand(0).isRegister() && - MI.getOperand(2).isImmediate() && - "invalid PPC ADDI instruction!"); - if (MI.getOperand(1).isRegister() && MI.getOperand(2).getImmedValue()==0) { - sourceReg = MI.getOperand(1).getReg(); - destReg = MI.getOperand(0).getReg(); - return true; - } - } else if (oc == PPC::ORI) { // ori r1, r2, 0 - assert(MI.getNumOperands() == 3 && - MI.getOperand(0).isRegister() && - MI.getOperand(1).isRegister() && - MI.getOperand(2).isImmediate() && - "invalid PPC ORI instruction!"); - if (MI.getOperand(2).getImmedValue()==0) { - sourceReg = MI.getOperand(1).getReg(); - destReg = MI.getOperand(0).getReg(); - return true; - } - } else if (oc == PPC::FMRS || oc == PPC::FMRD || - oc == PPC::FMRSD) { // fmr r1, r2 - assert(MI.getNumOperands() == 2 && - MI.getOperand(0).isRegister() && - MI.getOperand(1).isRegister() && - "invalid PPC FMR instruction"); - sourceReg = MI.getOperand(1).getReg(); - destReg = MI.getOperand(0).getReg(); - return true; - } else if (oc == PPC::MCRF) { // mcrf cr1, cr2 - assert(MI.getNumOperands() == 2 && - MI.getOperand(0).isRegister() && - MI.getOperand(1).isRegister() && - "invalid PPC MCRF instruction"); - sourceReg = MI.getOperand(1).getReg(); - destReg = MI.getOperand(0).getReg(); - return true; - } - return false; -} - -// commuteInstruction - We can commute rlwimi instructions, but only if the -// rotate amt is zero. We also have to munge the immediates a bit. -MachineInstr *PPC32InstrInfo::commuteInstruction(MachineInstr *MI) const { - // Normal instructions can be commuted the obvious way. - if (MI->getOpcode() != PPC::RLWIMI) - return TargetInstrInfo::commuteInstruction(MI); - - // Cannot commute if it has a non-zero rotate count. - if (MI->getOperand(3).getImmedValue() != 0) - return 0; - - // If we have a zero rotate count, we have: - // M = mask(MB,ME) - // Op0 = (Op1 & ~M) | (Op2 & M) - // Change this to: - // M = mask((ME+1)&31, (MB-1)&31) - // Op0 = (Op2 & ~M) | (Op1 & M) - - // Swap op1/op2 - unsigned Reg1 = MI->getOperand(1).getReg(); - unsigned Reg2 = MI->getOperand(2).getReg(); - MI->SetMachineOperandReg(2, Reg1); - MI->SetMachineOperandReg(1, Reg2); - - // Swap the mask around. - unsigned MB = MI->getOperand(4).getImmedValue(); - unsigned ME = MI->getOperand(5).getImmedValue(); - MI->getOperand(4).setImmedValue((ME+1) & 31); - MI->getOperand(5).setImmedValue((MB-1) & 31); - return MI; -} diff --git a/llvm/lib/Target/PowerPC/PPC32InstrInfo.h b/llvm/lib/Target/PowerPC/PPC32InstrInfo.h deleted file mode 100644 index a6cf5ad1b42..00000000000 --- a/llvm/lib/Target/PowerPC/PPC32InstrInfo.h +++ /dev/null @@ -1,61 +0,0 @@ -//===- PPC32InstrInfo.h - PowerPC32 Instruction Information -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the PowerPC implementation of the TargetInstrInfo class. -// -//===----------------------------------------------------------------------===// - -#ifndef POWERPC32_INSTRUCTIONINFO_H -#define POWERPC32_INSTRUCTIONINFO_H - -#include "PPC.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "PPC32RegisterInfo.h" - -namespace llvm { - -class PPC32InstrInfo : public TargetInstrInfo { - const PPC32RegisterInfo RI; -public: - PPC32InstrInfo(); - - /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As - /// such, whenever a client has an instance of instruction info, it should - /// always be able to get register info as well (through this method). - /// - virtual const MRegisterInfo &getRegisterInfo() const { return RI; } - - // - // Return true if the instruction is a register to register move and - // leave the source and dest operands in the passed parameters. - // - virtual bool isMoveInstr(const MachineInstr& MI, - unsigned& sourceReg, - unsigned& destReg) const; - - // commuteInstruction - We can commute rlwimi instructions, but only if the - // rotate amt is zero. We also have to munge the immediates a bit. - virtual MachineInstr *commuteInstruction(MachineInstr *MI) const; - - static unsigned invertPPCBranchOpcode(unsigned Opcode) { - switch (Opcode) { - default: assert(0 && "Unknown PPC branch opcode!"); - case PPC::BEQ: return PPC::BNE; - case PPC::BNE: return PPC::BEQ; - case PPC::BLT: return PPC::BGE; - case PPC::BGE: return PPC::BLT; - case PPC::BGT: return PPC::BLE; - case PPC::BLE: return PPC::BGT; - } - } -}; - -} - -#endif diff --git a/llvm/lib/Target/PowerPC/PPC32JITInfo.cpp b/llvm/lib/Target/PowerPC/PPC32JITInfo.cpp deleted file mode 100644 index c17dd265e59..00000000000 --- a/llvm/lib/Target/PowerPC/PPC32JITInfo.cpp +++ /dev/null @@ -1,243 +0,0 @@ -//===-- PPC32JITInfo.cpp - Implement the JIT interfaces for the PowerPC ---===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the JIT interfaces for the 32-bit PowerPC target. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "jit" -#include "PPCJITInfo.h" -#include "PPC32Relocations.h" -#include "llvm/CodeGen/MachineCodeEmitter.h" -#include "llvm/Config/alloca.h" -#include -using namespace llvm; - -static TargetJITInfo::JITCompilerFn JITCompilerFunction; - -#define BUILD_ADDIS(RD,RS,IMM16) \ - ((15 << 26) | ((RD) << 21) | ((RS) << 16) | ((IMM16) & 65535)) -#define BUILD_ORI(RD,RS,UIMM16) \ - ((24 << 26) | ((RS) << 21) | ((RD) << 16) | ((UIMM16) & 65535)) -#define BUILD_MTSPR(RS,SPR) \ - ((31 << 26) | ((RS) << 21) | ((SPR) << 16) | (467 << 1)) -#define BUILD_BCCTRx(BO,BI,LINK) \ - ((19 << 26) | ((BO) << 21) | ((BI) << 16) | (528 << 1) | ((LINK) & 1)) - -// Pseudo-ops -#define BUILD_LIS(RD,IMM16) BUILD_ADDIS(RD,0,IMM16) -#define BUILD_MTCTR(RS) BUILD_MTSPR(RS,9) -#define BUILD_BCTR(LINK) BUILD_BCCTRx(20,0,LINK) - - -static void EmitBranchToAt(void *At, void *To, bool isCall) { - intptr_t Addr = (intptr_t)To; - - // FIXME: should special case the short branch case. - unsigned *AtI = (unsigned*)At; - - AtI[0] = BUILD_LIS(12, Addr >> 16); // lis r12, hi16(address) - AtI[1] = BUILD_ORI(12, 12, Addr); // ori r12, r12, low16(address) - AtI[2] = BUILD_MTCTR(12); // mtctr r12 - AtI[3] = BUILD_BCTR(isCall); // bctr/bctrl -} - -extern "C" void PPC32CompilationCallback(); - -#if defined(__POWERPC__) || defined (__ppc__) || defined(_POWER) -// CompilationCallback stub - We can't use a C function with inline assembly in -// it, because we the prolog/epilog inserted by GCC won't work for us. Instead, -// write our own wrapper, which does things our way, so we have complete control -// over register saving and restoring. -asm( - ".text\n" - ".align 2\n" - ".globl _PPC32CompilationCallback\n" -"_PPC32CompilationCallback:\n" - // Make space for 29 ints r[3-31] and 14 doubles f[0-13] - "stwu r1, -272(r1)\n" - "mflr r11\n" - "stw r11, 280(r1)\n" // Set up a proper stack frame - "stmw r3, 156(r1)\n" // Save all of the integer registers - // Save all call-clobbered FP regs. - "stfd f1, 44(r1)\n" "stfd f2, 52(r1)\n" "stfd f3, 60(r1)\n" - "stfd f4, 68(r1)\n" "stfd f5, 76(r1)\n" "stfd f6, 84(r1)\n" - "stfd f7, 92(r1)\n" "stfd f8, 100(r1)\n" "stfd f9, 108(r1)\n" - "stfd f10, 116(r1)\n" "stfd f11, 124(r1)\n" "stfd f12, 132(r1)\n" - "stfd f13, 140(r1)\n" - - // Now that everything is saved, go to the C compilation callback function, - // passing the address of the intregs and fpregs. - "addi r3, r1, 156\n" // &IntRegs[0] - "addi r4, r1, 44\n" // &FPRegs[0] - "bl _PPC32CompilationCallbackC\n" - ); -#else -void PPC32CompilationCallback() { - assert(0 && "This is not a power pc, you can't execute this!"); - abort(); -} -#endif - -extern "C" void PPC32CompilationCallbackC(unsigned *IntRegs, double *FPRegs) { - unsigned *CameFromStub = (unsigned*)__builtin_return_address(0+1); - unsigned *CameFromOrig = (unsigned*)__builtin_return_address(1+1); - unsigned *CCStackPtr = (unsigned*)__builtin_frame_address(0); -//unsigned *StubStackPtr = (unsigned*)__builtin_frame_address(1); - unsigned *OrigStackPtr = (unsigned*)__builtin_frame_address(2+1); - - // Adjust pointer to the branch, not the return address. - --CameFromStub; - - void *Target = JITCompilerFunction(CameFromStub); - - // Check to see if CameFromOrig[-1] is a 'bl' instruction, and if we can - // rewrite it to branch directly to the destination. If so, rewrite it so it - // does not need to go through the stub anymore. - unsigned CameFromOrigInst = CameFromOrig[-1]; - if ((CameFromOrigInst >> 26) == 18) { // Direct call. - intptr_t Offset = ((intptr_t)Target-(intptr_t)CameFromOrig+4) >> 2; - if (Offset >= -(1 << 23) && Offset < (1 << 23)) { // In range? - // Clear the original target out. - CameFromOrigInst &= (63 << 26) | 3; - // Fill in the new target. - CameFromOrigInst |= (Offset & ((1 << 24)-1)) << 2; - // Replace the call. - CameFromOrig[-1] = CameFromOrigInst; - } - } - - // Locate the start of the stub. If this is a short call, adjust backwards - // the short amount, otherwise the full amount. - bool isShortStub = (*CameFromStub >> 26) == 18; - CameFromStub -= isShortStub ? 2 : 6; - - // Rewrite the stub with an unconditional branch to the target, for any users - // who took the address of the stub. - EmitBranchToAt(CameFromStub, Target, false); - - // Change the SP so that we pop two stack frames off when we return. - *CCStackPtr = (intptr_t)OrigStackPtr; - - // Put the address of the stub and the LR value that originally came into the - // stub in a place that is easy to get on the stack after we restore all regs. - CCStackPtr[2] = (intptr_t)Target; - CCStackPtr[1] = (intptr_t)CameFromOrig; - - // Note, this is not a standard epilog! -#if defined(__POWERPC__) || defined (__ppc__) || defined(_POWER) - register unsigned *IRR asm ("r2") = IntRegs; - register double *FRR asm ("r3") = FPRegs; - __asm__ __volatile__ ( - "lfd f1, 0(%0)\n" "lfd f2, 8(%0)\n" "lfd f3, 16(%0)\n" - "lfd f4, 24(%0)\n" "lfd f5, 32(%0)\n" "lfd f6, 40(%0)\n" - "lfd f7, 48(%0)\n" "lfd f8, 56(%0)\n" "lfd f9, 64(%0)\n" - "lfd f10, 72(%0)\n" "lfd f11, 80(%0)\n" "lfd f12, 88(%0)\n" - "lfd f13, 96(%0)\n" - "lmw r3, 0(%1)\n" // Load all integer regs - "lwz r0,4(r1)\n" // Get CameFromOrig (LR into stub) - "mtlr r0\n" // Put it in the LR register - "lwz r0,8(r1)\n" // Get target function pointer - "mtctr r0\n" // Put it into the CTR register - "lwz r1,0(r1)\n" // Pop two frames off - "bctr\n" :: // Return to stub! - "b" (FRR), "b" (IRR)); -#endif -} - - - -TargetJITInfo::LazyResolverFn -PPC32JITInfo::getLazyResolverFunction(JITCompilerFn Fn) { - JITCompilerFunction = Fn; - return PPC32CompilationCallback; -} - -void *PPC32JITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter &MCE) { - // If this is just a call to an external function, emit a branch instead of a - // call. The code is the same except for one bit of the last instruction. - if (Fn != PPC32CompilationCallback) { - MCE.startFunctionStub(4*4); - void *Addr = (void*)(intptr_t)MCE.getCurrentPCValue(); - MCE.emitWord(0); - MCE.emitWord(0); - MCE.emitWord(0); - MCE.emitWord(0); - EmitBranchToAt(Addr, Fn, false); - return MCE.finishFunctionStub(0); - } - - MCE.startFunctionStub(4*7); - MCE.emitWord(0x9421ffe0); // stwu r1,-32(r1) - MCE.emitWord(0x7d6802a6); // mflr r11 - MCE.emitWord(0x91610028); // stw r11, 40(r1) - void *Addr = (void*)(intptr_t)MCE.getCurrentPCValue(); - MCE.emitWord(0); - MCE.emitWord(0); - MCE.emitWord(0); - MCE.emitWord(0); - EmitBranchToAt(Addr, Fn, true/*is call*/); - return MCE.finishFunctionStub(0); -} - - -void PPC32JITInfo::relocate(void *Function, MachineRelocation *MR, - unsigned NumRelocs, unsigned char* GOTBase) { - for (unsigned i = 0; i != NumRelocs; ++i, ++MR) { - unsigned *RelocPos = (unsigned*)Function + MR->getMachineCodeOffset()/4; - intptr_t ResultPtr = (intptr_t)MR->getResultPointer(); - switch ((PPC::RelocationType)MR->getRelocationType()) { - default: assert(0 && "Unknown relocation type!"); - case PPC::reloc_pcrel_bx: - // PC-relative relocation for b and bl instructions. - ResultPtr = (ResultPtr-(intptr_t)RelocPos) >> 2; - assert(ResultPtr >= -(1 << 23) && ResultPtr < (1 << 23) && - "Relocation out of range!"); - *RelocPos |= (ResultPtr & ((1 << 24)-1)) << 2; - break; - - case PPC::reloc_absolute_ptr_high: // Pointer relocations. - case PPC::reloc_absolute_ptr_low: { - // Pointer relocations are used for the PPC external stubs and lazy - // resolver pointers that the Darwin ABI likes to use. Basically, the - // address of the global is actually stored in memory, and the address of - // the pointer is relocated into instructions instead of the pointer - // itself. Because we have to keep the mapping anyway, we just return - // pointers to the values in the map as our new location. - static std::set Pointers; - ResultPtr = (intptr_t)&*Pointers.insert((void*)ResultPtr).first; - } - // FALL THROUGH - case PPC::reloc_absolute_high: // high bits of ref -> low 16 of instr - case PPC::reloc_absolute_low: // low bits of ref -> low 16 of instr - ResultPtr += MR->getConstantVal(); - - // If this is a high-part access, get the high-part. - if (MR->getRelocationType() == PPC::reloc_absolute_high || - MR->getRelocationType() == PPC::reloc_absolute_ptr_high) { - // If the low part will have a carry (really a borrow) from the low - // 16-bits into the high 16, add a bit to borrow from. - if (((int)ResultPtr << 16) < 0) - ResultPtr += 1 << 16; - ResultPtr >>= 16; - } - - // Do the addition then mask, so the addition does not overflow the 16-bit - // immediate section of the instruction. - unsigned LowBits = (*RelocPos + ResultPtr) & 65535; - unsigned HighBits = *RelocPos & ~65535; - *RelocPos = LowBits | HighBits; // Slam into low 16-bits - break; - } - } -} - -void PPC32JITInfo::replaceMachineCodeForFunction(void *Old, void *New) { - EmitBranchToAt(Old, New, false); -} diff --git a/llvm/lib/Target/PowerPC/PPC32RegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPC32RegisterInfo.cpp deleted file mode 100644 index aad9861cd78..00000000000 --- a/llvm/lib/Target/PowerPC/PPC32RegisterInfo.cpp +++ /dev/null @@ -1,346 +0,0 @@ -//===- PPC32RegisterInfo.cpp - PowerPC32 Register Information ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the PowerPC32 implementation of the MRegisterInfo class. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "reginfo" -#include "PPC.h" -#include "PPCInstrBuilder.h" -#include "PPC32RegisterInfo.h" -#include "llvm/Constants.h" -#include "llvm/Type.h" -#include "llvm/CodeGen/ValueTypes.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/Target/TargetFrameInfo.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/ADT/STLExtras.h" -#include -#include -using namespace llvm; - -PPC32RegisterInfo::PPC32RegisterInfo() - : PPCGenRegisterInfo(PPC::ADJCALLSTACKDOWN, PPC::ADJCALLSTACKUP) { - ImmToIdxMap[PPC::LD] = PPC::LDX; ImmToIdxMap[PPC::STD] = PPC::STDX; - ImmToIdxMap[PPC::LBZ] = PPC::LBZX; ImmToIdxMap[PPC::STB] = PPC::STBX; - ImmToIdxMap[PPC::LHZ] = PPC::LHZX; ImmToIdxMap[PPC::LHA] = PPC::LHAX; - ImmToIdxMap[PPC::LWZ] = PPC::LWZX; ImmToIdxMap[PPC::LWA] = PPC::LWAX; - ImmToIdxMap[PPC::LFS] = PPC::LFSX; ImmToIdxMap[PPC::LFD] = PPC::LFDX; - ImmToIdxMap[PPC::STH] = PPC::STHX; ImmToIdxMap[PPC::STW] = PPC::STWX; - ImmToIdxMap[PPC::STFS] = PPC::STFSX; ImmToIdxMap[PPC::STFD] = PPC::STFDX; - ImmToIdxMap[PPC::ADDI] = PPC::ADD; -} - -void -PPC32RegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - unsigned SrcReg, int FrameIdx, - const TargetRegisterClass *RC) const { - if (SrcReg == PPC::LR) { - BuildMI(MBB, MI, PPC::MFLR, 1, PPC::R11); - addFrameReference(BuildMI(MBB, MI, PPC::STW, 3).addReg(PPC::R11), FrameIdx); - } else if (RC == PPC32::CRRCRegisterClass) { - BuildMI(MBB, MI, PPC::MFCR, 0, PPC::R11); - addFrameReference(BuildMI(MBB, MI, PPC::STW, 3).addReg(PPC::R11), FrameIdx); - } else if (RC == PPC32::GPRCRegisterClass) { - addFrameReference(BuildMI(MBB, MI, PPC::STW, 3).addReg(SrcReg),FrameIdx); - } else if (RC == PPC32::F8RCRegisterClass) { - addFrameReference(BuildMI(MBB, MI, PPC::STFD, 3).addReg(SrcReg),FrameIdx); - } else if (RC == PPC32::F4RCRegisterClass) { - addFrameReference(BuildMI(MBB, MI, PPC::STFS, 3).addReg(SrcReg),FrameIdx); - } else { - assert(0 && "Unknown regclass!"); - abort(); - } -} - -void -PPC32RegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - unsigned DestReg, int FrameIdx, - const TargetRegisterClass *RC) const { - if (DestReg == PPC::LR) { - addFrameReference(BuildMI(MBB, MI, PPC::LWZ, 2, PPC::R11), FrameIdx); - BuildMI(MBB, MI, PPC::MTLR, 1).addReg(PPC::R11); - } else if (RC == PPC32::CRRCRegisterClass) { - addFrameReference(BuildMI(MBB, MI, PPC::LWZ, 2, PPC::R11), FrameIdx); - BuildMI(MBB, MI, PPC::MTCRF, 1, DestReg).addReg(PPC::R11); - } else if (RC == PPC32::GPRCRegisterClass) { - addFrameReference(BuildMI(MBB, MI, PPC::LWZ, 2, DestReg), FrameIdx); - } else if (RC == PPC32::F8RCRegisterClass) { - addFrameReference(BuildMI(MBB, MI, PPC::LFD, 2, DestReg), FrameIdx); - } else if (RC == PPC32::F4RCRegisterClass) { - addFrameReference(BuildMI(MBB, MI, PPC::LFS, 2, DestReg), FrameIdx); - } else { - assert(0 && "Unknown regclass!"); - abort(); - } -} - -void PPC32RegisterInfo::copyRegToReg(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - unsigned DestReg, unsigned SrcReg, - const TargetRegisterClass *RC) const { - MachineInstr *I; - - if (RC == PPC32::GPRCRegisterClass) { - BuildMI(MBB, MI, PPC::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg); - } else if (RC == PPC32::F4RCRegisterClass) { - BuildMI(MBB, MI, PPC::FMRS, 1, DestReg).addReg(SrcReg); - } else if (RC == PPC32::F8RCRegisterClass) { - BuildMI(MBB, MI, PPC::FMRD, 1, DestReg).addReg(SrcReg); - } else if (RC == PPC32::CRRCRegisterClass) { - BuildMI(MBB, MI, PPC::MCRF, 1, DestReg).addReg(SrcReg); - } else { - std::cerr << "Attempt to copy register that is not GPR or FPR"; - abort(); - } -} - -unsigned PPC32RegisterInfo::isLoadFromStackSlot(MachineInstr *MI, - int &FrameIndex) const { - switch (MI->getOpcode()) { - default: break; - case PPC::LWZ: - case PPC::LFS: - case PPC::LFD: - if (MI->getOperand(1).isImmediate() && !MI->getOperand(1).getImmedValue() && - MI->getOperand(2).isFrameIndex()) { - FrameIndex = MI->getOperand(2).getFrameIndex(); - return MI->getOperand(0).getReg(); - } - break; - } - return 0; -} - -/// foldMemoryOperand - PowerPC (like most RISC's) can only fold spills into -/// copy instructions, turning them into load/store instructions. -MachineInstr *PPC32RegisterInfo::foldMemoryOperand(MachineInstr *MI, - unsigned OpNum, - int FrameIndex) const { - // Make sure this is a reg-reg copy. Note that we can't handle MCRF, because - // it takes more than one instruction to store it. - unsigned Opc = MI->getOpcode(); - - if ((Opc == PPC::OR && - MI->getOperand(1).getReg() == MI->getOperand(2).getReg())) { - if (OpNum == 0) { // move -> store - unsigned InReg = MI->getOperand(1).getReg(); - return addFrameReference(BuildMI(PPC::STW, - 3).addReg(InReg), FrameIndex); - } else { // move -> load - unsigned OutReg = MI->getOperand(0).getReg(); - return addFrameReference(BuildMI(PPC::LWZ, 2, OutReg), FrameIndex); - } - - } else if (Opc == PPC::FMRD) { - if (OpNum == 0) { // move -> store - unsigned InReg = MI->getOperand(1).getReg(); - return addFrameReference(BuildMI(PPC::STFD, - 3).addReg(InReg), FrameIndex); - } else { // move -> load - unsigned OutReg = MI->getOperand(0).getReg(); - return addFrameReference(BuildMI(PPC::LFD, 2, OutReg), FrameIndex); - } - } else if (Opc == PPC::FMRS) { - if (OpNum == 0) { // move -> store - unsigned InReg = MI->getOperand(1).getReg(); - return addFrameReference(BuildMI(PPC::STFS, - 3).addReg(InReg), FrameIndex); - } else { // move -> load - unsigned OutReg = MI->getOperand(0).getReg(); - return addFrameReference(BuildMI(PPC::LFS, 2, OutReg), FrameIndex); - } - } - return 0; -} - -//===----------------------------------------------------------------------===// -// Stack Frame Processing methods -//===----------------------------------------------------------------------===// - -// hasFP - Return true if the specified function should have a dedicated frame -// pointer register. This is true if the function has variable sized allocas or -// if frame pointer elimination is disabled. -// -static bool hasFP(MachineFunction &MF) { - return NoFramePointerElim || MF.getFrameInfo()->hasVarSizedObjects(); -} - -void PPC32RegisterInfo:: -eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { - if (hasFP(MF)) { - // If we have a frame pointer, convert as follows: - // ADJCALLSTACKDOWN -> addi, r1, r1, -amount - // ADJCALLSTACKUP -> addi, r1, r1, amount - MachineInstr *Old = I; - unsigned Amount = Old->getOperand(0).getImmedValue(); - if (Amount != 0) { - // We need to keep the stack aligned properly. To do this, we round the - // amount of space needed for the outgoing arguments up to the next - // alignment boundary. - unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment(); - Amount = (Amount+Align-1)/Align*Align; - - // Replace the pseudo instruction with a new instruction... - if (Old->getOpcode() == PPC::ADJCALLSTACKDOWN) { - MBB.insert(I, BuildMI(PPC::ADDI, 2, PPC::R1).addReg(PPC::R1) - .addSImm(-Amount)); - } else { - assert(Old->getOpcode() == PPC::ADJCALLSTACKUP); - MBB.insert(I, BuildMI(PPC::ADDI, 2, PPC::R1).addReg(PPC::R1) - .addSImm(Amount)); - } - } - } - MBB.erase(I); -} - -void -PPC32RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const { - unsigned i = 0; - MachineInstr &MI = *II; - MachineBasicBlock &MBB = *MI.getParent(); - MachineFunction &MF = *MBB.getParent(); - - while (!MI.getOperand(i).isFrameIndex()) { - ++i; - assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); - } - - int FrameIndex = MI.getOperand(i).getFrameIndex(); - - // Replace the FrameIndex with base register with GPR1 (SP) or GPR31 (FP). - MI.SetMachineOperandReg(i, hasFP(MF) ? PPC::R31 : PPC::R1); - - // Take into account whether it's an add or mem instruction - unsigned OffIdx = (i == 2) ? 1 : 2; - - // Now add the frame object offset to the offset from r1. - int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + - MI.getOperand(OffIdx).getImmedValue(); - - // If we're not using a Frame Pointer that has been set to the value of the - // SP before having the stack size subtracted from it, then add the stack size - // to Offset to get the correct offset. - Offset += MF.getFrameInfo()->getStackSize(); - - if (Offset > 32767 || Offset < -32768) { - // Insert a set of r0 with the full offset value before the ld, st, or add - MachineBasicBlock *MBB = MI.getParent(); - MBB->insert(II, BuildMI(PPC::LIS, 1, PPC::R0).addSImm(Offset >> 16)); - MBB->insert(II, BuildMI(PPC::ORI, 2, PPC::R0).addReg(PPC::R0) - .addImm(Offset)); - // convert into indexed form of the instruction - // sth 0:rA, 1:imm 2:(rB) ==> sthx 0:rA, 2:rB, 1:r0 - // addi 0:rA 1:rB, 2, imm ==> add 0:rA, 1:rB, 2:r0 - assert(ImmToIdxMap.count(MI.getOpcode()) && - "No indexed form of load or store available!"); - unsigned NewOpcode = ImmToIdxMap.find(MI.getOpcode())->second; - MI.setOpcode(NewOpcode); - MI.SetMachineOperandReg(1, MI.getOperand(i).getReg()); - MI.SetMachineOperandReg(2, PPC::R0); - } else { - MI.SetMachineOperandConst(OffIdx, MachineOperand::MO_SignExtendedImmed, - Offset); - } -} - - -void PPC32RegisterInfo::emitPrologue(MachineFunction &MF) const { - MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB - MachineBasicBlock::iterator MBBI = MBB.begin(); - MachineFrameInfo *MFI = MF.getFrameInfo(); - MachineInstr *MI; - - // Get the number of bytes to allocate from the FrameInfo - unsigned NumBytes = MFI->getStackSize(); - - // If we have calls, we cannot use the red zone to store callee save registers - // and we must set up a stack frame, so calculate the necessary size here. - if (MFI->hasCalls()) { - // We reserve argument space for call sites in the function immediately on - // entry to the current function. This eliminates the need for add/sub - // brackets around call sites. - NumBytes += MFI->getMaxCallFrameSize(); - } - - // If we are a leaf function, and use up to 224 bytes of stack space, - // and don't have a frame pointer, then we do not need to adjust the stack - // pointer (we fit in the Red Zone). - if ((NumBytes == 0) || (NumBytes <= 224 && !hasFP(MF) && !MFI->hasCalls())) { - MFI->setStackSize(0); - return; - } - - // Add the size of R1 to NumBytes size for the store of R1 to the bottom - // of the stack and round the size to a multiple of the alignment. - unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment(); - unsigned GPRSize = 4; - unsigned Size = hasFP(MF) ? GPRSize + GPRSize : GPRSize; - NumBytes = (NumBytes+Size+Align-1)/Align*Align; - - // Update frame info to pretend that this is part of the stack... - MFI->setStackSize(NumBytes); - - // Adjust stack pointer: r1 -= numbytes. - if (NumBytes <= 32768) { - MI=BuildMI(PPC::STWU,3).addReg(PPC::R1).addSImm(-NumBytes).addReg(PPC::R1); - MBB.insert(MBBI, MI); - } else { - int NegNumbytes = -NumBytes; - MI = BuildMI(PPC::LIS, 1, PPC::R0).addSImm(NegNumbytes >> 16); - MBB.insert(MBBI, MI); - MI = BuildMI(PPC::ORI, 2, PPC::R0).addReg(PPC::R0) - .addImm(NegNumbytes & 0xFFFF); - MBB.insert(MBBI, MI); - MI = BuildMI(PPC::STWUX, 3).addReg(PPC::R1).addReg(PPC::R1).addReg(PPC::R0); - MBB.insert(MBBI, MI); - } - - if (hasFP(MF)) { - MI = BuildMI(PPC::STW, 3).addReg(PPC::R31).addSImm(GPRSize).addReg(PPC::R1); - MBB.insert(MBBI, MI); - MI = BuildMI(PPC::OR, 2, PPC::R31).addReg(PPC::R1).addReg(PPC::R1); - MBB.insert(MBBI, MI); - } -} - -void PPC32RegisterInfo::emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const { - const MachineFrameInfo *MFI = MF.getFrameInfo(); - MachineBasicBlock::iterator MBBI = prior(MBB.end()); - MachineInstr *MI; - assert(MBBI->getOpcode() == PPC::BLR && - "Can only insert epilog into returning blocks"); - - // Get the number of bytes allocated from the FrameInfo... - unsigned NumBytes = MFI->getStackSize(); - unsigned GPRSize = 4; - - if (NumBytes != 0) { - if (hasFP(MF)) { - MI = BuildMI(PPC::LWZ, 2, PPC::R31).addSImm(GPRSize).addReg(PPC::R31); - MBB.insert(MBBI, MI); - } - MI = BuildMI(PPC::LWZ, 2, PPC::R1).addSImm(0).addReg(PPC::R1); - MBB.insert(MBBI, MI); - } -} - -#include "PPCGenRegisterInfo.inc" - diff --git a/llvm/lib/Target/PowerPC/PPC32RegisterInfo.h b/llvm/lib/Target/PowerPC/PPC32RegisterInfo.h deleted file mode 100644 index e9ef9ce2eef..00000000000 --- a/llvm/lib/Target/PowerPC/PPC32RegisterInfo.h +++ /dev/null @@ -1,64 +0,0 @@ -//===- PPC32RegisterInfo.h - PowerPC32 Register Information Impl -*- C++ -*-==// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the PowerPC implementation of the MRegisterInfo class. -// -//===----------------------------------------------------------------------===// - -#ifndef POWERPC32_REGISTERINFO_H -#define POWERPC32_REGISTERINFO_H - -#include "PPC.h" -#include "PPCGenRegisterInfo.h.inc" -#include - -namespace llvm { - -class Type; - -class PPC32RegisterInfo : public PPCGenRegisterInfo { - std::map ImmToIdxMap; -public: - PPC32RegisterInfo(); - - /// Code Generation virtual methods... - void storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - unsigned SrcReg, int FrameIndex, - const TargetRegisterClass *RC) const; - - void loadRegFromStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - unsigned DestReg, int FrameIndex, - const TargetRegisterClass *RC) const; - - void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, - unsigned DestReg, unsigned SrcReg, - const TargetRegisterClass *RC) const; - - unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const; - - /// foldMemoryOperand - PowerPC (like most RISC's) can only fold spills into - /// copy instructions, turning them into load/store instructions. - virtual MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum, - int FrameIndex) const; - - void eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const; - - void eliminateFrameIndex(MachineBasicBlock::iterator II) const; - - void emitPrologue(MachineFunction &MF) const; - void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; -}; - -} // end namespace llvm - -#endif diff --git a/llvm/lib/Target/PowerPC/PPC32Relocations.h b/llvm/lib/Target/PowerPC/PPC32Relocations.h deleted file mode 100644 index f6c9384d7d5..00000000000 --- a/llvm/lib/Target/PowerPC/PPC32Relocations.h +++ /dev/null @@ -1,58 +0,0 @@ -//===- PPC32Relocations.h - PPC32 Code Relocations --------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the PowerPC 32-bit target-specific relocation types. -// -//===----------------------------------------------------------------------===// - -#ifndef PPC32RELOCATIONS_H -#define PPC32RELOCATIONS_H - -#include "llvm/CodeGen/MachineRelocation.h" - -// Hack to rid us of a PPC pre-processor symbol which is erroneously -// defined in a PowerPC header file (bug in Linux/PPC) -#ifdef PPC -#undef PPC -#endif - -namespace llvm { - namespace PPC { - enum RelocationType { - // reloc_pcrel_bx - PC relative relocation, for the b or bl instructions. - reloc_pcrel_bx, - - // reloc_absolute_high - Absolute relocation, for the loadhi instruction - // (which is really addis). Add the high 16-bits of the specified global - // address into the low 16-bits of the instruction. - reloc_absolute_high, - - // reloc_absolute_low - Absolute relocation, for the la instruction (which - // is really an addi). Add the low 16-bits of teh specified global - // address into the low 16-bits of the instruction. - reloc_absolute_low, - - // reloc_absolute_ptr_high - Absolute relocation for references to lazy - // pointer stubs. In this case, the relocated instruction should be - // relocated to point to a POINTER to the indicated global. The low-16 - // bits of the instruction are rewritten with the high 16-bits of the - // address of the pointer. - reloc_absolute_ptr_high, - - // reloc_absolute_ptr_low - Absolute relocation for references to lazy - // pointer stubs. In this case, the relocated instruction should be - // relocated to point to a POINTER to the indicated global. The low-16 - // bits of the instruction are rewritten with the low 16-bits of the - // address of the pointer. - reloc_absolute_ptr_low, - }; - } -} - -#endif diff --git a/llvm/lib/Target/PowerPC/PPC32TargetMachine.h b/llvm/lib/Target/PowerPC/PPC32TargetMachine.h deleted file mode 100644 index 0df2ac7281f..00000000000 --- a/llvm/lib/Target/PowerPC/PPC32TargetMachine.h +++ /dev/null @@ -1,74 +0,0 @@ -//===-- PPC32TargetMachine.h - Define TargetMachine for PowerPC -*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares the PowerPC specific subclass of TargetMachine. -// -//===----------------------------------------------------------------------===// - -#ifndef POWERPC32_TARGETMACHINE_H -#define POWERPC32_TARGETMACHINE_H - -#include "PPCFrameInfo.h" -#include "PPCSubtarget.h" -#include "PPCJITInfo.h" -#include "PPC32InstrInfo.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetFrameInfo.h" -#include "llvm/PassManager.h" - -namespace llvm { - -class IntrinsicLowering; -class GlobalValue; -class IntrinsicLowering; - -// FIXME: Merge into only subclass. -class PowerPCTargetMachine : public TargetMachine { - PowerPCFrameInfo FrameInfo; - PPCSubtarget Subtarget; -protected: - PowerPCTargetMachine(const std::string &name, IntrinsicLowering *IL, - const Module &M, const std::string &FS, - const TargetData &TD, - const PowerPCFrameInfo &TFI); -public: - virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; } - virtual const TargetSubtarget *getSubtargetImpl() const{ return &Subtarget; } - - virtual bool addPassesToEmitFile(PassManager &PM, std::ostream &Out, - CodeGenFileType FileType); -}; - -class PPC32TargetMachine : public PowerPCTargetMachine { - PPC32InstrInfo InstrInfo; - PPC32JITInfo JITInfo; - -public: - PPC32TargetMachine(const Module &M, IntrinsicLowering *IL, - const std::string &FS); - virtual const PPC32InstrInfo *getInstrInfo() const { return &InstrInfo; } - virtual const MRegisterInfo *getRegisterInfo() const { - return &InstrInfo.getRegisterInfo(); - } - - virtual TargetJITInfo *getJITInfo() { - return &JITInfo; - } - - static unsigned getJITMatchQuality(); - - static unsigned getModuleMatchQuality(const Module &M); - - bool addPassesToEmitMachineCode(FunctionPassManager &PM, - MachineCodeEmitter &MCE); -}; - -} // end namespace llvm - -#endif diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index 1c6196cc2d5..670bc789c15 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -18,7 +18,7 @@ #define DEBUG_TYPE "asmprinter" #include "PPC.h" -#include "PPC32TargetMachine.h" +#include "PPCTargetMachine.h" #include "PPCSubtarget.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" diff --git a/llvm/lib/Target/PowerPC/PPCBranchSelector.cpp b/llvm/lib/Target/PowerPC/PPCBranchSelector.cpp index e4b65c49340..0c07d816218 100644 --- a/llvm/lib/Target/PowerPC/PPCBranchSelector.cpp +++ b/llvm/lib/Target/PowerPC/PPCBranchSelector.cpp @@ -18,7 +18,7 @@ #define DEBUG_TYPE "bsel" #include "PPC.h" #include "PPCInstrBuilder.h" -#include "PPC32InstrInfo.h" +#include "PPCInstrInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/Support/Debug.h" #include diff --git a/llvm/lib/Target/PowerPC/PPCCodeEmitter.cpp b/llvm/lib/Target/PowerPC/PPCCodeEmitter.cpp new file mode 100644 index 00000000000..5045c68ef12 --- /dev/null +++ b/llvm/lib/Target/PowerPC/PPCCodeEmitter.cpp @@ -0,0 +1,264 @@ +//===-- PPCCodeEmitter.cpp - JIT Code Emitter for PowerPC32 -----*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the PowerPC 32-bit CodeEmitter and associated machinery to +// JIT-compile bytecode to native PowerPC. +// +//===----------------------------------------------------------------------===// + +#include "PPCTargetMachine.h" +#include "PPCRelocations.h" +#include "PPC.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/Debug.h" +using namespace llvm; + +namespace { + class PPCCodeEmitter : public MachineFunctionPass { + TargetMachine &TM; + MachineCodeEmitter &MCE; + + // Tracks which instruction references which BasicBlock + std::vector > BBRefs; + // Tracks where each BasicBlock starts + std::map BBLocations; + + /// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr + /// + int getMachineOpValue(MachineInstr &MI, MachineOperand &MO); + + public: + PPCCodeEmitter(TargetMachine &T, MachineCodeEmitter &M) + : TM(T), MCE(M) {} + + const char *getPassName() const { return "PowerPC Machine Code Emitter"; } + + /// runOnMachineFunction - emits the given MachineFunction to memory + /// + bool runOnMachineFunction(MachineFunction &MF); + + /// emitBasicBlock - emits the given MachineBasicBlock to memory + /// + void emitBasicBlock(MachineBasicBlock &MBB); + + /// emitWord - write a 32-bit word to memory at the current PC + /// + void emitWord(unsigned w) { MCE.emitWord(w); } + + /// getValueBit - return the particular bit of Val + /// + unsigned getValueBit(int64_t Val, unsigned bit) { return (Val >> bit) & 1; } + + /// getBinaryCodeForInstr - This function, generated by the + /// CodeEmitterGenerator using TableGen, produces the binary encoding for + /// machine instructions. + /// + unsigned getBinaryCodeForInstr(MachineInstr &MI); + }; +} + +/// addPassesToEmitMachineCode - Add passes to the specified pass manager to get +/// machine code emitted. This uses a MachineCodeEmitter object to handle +/// actually outputting the machine code and resolving things like the address +/// of functions. This method should returns true if machine code emission is +/// not supported. +/// +bool PPC32TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM, + MachineCodeEmitter &MCE) { + // Machine code emitter pass for PowerPC + PM.add(new PPCCodeEmitter(*this, MCE)); + // Delete machine code for this function after emitting it + PM.add(createMachineCodeDeleter()); + return false; +} + +bool PPCCodeEmitter::runOnMachineFunction(MachineFunction &MF) { + MCE.startFunction(MF); + MCE.emitConstantPool(MF.getConstantPool()); + for (MachineFunction::iterator BB = MF.begin(), E = MF.end(); BB != E; ++BB) + emitBasicBlock(*BB); + MCE.finishFunction(MF); + + // Resolve branches to BasicBlocks for the entire function + for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) { + intptr_t Location = BBLocations[BBRefs[i].first]; + unsigned *Ref = BBRefs[i].second; + DEBUG(std::cerr << "Fixup @ " << (void*)Ref << " to " << (void*)Location + << "\n"); + unsigned Instr = *Ref; + intptr_t BranchTargetDisp = (Location - (intptr_t)Ref) >> 2; + + switch (Instr >> 26) { + default: assert(0 && "Unknown branch user!"); + case 18: // This is B or BL + *Ref |= (BranchTargetDisp & ((1 << 24)-1)) << 2; + break; + case 16: // This is BLT,BLE,BEQ,BGE,BGT,BNE, or other bcx instruction + *Ref |= (BranchTargetDisp & ((1 << 14)-1)) << 2; + break; + } + } + BBRefs.clear(); + BBLocations.clear(); + + return false; +} + +void PPCCodeEmitter::emitBasicBlock(MachineBasicBlock &MBB) { + assert(!PICEnabled && "CodeEmitter does not support PIC!"); + BBLocations[&MBB] = MCE.getCurrentPCValue(); + for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I){ + MachineInstr &MI = *I; + unsigned Opcode = MI.getOpcode(); + switch (MI.getOpcode()) { + default: + emitWord(getBinaryCodeForInstr(*I)); + break; + case PPC::IMPLICIT_DEF_GPR: + case PPC::IMPLICIT_DEF_F8: + case PPC::IMPLICIT_DEF_F4: + break; // pseudo opcode, no side effects + case PPC::MovePCtoLR: + assert(0 && "CodeEmitter does not support MovePCtoLR instruction"); + break; + } + } +} + +static unsigned enumRegToMachineReg(unsigned enumReg) { + switch (enumReg) { + case PPC::R0 : case PPC::F0 : case PPC::CR0: return 0; + case PPC::R1 : case PPC::F1 : case PPC::CR1: return 1; + case PPC::R2 : case PPC::F2 : case PPC::CR2: return 2; + case PPC::R3 : case PPC::F3 : case PPC::CR3: return 3; + case PPC::R4 : case PPC::F4 : case PPC::CR4: return 4; + case PPC::R5 : case PPC::F5 : case PPC::CR5: return 5; + case PPC::R6 : case PPC::F6 : case PPC::CR6: return 6; + case PPC::R7 : case PPC::F7 : case PPC::CR7: return 7; + case PPC::R8 : case PPC::F8 : return 8; + case PPC::R9 : case PPC::F9 : return 9; + case PPC::R10: case PPC::F10: return 10; + case PPC::R11: case PPC::F11: return 11; + case PPC::R12: case PPC::F12: return 12; + case PPC::R13: case PPC::F13: return 13; + case PPC::R14: case PPC::F14: return 14; + case PPC::R15: case PPC::F15: return 15; + case PPC::R16: case PPC::F16: return 16; + case PPC::R17: case PPC::F17: return 17; + case PPC::R18: case PPC::F18: return 18; + case PPC::R19: case PPC::F19: return 19; + case PPC::R20: case PPC::F20: return 20; + case PPC::R21: case PPC::F21: return 21; + case PPC::R22: case PPC::F22: return 22; + case PPC::R23: case PPC::F23: return 23; + case PPC::R24: case PPC::F24: return 24; + case PPC::R25: case PPC::F25: return 25; + case PPC::R26: case PPC::F26: return 26; + case PPC::R27: case PPC::F27: return 27; + case PPC::R28: case PPC::F28: return 28; + case PPC::R29: case PPC::F29: return 29; + case PPC::R30: case PPC::F30: return 30; + case PPC::R31: case PPC::F31: return 31; + default: + std::cerr << "Unhandled reg in enumRegToRealReg!\n"; + abort(); + } +} + +int PPCCodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) { + + int rv = 0; // Return value; defaults to 0 for unhandled cases + // or things that get fixed up later by the JIT. + if (MO.isRegister()) { + rv = enumRegToMachineReg(MO.getReg()); + + // Special encoding for MTCRF and MFOCRF, which uses a bit mask for the + // register, not the register number directly. + if ((MI.getOpcode() == PPC::MTCRF || MI.getOpcode() == PPC::MFOCRF) && + (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7)) { + rv = 0x80 >> rv; + } + } else if (MO.isImmediate()) { + rv = MO.getImmedValue(); + } else if (MO.isGlobalAddress() || MO.isExternalSymbol()) { + bool isExternal = MO.isExternalSymbol() || + MO.getGlobal()->hasWeakLinkage() || + MO.getGlobal()->isExternal(); + unsigned Reloc = 0; + if (MI.getOpcode() == PPC::CALLpcrel) + Reloc = PPC::reloc_pcrel_bx; + else { + switch (MI.getOpcode()) { + default: MI.dump(); assert(0 && "Unknown instruction for relocation!"); + case PPC::LIS: + if (isExternal) + Reloc = PPC::reloc_absolute_ptr_high; // Pointer to stub + else + Reloc = PPC::reloc_absolute_high; // Pointer to symbol + break; + case PPC::LA: + assert(!isExternal && "Something in the ISEL changed\n"); + Reloc = PPC::reloc_absolute_low; + break; + case PPC::LBZ: + case PPC::LHA: + case PPC::LHZ: + case PPC::LWZ: + case PPC::LFS: + case PPC::LFD: + case PPC::STB: + case PPC::STH: + case PPC::STW: + case PPC::STFS: + case PPC::STFD: + if (isExternal) + Reloc = PPC::reloc_absolute_ptr_low; + else + Reloc = PPC::reloc_absolute_low; + break; + } + } + if (MO.isGlobalAddress()) + MCE.addRelocation(MachineRelocation(MCE.getCurrentPCOffset(), + Reloc, MO.getGlobal(), 0)); + else + MCE.addRelocation(MachineRelocation(MCE.getCurrentPCOffset(), + Reloc, MO.getSymbolName(), 0)); + } else if (MO.isMachineBasicBlock()) { + unsigned* CurrPC = (unsigned*)(intptr_t)MCE.getCurrentPCValue(); + BBRefs.push_back(std::make_pair(MO.getMachineBasicBlock(), CurrPC)); + } else if (MO.isConstantPoolIndex()) { + unsigned index = MO.getConstantPoolIndex(); + unsigned Opcode = MI.getOpcode(); + rv = MCE.getConstantPoolEntryAddress(index); + if (Opcode == PPC::LIS) { + // lis wants hi16(addr) + if ((short)rv < 0) rv += 1 << 16; + rv >>= 16; + } else if (Opcode == PPC::LWZ || Opcode == PPC::LA || + Opcode == PPC::LFS || Opcode == PPC::LFD) { + // These load opcodes want lo16(addr) + rv &= 0xffff; + } else { + assert(0 && "Unknown constant pool using instruction!"); + } + } else { + std::cerr << "ERROR: Unknown type of MachineOperand: " << MO << "\n"; + abort(); + } + + return rv; +} + +#include "PPCGenCodeEmitter.inc" + diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 8c566ab7f0c..8396da66db2 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -13,8 +13,8 @@ //===----------------------------------------------------------------------===// #include "PPC.h" -#include "PPC32TargetMachine.h" -#include "PPC32ISelLowering.h" +#include "PPCTargetMachine.h" +#include "PPCISelLowering.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/SSARegMap.h" diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 9bab6ed8be3..604ff2fbec3 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#include "PPC32ISelLowering.h" -#include "PPC32TargetMachine.h" +#include "PPCISelLowering.h" +#include "PPCTargetMachine.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" diff --git a/llvm/lib/Target/PowerPC/PPCISelPattern.cpp b/llvm/lib/Target/PowerPC/PPCISelPattern.cpp new file mode 100644 index 00000000000..6fb119c862b --- /dev/null +++ b/llvm/lib/Target/PowerPC/PPCISelPattern.cpp @@ -0,0 +1,1889 @@ +//===-- PPC32ISelPattern.cpp - A pattern matching inst selector for PPC32 -===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Nate Begeman and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a pattern matching instruction selector for 32 bit PowerPC. +// Magic number generation for integer divide from the PowerPC Compiler Writer's +// Guide, section 3.2.3.5 +// +//===----------------------------------------------------------------------===// + +#include "PPC.h" +#include "PPCInstrBuilder.h" +#include "PPCTargetMachine.h" +#include "PPCISelLowering.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/SSARegMap.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/ADT/Statistic.h" +#include +#include +using namespace llvm; + +namespace { +Statistic<> Recorded("ppc-codegen", "Number of recording ops emitted"); +Statistic<> FusedFP ("ppc-codegen", "Number of fused fp operations"); +Statistic<> FrameOff("ppc-codegen", "Number of frame idx offsets collapsed"); + +//===--------------------------------------------------------------------===// +// ISel - PPC32 specific code to select PPC32 machine instructions for +// SelectionDAG operations. +//===--------------------------------------------------------------------===// + +class ISel : public SelectionDAGISel { + PPC32TargetLowering PPC32Lowering; + SelectionDAG *ISelDAG; // Hack to support us having a dag->dag transform + // for sdiv and udiv until it is put into the future + // dag combiner. + + /// ExprMap - As shared expressions are codegen'd, we keep track of which + /// vreg the value is produced in, so we only emit one copy of each compiled + /// tree. + std::map ExprMap; + + unsigned GlobalBaseReg; + bool GlobalBaseInitialized; + bool RecordSuccess; +public: + ISel(TargetMachine &TM) : SelectionDAGISel(PPC32Lowering), PPC32Lowering(TM), + ISelDAG(0) {} + + /// runOnFunction - Override this function in order to reset our per-function + /// variables. + virtual bool runOnFunction(Function &Fn) { + // Make sure we re-emit a set of the global base reg if necessary + GlobalBaseInitialized = false; + return SelectionDAGISel::runOnFunction(Fn); + } + + /// InstructionSelectBasicBlock - This callback is invoked by + /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. + virtual void InstructionSelectBasicBlock(SelectionDAG &DAG) { + DEBUG(BB->dump()); + // Codegen the basic block. + ISelDAG = &DAG; + Select(DAG.getRoot()); + + // Clear state used for selection. + ExprMap.clear(); + ISelDAG = 0; + } + + // convenience functions for virtual register creation + inline unsigned MakeIntReg() { + return RegMap->createVirtualRegister(PPC32::GPRCRegisterClass); + } + + // dag -> dag expanders for integer divide by constant + SDOperand BuildSDIVSequence(SDOperand N); + SDOperand BuildUDIVSequence(SDOperand N); + + unsigned getGlobalBaseReg(); + void MoveCRtoGPR(unsigned CCReg, ISD::CondCode CC, unsigned Result); + bool SelectBitfieldInsert(SDOperand OR, unsigned Result); + unsigned FoldIfWideZeroExtend(SDOperand N); + unsigned SelectCC(SDOperand LHS, SDOperand RHS, ISD::CondCode CC); + bool SelectIntImmediateExpr(SDOperand N, unsigned Result, + unsigned OCHi, unsigned OCLo, + bool IsArithmetic = false, bool Negate = false); + unsigned SelectExpr(SDOperand N, bool Recording=false); + void Select(SDOperand N); + + unsigned SelectAddr(SDOperand N, unsigned& Reg, int& offset); + void SelectBranchCC(SDOperand N); + + virtual const char *getPassName() const { + return "PowerPC Pattern Instruction Selection"; + } +}; + +// 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) { + if (isShiftedMask_32(Val)) { + // look for the first non-zero bit + MB = CountLeadingZeros_32(Val); + // look for the first zero bit after the run of ones + ME = CountLeadingZeros_32((Val - 1) ^ Val); + return true; + } else if (isShiftedMask_32(Val = ~Val)) { // invert mask + // effectively look for the first zero bit + ME = CountLeadingZeros_32(Val) - 1; + // effectively look for the first one bit after the run of zeros + MB = CountLeadingZeros_32((Val - 1) ^ Val) + 1; + return true; + } + // no run present + return false; +} + +// isRotateAndMask - Returns true if Mask and Shift can be folded in to a rotate +// and mask opcode and mask operation. +static bool isRotateAndMask(unsigned Opcode, unsigned Shift, unsigned Mask, + bool IsShiftMask, + unsigned &SH, unsigned &MB, unsigned &ME) { + if (Shift > 31) return false; + unsigned Indeterminant = ~0; // bit mask marking indeterminant results + + if (Opcode == ISD::SHL) { // shift left + // apply shift to mask if it comes first + if (IsShiftMask) Mask = Mask << Shift; + // determine which bits are made indeterminant by shift + Indeterminant = ~(0xFFFFFFFFu << Shift); + } else if (Opcode == ISD::SRA || Opcode == ISD::SRL) { // shift rights + // apply shift to mask if it comes first + if (IsShiftMask) Mask = Mask >> Shift; + // determine which bits are made indeterminant by shift + Indeterminant = ~(0xFFFFFFFFu >> Shift); + // adjust for the left rotate + Shift = 32 - Shift; + } + + // if the mask doesn't intersect any Indeterminant bits + if (Mask && !(Mask & Indeterminant)) { + SH = Shift; + // make sure the mask is still a mask (wrap arounds may not be) + return isRunOfOnes(Mask, MB, ME); + } + + // can't do it + return false; +} + +// isIntImmediate - This method tests to see if a constant operand. +// If so Imm will receive the 32 bit value. +static bool isIntImmediate(SDOperand N, unsigned& Imm) { + // test for constant + if (ConstantSDNode *CN = dyn_cast(N)) { + // retrieve value + Imm = (unsigned)CN->getValue(); + // passes muster + return true; + } + // not a constant + return false; +} + +// isOpcWithIntImmediate - This method tests to see if the node is a specific +// opcode and that it has a immediate integer right operand. +// If so Imm will receive the 32 bit value. +static bool isOpcWithIntImmediate(SDOperand N, unsigned Opc, unsigned& Imm) { + return N.getOpcode() == Opc && isIntImmediate(N.getOperand(1), Imm); +} + +// isOprShiftImm - Returns true if the specified operand is a shift opcode with +// a immediate shift count less than 32. +static bool isOprShiftImm(SDOperand N, unsigned& Opc, unsigned& SH) { + Opc = N.getOpcode(); + return (Opc == ISD::SHL || Opc == ISD::SRL || Opc == ISD::SRA) && + isIntImmediate(N.getOperand(1), SH) && SH < 32; +} + +// isOprNot - Returns true if the specified operand is an xor with immediate -1. +static bool isOprNot(SDOperand N) { + unsigned Imm; + return isOpcWithIntImmediate(N, ISD::XOR, Imm) && (signed)Imm == -1; +} + +// Immediate constant composers. +// Lo16 - grabs the lo 16 bits from a 32 bit constant. +// Hi16 - grabs the hi 16 bits from a 32 bit constant. +// HA16 - computes the hi bits required if the lo bits are add/subtracted in +// arithmethically. +static unsigned Lo16(unsigned x) { return x & 0x0000FFFF; } +static unsigned Hi16(unsigned x) { return Lo16(x >> 16); } +static unsigned HA16(unsigned x) { return Hi16((signed)x - (signed short)x); } + +/// NodeHasRecordingVariant - If SelectExpr can always produce code for +/// NodeOpcode that also sets CR0 as a side effect, return true. Otherwise, +/// return false. +static bool NodeHasRecordingVariant(unsigned NodeOpcode) { + switch(NodeOpcode) { + default: return false; + case ISD::AND: + case ISD::OR: + return true; + } +} + +/// getBCCForSetCC - Returns the PowerPC condition branch mnemonic corresponding +/// to Condition. +static unsigned getBCCForSetCC(ISD::CondCode CC) { + switch (CC) { + default: assert(0 && "Unknown condition!"); abort(); + case ISD::SETEQ: return PPC::BEQ; + case ISD::SETNE: return PPC::BNE; + case ISD::SETULT: + case ISD::SETLT: return PPC::BLT; + case ISD::SETULE: + case ISD::SETLE: return PPC::BLE; + case ISD::SETUGT: + case ISD::SETGT: return PPC::BGT; + case ISD::SETUGE: + case ISD::SETGE: return PPC::BGE; + } + return 0; +} + +/// getCRIdxForSetCC - Return the index of the condition register field +/// associated with the SetCC condition, and whether or not the field is +/// treated as inverted. That is, lt = 0; ge = 0 inverted. +static unsigned getCRIdxForSetCC(ISD::CondCode CC, bool& Inv) { + switch (CC) { + default: assert(0 && "Unknown condition!"); abort(); + case ISD::SETULT: + case ISD::SETLT: Inv = false; return 0; + case ISD::SETUGE: + case ISD::SETGE: Inv = true; return 0; + case ISD::SETUGT: + case ISD::SETGT: Inv = false; return 1; + case ISD::SETULE: + case ISD::SETLE: Inv = true; return 1; + case ISD::SETEQ: Inv = false; return 2; + case ISD::SETNE: Inv = true; return 2; + } + return 0; +} + +/// IndexedOpForOp - Return the indexed variant for each of the PowerPC load +/// and store immediate instructions. +static unsigned IndexedOpForOp(unsigned Opcode) { + switch(Opcode) { + default: assert(0 && "Unknown opcode!"); abort(); + case PPC::LBZ: return PPC::LBZX; case PPC::STB: return PPC::STBX; + case PPC::LHZ: return PPC::LHZX; case PPC::STH: return PPC::STHX; + case PPC::LHA: return PPC::LHAX; case PPC::STW: return PPC::STWX; + case PPC::LWZ: return PPC::LWZX; case PPC::STFS: return PPC::STFSX; + case PPC::LFS: return PPC::LFSX; case PPC::STFD: return PPC::STFDX; + case PPC::LFD: return PPC::LFDX; + } + return 0; +} + +// Structure used to return the necessary information to codegen an SDIV as +// a multiply. +struct ms { + int m; // magic number + int s; // shift amount +}; + +struct mu { + unsigned int m; // magic number + int a; // add indicator + int s; // shift amount +}; + +/// magic - calculate the magic numbers required to codegen an integer sdiv as +/// a sequence of multiply and shifts. Requires that the divisor not be 0, 1, +/// or -1. +static struct ms magic(int d) { + int p; + unsigned int ad, anc, delta, q1, r1, q2, r2, t; + const unsigned int two31 = 0x80000000U; + struct ms mag; + + ad = abs(d); + t = two31 + ((unsigned int)d >> 31); + anc = t - 1 - t%ad; // absolute value of nc + p = 31; // initialize p + q1 = two31/anc; // initialize q1 = 2p/abs(nc) + r1 = two31 - q1*anc; // initialize r1 = rem(2p,abs(nc)) + q2 = two31/ad; // initialize q2 = 2p/abs(d) + r2 = two31 - q2*ad; // initialize r2 = rem(2p,abs(d)) + do { + p = p + 1; + q1 = 2*q1; // update q1 = 2p/abs(nc) + r1 = 2*r1; // update r1 = rem(2p/abs(nc)) + if (r1 >= anc) { // must be unsigned comparison + q1 = q1 + 1; + r1 = r1 - anc; + } + q2 = 2*q2; // update q2 = 2p/abs(d) + r2 = 2*r2; // update r2 = rem(2p/abs(d)) + if (r2 >= ad) { // must be unsigned comparison + q2 = q2 + 1; + r2 = r2 - ad; + } + delta = ad - r2; + } while (q1 < delta || (q1 == delta && r1 == 0)); + + mag.m = q2 + 1; + if (d < 0) mag.m = -mag.m; // resulting magic number + mag.s = p - 32; // resulting shift + return mag; +} + +/// magicu - calculate the magic numbers required to codegen an integer udiv as +/// a sequence of multiply, add and shifts. Requires that the divisor not be 0. +static struct mu magicu(unsigned d) +{ + int p; + unsigned int nc, delta, q1, r1, q2, r2; + struct mu magu; + magu.a = 0; // initialize "add" indicator + nc = - 1 - (-d)%d; + p = 31; // initialize p + q1 = 0x80000000/nc; // initialize q1 = 2p/nc + r1 = 0x80000000 - q1*nc; // initialize r1 = rem(2p,nc) + q2 = 0x7FFFFFFF/d; // initialize q2 = (2p-1)/d + r2 = 0x7FFFFFFF - q2*d; // initialize r2 = rem((2p-1),d) + do { + p = p + 1; + if (r1 >= nc - r1 ) { + q1 = 2*q1 + 1; // update q1 + r1 = 2*r1 - nc; // update r1 + } + else { + q1 = 2*q1; // update q1 + r1 = 2*r1; // update r1 + } + if (r2 + 1 >= d - r2) { + if (q2 >= 0x7FFFFFFF) magu.a = 1; + q2 = 2*q2 + 1; // update q2 + r2 = 2*r2 + 1 - d; // update r2 + } + else { + if (q2 >= 0x80000000) magu.a = 1; + q2 = 2*q2; // update q2 + r2 = 2*r2 + 1; // update r2 + } + delta = d - 1 - r2; + } while (p < 64 && (q1 < delta || (q1 == delta && r1 == 0))); + magu.m = q2 + 1; // resulting magic number + magu.s = p - 32; // resulting shift + return magu; +} +} + +/// BuildSDIVSequence - Given an ISD::SDIV node expressing a divide by constant, +/// return a DAG expression to select that will generate the same value by +/// multiplying by a magic number. See: +/// +SDOperand ISel::BuildSDIVSequence(SDOperand N) { + int d = (int)cast(N.getOperand(1))->getSignExtended(); + ms magics = magic(d); + // Multiply the numerator (operand 0) by the magic value + SDOperand Q = ISelDAG->getNode(ISD::MULHS, MVT::i32, N.getOperand(0), + ISelDAG->getConstant(magics.m, MVT::i32)); + // If d > 0 and m < 0, add the numerator + if (d > 0 && magics.m < 0) + Q = ISelDAG->getNode(ISD::ADD, MVT::i32, Q, N.getOperand(0)); + // If d < 0 and m > 0, subtract the numerator. + if (d < 0 && magics.m > 0) + Q = ISelDAG->getNode(ISD::SUB, MVT::i32, Q, N.getOperand(0)); + // Shift right algebraic if shift value is nonzero + if (magics.s > 0) + Q = ISelDAG->getNode(ISD::SRA, MVT::i32, Q, + ISelDAG->getConstant(magics.s, MVT::i32)); + // Extract the sign bit and add it to the quotient + SDOperand T = + ISelDAG->getNode(ISD::SRL, MVT::i32, Q, ISelDAG->getConstant(31, MVT::i32)); + return ISelDAG->getNode(ISD::ADD, MVT::i32, Q, T); +} + +/// BuildUDIVSequence - Given an ISD::UDIV node expressing a divide by constant, +/// return a DAG expression to select that will generate the same value by +/// multiplying by a magic number. See: +/// +SDOperand ISel::BuildUDIVSequence(SDOperand N) { + unsigned d = + (unsigned)cast(N.getOperand(1))->getSignExtended(); + mu magics = magicu(d); + // Multiply the numerator (operand 0) by the magic value + SDOperand Q = ISelDAG->getNode(ISD::MULHU, MVT::i32, N.getOperand(0), + ISelDAG->getConstant(magics.m, MVT::i32)); + if (magics.a == 0) { + Q = ISelDAG->getNode(ISD::SRL, MVT::i32, Q, + ISelDAG->getConstant(magics.s, MVT::i32)); + } else { + SDOperand NPQ = ISelDAG->getNode(ISD::SUB, MVT::i32, N.getOperand(0), Q); + NPQ = ISelDAG->getNode(ISD::SRL, MVT::i32, NPQ, + ISelDAG->getConstant(1, MVT::i32)); + NPQ = ISelDAG->getNode(ISD::ADD, MVT::i32, NPQ, Q); + Q = ISelDAG->getNode(ISD::SRL, MVT::i32, NPQ, + ISelDAG->getConstant(magics.s-1, MVT::i32)); + } + return Q; +} + +/// getGlobalBaseReg - Output the instructions required to put the +/// base address to use for accessing globals into a register. +/// +unsigned ISel::getGlobalBaseReg() { + if (!GlobalBaseInitialized) { + // Insert the set of GlobalBaseReg into the first MBB of the function + MachineBasicBlock &FirstMBB = BB->getParent()->front(); + MachineBasicBlock::iterator MBBI = FirstMBB.begin(); + GlobalBaseReg = MakeIntReg(); + BuildMI(FirstMBB, MBBI, PPC::MovePCtoLR, 0, PPC::LR); + BuildMI(FirstMBB, MBBI, PPC::MFLR, 1, GlobalBaseReg); + GlobalBaseInitialized = true; + } + return GlobalBaseReg; +} + +/// MoveCRtoGPR - Move CCReg[Idx] to the least significant bit of Result. If +/// Inv is true, then invert the result. +void ISel::MoveCRtoGPR(unsigned CCReg, ISD::CondCode CC, unsigned Result){ + bool Inv; + unsigned IntCR = MakeIntReg(); + unsigned Idx = getCRIdxForSetCC(CC, Inv); + BuildMI(BB, PPC::MCRF, 1, PPC::CR7).addReg(CCReg); + bool GPOpt = + TLI.getTargetMachine().getSubtarget().isGigaProcessor(); + if (GPOpt) + BuildMI(BB, PPC::MFOCRF, 1, IntCR).addReg(PPC::CR7); + else + BuildMI(BB, PPC::MFCR, 0, IntCR); + if (Inv) { + unsigned Tmp1 = MakeIntReg(); + BuildMI(BB, PPC::RLWINM, 4, Tmp1).addReg(IntCR).addImm(32-(3-Idx)) + .addImm(31).addImm(31); + BuildMI(BB, PPC::XORI, 2, Result).addReg(Tmp1).addImm(1); + } else { + BuildMI(BB, PPC::RLWINM, 4, Result).addReg(IntCR).addImm(32-(3-Idx)) + .addImm(31).addImm(31); + } +} + +/// SelectBitfieldInsert - turn an or of two masked values into +/// the rotate left word immediate then mask insert (rlwimi) instruction. +/// Returns true on success, false if the caller still needs to select OR. +/// +/// Patterns matched: +/// 1. or shl, and 5. or and, and +/// 2. or and, shl 6. or shl, shr +/// 3. or shr, and 7. or shr, shl +/// 4. or and, shr +bool ISel::SelectBitfieldInsert(SDOperand OR, unsigned Result) { + bool IsRotate = false; + unsigned TgtMask = 0xFFFFFFFF, InsMask = 0xFFFFFFFF, Amount = 0; + unsigned Value; + + SDOperand Op0 = OR.getOperand(0); + SDOperand Op1 = OR.getOperand(1); + + unsigned Op0Opc = Op0.getOpcode(); + unsigned Op1Opc = Op1.getOpcode(); + + // Verify that we have the correct opcodes + if (ISD::SHL != Op0Opc && ISD::SRL != Op0Opc && ISD::AND != Op0Opc) + return false; + if (ISD::SHL != Op1Opc && ISD::SRL != Op1Opc && ISD::AND != Op1Opc) + return false; + + // Generate Mask value for Target + if (isIntImmediate(Op0.getOperand(1), Value)) { + switch(Op0Opc) { + case ISD::SHL: TgtMask <<= Value; break; + case ISD::SRL: TgtMask >>= Value; break; + case ISD::AND: TgtMask &= Value; break; + } + } else { + return false; + } + + // Generate Mask value for Insert + if (isIntImmediate(Op1.getOperand(1), Value)) { + switch(Op1Opc) { + case ISD::SHL: + Amount = Value; + InsMask <<= Amount; + if (Op0Opc == ISD::SRL) IsRotate = true; + break; + case ISD::SRL: + Amount = Value; + InsMask >>= Amount; + Amount = 32-Amount; + if (Op0Opc == ISD::SHL) IsRotate = true; + break; + case ISD::AND: + InsMask &= Value; + break; + } + } else { + return false; + } + + unsigned Tmp3 = 0; + + // If both of the inputs are ANDs and one of them has a logical shift by + // constant as its input, make that the inserted value so that we can combine + // the shift into the rotate part of the rlwimi instruction + if (Op0Opc == ISD::AND && Op1Opc == ISD::AND) { + if (Op1.getOperand(0).getOpcode() == ISD::SHL || + Op1.getOperand(0).getOpcode() == ISD::SRL) { + if (isIntImmediate(Op1.getOperand(0).getOperand(1), Value)) { + Amount = Op1.getOperand(0).getOpcode() == ISD::SHL ? + Value : 32 - Value; + Tmp3 = SelectExpr(Op1.getOperand(0).getOperand(0)); + } + } else if (Op0.getOperand(0).getOpcode() == ISD::SHL || + Op0.getOperand(0).getOpcode() == ISD::SRL) { + if (isIntImmediate(Op0.getOperand(0).getOperand(1), Value)) { + std::swap(Op0, Op1); + std::swap(TgtMask, InsMask); + Amount = Op1.getOperand(0).getOpcode() == ISD::SHL ? + Value : 32 - Value; + Tmp3 = SelectExpr(Op1.getOperand(0).getOperand(0)); + } + } + } + + // Verify that the Target mask and Insert mask together form a full word mask + // and that the Insert mask is a run of set bits (which implies both are runs + // of set bits). Given that, Select the arguments and generate the rlwimi + // instruction. + unsigned MB, ME; + if (((TgtMask & InsMask) == 0) && isRunOfOnes(InsMask, MB, ME)) { + unsigned Tmp1, Tmp2; + bool fullMask = (TgtMask ^ InsMask) == 0xFFFFFFFF; + // Check for rotlwi / rotrwi here, a special case of bitfield insert + // where both bitfield halves are sourced from the same value. + if (IsRotate && fullMask && + OR.getOperand(0).getOperand(0) == OR.getOperand(1).getOperand(0)) { + Tmp1 = SelectExpr(OR.getOperand(0).getOperand(0)); + BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp1).addImm(Amount) + .addImm(0).addImm(31); + return true; + } + if (Op0Opc == ISD::AND && fullMask) + Tmp1 = SelectExpr(Op0.getOperand(0)); + else + Tmp1 = SelectExpr(Op0); + Tmp2 = Tmp3 ? Tmp3 : SelectExpr(Op1.getOperand(0)); + BuildMI(BB, PPC::RLWIMI, 5, Result).addReg(Tmp1).addReg(Tmp2) + .addImm(Amount).addImm(MB).addImm(ME); + return true; + } + return false; +} + +/// FoldIfWideZeroExtend - 32 bit PowerPC implicit masks shift amounts to the +/// low six bits. If the shift amount is an ISD::AND node with a mask that is +/// wider than the implicit mask, then we can get rid of the AND and let the +/// shift do the mask. +unsigned ISel::FoldIfWideZeroExtend(SDOperand N) { + unsigned C; + if (isOpcWithIntImmediate(N, ISD::AND, C) && isMask_32(C) && C > 63) + return SelectExpr(N.getOperand(0)); + else + return SelectExpr(N); +} + +unsigned ISel::SelectCC(SDOperand LHS, SDOperand RHS, ISD::CondCode CC) { + unsigned Result, Tmp1, Tmp2; + bool AlreadySelected = false; + + // Allocate a condition register for this expression + Result = RegMap->createVirtualRegister(PPC32::CRRCRegisterClass); + + // Use U to determine whether the SETCC immediate range is signed or not. + bool U = ISD::isUnsignedIntSetCC(CC); + if (isIntImmediate(RHS, Tmp2) && + ((U && isUInt16(Tmp2)) || (!U && isInt16(Tmp2)))) { + Tmp2 = Lo16(Tmp2); + // For comparisons against zero, we can implicity set CR0 if a recording + // variant (e.g. 'or.' instead of 'or') of the instruction that defines + // operand zero of the SetCC node is available. + if (Tmp2 == 0 && + NodeHasRecordingVariant(LHS.getOpcode()) && LHS.Val->hasOneUse()) { + RecordSuccess = false; + Tmp1 = SelectExpr(LHS, true); + if (RecordSuccess) { + ++Recorded; + BuildMI(BB, PPC::MCRF, 1, Result).addReg(PPC::CR0); + return Result; + } + AlreadySelected = true; + } + // If we could not implicitly set CR0, then emit a compare immediate + // instead. + if (!AlreadySelected) Tmp1 = SelectExpr(LHS); + if (U) + BuildMI(BB, PPC::CMPLWI, 2, Result).addReg(Tmp1).addImm(Tmp2); + else + BuildMI(BB, PPC::CMPWI, 2, Result).addReg(Tmp1).addSImm(Tmp2); + } else { + unsigned CompareOpc; + if (MVT::isInteger(LHS.getValueType())) + CompareOpc = U ? PPC::CMPLW : PPC::CMPW; + else if (LHS.getValueType() == MVT::f32) + CompareOpc = PPC::FCMPUS; + else + CompareOpc = PPC::FCMPUD; + Tmp1 = SelectExpr(LHS); + Tmp2 = SelectExpr(RHS); + BuildMI(BB, CompareOpc, 2, Result).addReg(Tmp1).addReg(Tmp2); + } + return Result; +} + +/// Check to see if the load is a constant offset from a base register. +unsigned ISel::SelectAddr(SDOperand N, unsigned& Reg, int& offset) +{ + unsigned imm = 0, opcode = N.getOpcode(); + if (N.getOpcode() == ISD::ADD) { + bool isFrame = N.getOperand(0).getOpcode() == ISD::FrameIndex; + if (isIntImmediate(N.getOperand(1), imm) && isInt16(imm)) { + offset = Lo16(imm); + if (isFrame) { + ++FrameOff; + Reg = cast(N.getOperand(0))->getIndex(); + return 1; + } else { + Reg = SelectExpr(N.getOperand(0)); + return 0; + } + } else { + Reg = SelectExpr(N.getOperand(0)); + offset = SelectExpr(N.getOperand(1)); + return 2; + } + } + // Now check if we're dealing with a global, and whether or not we should emit + // an optimized load or store for statics. + if(GlobalAddressSDNode *GN = dyn_cast(N)) { + GlobalValue *GV = GN->getGlobal(); + if (!GV->hasWeakLinkage() && !GV->isExternal()) { + unsigned GlobalHi = MakeIntReg(); + if (PICEnabled) + BuildMI(BB, PPC::ADDIS, 2, GlobalHi).addReg(getGlobalBaseReg()) + .addGlobalAddress(GV); + else + BuildMI(BB, PPC::LIS, 1, GlobalHi).addGlobalAddress(GV); + Reg = GlobalHi; + offset = 0; + return 3; + } + } + Reg = SelectExpr(N); + offset = 0; + return 0; +} + +void ISel::SelectBranchCC(SDOperand N) +{ + MachineBasicBlock *Dest = + cast(N.getOperand(4))->getBasicBlock(); + + Select(N.getOperand(0)); //chain + ISD::CondCode CC = cast(N.getOperand(1))->get(); + unsigned CCReg = SelectCC(N.getOperand(2), N.getOperand(3), CC); + unsigned Opc = getBCCForSetCC(CC); + + // If this is a two way branch, then grab the fallthrough basic block argument + // and build a PowerPC branch pseudo-op, suitable for long branch conversion + // if necessary by the branch selection pass. Otherwise, emit a standard + // conditional branch. + if (N.getOpcode() == ISD::BRTWOWAY_CC) { + MachineBasicBlock *Fallthrough = + cast(N.getOperand(5))->getBasicBlock(); + BuildMI(BB, PPC::COND_BRANCH, 4).addReg(CCReg).addImm(Opc) + .addMBB(Dest).addMBB(Fallthrough); + BuildMI(BB, PPC::B, 1).addMBB(Fallthrough); + } else { + // Iterate to the next basic block + ilist::iterator It = BB; + ++It; + + // If the fallthrough path is off the end of the function, which would be + // undefined behavior, set it to be the same as the current block because + // we have nothing better to set it to, and leaving it alone will cause the + // PowerPC Branch Selection pass to crash. + if (It == BB->getParent()->end()) It = Dest; + BuildMI(BB, PPC::COND_BRANCH, 4).addReg(CCReg).addImm(Opc) + .addMBB(Dest).addMBB(It); + } + return; +} + +// SelectIntImmediateExpr - Choose code for opcodes with immediate value. +bool ISel::SelectIntImmediateExpr(SDOperand N, unsigned Result, + unsigned OCHi, unsigned OCLo, + bool IsArithmetic, bool Negate) { + // check constant + ConstantSDNode *CN = dyn_cast(N.getOperand(1)); + // exit if not a constant + if (!CN) return false; + // extract immediate + unsigned C = (unsigned)CN->getValue(); + // negate if required (ISD::SUB) + if (Negate) C = -C; + // get the hi and lo portions of constant + unsigned Hi = IsArithmetic ? HA16(C) : Hi16(C); + unsigned Lo = Lo16(C); + // assume no intermediate result from lo instruction (same as final result) + unsigned Tmp = Result; + // check if two instructions are needed + if (Hi && Lo) { + // exit if usage indicates it would be better to load immediate into a + // register + if (CN->use_size() > 2) return false; + // need intermediate result for two instructions + Tmp = MakeIntReg(); + } + // get first operand + unsigned Opr0 = SelectExpr(N.getOperand(0)); + // is a lo instruction needed + if (Lo) { + // generate instruction for lo portion + BuildMI(BB, OCLo, 2, Tmp).addReg(Opr0).addImm(Lo); + // need to switch out first operand for hi instruction + Opr0 = Tmp; + } + // is a hi instruction needed + if (Hi) { + // generate instruction for hi portion + BuildMI(BB, OCHi, 2, Result).addReg(Opr0).addImm(Hi); + } + return true; +} + +unsigned ISel::SelectExpr(SDOperand N, bool Recording) { + unsigned Result; + unsigned Tmp1, Tmp2, Tmp3; + unsigned Opc = 0; + unsigned opcode = N.getOpcode(); + + SDNode *Node = N.Val; + MVT::ValueType DestType = N.getValueType(); + + if (Node->getOpcode() == ISD::CopyFromReg) { + unsigned Reg = cast(Node->getOperand(1))->getReg(); + // Just use the specified register as our input. + if (MRegisterInfo::isVirtualRegister(Reg) || Reg == PPC::R1) + return Reg; + } + + unsigned &Reg = ExprMap[N]; + if (Reg) return Reg; + + switch (N.getOpcode()) { + default: + Reg = Result = (N.getValueType() != MVT::Other) ? + MakeReg(N.getValueType()) : 1; + break; + case ISD::AssertSext: + case ISD::AssertZext: + // Don't allocate a vreg for these nodes. + return Reg = SelectExpr(N.getOperand(0)); + case ISD::TAILCALL: + case ISD::CALL: + // If this is a call instruction, make sure to prepare ALL of the result + // values as well as the chain. + if (Node->getNumValues() == 1) + Reg = Result = 1; // Void call, just a chain. + else { + Result = MakeReg(Node->getValueType(0)); + ExprMap[N.getValue(0)] = Result; + for (unsigned i = 1, e = N.Val->getNumValues()-1; i != e; ++i) + ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i)); + ExprMap[SDOperand(Node, Node->getNumValues()-1)] = 1; + } + break; + case ISD::ADD_PARTS: + case ISD::SUB_PARTS: + Result = MakeReg(Node->getValueType(0)); + ExprMap[N.getValue(0)] = Result; + for (unsigned i = 1, e = N.Val->getNumValues(); i != e; ++i) + ExprMap[N.getValue(i)] = MakeReg(Node->getValueType(i)); + break; + } + + switch (opcode) { + default: + Node->dump(); std::cerr << '\n'; + assert(0 && "Node not handled!\n"); + case PPCISD::FSEL: + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + Tmp3 = SelectExpr(N.getOperand(2)); + + // Extend the comparison to 64-bits if needed. + if (N.getOperand(0).getValueType() == MVT::f32) { + unsigned Tmp1New = MakeReg(MVT::f64); + BuildMI(BB, PPC::FMRSD, 1, Tmp1New).addReg(Tmp1); + Tmp1 = Tmp1New; + } + + Opc = N.Val->getValueType(0) == MVT::f32 ? PPC::FSELS : PPC::FSELD; + BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3); + return Result; + case PPCISD::FCFID: + Tmp1 = SelectExpr(N.getOperand(0)); + BuildMI(BB, PPC::FCFID, 1, Result).addReg(Tmp1); + return Result; + case PPCISD::FCTIDZ: + Tmp1 = SelectExpr(N.getOperand(0)); + BuildMI(BB, PPC::FCTIDZ, 1, Result).addReg(Tmp1); + return Result; + case PPCISD::FCTIWZ: + Tmp1 = SelectExpr(N.getOperand(0)); + BuildMI(BB, PPC::FCTIWZ, 1, Result).addReg(Tmp1); + return Result; + case ISD::UNDEF: + if (Node->getValueType(0) == MVT::i32) + BuildMI(BB, PPC::IMPLICIT_DEF_GPR, 0, Result); + else if (Node->getValueType(0) == MVT::f32) + BuildMI(BB, PPC::IMPLICIT_DEF_F4, 0, Result); + else + BuildMI(BB, PPC::IMPLICIT_DEF_F8, 0, Result); + return Result; + case ISD::DYNAMIC_STACKALLOC: + // Generate both result values. FIXME: Need a better commment here? + if (Result != 1) + ExprMap[N.getValue(1)] = 1; + else + Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); + + // FIXME: We are currently ignoring the requested alignment for handling + // greater than the stack alignment. This will need to be revisited at some + // point. Align = N.getOperand(2); + if (!isa(N.getOperand(2)) || + cast(N.getOperand(2))->getValue() != 0) { + std::cerr << "Cannot allocate stack object with greater alignment than" + << " the stack alignment yet!"; + abort(); + } + Select(N.getOperand(0)); + Tmp1 = SelectExpr(N.getOperand(1)); + // Subtract size from stack pointer, thereby allocating some space. + BuildMI(BB, PPC::SUBF, 2, PPC::R1).addReg(Tmp1).addReg(PPC::R1); + // Put a pointer to the space into the result register by copying the SP + BuildMI(BB, PPC::OR, 2, Result).addReg(PPC::R1).addReg(PPC::R1); + return Result; + + case ISD::ConstantPool: + Tmp1 = BB->getParent()->getConstantPool()-> + getConstantPoolIndex(cast(N)->get()); + Tmp2 = MakeIntReg(); + if (PICEnabled) + BuildMI(BB, PPC::ADDIS, 2, Tmp2).addReg(getGlobalBaseReg()) + .addConstantPoolIndex(Tmp1); + else + BuildMI(BB, PPC::LIS, 1, Tmp2).addConstantPoolIndex(Tmp1); + BuildMI(BB, PPC::LA, 2, Result).addReg(Tmp2).addConstantPoolIndex(Tmp1); + return Result; + + case ISD::FrameIndex: + Tmp1 = cast(N)->getIndex(); + addFrameReference(BuildMI(BB, PPC::ADDI, 2, Result), (int)Tmp1, 0, false); + return Result; + + case ISD::GlobalAddress: { + GlobalValue *GV = cast(N)->getGlobal(); + Tmp1 = MakeIntReg(); + if (PICEnabled) + BuildMI(BB, PPC::ADDIS, 2, Tmp1).addReg(getGlobalBaseReg()) + .addGlobalAddress(GV); + else + BuildMI(BB, PPC::LIS, 1, Tmp1).addGlobalAddress(GV); + if (GV->hasWeakLinkage() || GV->isExternal()) { + BuildMI(BB, PPC::LWZ, 2, Result).addGlobalAddress(GV).addReg(Tmp1); + } else { + BuildMI(BB, PPC::LA, 2, Result).addReg(Tmp1).addGlobalAddress(GV); + } + return Result; + } + + case ISD::LOAD: + case ISD::EXTLOAD: + case ISD::ZEXTLOAD: + case ISD::SEXTLOAD: { + MVT::ValueType TypeBeingLoaded = (ISD::LOAD == opcode) ? + Node->getValueType(0) : cast(Node->getOperand(3))->getVT(); + bool sext = (ISD::SEXTLOAD == opcode); + + // Make sure we generate both values. + if (Result != 1) + ExprMap[N.getValue(1)] = 1; // Generate the token + else + Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType()); + + SDOperand Chain = N.getOperand(0); + SDOperand Address = N.getOperand(1); + Select(Chain); + + switch (TypeBeingLoaded) { + default: Node->dump(); assert(0 && "Cannot load this type!"); + case MVT::i1: Opc = PPC::LBZ; break; + case MVT::i8: Opc = PPC::LBZ; break; + case MVT::i16: Opc = sext ? PPC::LHA : PPC::LHZ; break; + case MVT::i32: Opc = PPC::LWZ; break; + case MVT::f32: Opc = PPC::LFS; break; + case MVT::f64: Opc = PPC::LFD; break; + } + + if (ConstantPoolSDNode *CP = dyn_cast(Address)) { + Tmp1 = MakeIntReg(); + unsigned CPI = BB->getParent()->getConstantPool()-> + getConstantPoolIndex(CP->get()); + if (PICEnabled) + BuildMI(BB, PPC::ADDIS, 2, Tmp1).addReg(getGlobalBaseReg()) + .addConstantPoolIndex(CPI); + else + BuildMI(BB, PPC::LIS, 1, Tmp1).addConstantPoolIndex(CPI); + BuildMI(BB, Opc, 2, Result).addConstantPoolIndex(CPI).addReg(Tmp1); + } else if (Address.getOpcode() == ISD::FrameIndex) { + Tmp1 = cast(Address)->getIndex(); + addFrameReference(BuildMI(BB, Opc, 2, Result), (int)Tmp1); + } else { + int offset; + switch(SelectAddr(Address, Tmp1, offset)) { + default: assert(0 && "Unhandled return value from SelectAddr"); + case 0: // imm offset, no frame, no index + BuildMI(BB, Opc, 2, Result).addSImm(offset).addReg(Tmp1); + break; + case 1: // imm offset + frame index + addFrameReference(BuildMI(BB, Opc, 2, Result), (int)Tmp1, offset); + break; + case 2: // base+index addressing + Opc = IndexedOpForOp(Opc); + BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(offset); + break; + case 3: { + GlobalAddressSDNode *GN = cast(Address); + GlobalValue *GV = GN->getGlobal(); + BuildMI(BB, Opc, 2, Result).addGlobalAddress(GV).addReg(Tmp1); + } + } + } + return Result; + } + + case ISD::TAILCALL: + case ISD::CALL: { + unsigned GPR_idx = 0, FPR_idx = 0; + static const unsigned GPR[] = { + PPC::R3, PPC::R4, PPC::R5, PPC::R6, + PPC::R7, PPC::R8, PPC::R9, PPC::R10, + }; + static const unsigned FPR[] = { + PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, + PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13 + }; + + // Lower the chain for this call. + Select(N.getOperand(0)); + ExprMap[N.getValue(Node->getNumValues()-1)] = 1; + + MachineInstr *CallMI; + // Emit the correct call instruction based on the type of symbol called. + if (GlobalAddressSDNode *GASD = + dyn_cast(N.getOperand(1))) { + CallMI = BuildMI(PPC::CALLpcrel, 1).addGlobalAddress(GASD->getGlobal(), + true); + } else if (ExternalSymbolSDNode *ESSDN = + dyn_cast(N.getOperand(1))) { + CallMI = BuildMI(PPC::CALLpcrel, 1).addExternalSymbol(ESSDN->getSymbol(), + true); + } else { + Tmp1 = SelectExpr(N.getOperand(1)); + BuildMI(BB, PPC::MTCTR, 1).addReg(Tmp1); + BuildMI(BB, PPC::OR, 2, PPC::R12).addReg(Tmp1).addReg(Tmp1); + CallMI = BuildMI(PPC::CALLindirect, 3).addImm(20).addImm(0) + .addReg(PPC::R12); + } + + // Load the register args to virtual regs + std::vector ArgVR; + for(int i = 2, e = Node->getNumOperands(); i < e; ++i) + ArgVR.push_back(SelectExpr(N.getOperand(i))); + + // Copy the virtual registers into the appropriate argument register + for(int i = 0, e = ArgVR.size(); i < e; ++i) { + switch(N.getOperand(i+2).getValueType()) { + default: Node->dump(); assert(0 && "Unknown value type for call"); + case MVT::i32: + assert(GPR_idx < 8 && "Too many int args"); + if (N.getOperand(i+2).getOpcode() != ISD::UNDEF) { + BuildMI(BB, PPC::OR,2,GPR[GPR_idx]).addReg(ArgVR[i]).addReg(ArgVR[i]); + CallMI->addRegOperand(GPR[GPR_idx], MachineOperand::Use); + } + ++GPR_idx; + break; + case MVT::f64: + case MVT::f32: + assert(FPR_idx < 13 && "Too many fp args"); + BuildMI(BB, N.getOperand(i+2).getValueType() == MVT::f32 ? PPC::FMRS : + PPC::FMRD, 1, FPR[FPR_idx]).addReg(ArgVR[i]); + CallMI->addRegOperand(FPR[FPR_idx], MachineOperand::Use); + ++FPR_idx; + break; + } + } + + // Put the call instruction in the correct place in the MachineBasicBlock + BB->push_back(CallMI); + + switch (Node->getValueType(0)) { + default: assert(0 && "Unknown value type for call result!"); + case MVT::Other: return 1; + case MVT::i32: + if (Node->getValueType(1) == MVT::i32) { + BuildMI(BB, PPC::OR, 2, Result+1).addReg(PPC::R3).addReg(PPC::R3); + BuildMI(BB, PPC::OR, 2, Result).addReg(PPC::R4).addReg(PPC::R4); + } else { + BuildMI(BB, PPC::OR, 2, Result).addReg(PPC::R3).addReg(PPC::R3); + } + break; + case MVT::f32: + BuildMI(BB, PPC::FMRS, 1, Result).addReg(PPC::F1); + break; + case MVT::f64: + BuildMI(BB, PPC::FMRD, 1, Result).addReg(PPC::F1); + break; + } + return Result+N.ResNo; + } + + case ISD::SIGN_EXTEND_INREG: + Tmp1 = SelectExpr(N.getOperand(0)); + switch(cast(Node->getOperand(1))->getVT()) { + default: Node->dump(); assert(0 && "Unhandled SIGN_EXTEND type"); break; + case MVT::i16: + BuildMI(BB, PPC::EXTSH, 1, Result).addReg(Tmp1); + break; + case MVT::i8: + BuildMI(BB, PPC::EXTSB, 1, Result).addReg(Tmp1); + break; + } + return Result; + + case ISD::CopyFromReg: + DestType = N.getValue(0).getValueType(); + if (Result == 1) + Result = ExprMap[N.getValue(0)] = MakeReg(DestType); + else + ExprMap[N.getValue(1)] = 1; + Tmp1 = dyn_cast(Node->getOperand(1))->getReg(); + if (MVT::isInteger(DestType)) + BuildMI(BB, PPC::OR, 2, Result).addReg(Tmp1).addReg(Tmp1); + else if (DestType == MVT::f32) + BuildMI(BB, PPC::FMRS, 1, Result).addReg(Tmp1); + else + BuildMI(BB, PPC::FMRD, 1, Result).addReg(Tmp1); + return Result; + + case ISD::SHL: + if (isIntImmediate(N.getOperand(1), Tmp2)) { + unsigned SH, MB, ME; + if (isOpcWithIntImmediate(N.getOperand(0), ISD::AND, Tmp3) && + isRotateAndMask(ISD::SHL, Tmp2, Tmp3, true, SH, MB, ME)) { + Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); + BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp1).addImm(SH) + .addImm(MB).addImm(ME); + return Result; + } + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 &= 0x1F; + BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp1).addImm(Tmp2).addImm(0) + .addImm(31-Tmp2); + } else { + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = FoldIfWideZeroExtend(N.getOperand(1)); + BuildMI(BB, PPC::SLW, 2, Result).addReg(Tmp1).addReg(Tmp2); + } + return Result; + + case ISD::SRL: + if (isIntImmediate(N.getOperand(1), Tmp2)) { + unsigned SH, MB, ME; + if (isOpcWithIntImmediate(N.getOperand(0), ISD::AND, Tmp3) && + isRotateAndMask(ISD::SRL, Tmp2, Tmp3, true, SH, MB, ME)) { + Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); + BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp1).addImm(SH & 0x1F) + .addImm(MB).addImm(ME); + return Result; + } + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 &= 0x1F; + BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp1).addImm((32-Tmp2) & 0x1F) + .addImm(Tmp2).addImm(31); + } else { + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = FoldIfWideZeroExtend(N.getOperand(1)); + BuildMI(BB, PPC::SRW, 2, Result).addReg(Tmp1).addReg(Tmp2); + } + return Result; + + case ISD::SRA: + if (isIntImmediate(N.getOperand(1), Tmp2)) { + unsigned SH, MB, ME; + if (isOpcWithIntImmediate(N.getOperand(0), ISD::AND, Tmp3) && + isRotateAndMask(ISD::SRA, Tmp2, Tmp3, true, SH, MB, ME)) { + Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); + BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp1).addImm(SH) + .addImm(MB).addImm(ME); + return Result; + } + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 &= 0x1F; + BuildMI(BB, PPC::SRAWI, 2, Result).addReg(Tmp1).addImm(Tmp2); + } else { + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = FoldIfWideZeroExtend(N.getOperand(1)); + BuildMI(BB, PPC::SRAW, 2, Result).addReg(Tmp1).addReg(Tmp2); + } + return Result; + + case ISD::CTLZ: + Tmp1 = SelectExpr(N.getOperand(0)); + BuildMI(BB, PPC::CNTLZW, 1, Result).addReg(Tmp1); + return Result; + + case ISD::ADD: + if (SelectIntImmediateExpr(N, Result, PPC::ADDIS, PPC::ADDI, true)) + return Result; + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, PPC::ADD, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + + case ISD::FADD: + if (!NoExcessFPPrecision && N.getOperand(0).getOpcode() == ISD::FMUL && + N.getOperand(0).Val->hasOneUse()) { + ++FusedFP; // Statistic + Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(0).getOperand(1)); + Tmp3 = SelectExpr(N.getOperand(1)); + Opc = DestType == MVT::f64 ? PPC::FMADD : PPC::FMADDS; + BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3); + return Result; + } + if (!NoExcessFPPrecision && N.getOperand(1).getOpcode() == ISD::FMUL && + N.getOperand(1).Val->hasOneUse()) { + ++FusedFP; // Statistic + Tmp1 = SelectExpr(N.getOperand(1).getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1).getOperand(1)); + Tmp3 = SelectExpr(N.getOperand(0)); + Opc = DestType == MVT::f64 ? PPC::FMADD : PPC::FMADDS; + BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3); + return Result; + } + Opc = DestType == MVT::f64 ? PPC::FADD : PPC::FADDS; + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + + case ISD::AND: + if (isIntImmediate(N.getOperand(1), Tmp2)) { + if (isShiftedMask_32(Tmp2) || isShiftedMask_32(~Tmp2)) { + unsigned SH, MB, ME; + Opc = Recording ? PPC::RLWINMo : PPC::RLWINM; + unsigned OprOpc; + if (isOprShiftImm(N.getOperand(0), OprOpc, Tmp3) && + isRotateAndMask(OprOpc, Tmp3, Tmp2, false, SH, MB, ME)) { + Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); + } else { + Tmp1 = SelectExpr(N.getOperand(0)); + isRunOfOnes(Tmp2, MB, ME); + SH = 0; + } + BuildMI(BB, Opc, 4, Result).addReg(Tmp1).addImm(SH) + .addImm(MB).addImm(ME); + RecordSuccess = true; + return Result; + } else if (isUInt16(Tmp2)) { + Tmp2 = Lo16(Tmp2); + Tmp1 = SelectExpr(N.getOperand(0)); + BuildMI(BB, PPC::ANDIo, 2, Result).addReg(Tmp1).addImm(Tmp2); + RecordSuccess = true; + return Result; + } else if (isUInt16(Tmp2)) { + Tmp2 = Hi16(Tmp2); + Tmp1 = SelectExpr(N.getOperand(0)); + BuildMI(BB, PPC::ANDISo, 2, Result).addReg(Tmp1).addImm(Tmp2); + RecordSuccess = true; + return Result; + } + } + if (isOprNot(N.getOperand(1))) { + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1).getOperand(0)); + BuildMI(BB, PPC::ANDC, 2, Result).addReg(Tmp1).addReg(Tmp2); + RecordSuccess = false; + return Result; + } + if (isOprNot(N.getOperand(0))) { + Tmp1 = SelectExpr(N.getOperand(1)); + Tmp2 = SelectExpr(N.getOperand(0).getOperand(0)); + BuildMI(BB, PPC::ANDC, 2, Result).addReg(Tmp1).addReg(Tmp2); + RecordSuccess = false; + return Result; + } + // emit a regular and + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + Opc = Recording ? PPC::ANDo : PPC::AND; + BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); + RecordSuccess = true; + return Result; + + case ISD::OR: + if (SelectBitfieldInsert(N, Result)) + return Result; + if (SelectIntImmediateExpr(N, Result, PPC::ORIS, PPC::ORI)) + return Result; + if (isOprNot(N.getOperand(1))) { + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1).getOperand(0)); + BuildMI(BB, PPC::ORC, 2, Result).addReg(Tmp1).addReg(Tmp2); + RecordSuccess = false; + return Result; + } + if (isOprNot(N.getOperand(0))) { + Tmp1 = SelectExpr(N.getOperand(1)); + Tmp2 = SelectExpr(N.getOperand(0).getOperand(0)); + BuildMI(BB, PPC::ORC, 2, Result).addReg(Tmp1).addReg(Tmp2); + RecordSuccess = false; + return Result; + } + // emit regular or + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + Opc = Recording ? PPC::ORo : PPC::OR; + RecordSuccess = true; + BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + + case ISD::XOR: { + // Check for EQV: xor, (xor a, -1), b + if (isOprNot(N.getOperand(0))) { + Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, PPC::EQV, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + } + // Check for NOT, NOR, EQV, and NAND: xor (copy, or, xor, and), -1 + if (isOprNot(N)) { + switch(N.getOperand(0).getOpcode()) { + case ISD::OR: + Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(0).getOperand(1)); + BuildMI(BB, PPC::NOR, 2, Result).addReg(Tmp1).addReg(Tmp2); + break; + case ISD::AND: + Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(0).getOperand(1)); + BuildMI(BB, PPC::NAND, 2, Result).addReg(Tmp1).addReg(Tmp2); + break; + case ISD::XOR: + Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(0).getOperand(1)); + BuildMI(BB, PPC::EQV, 2, Result).addReg(Tmp1).addReg(Tmp2); + break; + default: + Tmp1 = SelectExpr(N.getOperand(0)); + BuildMI(BB, PPC::NOR, 2, Result).addReg(Tmp1).addReg(Tmp1); + break; + } + return Result; + } + if (SelectIntImmediateExpr(N, Result, PPC::XORIS, PPC::XORI)) + return Result; + // emit regular xor + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, PPC::XOR, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + } + + case ISD::FSUB: + if (!NoExcessFPPrecision && N.getOperand(0).getOpcode() == ISD::FMUL && + N.getOperand(0).Val->hasOneUse()) { + ++FusedFP; // Statistic + Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(0).getOperand(1)); + Tmp3 = SelectExpr(N.getOperand(1)); + Opc = DestType == MVT::f64 ? PPC::FMSUB : PPC::FMSUBS; + BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3); + return Result; + } + if (!NoExcessFPPrecision && N.getOperand(1).getOpcode() == ISD::FMUL && + N.getOperand(1).Val->hasOneUse()) { + ++FusedFP; // Statistic + Tmp1 = SelectExpr(N.getOperand(1).getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1).getOperand(1)); + Tmp3 = SelectExpr(N.getOperand(0)); + Opc = DestType == MVT::f64 ? PPC::FNMSUB : PPC::FNMSUBS; + BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3); + return Result; + } + Opc = DestType == MVT::f64 ? PPC::FSUB : PPC::FSUBS; + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + case ISD::SUB: + if (isIntImmediate(N.getOperand(0), Tmp1) && isInt16(Tmp1)) { + Tmp1 = Lo16(Tmp1); + Tmp2 = SelectExpr(N.getOperand(1)); + if (0 == Tmp1) + BuildMI(BB, PPC::NEG, 1, Result).addReg(Tmp2); + else + BuildMI(BB, PPC::SUBFIC, 2, Result).addReg(Tmp2).addSImm(Tmp1); + return Result; + } + if (SelectIntImmediateExpr(N, Result, PPC::ADDIS, PPC::ADDI, true, true)) + return Result; + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, PPC::SUBF, 2, Result).addReg(Tmp2).addReg(Tmp1); + return Result; + + case ISD::FMUL: + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, DestType == MVT::f32 ? PPC::FMULS : PPC::FMUL, 2, + Result).addReg(Tmp1).addReg(Tmp2); + return Result; + + case ISD::MUL: + Tmp1 = SelectExpr(N.getOperand(0)); + if (isIntImmediate(N.getOperand(1), Tmp2) && isInt16(Tmp2)) { + Tmp2 = Lo16(Tmp2); + BuildMI(BB, PPC::MULLI, 2, Result).addReg(Tmp1).addSImm(Tmp2); + } else { + Tmp2 = SelectExpr(N.getOperand(1)); + BuildMI(BB, PPC::MULLW, 2, Result).addReg(Tmp1).addReg(Tmp2); + } + return Result; + + case ISD::MULHS: + case ISD::MULHU: + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + Opc = (ISD::MULHU == opcode) ? PPC::MULHWU : PPC::MULHW; + BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + + case ISD::FDIV: + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + switch (DestType) { + default: assert(0 && "Unknown type to ISD::FDIV"); break; + case MVT::f32: Opc = PPC::FDIVS; break; + case MVT::f64: Opc = PPC::FDIV; break; + } + BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + + case ISD::SDIV: + if (isIntImmediate(N.getOperand(1), Tmp3)) { + if ((signed)Tmp3 > 0 && isPowerOf2_32(Tmp3)) { + Tmp3 = Log2_32(Tmp3); + Tmp1 = MakeIntReg(); + Tmp2 = SelectExpr(N.getOperand(0)); + BuildMI(BB, PPC::SRAWI, 2, Tmp1).addReg(Tmp2).addImm(Tmp3); + BuildMI(BB, PPC::ADDZE, 1, Result).addReg(Tmp1); + return Result; + } else if ((signed)Tmp3 < 0 && isPowerOf2_32(-Tmp3)) { + Tmp3 = Log2_32(-Tmp3); + Tmp2 = SelectExpr(N.getOperand(0)); + Tmp1 = MakeIntReg(); + unsigned Tmp4 = MakeIntReg(); + BuildMI(BB, PPC::SRAWI, 2, Tmp1).addReg(Tmp2).addImm(Tmp3); + BuildMI(BB, PPC::ADDZE, 1, Tmp4).addReg(Tmp1); + BuildMI(BB, PPC::NEG, 1, Result).addReg(Tmp4); + return Result; + } else if (Tmp3) { + ExprMap.erase(N); + return SelectExpr(BuildSDIVSequence(N)); + } + } + // fall thru + case ISD::UDIV: + // If this is a divide by constant, we can emit code using some magic + // constants to implement it as a multiply instead. + if (isIntImmediate(N.getOperand(1), Tmp3) && Tmp3) { + ExprMap.erase(N); + return SelectExpr(BuildUDIVSequence(N)); + } + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + Opc = (ISD::UDIV == opcode) ? PPC::DIVWU : PPC::DIVW; break; + BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(Tmp2); + return Result; + + case ISD::ADD_PARTS: + case ISD::SUB_PARTS: { + assert(N.getNumOperands() == 4 && N.getValueType() == MVT::i32 && + "Not an i64 add/sub!"); + unsigned Tmp4 = 0; + Tmp1 = SelectExpr(N.getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(1)); + + if (N.getOpcode() == ISD::ADD_PARTS) { + bool ME = false, ZE = false; + if (isIntImmediate(N.getOperand(3), Tmp3)) { + ME = (signed)Tmp3 == -1; + ZE = Tmp3 == 0; + } + + if (!ZE && !ME) + Tmp4 = SelectExpr(N.getOperand(3)); + + if (isIntImmediate(N.getOperand(2), Tmp3) && + ((signed)Tmp3 >= -32768 || (signed)Tmp3 < 32768)) { + // Codegen the low 32 bits of the add. Interestingly, there is no + // shifted form of add immediate carrying. + BuildMI(BB, PPC::ADDIC, 2, Result).addReg(Tmp1).addSImm(Tmp3); + } else { + Tmp3 = SelectExpr(N.getOperand(2)); + BuildMI(BB, PPC::ADDC, 2, Result).addReg(Tmp1).addReg(Tmp3); + } + + // Codegen the high 32 bits, adding zero, minus one, or the full value + // along with the carry flag produced by addc/addic to tmp2. + if (ZE) { + BuildMI(BB, PPC::ADDZE, 1, Result+1).addReg(Tmp2); + } else if (ME) { + BuildMI(BB, PPC::ADDME, 1, Result+1).addReg(Tmp2); + } else { + BuildMI(BB, PPC::ADDE, 2, Result+1).addReg(Tmp2).addReg(Tmp4); + } + } else { + Tmp3 = SelectExpr(N.getOperand(2)); + Tmp4 = SelectExpr(N.getOperand(3)); + BuildMI(BB, PPC::SUBFC, 2, Result).addReg(Tmp3).addReg(Tmp1); + BuildMI(BB, PPC::SUBFE, 2, Result+1).addReg(Tmp4).addReg(Tmp2); + } + return Result+N.ResNo; + } + + case ISD::SETCC: { + ISD::CondCode CC = cast(Node->getOperand(2))->get(); + if (isIntImmediate(Node->getOperand(1), Tmp3)) { + // We can codegen setcc op, imm very efficiently compared to a brcond. + // Check for those cases here. + // setcc op, 0 + if (Tmp3 == 0) { + Tmp1 = SelectExpr(Node->getOperand(0)); + switch (CC) { + default: Node->dump(); assert(0 && "Unhandled SetCC condition");abort(); + case ISD::SETEQ: + Tmp2 = MakeIntReg(); + BuildMI(BB, PPC::CNTLZW, 1, Tmp2).addReg(Tmp1); + BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp2).addImm(27) + .addImm(5).addImm(31); + break; + case ISD::SETNE: + Tmp2 = MakeIntReg(); + BuildMI(BB, PPC::ADDIC, 2, Tmp2).addReg(Tmp1).addSImm(-1); + BuildMI(BB, PPC::SUBFE, 2, Result).addReg(Tmp2).addReg(Tmp1); + break; + case ISD::SETLT: + BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp1).addImm(1) + .addImm(31).addImm(31); + break; + case ISD::SETGT: + Tmp2 = MakeIntReg(); + Tmp3 = MakeIntReg(); + BuildMI(BB, PPC::NEG, 2, Tmp2).addReg(Tmp1); + BuildMI(BB, PPC::ANDC, 2, Tmp3).addReg(Tmp2).addReg(Tmp1); + BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp3).addImm(1) + .addImm(31).addImm(31); + break; + } + return Result; + } else if (Tmp3 == ~0U) { // setcc op, -1 + Tmp1 = SelectExpr(Node->getOperand(0)); + switch (CC) { + default: assert(0 && "Unhandled SetCC condition"); abort(); + case ISD::SETEQ: + Tmp2 = MakeIntReg(); + Tmp3 = MakeIntReg(); + BuildMI(BB, PPC::ADDIC, 2, Tmp2).addReg(Tmp1).addSImm(1); + BuildMI(BB, PPC::LI, 1, Tmp3).addSImm(0); + BuildMI(BB, PPC::ADDZE, 1, Result).addReg(Tmp3); + break; + case ISD::SETNE: + Tmp2 = MakeIntReg(); + Tmp3 = MakeIntReg(); + BuildMI(BB, PPC::NOR, 2, Tmp2).addReg(Tmp1).addReg(Tmp1); + BuildMI(BB, PPC::ADDIC, 2, Tmp3).addReg(Tmp2).addSImm(-1); + BuildMI(BB, PPC::SUBFE, 2, Result).addReg(Tmp3).addReg(Tmp2); + break; + case ISD::SETLT: + Tmp2 = MakeIntReg(); + Tmp3 = MakeIntReg(); + BuildMI(BB, PPC::ADDI, 2, Tmp2).addReg(Tmp1).addSImm(1); + BuildMI(BB, PPC::AND, 2, Tmp3).addReg(Tmp2).addReg(Tmp1); + BuildMI(BB, PPC::RLWINM, 4, Result).addReg(Tmp3).addImm(1) + .addImm(31).addImm(31); + break; + case ISD::SETGT: + Tmp2 = MakeIntReg(); + BuildMI(BB, PPC::RLWINM, 4, Tmp2).addReg(Tmp1).addImm(1) + .addImm(31).addImm(31); + BuildMI(BB, PPC::XORI, 2, Result).addReg(Tmp2).addImm(1); + break; + } + return Result; + } + } + + unsigned CCReg = SelectCC(N.getOperand(0), N.getOperand(1), CC); + MoveCRtoGPR(CCReg, CC, Result); + return Result; + } + + case ISD::SELECT_CC: { + ISD::CondCode CC = cast(N.getOperand(4))->get(); + + // handle the setcc cases here. select_cc lhs, 0, 1, 0, cc + ConstantSDNode *N1C = dyn_cast(N.getOperand(1)); + ConstantSDNode *N2C = dyn_cast(N.getOperand(2)); + ConstantSDNode *N3C = dyn_cast(N.getOperand(3)); + if (N1C && N2C && N3C && N1C->isNullValue() && N3C->isNullValue() && + N2C->getValue() == 1ULL && CC == ISD::SETNE) { + Tmp1 = SelectExpr(Node->getOperand(0)); + Tmp2 = MakeIntReg(); + BuildMI(BB, PPC::ADDIC, 2, Tmp2).addReg(Tmp1).addSImm(-1); + BuildMI(BB, PPC::SUBFE, 2, Result).addReg(Tmp2).addReg(Tmp1); + return Result; + } + + // If the False value only has one use, we can generate better code by + // selecting it in the fallthrough basic block rather than here, which + // increases register pressure. + unsigned TrueValue = SelectExpr(N.getOperand(2)); + unsigned FalseValue; + + // If the false value is simple enough, evaluate it inline in the false + // block. + if (N.getOperand(3).Val->hasOneUse() && + (isa(N.getOperand(3)) || + isa(N.getOperand(3)))) + FalseValue = 0; + else + FalseValue = SelectExpr(N.getOperand(3)); + unsigned CCReg = SelectCC(N.getOperand(0), N.getOperand(1), CC); + Opc = getBCCForSetCC(CC); + + // Create an iterator with which to insert the MBB for copying the false + // value and the MBB to hold the PHI instruction for this SetCC. + MachineBasicBlock *thisMBB = BB; + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + ilist::iterator It = BB; + ++It; + + // thisMBB: + // ... + // TrueVal = ... + // cmpTY ccX, r1, r2 + // bCC copy1MBB + // fallthrough --> copy0MBB + MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB); + BuildMI(BB, Opc, 2).addReg(CCReg).addMBB(sinkMBB); + MachineFunction *F = BB->getParent(); + F->getBasicBlockList().insert(It, copy0MBB); + F->getBasicBlockList().insert(It, sinkMBB); + // Update machine-CFG edges + BB->addSuccessor(copy0MBB); + BB->addSuccessor(sinkMBB); + + // copy0MBB: + // %FalseValue = ... + // # fallthrough to sinkMBB + BB = copy0MBB; + + // If the false value is simple enough, evaluate it here, to avoid it being + // evaluated on the true edge. + if (FalseValue == 0) + FalseValue = SelectExpr(N.getOperand(3)); + + // Update machine-CFG edges + BB->addSuccessor(sinkMBB); + + // sinkMBB: + // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] + // ... + BB = sinkMBB; + BuildMI(BB, PPC::PHI, 4, Result).addReg(FalseValue) + .addMBB(copy0MBB).addReg(TrueValue).addMBB(thisMBB); + return Result; + } + + case ISD::Constant: { + assert(N.getValueType() == MVT::i32 && + "Only i32 constants are legal on this target!"); + unsigned v = (unsigned)cast(N)->getValue(); + if (isInt16(v)) { + BuildMI(BB, PPC::LI, 1, Result).addSImm(Lo16(v)); + } else { + unsigned Hi = Hi16(v); + unsigned Lo = Lo16(v); + if (Lo) { + Tmp1 = MakeIntReg(); + BuildMI(BB, PPC::LIS, 1, Tmp1).addSImm(Hi); + BuildMI(BB, PPC::ORI, 2, Result).addReg(Tmp1).addImm(Lo); + } else { + BuildMI(BB, PPC::LIS, 1, Result).addSImm(Hi); + } + } + return Result; + } + + case ISD::FNEG: + if (!NoExcessFPPrecision && + ISD::FADD == N.getOperand(0).getOpcode() && + N.getOperand(0).Val->hasOneUse() && + ISD::FMUL == N.getOperand(0).getOperand(0).getOpcode() && + N.getOperand(0).getOperand(0).Val->hasOneUse()) { + ++FusedFP; // Statistic + Tmp1 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(0).getOperand(0).getOperand(1)); + Tmp3 = SelectExpr(N.getOperand(0).getOperand(1)); + Opc = DestType == MVT::f64 ? PPC::FNMADD : PPC::FNMADDS; + BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3); + } else if (!NoExcessFPPrecision && + ISD::FADD == N.getOperand(0).getOpcode() && + N.getOperand(0).Val->hasOneUse() && + ISD::FMUL == N.getOperand(0).getOperand(1).getOpcode() && + N.getOperand(0).getOperand(1).Val->hasOneUse()) { + ++FusedFP; // Statistic + Tmp1 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(0)); + Tmp2 = SelectExpr(N.getOperand(0).getOperand(1).getOperand(1)); + Tmp3 = SelectExpr(N.getOperand(0).getOperand(0)); + Opc = DestType == MVT::f64 ? PPC::FNMADD : PPC::FNMADDS; + BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3); + } else if (ISD::FABS == N.getOperand(0).getOpcode()) { + Tmp1 = SelectExpr(N.getOperand(0).getOperand(0)); + if (N.getOperand(0).getValueType() == MVT::f32) + BuildMI(BB, PPC::FNABSS, 1, Result).addReg(Tmp1); + else + BuildMI(BB, PPC::FNABSD, 1, Result).addReg(Tmp1); + + } else { + Tmp1 = SelectExpr(N.getOperand(0)); + if (N.getOperand(0).getValueType() == MVT::f32) + BuildMI(BB, PPC::FNEGS, 1, Result).addReg(Tmp1); + else + BuildMI(BB, PPC::FNEGD, 1, Result).addReg(Tmp1); + } + return Result; + + case ISD::FABS: + Tmp1 = SelectExpr(N.getOperand(0)); + if (N.getOperand(0).getValueType() == MVT::f32) + BuildMI(BB, PPC::FABSS, 1, Result).addReg(Tmp1); + else + BuildMI(BB, PPC::FABSD, 1, Result).addReg(Tmp1); + return Result; + + case ISD::FSQRT: + Tmp1 = SelectExpr(N.getOperand(0)); + Opc = DestType == MVT::f64 ? PPC::FSQRT : PPC::FSQRTS; + BuildMI(BB, Opc, 1, Result).addReg(Tmp1); + return Result; + + case ISD::FP_ROUND: + assert (DestType == MVT::f32 && + N.getOperand(0).getValueType() == MVT::f64 && + "only f64 to f32 conversion supported here"); + Tmp1 = SelectExpr(N.getOperand(0)); + BuildMI(BB, PPC::FRSP, 1, Result).addReg(Tmp1); + return Result; + + case ISD::FP_EXTEND: + assert (DestType == MVT::f64 && + N.getOperand(0).getValueType() == MVT::f32 && + "only f32 to f64 conversion supported here"); + Tmp1 = SelectExpr(N.getOperand(0)); + BuildMI(BB, PPC::FMRSD, 1, Result).addReg(Tmp1); + return Result; + } + return 0; +} + +void ISel::Select(SDOperand N) { + unsigned Tmp1, Tmp2, Tmp3, Opc; + unsigned opcode = N.getOpcode(); + + if (!ExprMap.insert(std::make_pair(N, 1)).second) + return; // Already selected. + + SDNode *Node = N.Val; + + switch (Node->getOpcode()) { + default: + Node->dump(); std::cerr << "\n"; + assert(0 && "Node not handled yet!"); + case ISD::EntryToken: return; // Noop + case ISD::TokenFactor: + for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) + Select(Node->getOperand(i)); + return; + case ISD::CALLSEQ_START: + case ISD::CALLSEQ_END: + Select(N.getOperand(0)); + Tmp1 = cast(N.getOperand(1))->getValue(); + Opc = N.getOpcode() == ISD::CALLSEQ_START ? PPC::ADJCALLSTACKDOWN : + PPC::ADJCALLSTACKUP; + BuildMI(BB, Opc, 1).addImm(Tmp1); + return; + case ISD::BR: { + MachineBasicBlock *Dest = + cast(N.getOperand(1))->getBasicBlock(); + Select(N.getOperand(0)); + BuildMI(BB, PPC::B, 1).addMBB(Dest); + return; + } + case ISD::BR_CC: + case ISD::BRTWOWAY_CC: + SelectBranchCC(N); + return; + case ISD::CopyToReg: + Select(N.getOperand(0)); + Tmp1 = SelectExpr(N.getOperand(2)); + Tmp2 = cast(N.getOperand(1))->getReg(); + + if (Tmp1 != Tmp2) { + if (N.getOperand(2).getValueType() == MVT::f64) + BuildMI(BB, PPC::FMRD, 1, Tmp2).addReg(Tmp1); + else if (N.getOperand(2).getValueType() == MVT::f32) + BuildMI(BB, PPC::FMRS, 1, Tmp2).addReg(Tmp1); + else + BuildMI(BB, PPC::OR, 2, Tmp2).addReg(Tmp1).addReg(Tmp1); + } + return; + case ISD::ImplicitDef: + Select(N.getOperand(0)); + Tmp1 = cast(N.getOperand(1))->getReg(); + if (N.getOperand(1).getValueType() == MVT::i32) + BuildMI(BB, PPC::IMPLICIT_DEF_GPR, 0, Tmp1); + else if (N.getOperand(1).getValueType() == MVT::f32) + BuildMI(BB, PPC::IMPLICIT_DEF_F4, 0, Tmp1); + else + BuildMI(BB, PPC::IMPLICIT_DEF_F8, 0, Tmp1); + return; + case ISD::RET: + switch (N.getNumOperands()) { + default: + assert(0 && "Unknown return instruction!"); + case 3: + assert(N.getOperand(1).getValueType() == MVT::i32 && + N.getOperand(2).getValueType() == MVT::i32 && + "Unknown two-register value!"); + Select(N.getOperand(0)); + Tmp1 = SelectExpr(N.getOperand(1)); + Tmp2 = SelectExpr(N.getOperand(2)); + BuildMI(BB, PPC::OR, 2, PPC::R3).addReg(Tmp2).addReg(Tmp2); + BuildMI(BB, PPC::OR, 2, PPC::R4).addReg(Tmp1).addReg(Tmp1); + break; + case 2: + Select(N.getOperand(0)); + Tmp1 = SelectExpr(N.getOperand(1)); + switch (N.getOperand(1).getValueType()) { + default: + assert(0 && "Unknown return type!"); + case MVT::f64: + BuildMI(BB, PPC::FMRD, 1, PPC::F1).addReg(Tmp1); + break; + case MVT::f32: + BuildMI(BB, PPC::FMRS, 1, PPC::F1).addReg(Tmp1); + break; + case MVT::i32: + BuildMI(BB, PPC::OR, 2, PPC::R3).addReg(Tmp1).addReg(Tmp1); + break; + } + case 1: + Select(N.getOperand(0)); + break; + } + BuildMI(BB, PPC::BLR, 0); // Just emit a 'ret' instruction + return; + case ISD::TRUNCSTORE: + case ISD::STORE: { + SDOperand Chain = N.getOperand(0); + SDOperand Value = N.getOperand(1); + SDOperand Address = N.getOperand(2); + Select(Chain); + + Tmp1 = SelectExpr(Value); //value + + if (opcode == ISD::STORE) { + switch(Value.getValueType()) { + default: assert(0 && "unknown Type in store"); + case MVT::i32: Opc = PPC::STW; break; + case MVT::f64: Opc = PPC::STFD; break; + case MVT::f32: Opc = PPC::STFS; break; + } + } else { //ISD::TRUNCSTORE + switch(cast(Node->getOperand(4))->getVT()) { + default: assert(0 && "unknown Type in store"); + case MVT::i8: Opc = PPC::STB; break; + case MVT::i16: Opc = PPC::STH; break; + } + } + + if(Address.getOpcode() == ISD::FrameIndex) { + Tmp2 = cast(Address)->getIndex(); + addFrameReference(BuildMI(BB, Opc, 3).addReg(Tmp1), (int)Tmp2); + } else { + int offset; + switch(SelectAddr(Address, Tmp2, offset)) { + default: assert(0 && "Unhandled return value from SelectAddr"); + case 0: // imm offset, no frame, no index + BuildMI(BB, Opc, 3).addReg(Tmp1).addSImm(offset).addReg(Tmp2); + break; + case 1: // imm offset + frame index + addFrameReference(BuildMI(BB, Opc, 3).addReg(Tmp1), (int)Tmp2, offset); + break; + case 2: // base+index addressing + Opc = IndexedOpForOp(Opc); + BuildMI(BB, Opc, 3).addReg(Tmp1).addReg(Tmp2).addReg(offset); + break; + case 3: { + GlobalAddressSDNode *GN = cast(Address); + GlobalValue *GV = GN->getGlobal(); + BuildMI(BB, Opc, 3).addReg(Tmp1).addGlobalAddress(GV).addReg(Tmp2); + } + } + } + return; + } + case ISD::EXTLOAD: + case ISD::SEXTLOAD: + case ISD::ZEXTLOAD: + case ISD::LOAD: + case ISD::CopyFromReg: + case ISD::TAILCALL: + case ISD::CALL: + case ISD::DYNAMIC_STACKALLOC: + ExprMap.erase(N); + SelectExpr(N); + return; + } + assert(0 && "Should not be reached!"); +} + + +/// createPPC32PatternInstructionSelector - This pass converts an LLVM function +/// into a machine code representation using pattern matching and a machine +/// description file. +/// +FunctionPass *llvm::createPPC32ISelPattern(TargetMachine &TM) { + return new ISel(TM); +} + diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp new file mode 100644 index 00000000000..314b7481263 --- /dev/null +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -0,0 +1,111 @@ +//===- PPC32InstrInfo.cpp - PowerPC32 Instruction Information ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the PowerPC implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "PPCInstrInfo.h" +#include "PPCGenInstrInfo.inc" +#include "PPC.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include +using namespace llvm; + +PPC32InstrInfo::PPC32InstrInfo() + : TargetInstrInfo(PPCInsts, sizeof(PPCInsts)/sizeof(PPCInsts[0])) {} + +bool PPC32InstrInfo::isMoveInstr(const MachineInstr& MI, + unsigned& sourceReg, + unsigned& destReg) const { + MachineOpCode oc = MI.getOpcode(); + if (oc == PPC::OR) { // or r1, r2, r2 + assert(MI.getNumOperands() == 3 && + MI.getOperand(0).isRegister() && + MI.getOperand(1).isRegister() && + MI.getOperand(2).isRegister() && + "invalid PPC OR instruction!"); + if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) { + sourceReg = MI.getOperand(1).getReg(); + destReg = MI.getOperand(0).getReg(); + return true; + } + } else if (oc == PPC::ADDI) { // addi r1, r2, 0 + assert(MI.getNumOperands() == 3 && + MI.getOperand(0).isRegister() && + MI.getOperand(2).isImmediate() && + "invalid PPC ADDI instruction!"); + if (MI.getOperand(1).isRegister() && MI.getOperand(2).getImmedValue()==0) { + sourceReg = MI.getOperand(1).getReg(); + destReg = MI.getOperand(0).getReg(); + return true; + } + } else if (oc == PPC::ORI) { // ori r1, r2, 0 + assert(MI.getNumOperands() == 3 && + MI.getOperand(0).isRegister() && + MI.getOperand(1).isRegister() && + MI.getOperand(2).isImmediate() && + "invalid PPC ORI instruction!"); + if (MI.getOperand(2).getImmedValue()==0) { + sourceReg = MI.getOperand(1).getReg(); + destReg = MI.getOperand(0).getReg(); + return true; + } + } else if (oc == PPC::FMRS || oc == PPC::FMRD || + oc == PPC::FMRSD) { // fmr r1, r2 + assert(MI.getNumOperands() == 2 && + MI.getOperand(0).isRegister() && + MI.getOperand(1).isRegister() && + "invalid PPC FMR instruction"); + sourceReg = MI.getOperand(1).getReg(); + destReg = MI.getOperand(0).getReg(); + return true; + } else if (oc == PPC::MCRF) { // mcrf cr1, cr2 + assert(MI.getNumOperands() == 2 && + MI.getOperand(0).isRegister() && + MI.getOperand(1).isRegister() && + "invalid PPC MCRF instruction"); + sourceReg = MI.getOperand(1).getReg(); + destReg = MI.getOperand(0).getReg(); + return true; + } + return false; +} + +// commuteInstruction - We can commute rlwimi instructions, but only if the +// rotate amt is zero. We also have to munge the immediates a bit. +MachineInstr *PPC32InstrInfo::commuteInstruction(MachineInstr *MI) const { + // Normal instructions can be commuted the obvious way. + if (MI->getOpcode() != PPC::RLWIMI) + return TargetInstrInfo::commuteInstruction(MI); + + // Cannot commute if it has a non-zero rotate count. + if (MI->getOperand(3).getImmedValue() != 0) + return 0; + + // If we have a zero rotate count, we have: + // M = mask(MB,ME) + // Op0 = (Op1 & ~M) | (Op2 & M) + // Change this to: + // M = mask((ME+1)&31, (MB-1)&31) + // Op0 = (Op2 & ~M) | (Op1 & M) + + // Swap op1/op2 + unsigned Reg1 = MI->getOperand(1).getReg(); + unsigned Reg2 = MI->getOperand(2).getReg(); + MI->SetMachineOperandReg(2, Reg1); + MI->SetMachineOperandReg(1, Reg2); + + // Swap the mask around. + unsigned MB = MI->getOperand(4).getImmedValue(); + unsigned ME = MI->getOperand(5).getImmedValue(); + MI->getOperand(4).setImmedValue((ME+1) & 31); + MI->getOperand(5).setImmedValue((MB-1) & 31); + return MI; +} diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.h b/llvm/lib/Target/PowerPC/PPCInstrInfo.h new file mode 100644 index 00000000000..631bce11353 --- /dev/null +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.h @@ -0,0 +1,61 @@ +//===- PPC32InstrInfo.h - PowerPC32 Instruction Information -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the PowerPC implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef POWERPC32_INSTRUCTIONINFO_H +#define POWERPC32_INSTRUCTIONINFO_H + +#include "PPC.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "PPCRegisterInfo.h" + +namespace llvm { + +class PPC32InstrInfo : public TargetInstrInfo { + const PPC32RegisterInfo RI; +public: + PPC32InstrInfo(); + + /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As + /// such, whenever a client has an instance of instruction info, it should + /// always be able to get register info as well (through this method). + /// + virtual const MRegisterInfo &getRegisterInfo() const { return RI; } + + // + // Return true if the instruction is a register to register move and + // leave the source and dest operands in the passed parameters. + // + virtual bool isMoveInstr(const MachineInstr& MI, + unsigned& sourceReg, + unsigned& destReg) const; + + // commuteInstruction - We can commute rlwimi instructions, but only if the + // rotate amt is zero. We also have to munge the immediates a bit. + virtual MachineInstr *commuteInstruction(MachineInstr *MI) const; + + static unsigned invertPPCBranchOpcode(unsigned Opcode) { + switch (Opcode) { + default: assert(0 && "Unknown PPC branch opcode!"); + case PPC::BEQ: return PPC::BNE; + case PPC::BNE: return PPC::BEQ; + case PPC::BLT: return PPC::BGE; + case PPC::BGE: return PPC::BLT; + case PPC::BGT: return PPC::BLE; + case PPC::BLE: return PPC::BGT; + } + } +}; + +} + +#endif diff --git a/llvm/lib/Target/PowerPC/PPCJITInfo.cpp b/llvm/lib/Target/PowerPC/PPCJITInfo.cpp new file mode 100644 index 00000000000..30455606e77 --- /dev/null +++ b/llvm/lib/Target/PowerPC/PPCJITInfo.cpp @@ -0,0 +1,243 @@ +//===-- PPC32JITInfo.cpp - Implement the JIT interfaces for the PowerPC ---===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the JIT interfaces for the 32-bit PowerPC target. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "jit" +#include "PPCJITInfo.h" +#include "PPCRelocations.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" +#include "llvm/Config/alloca.h" +#include +using namespace llvm; + +static TargetJITInfo::JITCompilerFn JITCompilerFunction; + +#define BUILD_ADDIS(RD,RS,IMM16) \ + ((15 << 26) | ((RD) << 21) | ((RS) << 16) | ((IMM16) & 65535)) +#define BUILD_ORI(RD,RS,UIMM16) \ + ((24 << 26) | ((RS) << 21) | ((RD) << 16) | ((UIMM16) & 65535)) +#define BUILD_MTSPR(RS,SPR) \ + ((31 << 26) | ((RS) << 21) | ((SPR) << 16) | (467 << 1)) +#define BUILD_BCCTRx(BO,BI,LINK) \ + ((19 << 26) | ((BO) << 21) | ((BI) << 16) | (528 << 1) | ((LINK) & 1)) + +// Pseudo-ops +#define BUILD_LIS(RD,IMM16) BUILD_ADDIS(RD,0,IMM16) +#define BUILD_MTCTR(RS) BUILD_MTSPR(RS,9) +#define BUILD_BCTR(LINK) BUILD_BCCTRx(20,0,LINK) + + +static void EmitBranchToAt(void *At, void *To, bool isCall) { + intptr_t Addr = (intptr_t)To; + + // FIXME: should special case the short branch case. + unsigned *AtI = (unsigned*)At; + + AtI[0] = BUILD_LIS(12, Addr >> 16); // lis r12, hi16(address) + AtI[1] = BUILD_ORI(12, 12, Addr); // ori r12, r12, low16(address) + AtI[2] = BUILD_MTCTR(12); // mtctr r12 + AtI[3] = BUILD_BCTR(isCall); // bctr/bctrl +} + +extern "C" void PPC32CompilationCallback(); + +#if defined(__POWERPC__) || defined (__ppc__) || defined(_POWER) +// CompilationCallback stub - We can't use a C function with inline assembly in +// it, because we the prolog/epilog inserted by GCC won't work for us. Instead, +// write our own wrapper, which does things our way, so we have complete control +// over register saving and restoring. +asm( + ".text\n" + ".align 2\n" + ".globl _PPC32CompilationCallback\n" +"_PPC32CompilationCallback:\n" + // Make space for 29 ints r[3-31] and 14 doubles f[0-13] + "stwu r1, -272(r1)\n" + "mflr r11\n" + "stw r11, 280(r1)\n" // Set up a proper stack frame + "stmw r3, 156(r1)\n" // Save all of the integer registers + // Save all call-clobbered FP regs. + "stfd f1, 44(r1)\n" "stfd f2, 52(r1)\n" "stfd f3, 60(r1)\n" + "stfd f4, 68(r1)\n" "stfd f5, 76(r1)\n" "stfd f6, 84(r1)\n" + "stfd f7, 92(r1)\n" "stfd f8, 100(r1)\n" "stfd f9, 108(r1)\n" + "stfd f10, 116(r1)\n" "stfd f11, 124(r1)\n" "stfd f12, 132(r1)\n" + "stfd f13, 140(r1)\n" + + // Now that everything is saved, go to the C compilation callback function, + // passing the address of the intregs and fpregs. + "addi r3, r1, 156\n" // &IntRegs[0] + "addi r4, r1, 44\n" // &FPRegs[0] + "bl _PPC32CompilationCallbackC\n" + ); +#else +void PPC32CompilationCallback() { + assert(0 && "This is not a power pc, you can't execute this!"); + abort(); +} +#endif + +extern "C" void PPC32CompilationCallbackC(unsigned *IntRegs, double *FPRegs) { + unsigned *CameFromStub = (unsigned*)__builtin_return_address(0+1); + unsigned *CameFromOrig = (unsigned*)__builtin_return_address(1+1); + unsigned *CCStackPtr = (unsigned*)__builtin_frame_address(0); +//unsigned *StubStackPtr = (unsigned*)__builtin_frame_address(1); + unsigned *OrigStackPtr = (unsigned*)__builtin_frame_address(2+1); + + // Adjust pointer to the branch, not the return address. + --CameFromStub; + + void *Target = JITCompilerFunction(CameFromStub); + + // Check to see if CameFromOrig[-1] is a 'bl' instruction, and if we can + // rewrite it to branch directly to the destination. If so, rewrite it so it + // does not need to go through the stub anymore. + unsigned CameFromOrigInst = CameFromOrig[-1]; + if ((CameFromOrigInst >> 26) == 18) { // Direct call. + intptr_t Offset = ((intptr_t)Target-(intptr_t)CameFromOrig+4) >> 2; + if (Offset >= -(1 << 23) && Offset < (1 << 23)) { // In range? + // Clear the original target out. + CameFromOrigInst &= (63 << 26) | 3; + // Fill in the new target. + CameFromOrigInst |= (Offset & ((1 << 24)-1)) << 2; + // Replace the call. + CameFromOrig[-1] = CameFromOrigInst; + } + } + + // Locate the start of the stub. If this is a short call, adjust backwards + // the short amount, otherwise the full amount. + bool isShortStub = (*CameFromStub >> 26) == 18; + CameFromStub -= isShortStub ? 2 : 6; + + // Rewrite the stub with an unconditional branch to the target, for any users + // who took the address of the stub. + EmitBranchToAt(CameFromStub, Target, false); + + // Change the SP so that we pop two stack frames off when we return. + *CCStackPtr = (intptr_t)OrigStackPtr; + + // Put the address of the stub and the LR value that originally came into the + // stub in a place that is easy to get on the stack after we restore all regs. + CCStackPtr[2] = (intptr_t)Target; + CCStackPtr[1] = (intptr_t)CameFromOrig; + + // Note, this is not a standard epilog! +#if defined(__POWERPC__) || defined (__ppc__) || defined(_POWER) + register unsigned *IRR asm ("r2") = IntRegs; + register double *FRR asm ("r3") = FPRegs; + __asm__ __volatile__ ( + "lfd f1, 0(%0)\n" "lfd f2, 8(%0)\n" "lfd f3, 16(%0)\n" + "lfd f4, 24(%0)\n" "lfd f5, 32(%0)\n" "lfd f6, 40(%0)\n" + "lfd f7, 48(%0)\n" "lfd f8, 56(%0)\n" "lfd f9, 64(%0)\n" + "lfd f10, 72(%0)\n" "lfd f11, 80(%0)\n" "lfd f12, 88(%0)\n" + "lfd f13, 96(%0)\n" + "lmw r3, 0(%1)\n" // Load all integer regs + "lwz r0,4(r1)\n" // Get CameFromOrig (LR into stub) + "mtlr r0\n" // Put it in the LR register + "lwz r0,8(r1)\n" // Get target function pointer + "mtctr r0\n" // Put it into the CTR register + "lwz r1,0(r1)\n" // Pop two frames off + "bctr\n" :: // Return to stub! + "b" (FRR), "b" (IRR)); +#endif +} + + + +TargetJITInfo::LazyResolverFn +PPC32JITInfo::getLazyResolverFunction(JITCompilerFn Fn) { + JITCompilerFunction = Fn; + return PPC32CompilationCallback; +} + +void *PPC32JITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter &MCE) { + // If this is just a call to an external function, emit a branch instead of a + // call. The code is the same except for one bit of the last instruction. + if (Fn != PPC32CompilationCallback) { + MCE.startFunctionStub(4*4); + void *Addr = (void*)(intptr_t)MCE.getCurrentPCValue(); + MCE.emitWord(0); + MCE.emitWord(0); + MCE.emitWord(0); + MCE.emitWord(0); + EmitBranchToAt(Addr, Fn, false); + return MCE.finishFunctionStub(0); + } + + MCE.startFunctionStub(4*7); + MCE.emitWord(0x9421ffe0); // stwu r1,-32(r1) + MCE.emitWord(0x7d6802a6); // mflr r11 + MCE.emitWord(0x91610028); // stw r11, 40(r1) + void *Addr = (void*)(intptr_t)MCE.getCurrentPCValue(); + MCE.emitWord(0); + MCE.emitWord(0); + MCE.emitWord(0); + MCE.emitWord(0); + EmitBranchToAt(Addr, Fn, true/*is call*/); + return MCE.finishFunctionStub(0); +} + + +void PPC32JITInfo::relocate(void *Function, MachineRelocation *MR, + unsigned NumRelocs, unsigned char* GOTBase) { + for (unsigned i = 0; i != NumRelocs; ++i, ++MR) { + unsigned *RelocPos = (unsigned*)Function + MR->getMachineCodeOffset()/4; + intptr_t ResultPtr = (intptr_t)MR->getResultPointer(); + switch ((PPC::RelocationType)MR->getRelocationType()) { + default: assert(0 && "Unknown relocation type!"); + case PPC::reloc_pcrel_bx: + // PC-relative relocation for b and bl instructions. + ResultPtr = (ResultPtr-(intptr_t)RelocPos) >> 2; + assert(ResultPtr >= -(1 << 23) && ResultPtr < (1 << 23) && + "Relocation out of range!"); + *RelocPos |= (ResultPtr & ((1 << 24)-1)) << 2; + break; + + case PPC::reloc_absolute_ptr_high: // Pointer relocations. + case PPC::reloc_absolute_ptr_low: { + // Pointer relocations are used for the PPC external stubs and lazy + // resolver pointers that the Darwin ABI likes to use. Basically, the + // address of the global is actually stored in memory, and the address of + // the pointer is relocated into instructions instead of the pointer + // itself. Because we have to keep the mapping anyway, we just return + // pointers to the values in the map as our new location. + static std::set Pointers; + ResultPtr = (intptr_t)&*Pointers.insert((void*)ResultPtr).first; + } + // FALL THROUGH + case PPC::reloc_absolute_high: // high bits of ref -> low 16 of instr + case PPC::reloc_absolute_low: // low bits of ref -> low 16 of instr + ResultPtr += MR->getConstantVal(); + + // If this is a high-part access, get the high-part. + if (MR->getRelocationType() == PPC::reloc_absolute_high || + MR->getRelocationType() == PPC::reloc_absolute_ptr_high) { + // If the low part will have a carry (really a borrow) from the low + // 16-bits into the high 16, add a bit to borrow from. + if (((int)ResultPtr << 16) < 0) + ResultPtr += 1 << 16; + ResultPtr >>= 16; + } + + // Do the addition then mask, so the addition does not overflow the 16-bit + // immediate section of the instruction. + unsigned LowBits = (*RelocPos + ResultPtr) & 65535; + unsigned HighBits = *RelocPos & ~65535; + *RelocPos = LowBits | HighBits; // Slam into low 16-bits + break; + } + } +} + +void PPC32JITInfo::replaceMachineCodeForFunction(void *Old, void *New) { + EmitBranchToAt(Old, New, false); +} diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp new file mode 100644 index 00000000000..8e2e19f75ae --- /dev/null +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -0,0 +1,346 @@ +//===- PPC32RegisterInfo.cpp - PowerPC32 Register Information ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the PowerPC32 implementation of the MRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "reginfo" +#include "PPC.h" +#include "PPCInstrBuilder.h" +#include "PPCRegisterInfo.h" +#include "llvm/Constants.h" +#include "llvm/Type.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/STLExtras.h" +#include +#include +using namespace llvm; + +PPC32RegisterInfo::PPC32RegisterInfo() + : PPCGenRegisterInfo(PPC::ADJCALLSTACKDOWN, PPC::ADJCALLSTACKUP) { + ImmToIdxMap[PPC::LD] = PPC::LDX; ImmToIdxMap[PPC::STD] = PPC::STDX; + ImmToIdxMap[PPC::LBZ] = PPC::LBZX; ImmToIdxMap[PPC::STB] = PPC::STBX; + ImmToIdxMap[PPC::LHZ] = PPC::LHZX; ImmToIdxMap[PPC::LHA] = PPC::LHAX; + ImmToIdxMap[PPC::LWZ] = PPC::LWZX; ImmToIdxMap[PPC::LWA] = PPC::LWAX; + ImmToIdxMap[PPC::LFS] = PPC::LFSX; ImmToIdxMap[PPC::LFD] = PPC::LFDX; + ImmToIdxMap[PPC::STH] = PPC::STHX; ImmToIdxMap[PPC::STW] = PPC::STWX; + ImmToIdxMap[PPC::STFS] = PPC::STFSX; ImmToIdxMap[PPC::STFD] = PPC::STFDX; + ImmToIdxMap[PPC::ADDI] = PPC::ADD; +} + +void +PPC32RegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned SrcReg, int FrameIdx, + const TargetRegisterClass *RC) const { + if (SrcReg == PPC::LR) { + BuildMI(MBB, MI, PPC::MFLR, 1, PPC::R11); + addFrameReference(BuildMI(MBB, MI, PPC::STW, 3).addReg(PPC::R11), FrameIdx); + } else if (RC == PPC32::CRRCRegisterClass) { + BuildMI(MBB, MI, PPC::MFCR, 0, PPC::R11); + addFrameReference(BuildMI(MBB, MI, PPC::STW, 3).addReg(PPC::R11), FrameIdx); + } else if (RC == PPC32::GPRCRegisterClass) { + addFrameReference(BuildMI(MBB, MI, PPC::STW, 3).addReg(SrcReg),FrameIdx); + } else if (RC == PPC32::F8RCRegisterClass) { + addFrameReference(BuildMI(MBB, MI, PPC::STFD, 3).addReg(SrcReg),FrameIdx); + } else if (RC == PPC32::F4RCRegisterClass) { + addFrameReference(BuildMI(MBB, MI, PPC::STFS, 3).addReg(SrcReg),FrameIdx); + } else { + assert(0 && "Unknown regclass!"); + abort(); + } +} + +void +PPC32RegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, int FrameIdx, + const TargetRegisterClass *RC) const { + if (DestReg == PPC::LR) { + addFrameReference(BuildMI(MBB, MI, PPC::LWZ, 2, PPC::R11), FrameIdx); + BuildMI(MBB, MI, PPC::MTLR, 1).addReg(PPC::R11); + } else if (RC == PPC32::CRRCRegisterClass) { + addFrameReference(BuildMI(MBB, MI, PPC::LWZ, 2, PPC::R11), FrameIdx); + BuildMI(MBB, MI, PPC::MTCRF, 1, DestReg).addReg(PPC::R11); + } else if (RC == PPC32::GPRCRegisterClass) { + addFrameReference(BuildMI(MBB, MI, PPC::LWZ, 2, DestReg), FrameIdx); + } else if (RC == PPC32::F8RCRegisterClass) { + addFrameReference(BuildMI(MBB, MI, PPC::LFD, 2, DestReg), FrameIdx); + } else if (RC == PPC32::F4RCRegisterClass) { + addFrameReference(BuildMI(MBB, MI, PPC::LFS, 2, DestReg), FrameIdx); + } else { + assert(0 && "Unknown regclass!"); + abort(); + } +} + +void PPC32RegisterInfo::copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *RC) const { + MachineInstr *I; + + if (RC == PPC32::GPRCRegisterClass) { + BuildMI(MBB, MI, PPC::OR, 2, DestReg).addReg(SrcReg).addReg(SrcReg); + } else if (RC == PPC32::F4RCRegisterClass) { + BuildMI(MBB, MI, PPC::FMRS, 1, DestReg).addReg(SrcReg); + } else if (RC == PPC32::F8RCRegisterClass) { + BuildMI(MBB, MI, PPC::FMRD, 1, DestReg).addReg(SrcReg); + } else if (RC == PPC32::CRRCRegisterClass) { + BuildMI(MBB, MI, PPC::MCRF, 1, DestReg).addReg(SrcReg); + } else { + std::cerr << "Attempt to copy register that is not GPR or FPR"; + abort(); + } +} + +unsigned PPC32RegisterInfo::isLoadFromStackSlot(MachineInstr *MI, + int &FrameIndex) const { + switch (MI->getOpcode()) { + default: break; + case PPC::LWZ: + case PPC::LFS: + case PPC::LFD: + if (MI->getOperand(1).isImmediate() && !MI->getOperand(1).getImmedValue() && + MI->getOperand(2).isFrameIndex()) { + FrameIndex = MI->getOperand(2).getFrameIndex(); + return MI->getOperand(0).getReg(); + } + break; + } + return 0; +} + +/// foldMemoryOperand - PowerPC (like most RISC's) can only fold spills into +/// copy instructions, turning them into load/store instructions. +MachineInstr *PPC32RegisterInfo::foldMemoryOperand(MachineInstr *MI, + unsigned OpNum, + int FrameIndex) const { + // Make sure this is a reg-reg copy. Note that we can't handle MCRF, because + // it takes more than one instruction to store it. + unsigned Opc = MI->getOpcode(); + + if ((Opc == PPC::OR && + MI->getOperand(1).getReg() == MI->getOperand(2).getReg())) { + if (OpNum == 0) { // move -> store + unsigned InReg = MI->getOperand(1).getReg(); + return addFrameReference(BuildMI(PPC::STW, + 3).addReg(InReg), FrameIndex); + } else { // move -> load + unsigned OutReg = MI->getOperand(0).getReg(); + return addFrameReference(BuildMI(PPC::LWZ, 2, OutReg), FrameIndex); + } + + } else if (Opc == PPC::FMRD) { + if (OpNum == 0) { // move -> store + unsigned InReg = MI->getOperand(1).getReg(); + return addFrameReference(BuildMI(PPC::STFD, + 3).addReg(InReg), FrameIndex); + } else { // move -> load + unsigned OutReg = MI->getOperand(0).getReg(); + return addFrameReference(BuildMI(PPC::LFD, 2, OutReg), FrameIndex); + } + } else if (Opc == PPC::FMRS) { + if (OpNum == 0) { // move -> store + unsigned InReg = MI->getOperand(1).getReg(); + return addFrameReference(BuildMI(PPC::STFS, + 3).addReg(InReg), FrameIndex); + } else { // move -> load + unsigned OutReg = MI->getOperand(0).getReg(); + return addFrameReference(BuildMI(PPC::LFS, 2, OutReg), FrameIndex); + } + } + return 0; +} + +//===----------------------------------------------------------------------===// +// Stack Frame Processing methods +//===----------------------------------------------------------------------===// + +// hasFP - Return true if the specified function should have a dedicated frame +// pointer register. This is true if the function has variable sized allocas or +// if frame pointer elimination is disabled. +// +static bool hasFP(MachineFunction &MF) { + return NoFramePointerElim || MF.getFrameInfo()->hasVarSizedObjects(); +} + +void PPC32RegisterInfo:: +eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + if (hasFP(MF)) { + // If we have a frame pointer, convert as follows: + // ADJCALLSTACKDOWN -> addi, r1, r1, -amount + // ADJCALLSTACKUP -> addi, r1, r1, amount + MachineInstr *Old = I; + unsigned Amount = Old->getOperand(0).getImmedValue(); + if (Amount != 0) { + // We need to keep the stack aligned properly. To do this, we round the + // amount of space needed for the outgoing arguments up to the next + // alignment boundary. + unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment(); + Amount = (Amount+Align-1)/Align*Align; + + // Replace the pseudo instruction with a new instruction... + if (Old->getOpcode() == PPC::ADJCALLSTACKDOWN) { + MBB.insert(I, BuildMI(PPC::ADDI, 2, PPC::R1).addReg(PPC::R1) + .addSImm(-Amount)); + } else { + assert(Old->getOpcode() == PPC::ADJCALLSTACKUP); + MBB.insert(I, BuildMI(PPC::ADDI, 2, PPC::R1).addReg(PPC::R1) + .addSImm(Amount)); + } + } + } + MBB.erase(I); +} + +void +PPC32RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const { + unsigned i = 0; + MachineInstr &MI = *II; + MachineBasicBlock &MBB = *MI.getParent(); + MachineFunction &MF = *MBB.getParent(); + + while (!MI.getOperand(i).isFrameIndex()) { + ++i; + assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); + } + + int FrameIndex = MI.getOperand(i).getFrameIndex(); + + // Replace the FrameIndex with base register with GPR1 (SP) or GPR31 (FP). + MI.SetMachineOperandReg(i, hasFP(MF) ? PPC::R31 : PPC::R1); + + // Take into account whether it's an add or mem instruction + unsigned OffIdx = (i == 2) ? 1 : 2; + + // Now add the frame object offset to the offset from r1. + int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) + + MI.getOperand(OffIdx).getImmedValue(); + + // If we're not using a Frame Pointer that has been set to the value of the + // SP before having the stack size subtracted from it, then add the stack size + // to Offset to get the correct offset. + Offset += MF.getFrameInfo()->getStackSize(); + + if (Offset > 32767 || Offset < -32768) { + // Insert a set of r0 with the full offset value before the ld, st, or add + MachineBasicBlock *MBB = MI.getParent(); + MBB->insert(II, BuildMI(PPC::LIS, 1, PPC::R0).addSImm(Offset >> 16)); + MBB->insert(II, BuildMI(PPC::ORI, 2, PPC::R0).addReg(PPC::R0) + .addImm(Offset)); + // convert into indexed form of the instruction + // sth 0:rA, 1:imm 2:(rB) ==> sthx 0:rA, 2:rB, 1:r0 + // addi 0:rA 1:rB, 2, imm ==> add 0:rA, 1:rB, 2:r0 + assert(ImmToIdxMap.count(MI.getOpcode()) && + "No indexed form of load or store available!"); + unsigned NewOpcode = ImmToIdxMap.find(MI.getOpcode())->second; + MI.setOpcode(NewOpcode); + MI.SetMachineOperandReg(1, MI.getOperand(i).getReg()); + MI.SetMachineOperandReg(2, PPC::R0); + } else { + MI.SetMachineOperandConst(OffIdx, MachineOperand::MO_SignExtendedImmed, + Offset); + } +} + + +void PPC32RegisterInfo::emitPrologue(MachineFunction &MF) const { + MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB + MachineBasicBlock::iterator MBBI = MBB.begin(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + MachineInstr *MI; + + // Get the number of bytes to allocate from the FrameInfo + unsigned NumBytes = MFI->getStackSize(); + + // If we have calls, we cannot use the red zone to store callee save registers + // and we must set up a stack frame, so calculate the necessary size here. + if (MFI->hasCalls()) { + // We reserve argument space for call sites in the function immediately on + // entry to the current function. This eliminates the need for add/sub + // brackets around call sites. + NumBytes += MFI->getMaxCallFrameSize(); + } + + // If we are a leaf function, and use up to 224 bytes of stack space, + // and don't have a frame pointer, then we do not need to adjust the stack + // pointer (we fit in the Red Zone). + if ((NumBytes == 0) || (NumBytes <= 224 && !hasFP(MF) && !MFI->hasCalls())) { + MFI->setStackSize(0); + return; + } + + // Add the size of R1 to NumBytes size for the store of R1 to the bottom + // of the stack and round the size to a multiple of the alignment. + unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment(); + unsigned GPRSize = 4; + unsigned Size = hasFP(MF) ? GPRSize + GPRSize : GPRSize; + NumBytes = (NumBytes+Size+Align-1)/Align*Align; + + // Update frame info to pretend that this is part of the stack... + MFI->setStackSize(NumBytes); + + // Adjust stack pointer: r1 -= numbytes. + if (NumBytes <= 32768) { + MI=BuildMI(PPC::STWU,3).addReg(PPC::R1).addSImm(-NumBytes).addReg(PPC::R1); + MBB.insert(MBBI, MI); + } else { + int NegNumbytes = -NumBytes; + MI = BuildMI(PPC::LIS, 1, PPC::R0).addSImm(NegNumbytes >> 16); + MBB.insert(MBBI, MI); + MI = BuildMI(PPC::ORI, 2, PPC::R0).addReg(PPC::R0) + .addImm(NegNumbytes & 0xFFFF); + MBB.insert(MBBI, MI); + MI = BuildMI(PPC::STWUX, 3).addReg(PPC::R1).addReg(PPC::R1).addReg(PPC::R0); + MBB.insert(MBBI, MI); + } + + if (hasFP(MF)) { + MI = BuildMI(PPC::STW, 3).addReg(PPC::R31).addSImm(GPRSize).addReg(PPC::R1); + MBB.insert(MBBI, MI); + MI = BuildMI(PPC::OR, 2, PPC::R31).addReg(PPC::R1).addReg(PPC::R1); + MBB.insert(MBBI, MI); + } +} + +void PPC32RegisterInfo::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + MachineBasicBlock::iterator MBBI = prior(MBB.end()); + MachineInstr *MI; + assert(MBBI->getOpcode() == PPC::BLR && + "Can only insert epilog into returning blocks"); + + // Get the number of bytes allocated from the FrameInfo... + unsigned NumBytes = MFI->getStackSize(); + unsigned GPRSize = 4; + + if (NumBytes != 0) { + if (hasFP(MF)) { + MI = BuildMI(PPC::LWZ, 2, PPC::R31).addSImm(GPRSize).addReg(PPC::R31); + MBB.insert(MBBI, MI); + } + MI = BuildMI(PPC::LWZ, 2, PPC::R1).addSImm(0).addReg(PPC::R1); + MBB.insert(MBBI, MI); + } +} + +#include "PPCGenRegisterInfo.inc" + diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h new file mode 100644 index 00000000000..e9ef9ce2eef --- /dev/null +++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h @@ -0,0 +1,64 @@ +//===- PPC32RegisterInfo.h - PowerPC32 Register Information Impl -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the PowerPC implementation of the MRegisterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef POWERPC32_REGISTERINFO_H +#define POWERPC32_REGISTERINFO_H + +#include "PPC.h" +#include "PPCGenRegisterInfo.h.inc" +#include + +namespace llvm { + +class Type; + +class PPC32RegisterInfo : public PPCGenRegisterInfo { + std::map ImmToIdxMap; +public: + PPC32RegisterInfo(); + + /// Code Generation virtual methods... + void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned SrcReg, int FrameIndex, + const TargetRegisterClass *RC) const; + + void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC) const; + + void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *RC) const; + + unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const; + + /// foldMemoryOperand - PowerPC (like most RISC's) can only fold spills into + /// copy instructions, turning them into load/store instructions. + virtual MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum, + int FrameIndex) const; + + void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const; + + void eliminateFrameIndex(MachineBasicBlock::iterator II) const; + + void emitPrologue(MachineFunction &MF) const; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; +}; + +} // end namespace llvm + +#endif diff --git a/llvm/lib/Target/PowerPC/PPCRelocations.h b/llvm/lib/Target/PowerPC/PPCRelocations.h new file mode 100644 index 00000000000..f6c9384d7d5 --- /dev/null +++ b/llvm/lib/Target/PowerPC/PPCRelocations.h @@ -0,0 +1,58 @@ +//===- PPC32Relocations.h - PPC32 Code Relocations --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the PowerPC 32-bit target-specific relocation types. +// +//===----------------------------------------------------------------------===// + +#ifndef PPC32RELOCATIONS_H +#define PPC32RELOCATIONS_H + +#include "llvm/CodeGen/MachineRelocation.h" + +// Hack to rid us of a PPC pre-processor symbol which is erroneously +// defined in a PowerPC header file (bug in Linux/PPC) +#ifdef PPC +#undef PPC +#endif + +namespace llvm { + namespace PPC { + enum RelocationType { + // reloc_pcrel_bx - PC relative relocation, for the b or bl instructions. + reloc_pcrel_bx, + + // reloc_absolute_high - Absolute relocation, for the loadhi instruction + // (which is really addis). Add the high 16-bits of the specified global + // address into the low 16-bits of the instruction. + reloc_absolute_high, + + // reloc_absolute_low - Absolute relocation, for the la instruction (which + // is really an addi). Add the low 16-bits of teh specified global + // address into the low 16-bits of the instruction. + reloc_absolute_low, + + // reloc_absolute_ptr_high - Absolute relocation for references to lazy + // pointer stubs. In this case, the relocated instruction should be + // relocated to point to a POINTER to the indicated global. The low-16 + // bits of the instruction are rewritten with the high 16-bits of the + // address of the pointer. + reloc_absolute_ptr_high, + + // reloc_absolute_ptr_low - Absolute relocation for references to lazy + // pointer stubs. In this case, the relocated instruction should be + // relocated to point to a POINTER to the indicated global. The low-16 + // bits of the instruction are rewritten with the low 16-bits of the + // address of the pointer. + reloc_absolute_ptr_low, + }; + } +} + +#endif diff --git a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp index ce759d08959..a222f8c66fa 100644 --- a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -13,7 +13,7 @@ #include "PPC.h" #include "PPCFrameInfo.h" -#include "PPC32TargetMachine.h" +#include "PPCTargetMachine.h" #include "PPCJITInfo.h" #include "llvm/Module.h" #include "llvm/PassManager.h" diff --git a/llvm/lib/Target/PowerPC/PPCTargetMachine.h b/llvm/lib/Target/PowerPC/PPCTargetMachine.h new file mode 100644 index 00000000000..33180cdecf9 --- /dev/null +++ b/llvm/lib/Target/PowerPC/PPCTargetMachine.h @@ -0,0 +1,74 @@ +//===-- PPC32TargetMachine.h - Define TargetMachine for PowerPC -*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the PowerPC specific subclass of TargetMachine. +// +//===----------------------------------------------------------------------===// + +#ifndef POWERPC32_TARGETMACHINE_H +#define POWERPC32_TARGETMACHINE_H + +#include "PPCFrameInfo.h" +#include "PPCSubtarget.h" +#include "PPCJITInfo.h" +#include "PPCInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/PassManager.h" + +namespace llvm { + +class IntrinsicLowering; +class GlobalValue; +class IntrinsicLowering; + +// FIXME: Merge into only subclass. +class PowerPCTargetMachine : public TargetMachine { + PowerPCFrameInfo FrameInfo; + PPCSubtarget Subtarget; +protected: + PowerPCTargetMachine(const std::string &name, IntrinsicLowering *IL, + const Module &M, const std::string &FS, + const TargetData &TD, + const PowerPCFrameInfo &TFI); +public: + virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; } + virtual const TargetSubtarget *getSubtargetImpl() const{ return &Subtarget; } + + virtual bool addPassesToEmitFile(PassManager &PM, std::ostream &Out, + CodeGenFileType FileType); +}; + +class PPC32TargetMachine : public PowerPCTargetMachine { + PPC32InstrInfo InstrInfo; + PPC32JITInfo JITInfo; + +public: + PPC32TargetMachine(const Module &M, IntrinsicLowering *IL, + const std::string &FS); + virtual const PPC32InstrInfo *getInstrInfo() const { return &InstrInfo; } + virtual const MRegisterInfo *getRegisterInfo() const { + return &InstrInfo.getRegisterInfo(); + } + + virtual TargetJITInfo *getJITInfo() { + return &JITInfo; + } + + static unsigned getJITMatchQuality(); + + static unsigned getModuleMatchQuality(const Module &M); + + bool addPassesToEmitMachineCode(FunctionPassManager &PM, + MachineCodeEmitter &MCE); +}; + +} // end namespace llvm + +#endif -- cgit v1.2.3