aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/PowerPC/PPCISelPattern.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-01-12 01:46:07 +0000
committerChris Lattner <sabre@nondot.org>2006-01-12 01:46:07 +0000
commit05f1fe8d448013531f86a24b5173fe57330291ef (patch)
tree24f58fba2ad290ad82d6d671c8ecb78f6dbe1114 /lib/Target/PowerPC/PPCISelPattern.cpp
parent271426a99a6afb5a884b6dcf2e50a6a9680ec839 (diff)
Goodbye PPC pattern isel. You have served us well, but it is now time for
you to ride off into the sunset. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25236 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/PowerPC/PPCISelPattern.cpp')
-rw-r--r--lib/Target/PowerPC/PPCISelPattern.cpp1713
1 files changed, 0 insertions, 1713 deletions
diff --git a/lib/Target/PowerPC/PPCISelPattern.cpp b/lib/Target/PowerPC/PPCISelPattern.cpp
deleted file mode 100644
index bae19f8fb7..0000000000
--- a/lib/Target/PowerPC/PPCISelPattern.cpp
+++ /dev/null
@@ -1,1713 +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 "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 <set>
-#include <algorithm>
-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 {
- PPCTargetLowering PPCLowering;
- 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<SDOperand, unsigned> ExprMap;
-
- unsigned GlobalBaseReg;
- bool GlobalBaseInitialized;
- bool RecordSuccess;
-public:
- ISel(TargetMachine &TM) : SelectionDAGISel(PPCLowering), PPCLowering(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(PPC::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::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<ConstantSDNode>(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;
-}
-}
-
-/// 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<PPCSubtarget>().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(PPC::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<FrameIndexSDNode>(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<GlobalAddressSDNode>(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<BasicBlockSDNode>(N.getOperand(4))->getBasicBlock();
-
- Select(N.getOperand(0)); //chain
- ISD::CondCode CC = cast<CondCodeSDNode>(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<BasicBlockSDNode>(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<MachineBasicBlock>::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<ConstantSDNode>(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<RegisterSDNode>(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<ConstantSDNode>(N.getOperand(2)) ||
- cast<ConstantSDNode>(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::OR4, 2, Result).addReg(PPC::R1).addReg(PPC::R1);
- return Result;
-
- case ISD::ConstantPool:
- Tmp1 = BB->getParent()->getConstantPool()->
- getConstantPoolIndex(cast<ConstantPoolSDNode>(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<FrameIndexSDNode>(N)->getIndex();
- addFrameReference(BuildMI(BB, PPC::ADDI, 2, Result), (int)Tmp1, 0, false);
- return Result;
-
- case ISD::GlobalAddress: {
- GlobalValue *GV = cast<GlobalAddressSDNode>(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<VTSDNode>(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<ConstantPoolSDNode>(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<FrameIndexSDNode>(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<GlobalAddressSDNode>(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<GlobalAddressSDNode>(N.getOperand(1))) {
- CallMI = BuildMI(PPC::BL, 1).addGlobalAddress(GASD->getGlobal(), true);
- } else if (ExternalSymbolSDNode *ESSDN =
- dyn_cast<ExternalSymbolSDNode>(N.getOperand(1))) {
- CallMI = BuildMI(PPC::BL, 1).addExternalSymbol(ESSDN->getSymbol(), true);
- } else {
- Tmp1 = SelectExpr(N.getOperand(1));
- BuildMI(BB, PPC::MTCTR, 1).addReg(Tmp1);
- BuildMI(BB, PPC::OR4, 2, PPC::R12).addReg(Tmp1).addReg(Tmp1);
- CallMI = BuildMI(PPC::BCTRL, 1).addReg(PPC::R12);
- }
-
- // Load the register args to virtual regs
- std::vector<unsigned> 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::OR4,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::OR4, 2, Result+1).addReg(PPC::R3).addReg(PPC::R3);
- BuildMI(BB, PPC::OR4, 2, Result).addReg(PPC::R4).addReg(PPC::R4);
- } else {
- BuildMI(BB, PPC::OR4, 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<VTSDNode>(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<RegisterSDNode>(Node->getOperand(1))->getReg();
- if (MVT::isInteger(DestType))
- BuildMI(BB, PPC::OR4, 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)