X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FMips%2FMipsInstrInfo.cpp;h=cda50527baed709bee0ca9497b0b3674a7d27e1f;hb=69244300b8a0112efb44b6273ecea4ca6264b8cf;hp=808403067e82ee3c9ac994294030c27342d980c1;hpb=972f5896e417d8e81cf400083fab15a37b6d4277;p=oota-llvm.git diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index 808403067e8..cda50527bae 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -2,8 +2,8 @@ // // The LLVM Compiler Infrastructure // -// This file was developed by Bruno Cardoso Lopes and is distributed under the -// University of Illinois Open Source License. See LICENSE.TXT for details. +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // @@ -13,6 +13,7 @@ #include "Mips.h" #include "MipsInstrInfo.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "MipsGenInstrInfo.inc" @@ -20,11 +21,11 @@ using namespace llvm; // TODO: Add the subtarget support on this constructor MipsInstrInfo::MipsInstrInfo(MipsTargetMachine &tm) - : TargetInstrInfo(MipsInsts, sizeof(MipsInsts)/sizeof(MipsInsts[0])), + : TargetInstrInfoImpl(MipsInsts, array_lengthof(MipsInsts)), TM(tm), RI(*this) {} static bool isZeroImm(const MachineOperand &op) { - return op.isImmediate() && op.getImmedValue() == 0; + return op.isImmediate() && op.getImm() == 0; } /// Return true if the instruction is a register to register move and @@ -67,14 +68,13 @@ isMoveInstr(const MachineInstr &MI, unsigned &SrcReg, unsigned &DstReg) const unsigned MipsInstrInfo:: isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const { - // TODO: add lhu, lbu ??? if (MI->getOpcode() == Mips::LW) { if ((MI->getOperand(2).isFrameIndex()) && // is a stack slot (MI->getOperand(1).isImmediate()) && // the imm is zero (isZeroImm(MI->getOperand(1)))) { - FrameIndex = MI->getOperand(2).getFrameIndex(); + FrameIndex = MI->getOperand(2).getIndex(); return MI->getOperand(0).getReg(); } } @@ -90,25 +90,368 @@ isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const unsigned MipsInstrInfo:: isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const { - // TODO: add sb, sh ??? if (MI->getOpcode() == Mips::SW) { if ((MI->getOperand(0).isFrameIndex()) && // is a stack slot (MI->getOperand(1).isImmediate()) && // the imm is zero (isZeroImm(MI->getOperand(1)))) { - FrameIndex = MI->getOperand(0).getFrameIndex(); + FrameIndex = MI->getOperand(0).getIndex(); return MI->getOperand(2).getReg(); } } return 0; } +/// insertNoop - If data hazard condition is found insert the target nop +/// instruction. +void MipsInstrInfo:: +insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const +{ + BuildMI(MBB, MI, get(Mips::NOP)); +} + +//===----------------------------------------------------------------------===// +// Branch Analysis +//===----------------------------------------------------------------------===// + +/// GetCondFromBranchOpc - Return the Mips CC that matches +/// the correspondent Branch instruction opcode. +static Mips::CondCode GetCondFromBranchOpc(unsigned BrOpc) +{ + switch (BrOpc) { + default: return Mips::COND_INVALID; + case Mips::BEQ : return Mips::COND_E; + case Mips::BNE : return Mips::COND_NE; + case Mips::BGTZ : return Mips::COND_GZ; + case Mips::BGEZ : return Mips::COND_GEZ; + case Mips::BLTZ : return Mips::COND_LZ; + case Mips::BLEZ : return Mips::COND_LEZ; + } +} + +/// GetCondBranchFromCond - Return the Branch instruction +/// opcode that matches the cc. +unsigned Mips::GetCondBranchFromCond(Mips::CondCode CC) +{ + switch (CC) { + default: assert(0 && "Illegal condition code!"); + case Mips::COND_E : return Mips::BEQ; + case Mips::COND_NE : return Mips::BNE; + case Mips::COND_GZ : return Mips::BGTZ; + case Mips::COND_GEZ : return Mips::BGEZ; + case Mips::COND_LZ : return Mips::BLTZ; + case Mips::COND_LEZ : return Mips::BLEZ; + } +} + +/// GetOppositeBranchCondition - Return the inverse of the specified +/// condition, e.g. turning COND_E to COND_NE. +Mips::CondCode Mips::GetOppositeBranchCondition(Mips::CondCode CC) +{ + switch (CC) { + default: assert(0 && "Illegal condition code!"); + case Mips::COND_E : return Mips::COND_NE; + case Mips::COND_NE : return Mips::COND_E; + case Mips::COND_GZ : return Mips::COND_LEZ; + case Mips::COND_GEZ : return Mips::COND_LZ; + case Mips::COND_LZ : return Mips::COND_GEZ; + case Mips::COND_LEZ : return Mips::COND_GZ; + } +} + +bool MipsInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, + MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + std::vector &Cond) const +{ + // If the block has no terminators, it just falls into the block after it. + MachineBasicBlock::iterator I = MBB.end(); + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) + return false; + + // Get the last instruction in the block. + MachineInstr *LastInst = I; + + // If there is only one terminator instruction, process it. + unsigned LastOpc = LastInst->getOpcode(); + if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { + if (!LastInst->getDesc()->isBranch()) + return true; + + // Unconditional branch + if (LastOpc == Mips::J) { + TBB = LastInst->getOperand(0).getMBB(); + return false; + } + + Mips::CondCode BranchCode = GetCondFromBranchOpc(LastInst->getOpcode()); + if (BranchCode == Mips::COND_INVALID) + return true; // Can't handle indirect branch. + + // Conditional branch + // Block ends with fall-through condbranch. + if (LastOpc != Mips::COND_INVALID) { + int LastNumOp = LastInst->getNumOperands(); + + TBB = LastInst->getOperand(LastNumOp-1).getMBB(); + Cond.push_back(MachineOperand::CreateImm(BranchCode)); + + for (int i=0; igetOperand(i)); + } + + return false; + } + } + + // Get the instruction before it if it is a terminator. + MachineInstr *SecondLastInst = I; + + // If there are three terminators, we don't know what sort of block this is. + if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(--I)) + return true; + + // If the block ends with Mips::J and a Mips::BNE/Mips::BEQ, handle it. + unsigned SecondLastOpc = SecondLastInst->getOpcode(); + Mips::CondCode BranchCode = GetCondFromBranchOpc(SecondLastOpc); + + if (SecondLastOpc != Mips::COND_INVALID && LastOpc == Mips::J) { + int SecondNumOp = SecondLastInst->getNumOperands(); + + TBB = SecondLastInst->getOperand(SecondNumOp-1).getMBB(); + Cond.push_back(MachineOperand::CreateImm(BranchCode)); + + for (int i=0; igetOperand(i)); + } + + FBB = LastInst->getOperand(0).getMBB(); + return false; + } + + // If the block ends with two unconditional branches, handle it. The last + // one is not executed, so remove it. + if ((SecondLastOpc == Mips::J) && (LastOpc == Mips::J)) { + TBB = SecondLastInst->getOperand(0).getMBB(); + I = LastInst; + I->eraseFromParent(); + return false; + } + + // Otherwise, can't handle this. + return true; +} + unsigned MipsInstrInfo:: InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, const std::vector &Cond) const { - // TODO: add Mips::J here. - assert(0 && "Cant handle any kind of branches!"); - return 1; + // Shouldn't be a fall through. + assert(TBB && "InsertBranch must not be told to insert a fallthrough"); + assert((Cond.size() == 3 || Cond.size() == 2 || Cond.size() == 0) && + "Mips branch conditions can have two|three components!"); + + if (FBB == 0) { // One way branch. + if (Cond.empty()) { + // Unconditional branch? + BuildMI(&MBB, get(Mips::J)).addMBB(TBB); + } else { + // Conditional branch. + unsigned Opc = GetCondBranchFromCond((Mips::CondCode)Cond[0].getImm()); + const TargetInstrDescriptor &TID = get(Opc); + + if (TID.numOperands == 3) + BuildMI(&MBB, TID).addReg(Cond[1].getReg()) + .addReg(Cond[2].getReg()) + .addMBB(TBB); + else + BuildMI(&MBB, TID).addReg(Cond[1].getReg()) + .addMBB(TBB); + + } + return 1; + } + + // Two-way Conditional branch. + unsigned Opc = GetCondBranchFromCond((Mips::CondCode)Cond[0].getImm()); + const TargetInstrDescriptor &TID = get(Opc); + + if (TID.numOperands == 3) + BuildMI(&MBB, TID).addReg(Cond[1].getReg()) + .addReg(Cond[2].getReg()) + .addMBB(TBB); + else + BuildMI(&MBB, TID).addReg(Cond[1].getReg()) + .addMBB(TBB); + + BuildMI(&MBB, get(Mips::J)).addMBB(FBB); + return 2; +} + +void MipsInstrInfo:: +copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC) const { + if (DestRC != SrcRC) { + cerr << "Not yet supported!"; + abort(); + } + + if (DestRC == Mips::CPURegsRegisterClass) + BuildMI(MBB, I, get(Mips::ADDu), DestReg).addReg(Mips::ZERO) + .addReg(SrcReg); + else + assert (0 && "Can't copy this register"); +} + +void MipsInstrInfo:: +storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned SrcReg, bool isKill, int FI, + const TargetRegisterClass *RC) const +{ + if (RC == Mips::CPURegsRegisterClass) + BuildMI(MBB, I, get(Mips::SW)).addReg(SrcReg, false, false, isKill) + .addImm(0).addFrameIndex(FI); + else + assert(0 && "Can't store this register to stack slot"); +} + +void MipsInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg, + bool isKill, + SmallVectorImpl &Addr, + const TargetRegisterClass *RC, + SmallVectorImpl &NewMIs) const { + if (RC != Mips::CPURegsRegisterClass) + assert(0 && "Can't store this register"); + MachineInstrBuilder MIB = BuildMI(get(Mips::SW)) + .addReg(SrcReg, false, false, isKill); + for (unsigned i = 0, e = Addr.size(); i != e; ++i) { + MachineOperand &MO = Addr[i]; + if (MO.isRegister()) + MIB.addReg(MO.getReg()); + else if (MO.isImmediate()) + MIB.addImm(MO.getImm()); + else + MIB.addFrameIndex(MO.getIndex()); + } + NewMIs.push_back(MIB); + return; +} + +void MipsInstrInfo:: +loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned DestReg, int FI, + const TargetRegisterClass *RC) const +{ + if (RC == Mips::CPURegsRegisterClass) + BuildMI(MBB, I, get(Mips::LW), DestReg).addImm(0).addFrameIndex(FI); + else + assert(0 && "Can't load this register from stack slot"); } + +void MipsInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg, + SmallVectorImpl &Addr, + const TargetRegisterClass *RC, + SmallVectorImpl &NewMIs) const { + if (RC != Mips::CPURegsRegisterClass) + assert(0 && "Can't load this register"); + MachineInstrBuilder MIB = BuildMI(get(Mips::LW), DestReg); + for (unsigned i = 0, e = Addr.size(); i != e; ++i) { + MachineOperand &MO = Addr[i]; + if (MO.isRegister()) + MIB.addReg(MO.getReg()); + else if (MO.isImmediate()) + MIB.addImm(MO.getImm()); + else + MIB.addFrameIndex(MO.getIndex()); + } + NewMIs.push_back(MIB); + return; +} + +MachineInstr *MipsInstrInfo:: +foldMemoryOperand(MachineInstr* MI, + SmallVectorImpl &Ops, int FI) const +{ + if (Ops.size() != 1) return NULL; + + MachineInstr *NewMI = NULL; + + switch (MI->getOpcode()) + { + case Mips::ADDu: + if ((MI->getOperand(0).isRegister()) && + (MI->getOperand(1).isRegister()) && + (MI->getOperand(1).getReg() == Mips::ZERO) && + (MI->getOperand(2).isRegister())) + { + if (Ops[0] == 0) // COPY -> STORE + NewMI = BuildMI(get(Mips::SW)).addFrameIndex(FI) + .addImm(0).addReg(MI->getOperand(2).getReg()); + else // COPY -> LOAD + NewMI = BuildMI(get(Mips::LW), MI->getOperand(0) + .getReg()).addImm(0).addFrameIndex(FI); + } + break; + } + + if (NewMI) + NewMI->copyKillDeadInfo(MI); + return NewMI; +} + +unsigned MipsInstrInfo:: +RemoveBranch(MachineBasicBlock &MBB) const +{ + MachineBasicBlock::iterator I = MBB.end(); + if (I == MBB.begin()) return 0; + --I; + if (I->getOpcode() != Mips::J && + GetCondFromBranchOpc(I->getOpcode()) == Mips::COND_INVALID) + return 0; + + // Remove the branch. + I->eraseFromParent(); + + I = MBB.end(); + + if (I == MBB.begin()) return 1; + --I; + if (GetCondFromBranchOpc(I->getOpcode()) == Mips::COND_INVALID) + return 1; + + // Remove the branch. + I->eraseFromParent(); + return 2; +} + +/// BlockHasNoFallThrough - Analyse if MachineBasicBlock does not +/// fall-through into its successor block. +bool MipsInstrInfo:: +BlockHasNoFallThrough(MachineBasicBlock &MBB) const +{ + if (MBB.empty()) return false; + + switch (MBB.back().getOpcode()) { + case Mips::RET: // Return. + case Mips::JR: // Indirect branch. + case Mips::J: // Uncond branch. + return true; + default: return false; + } +} + +/// ReverseBranchCondition - Return the inverse opcode of the +/// specified Branch instruction. +bool MipsInstrInfo:: +ReverseBranchCondition(std::vector &Cond) const +{ + assert( (Cond.size() == 3 || Cond.size() == 2) && + "Invalid Mips branch condition!"); + Cond[0].setImm(GetOppositeBranchCondition((Mips::CondCode)Cond[0].getImm())); + return false; +} + +