diff options
author | Nate Begeman <natebegeman@mac.com> | 2005-08-13 05:59:16 +0000 |
---|---|---|
committer | Nate Begeman <natebegeman@mac.com> | 2005-08-13 05:59:16 +0000 |
commit | 8f331325a22746d89fc30ea59672012c8c58cf49 (patch) | |
tree | d03cb1f41451fe6411ca507c625fb87d6ed9c9f9 | |
parent | 7ac17529d2d00554ccc3fffd3691f924f7b4019a (diff) |
Remove support for 64b PPC, it's been broken for a long time. It'll be
back once a DAG->DAG ISel exists.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22778 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/PowerPC/Makefile | 5 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPC64CodeEmitter.cpp | 35 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPC64ISelPattern.cpp | 1632 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPC64InstrInfo.cpp | 59 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPC64InstrInfo.h | 56 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPC64JITInfo.h | 35 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPC64RegisterInfo.cpp | 317 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPC64RegisterInfo.h | 56 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPC64TargetMachine.h | 43 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCTargetMachine.cpp | 38 |
10 files changed, 4 insertions, 2272 deletions
diff --git a/lib/Target/PowerPC/Makefile b/lib/Target/PowerPC/Makefile index 8975398c03..0a6463f62d 100644 --- a/lib/Target/PowerPC/Makefile +++ b/lib/Target/PowerPC/Makefile @@ -8,12 +8,11 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../.. LIBRARYNAME = LLVMPowerPC -TARGET = PowerPC PPC32 PPC64 +TARGET = PowerPC PPC32 # Make sure that tblgen is run, first thing. BUILT_SOURCES = PowerPCGenInstrNames.inc PowerPCGenRegisterNames.inc \ PowerPCGenAsmWriter.inc PPC32GenCodeEmitter.inc \ - PPC32GenRegisterInfo.h.inc PPC32GenRegisterInfo.inc PPC32GenInstrInfo.inc \ - PPC64GenRegisterInfo.h.inc PPC64GenRegisterInfo.inc PPC64GenInstrInfo.inc + PPC32GenRegisterInfo.h.inc PPC32GenRegisterInfo.inc PPC32GenInstrInfo.inc include $(LEVEL)/Makefile.common diff --git a/lib/Target/PowerPC/PPC64CodeEmitter.cpp b/lib/Target/PowerPC/PPC64CodeEmitter.cpp deleted file mode 100644 index 6c438049f4..0000000000 --- a/lib/Target/PowerPC/PPC64CodeEmitter.cpp +++ /dev/null @@ -1,35 +0,0 @@ -//===-- PPC64CodeEmitter.cpp - JIT Code Emitter for PPC64 -----*- 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. -// -//===----------------------------------------------------------------------===// -// -// -//===----------------------------------------------------------------------===// - -#include "PPC64JITInfo.h" -#include "PPC64TargetMachine.h" -using namespace llvm; - -/// 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 PPC64TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM, - MachineCodeEmitter &MCE) { - return true; - // It should go something like this: - // PM.add(new Emitter(MCE)); // Machine code emitter pass for PPC64 - // Delete machine code for this function after emitting it: - // PM.add(createMachineCodeDeleter()); -} - -void PPC64JITInfo::replaceMachineCodeForFunction (void *Old, void *New) { - assert (0 && "PPC64JITInfo::replaceMachineCodeForFunction not implemented"); -} - diff --git a/lib/Target/PowerPC/PPC64ISelPattern.cpp b/lib/Target/PowerPC/PPC64ISelPattern.cpp deleted file mode 100644 index eb4410b32a..0000000000 --- a/lib/Target/PowerPC/PPC64ISelPattern.cpp +++ /dev/null @@ -1,1632 +0,0 @@ -//===-- PPC64ISelPattern.cpp - A pattern matching inst selector for PPC64 -===// -// -// 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 64 bit PowerPC. -// -//===----------------------------------------------------------------------===// - -#include "PowerPC.h" -#include "PowerPCInstrBuilder.h" -#include "PowerPCInstrInfo.h" -#include "PPC64RegisterInfo.h" -#include "llvm/Constants.h" // FIXME: REMOVE -#include "llvm/Function.h" -#include "llvm/CodeGen/MachineConstantPool.h" // FIXME: REMOVE -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/CodeGen/SelectionDAGISel.h" -#include "llvm/CodeGen/SSARegMap.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetLowering.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/ADT/Statistic.h" -#include <set> -#include <algorithm> -using namespace llvm; - -//===----------------------------------------------------------------------===// -// PPC64TargetLowering - PPC64 Implementation of the TargetLowering interface -namespace { - class PPC64TargetLowering : public TargetLowering { - int VarArgsFrameIndex; // FrameIndex for start of varargs area. - int ReturnAddrIndex; // FrameIndex for return slot. - public: - PPC64TargetLowering(TargetMachine &TM) : TargetLowering(TM) { - // Fold away setcc operations if possible. - setSetCCIsExpensive(); - - // Set up the register classes. - addRegisterClass(MVT::i64, PPC64::GPRCRegisterClass); - addRegisterClass(MVT::f32, PPC64::FPRCRegisterClass); - addRegisterClass(MVT::f64, PPC64::FPRCRegisterClass); - - // PowerPC has no intrinsics for these particular operations - setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand); - setOperationAction(ISD::MEMMOVE, MVT::Other, Expand); - setOperationAction(ISD::MEMSET, MVT::Other, Expand); - setOperationAction(ISD::MEMCPY, MVT::Other, Expand); - - // We don't support sin/cos/sqrt/fmod - setOperationAction(ISD::FSIN , MVT::f64, Expand); - setOperationAction(ISD::FCOS , MVT::f64, Expand); - setOperationAction(ISD::FSQRT, MVT::f64, Expand); - setOperationAction(ISD::SREM , MVT::f64, Expand); - setOperationAction(ISD::FSIN , MVT::f32, Expand); - setOperationAction(ISD::FCOS , MVT::f32, Expand); - setOperationAction(ISD::FSQRT, MVT::f32, Expand); - setOperationAction(ISD::SREM , MVT::f32, Expand); - - // PPC 64 has i16 and i32 but no i8 (or i1) SEXTLOAD - setOperationAction(ISD::SEXTLOAD, MVT::i1, Expand); - setOperationAction(ISD::SEXTLOAD, MVT::i8, Expand); - - // PowerPC has no SREM/UREM instructions - setOperationAction(ISD::SREM, MVT::i64, Expand); - setOperationAction(ISD::UREM, MVT::i64, Expand); - - // PowerPC has these, but they are not implemented - setOperationAction(ISD::CTPOP, MVT::i64, Expand); - setOperationAction(ISD::CTTZ , MVT::i64, Expand); - setOperationAction(ISD::CTLZ , MVT::i64, Expand); - - setShiftAmountFlavor(Extend); // shl X, 32 == 0 - addLegalFPImmediate(+0.0); // Necessary for FSEL - addLegalFPImmediate(-0.0); // - - computeRegisterProperties(); - } - - /// LowerArguments - This hook must be implemented to indicate how we should - /// lower the arguments for the specified function, into the specified DAG. - virtual std::vector<SDOperand> - LowerArguments(Function &F, SelectionDAG &DAG); - - /// LowerCallTo - This hook lowers an abstract call to a function into an - /// actual call. - virtual std::pair<SDOperand, SDOperand> - LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, unsigned CC, - bool isTailCall, SDOperand Callee, ArgListTy &Args, - SelectionDAG &DAG); - - virtual std::pair<SDOperand, SDOperand> - LowerVAStart(SDOperand Chain, SelectionDAG &DAG, SDOperand Dest); - - virtual std::pair<SDOperand,SDOperand> - LowerVAArgNext(SDOperand Chain, SDOperand VAList, - const Type *ArgTy, SelectionDAG &DAG); - - virtual std::pair<SDOperand, SDOperand> - LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth, - SelectionDAG &DAG); - }; -} - - -std::vector<SDOperand> -PPC64TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { - // - // add beautiful description of PPC stack frame format, or at least some docs - // - MachineFunction &MF = DAG.getMachineFunction(); - MachineFrameInfo *MFI = MF.getFrameInfo(); - MachineBasicBlock& BB = MF.front(); - std::vector<SDOperand> ArgValues; - - // Due to the rather complicated nature of the PowerPC ABI, rather than a - // fixed size array of physical args, for the sake of simplicity let the STL - // handle tracking them for us. - std::vector<unsigned> argVR, argPR, argOp; - unsigned ArgOffset = 48; - unsigned GPR_remaining = 8; - unsigned FPR_remaining = 13; - 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 - }; - - // Add DAG nodes to load the arguments... On entry to a function on PPC, - // the arguments start at offset 48, although they are likely to be passed - // in registers. - for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) { - SDOperand newroot, argt; - bool needsLoad = false; - MVT::ValueType ObjectVT = getValueType(I->getType()); - - switch (ObjectVT) { - default: assert(0 && "Unhandled argument type!"); - case MVT::i1: - case MVT::i8: - case MVT::i16: - case MVT::i32: - case MVT::i64: - if (GPR_remaining > 0) { - BuildMI(&BB, PPC::IMPLICIT_DEF, 0, GPR[GPR_idx]); - argt = newroot = DAG.getCopyFromReg(GPR[GPR_idx], MVT::i32, - DAG.getRoot()); - if (ObjectVT != MVT::i64) - argt = DAG.getNode(ISD::TRUNCATE, ObjectVT, newroot); - } else { - needsLoad = true; - } - break; - case MVT::f32: - case MVT::f64: - if (FPR_remaining > 0) { - BuildMI(&BB, PPC::IMPLICIT_DEF, 0, FPR[FPR_idx]); - argt = newroot = DAG.getCopyFromReg(FPR[FPR_idx], ObjectVT, - DAG.getRoot()); - --FPR_remaining; - ++FPR_idx; - } else { - needsLoad = true; - } - break; - } - - // We need to load the argument to a virtual register if we determined above - // that we ran out of physical registers of the appropriate type - if (needsLoad) { - unsigned SubregOffset = 0; - switch (ObjectVT) { - default: assert(0 && "Unhandled argument type!"); - case MVT::i1: - case MVT::i8: SubregOffset = 7; break; - case MVT::i16: SubregOffset = 6; break; - case MVT::i32: - case MVT::f32: SubregOffset = 4; break; - case MVT::i64: - case MVT::f64: SubregOffset = 0; break; - } - int FI = MFI->CreateFixedObject(8, ArgOffset); - SDOperand FIN = DAG.getFrameIndex(FI, MVT::i64); - FIN = DAG.getNode(ISD::ADD, MVT::i64, FIN, - DAG.getConstant(SubregOffset, MVT::i64)); - argt = newroot = DAG.getLoad(ObjectVT, DAG.getEntryNode(), FIN, - DAG.getSrcValue(NULL)); - } - - // Every 4 bytes of argument space consumes one of the GPRs available for - // argument passing. - if (GPR_remaining > 0) { - --GPR_remaining; - ++GPR_idx; - } - ArgOffset += 8; - - DAG.setRoot(newroot.getValue(1)); - ArgValues.push_back(argt); - } - - // If the function takes variable number of arguments, make a frame index for - // the start of the first vararg value... for expansion of llvm.va_start. - if (F.isVarArg()) { - VarArgsFrameIndex = MFI->CreateFixedObject(8, ArgOffset); - SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64); - // If this function is vararg, store any remaining integer argument regs - // to their spots on the stack so that they may be loaded by deferencing the - // result of va_next. - std::vector<SDOperand> MemOps; - for (; GPR_remaining > 0; --GPR_remaining, ++GPR_idx) { - BuildMI(&BB, PPC::IMPLICIT_DEF, 0, GPR[GPR_idx]); - SDOperand Val = DAG.getCopyFromReg(GPR[GPR_idx], MVT::i64, DAG.getRoot()); - SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1), - Val, FIN, DAG.getSrcValue(NULL)); - MemOps.push_back(Store); - // Increment the address by eight for the next argument to store - SDOperand PtrOff = DAG.getConstant(8, getPointerTy()); - FIN = DAG.getNode(ISD::ADD, MVT::i32, FIN, PtrOff); - } - DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, MemOps)); - } - - return ArgValues; -} - -std::pair<SDOperand, SDOperand> -PPC64TargetLowering::LowerCallTo(SDOperand Chain, - const Type *RetTy, bool isVarArg, - unsigned CallingConv, bool isTailCall, - SDOperand Callee, ArgListTy &Args, - SelectionDAG &DAG) { - // args_to_use will accumulate outgoing args for the ISD::CALL case in - // SelectExpr to use to put the arguments in the appropriate registers. - std::vector<SDOperand> args_to_use; - - // Count how many bytes are to be pushed on the stack, including the linkage - // area, and parameter passing area. - unsigned NumBytes = 48; - - if (Args.empty()) { - Chain = DAG.getNode(ISD::CALLSEQ_START, MVT::Other, Chain, - DAG.getConstant(NumBytes, getPointerTy())); - } else { - NumBytes = 8 * Args.size(); // All arguments are rounded up to 8 bytes - - // Just to be safe, we'll always reserve the full 48 bytes of linkage area - // plus 64 bytes of argument space in case any called code gets funky on us. - // (Required by ABI to support var arg) - if (NumBytes < 112) NumBytes = 112; - - // Adjust the stack pointer for the new arguments... - // These operations are automatically eliminated by the prolog/epilog pass - Chain = DAG.getNode(ISD::CALLSEQ_START, MVT::Other, Chain, - DAG.getConstant(NumBytes, getPointerTy())); - - // Set up a copy of the stack pointer for use loading and storing any - // arguments that may not fit in the registers available for argument - // passing. - SDOperand StackPtr = DAG.getCopyFromReg(PPC::R1, MVT::i32, - DAG.getEntryNode()); - - // Figure out which arguments are going to go in registers, and which in - // memory. Also, if this is a vararg function, floating point operations - // must be stored to our stack, and loaded into integer regs as well, if - // any integer regs are available for argument passing. - unsigned ArgOffset = 48; - unsigned GPR_remaining = 8; - unsigned FPR_remaining = 13; - - std::vector<SDOperand> MemOps; - for (unsigned i = 0, e = Args.size(); i != e; ++i) { - // PtrOff will be used to store the current argument to the stack if a - // register cannot be found for it. - SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy()); - PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff); - MVT::ValueType ArgVT = getValueType(Args[i].second); - - switch (ArgVT) { - default: assert(0 && "Unexpected ValueType for argument!"); - case MVT::i1: - case MVT::i8: - case MVT::i16: - case MVT::i32: - // Promote the integer to 64 bits. If the input type is signed use a - // sign extend, otherwise use a zero extend. - if (Args[i].second->isSigned()) - Args[i].first =DAG.getNode(ISD::SIGN_EXTEND, MVT::i64, Args[i].first); - else - Args[i].first =DAG.getNode(ISD::ZERO_EXTEND, MVT::i64, Args[i].first); - // FALL THROUGH - case MVT::i64: - if (GPR_remaining > 0) { - args_to_use.push_back(Args[i].first); - --GPR_remaining; - } else { - MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, - Args[i].first, PtrOff, - DAG.getSrcValue(NULL))); - } - ArgOffset += 8; - break; - case MVT::f32: - case MVT::f64: - if (FPR_remaining > 0) { - args_to_use.push_back(Args[i].first); - --FPR_remaining; - if (isVarArg) { - SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Chain, - Args[i].first, PtrOff, - DAG.getSrcValue(NULL)); - MemOps.push_back(Store); - // Float varargs are always shadowed in available integer registers - if (GPR_remaining > 0) { - SDOperand Load = DAG.getLoad(MVT::i64, Store, PtrOff, - DAG.getSrcValue(NULL)); - MemOps.push_back(Load); - args_to_use.push_back(Load); - --GPR_remaining; - } - } else { - // If we have any FPRs remaining, we may also have GPRs remaining. - // Args passed in FPRs also consume an available GPR. - if (GPR_remaining > 0) { - args_to_use.push_back(DAG.getNode(ISD::UNDEF, MVT::i64)); - --GPR_remaining; - } - } - } else { - MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, - Args[i].first, PtrOff, - DAG.getSrcValue(NULL))); - } - ArgOffset += 8; - break; - } - } - if (!MemOps.empty()) - Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, MemOps); - } - - std::vector<MVT::ValueType> RetVals; - MVT::ValueType RetTyVT = getValueType(RetTy); - if (RetTyVT != MVT::isVoid) - RetVals.push_back(RetTyVT); - RetVals.push_back(MVT::Other); - - SDOperand TheCall = SDOperand(DAG.getCall(RetVals, - Chain, Callee, args_to_use), 0); - Chain = TheCall.getValue(RetTyVT != MVT::isVoid); - Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain, - DAG.getConstant(NumBytes, getPointerTy())); - return std::make_pair(TheCall, Chain); -} - -std::pair<SDOperand, SDOperand> -PPC64TargetLowering::LowerVAStart(SDOperand Chain, SelectionDAG &DAG, SDOperand Dest) { - // vastart just stores the address of the VarArgsFrameIndex slot. - SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i64); - SDOperand Result = DAG.getNode(ISD::STORE, MVT::Other, Chain, FR, Dest, DAG.getSrcValue(NULL)); - return std::make_pair(Result, Result); -} - -std::pair<SDOperand,SDOperand> PPC64TargetLowering:: -LowerVAArgNext(SDOperand Chain, SDOperand VAList, - const Type *ArgTy, SelectionDAG &DAG) { - MVT::ValueType ArgVT = getValueType(ArgTy); - SDOperand Result; - SDOperand Val = DAG.getLoad(MVT::i64, Chain, VAList, DAG.getSrcValue(NULL)); - Result = DAG.getLoad(ArgVT, Val.getValue(1), Val, DAG.getSrcValue(NULL)); - Val = DAG.getNode(ISD::ADD, VAList.getValueType(), Val, - DAG.getConstant(8, VAList.getValueType())); - Chain = DAG.getNode(ISD::STORE, MVT::Other, Chain, - Val, VAList, DAG.getSrcValue(NULL)); - return std::make_pair(Result, Chain); -} - -std::pair<SDOperand, SDOperand> PPC64TargetLowering:: -LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth, - SelectionDAG &DAG) { - assert(0 && "LowerFrameReturnAddress unimplemented"); - abort(); -} - -namespace { -Statistic<>NotLogic("ppc-codegen", "Number of inverted logical ops"); -Statistic<>FusedFP("ppc-codegen", "Number of fused fp operations"); -//===--------------------------------------------------------------------===// -/// ISel - PPC64 specific code to select PPC64 machine instructions for -/// SelectionDAG operations. -//===--------------------------------------------------------------------===// -class ISel : public SelectionDAGISel { - - /// Comment Here. - PPC64TargetLowering PPC64Lowering; - - /// 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<SDOperand, unsigned> ExprMap; - - unsigned GlobalBaseReg; - bool GlobalBaseInitialized; - -public: - ISel(TargetMachine &TM) : SelectionDAGISel(PPC64Lowering), PPC64Lowering(TM) - {} - - /// 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. - Select(DAG.getRoot()); - - // Clear state used for selection. - ExprMap.clear(); - } - - unsigned getGlobalBaseReg(); - unsigned getConstDouble(double floatVal, unsigned Result); - unsigned SelectSetCR0(SDOperand CC); - unsigned SelectExpr(SDOperand N); - unsigned SelectExprFP(SDOperand N, unsigned Result); - void Select(SDOperand N); - - bool SelectAddr(SDOperand N, unsigned& Reg, int& offset); - void SelectBranchCC(SDOperand N); -}; - -/// getImmediateForOpcode - This method returns a value indicating whether -/// the ConstantSDNode N can be used as an immediate to Opcode. The return -/// values are either 0, 1 or 2. 0 indicates that either N is not a -/// ConstantSDNode, or is not suitable for use by that opcode. A return value -/// of 1 indicates that the constant may be used in normal immediate form. A -/// return value of 2 indicates that the constant may be used in shifted -/// immediate form. A return value of 3 indicates that log base 2 of the -/// constant may be used. -/// -static unsigned getImmediateForOpcode(SDOperand N, unsigned Opcode, - unsigned& Imm, bool U = false) { - if (N.getOpcode() != ISD::Constant) return 0; - - int v = (int)cast<ConstantSDNode>(N)->getSignExtended(); - - switch(Opcode) { - default: return 0; - case ISD::ADD: - if (isInt16(v)) { Imm = v & 0xFFFF; return 1; } - if ((v & 0x0000FFFF) == 0) { Imm = v >> 16; return 2; } - break; - case ISD::AND: - case ISD::XOR: - case ISD::OR: - if (isUInt16(v)) { Imm = v & 0xFFFF; return 1; } - if ((v & 0x0000FFFF) == 0) { Imm = v >> 16; return 2; } - break; - case ISD::MUL: - case ISD::SUB: - if (isInt16(v)) { Imm = v & 0xFFFF; return 1; } - break; - case ISD::SETCC: - if (U && isUInt16(v)) { Imm = v & 0xFFFF; return 1; } - if (!U && isInt16(v)) { Imm = v & 0xFFFF; return 1; } - break; - case ISD::SDIV: - if (isPowerOf2_32(v)) { Imm = Log2_32(v); return 3; } - break; - } - return 0; -} - -/// getBCCForSetCC - Returns the PowerPC condition branch mnemonic corresponding -/// to Condition. If the Condition is unordered or unsigned, the bool argument -/// U is set to true, otherwise it is set to false. -static unsigned getBCCForSetCC(unsigned Condition, bool& U) { - U = false; - switch (Condition) { - default: assert(0 && "Unknown condition!"); abort(); - case ISD::SETEQ: return PPC::BEQ; - case ISD::SETNE: return PPC::BNE; - case ISD::SETULT: U = true; - case ISD::SETLT: return PPC::BLT; - case ISD::SETULE: U = true; - case ISD::SETLE: return PPC::BLE; - case ISD::SETUGT: U = true; - case ISD::SETGT: return PPC::BGT; - case ISD::SETUGE: U = true; - case ISD::SETGE: return PPC::BGE; - } - 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::STD: return PPC::STDX; - case PPC::LD: return PPC::LDX; 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; -} -} - -/// 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 = MakeReg(MVT::i64); - BuildMI(FirstMBB, MBBI, PPC::MovePCtoLR, 0, PPC::LR); - BuildMI(FirstMBB, MBBI, PPC::MFLR, 1, GlobalBaseReg).addReg(PPC::LR); - GlobalBaseInitialized = true; - } - return GlobalBaseReg; -} - -/// getConstDouble - Loads a floating point value into a register, via the -/// Constant Pool. Optionally takes a register in which to load the value. -unsigned ISel::getConstDouble(double doubleVal, unsigned Result=0) { - unsigned Tmp1 = MakeReg(MVT::i64); - if (0 == Result) Result = MakeReg(MVT::f64); - MachineConstantPool *CP = BB->getParent()->getConstantPool(); - ConstantFP *CFP = ConstantFP::get(Type::DoubleTy, doubleVal); - unsigned CPI = CP->getConstantPoolIndex(CFP); - BuildMI(BB, PPC::ADDIS, 2, Tmp1).addReg(getGlobalBaseReg()) - .addConstantPoolIndex(CPI); - BuildMI(BB, PPC::LFD, 2, Result).addConstantPoolIndex(CPI).addReg(Tmp1); - return Result; -} - -unsigned ISel::SelectSetCR0(SDOperand CC) { - unsigned Opc, Tmp1, Tmp2; - static const unsigned CompareOpcodes[] = - { PPC::FCMPU, PPC::FCMPU, PPC::CMPW, PPC::CMPLW }; - - // If the first operand to the select is a SETCC node, then we can fold it - // into the branch that selects which value to return. - if (CC.getOpcode() == ISD::SETCC) { - bool U; - Opc = getBCCForSetCC(cast<CondCodeSDNode>(CC.getOperand(2))->get(), U); - Tmp1 = SelectExpr(CC.getOperand(0)); - - // Pass the optional argument U to getImmediateForOpcode for SETCC, - // so that it knows whether the SETCC immediate range is signed or not. - if (1 == getImmediateForOpcode(CC.getOperand(1), ISD::SETCC, - Tmp2, U)) { - if (U) - BuildMI(BB, PPC::CMPLWI, 2, PPC::CR0).addReg(Tmp1).addImm(Tmp2); - else - BuildMI(BB, PPC::CMPWI, 2, PPC::CR0).addReg(Tmp1).addSImm(Tmp2); - } else { - bool IsInteger = MVT::isInteger(CC.getOperand(0).getValueType()); - unsigned CompareOpc = CompareOpcodes[2 * IsInteger + U]; - Tmp2 = SelectExpr(CC.getOperand(1)); - BuildMI(BB, CompareOpc, 2, PPC::CR0).addReg(Tmp1).addReg(Tmp2); - } - } else { - Tmp1 = SelectExpr(CC); - BuildMI(BB, PPC::CMPLWI, 2, PPC::CR0).addReg(Tmp1).addImm(0); - Opc = PPC::BNE; - } - return Opc; -} - -/// Check to see if the load is a constant offset from a base register -bool ISel::SelectAddr(SDOperand N, unsigned& Reg, int& offset) -{ - unsigned imm = 0, opcode = N.getOpcode(); - if (N.getOpcode() == ISD::ADD) { - Reg = SelectExpr(N.getOperand(0)); - if (1 == getImmediateForOpcode(N.getOperand(1), opcode, imm)) { - offset = imm; - return false; - } - offset = SelectExpr(N.getOperand(1)); - return true; - } - Reg = SelectExpr(N); - offset = 0; - return false; -} - -void ISel::SelectBranchCC(SDOperand N) -{ - assert(N.getOpcode() == ISD::BRCOND && "Not a BranchCC???"); - MachineBasicBlock *Dest = - cast<BasicBlockSDNode>(N.getOperand(2))->getBasicBlock(); - - // Get the MBB we will fall through to so that we can hand it off to the - // branch selection pass as an argument to the PPC::COND_BRANCH pseudo op. - //ilist<MachineBasicBlock>::iterator It = BB; - //MachineBasicBlock *Fallthrough = ++It; - - Select(N.getOperand(0)); //chain - unsigned Opc = SelectSetCR0(N.getOperand(1)); - // FIXME: Use this once we have something approximating two-way branches - // We cannot currently use this in case the ISel hands us something like - // BRcc MBBx - // BR MBBy - // since the fallthrough basic block for the conditional branch does not start - // with the unconditional branch (it is skipped over). - //BuildMI(BB, PPC::COND_BRANCH, 4).addReg(PPC::CR0).addImm(Opc) - // .addMBB(Dest).addMBB(Fallthrough); - BuildMI(BB, Opc, 2).addReg(PPC::CR0).addMBB(Dest); - return; -} - -unsigned ISel::SelectExprFP(SDOperand N, unsigned Result) -{ - unsigned Tmp1, Tmp2, Tmp3; - unsigned Opc = 0; - SDNode *Node = N.Val; - MVT::ValueType DestType = N.getValueType(); - unsigned opcode = N.getOpcode(); - - switch (opcode) { - default: - Node->dump(); - assert(0 && "Node not handled!\n"); - - case ISD::SELECT: { - SDNode *Cond = N.getOperand(0).Val; - // Attempt to generate FSEL. We can do this whenever we have an FP result, - // and an FP comparison in the SetCC node. - if (Cond->getOpcode() == ISD::SETCC && - !MVT::isInteger(N.getOperand(1).getValueType()) && - cast<CondCodeSDNode>(Cond->getOperand(2))->get() != ISD::SETEQ && - cast<CondCodeSDNode>(Cond->getOperand(2))->get() != ISD::SETNE) { - MVT::ValueType VT = Cond->getOperand(0).getValueType(); - ISD::CondCode CC = cast<CondCodeSDNode>(Cond->getOperand(2))->get(); - Tmp1 = SelectExpr(Cond->getOperand(0)); // Val to compare against - unsigned TV = SelectExpr(N.getOperand(1)); // Use if TRUE - unsigned FV = SelectExpr(N.getOperand(2)); // Use if FALSE - - ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(Cond->getOperand(1)); - if (CN && (CN->isExactlyValue(-0.0) || CN->isExactlyValue(0.0))) { - switch(CC) { - default: assert(0 && "Invalid FSEL condition"); abort(); - case ISD::SETULT: - case ISD::SETLT: - BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp1).addReg(FV).addReg(TV); - return Result; - case ISD::SETUGE: - case ISD::SETGE: - BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp1).addReg(TV).addReg(FV); - return Result; - case ISD::SETUGT: - case ISD::SETGT: { - Tmp2 = MakeReg(VT); - BuildMI(BB, PPC::FNEG, 1, Tmp2).addReg(Tmp1); - BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp2).addReg(FV).addReg(TV); - return Result; - } - case ISD::SETULE: - case ISD::SETLE: { - Tmp2 = MakeReg(VT); - BuildMI(BB, PPC::FNEG, 1, Tmp2).addReg(Tmp1); - BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp2).addReg(TV).addReg(FV); - return Result; - } - } - } else { - Opc = (MVT::f64 == VT) ? PPC::FSUB : PPC::FSUBS; - Tmp2 = SelectExpr(Cond->getOperand(1)); - Tmp3 = MakeReg(VT); - switch(CC) { - default: assert(0 && "Invalid FSEL condition"); abort(); - case ISD::SETULT: - case ISD::SETLT: - BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp1).addReg(Tmp2); - BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp3).addReg(FV).addReg(TV); - return Result; - case ISD::SETUGE: - case ISD::SETGE: - BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp1).addReg(Tmp2); - BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp3).addReg(TV).addReg(FV); - return Result; - case ISD::SETUGT: - case ISD::SETGT: - BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp2).addReg(Tmp1); - BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp3).addReg(FV).addReg(TV); - return Result; - case ISD::SETULE: - case ISD::SETLE: - BuildMI(BB, Opc, 2, Tmp3).addReg(Tmp2).addReg(Tmp1); - BuildMI(BB, PPC::FSEL, 3, Result).addReg(Tmp3).addReg(TV).addReg(FV); - return Result; - } - } - assert(0 && "Should never get here"); - return 0; - } - - unsigned TrueValue = SelectExpr(N.getOperand(1)); //Use if TRUE - unsigned FalseValue = SelectExpr(N.getOperand(2)); //Use if FALSE - Opc = SelectSetCR0(N.getOperand(0)); - - // 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<MachineBasicBlock>::iterator It = BB; - ++It; - - // thisMBB: - // ... - // TrueVal = ... - // cmpTY cr0, r1, r2 - // bCC copy1MBB - // fallthrough --> copy0MBB - MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB); - MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB); - BuildMI(BB, Opc, 2).addReg(PPC::CR0).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; - // 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::FNEG: - if (!NoExcessFPPrecision && - ISD::ADD == N.getOperand(0).getOpcode() && - N.getOperand(0).Val->hasOneUse() && - ISD::MUL == 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::SUB == N.getOperand(0).getOpcode() && - N.getOperand(0).Val->hasOneUse() && - ISD::MUL == 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::FNMSUB : PPC::FNMSUBS; - BuildMI(BB, Opc, 3, Result).addReg(Tmp1).addReg(Tmp2).addReg(Tmp3); - } else if (ISD::FABS == N.getOperand(0).getOpc |