mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	and MCSubtargetInfo. - Added methods to update subtarget features (used when targets automatically detect subtarget features or switch modes). - Teach X86Subtarget to update MCSubtargetInfo features bits since the MCSubtargetInfo layer can be shared with other modules. - These fixes .code 16 / .code 32 support since mode switch is updated in MCSubtargetInfo so MC code emitter can do the right thing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134884 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			423 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			423 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===- PTXInstrInfo.cpp - PTX Instruction Information ---------------------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file contains the PTX implementation of the TargetInstrInfo class.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #define DEBUG_TYPE "ptx-instrinfo"
 | |
| 
 | |
| #include "PTX.h"
 | |
| #include "PTXInstrInfo.h"
 | |
| #include "llvm/CodeGen/MachineInstrBuilder.h"
 | |
| #include "llvm/CodeGen/SelectionDAG.h"
 | |
| #include "llvm/CodeGen/SelectionDAGNodes.h"
 | |
| #include "llvm/Target/TargetRegistry.h"
 | |
| #include "llvm/Support/Debug.h"
 | |
| #include "llvm/Support/raw_ostream.h"
 | |
| 
 | |
| #define GET_INSTRINFO_CTOR
 | |
| #define GET_INSTRINFO_MC_DESC
 | |
| #include "PTXGenInstrInfo.inc"
 | |
| 
 | |
| using namespace llvm;
 | |
| 
 | |
| PTXInstrInfo::PTXInstrInfo(PTXTargetMachine &_TM)
 | |
|   : PTXGenInstrInfo(),
 | |
|     RI(_TM, *this), TM(_TM) {}
 | |
| 
 | |
| static const struct map_entry {
 | |
|   const TargetRegisterClass *cls;
 | |
|   const int opcode;
 | |
| } map[] = {
 | |
|   { &PTX::RegI16RegClass, PTX::MOVU16rr },
 | |
|   { &PTX::RegI32RegClass, PTX::MOVU32rr },
 | |
|   { &PTX::RegI64RegClass, PTX::MOVU64rr },
 | |
|   { &PTX::RegF32RegClass, PTX::MOVF32rr },
 | |
|   { &PTX::RegF64RegClass, PTX::MOVF64rr },
 | |
|   { &PTX::RegPredRegClass,   PTX::MOVPREDrr }
 | |
| };
 | |
| 
 | |
| void PTXInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
 | |
|                                MachineBasicBlock::iterator I, DebugLoc DL,
 | |
|                                unsigned DstReg, unsigned SrcReg,
 | |
|                                bool KillSrc) const {
 | |
|   for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++ i) {
 | |
|     if (map[i].cls->contains(DstReg, SrcReg)) {
 | |
|       const MCInstrDesc &MCID = get(map[i].opcode);
 | |
|       MachineInstr *MI = BuildMI(MBB, I, DL, MCID, DstReg).
 | |
|         addReg(SrcReg, getKillRegState(KillSrc));
 | |
|       AddDefaultPredicate(MI);
 | |
|       return;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   llvm_unreachable("Impossible reg-to-reg copy");
 | |
| }
 | |
| 
 | |
| bool PTXInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
 | |
|                                 MachineBasicBlock::iterator I,
 | |
|                                 unsigned DstReg, unsigned SrcReg,
 | |
|                                 const TargetRegisterClass *DstRC,
 | |
|                                 const TargetRegisterClass *SrcRC,
 | |
|                                 DebugLoc DL) const {
 | |
|   if (DstRC != SrcRC)
 | |
|     return false;
 | |
| 
 | |
|   for (int i = 0, e = sizeof(map)/sizeof(map[0]); i != e; ++ i)
 | |
|     if (DstRC == map[i].cls) {
 | |
|       const MCInstrDesc &MCID = get(map[i].opcode);
 | |
|       MachineInstr *MI = BuildMI(MBB, I, DL, MCID, DstReg).addReg(SrcReg);
 | |
|       AddDefaultPredicate(MI);
 | |
|       return true;
 | |
|     }
 | |
| 
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| bool PTXInstrInfo::isMoveInstr(const MachineInstr& MI,
 | |
|                                unsigned &SrcReg, unsigned &DstReg,
 | |
|                                unsigned &SrcSubIdx, unsigned &DstSubIdx) const {
 | |
|   switch (MI.getOpcode()) {
 | |
|     default:
 | |
|       return false;
 | |
|     case PTX::MOVU16rr:
 | |
|     case PTX::MOVU32rr:
 | |
|     case PTX::MOVU64rr:
 | |
|     case PTX::MOVF32rr:
 | |
|     case PTX::MOVF64rr:
 | |
|     case PTX::MOVPREDrr:
 | |
|       assert(MI.getNumOperands() >= 2 &&
 | |
|              MI.getOperand(0).isReg() && MI.getOperand(1).isReg() &&
 | |
|              "Invalid register-register move instruction");
 | |
|       SrcSubIdx = DstSubIdx = 0; // No sub-registers
 | |
|       DstReg = MI.getOperand(0).getReg();
 | |
|       SrcReg = MI.getOperand(1).getReg();
 | |
|       return true;
 | |
|   }
 | |
| }
 | |
| 
 | |
| // predicate support
 | |
| 
 | |
| bool PTXInstrInfo::isPredicated(const MachineInstr *MI) const {
 | |
|   int i = MI->findFirstPredOperandIdx();
 | |
|   return i != -1 && MI->getOperand(i).getReg() != PTX::NoRegister;
 | |
| }
 | |
| 
 | |
| bool PTXInstrInfo::isUnpredicatedTerminator(const MachineInstr *MI) const {
 | |
|   return !isPredicated(MI) && get(MI->getOpcode()).isTerminator();
 | |
| }
 | |
| 
 | |
| bool PTXInstrInfo::
 | |
| PredicateInstruction(MachineInstr *MI,
 | |
|                      const SmallVectorImpl<MachineOperand> &Pred) const {
 | |
|   if (Pred.size() < 2)
 | |
|     llvm_unreachable("lesser than 2 predicate operands are provided");
 | |
| 
 | |
|   int i = MI->findFirstPredOperandIdx();
 | |
|   if (i == -1)
 | |
|     llvm_unreachable("missing predicate operand");
 | |
| 
 | |
|   MI->getOperand(i).setReg(Pred[0].getReg());
 | |
|   MI->getOperand(i+1).setImm(Pred[1].getImm());
 | |
| 
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| bool PTXInstrInfo::
 | |
| SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
 | |
|                   const SmallVectorImpl<MachineOperand> &Pred2) const {
 | |
|   const MachineOperand &PredReg1 = Pred1[0];
 | |
|   const MachineOperand &PredReg2 = Pred2[0];
 | |
|   if (PredReg1.getReg() != PredReg2.getReg())
 | |
|     return false;
 | |
| 
 | |
|   const MachineOperand &PredOp1 = Pred1[1];
 | |
|   const MachineOperand &PredOp2 = Pred2[1];
 | |
|   if (PredOp1.getImm() != PredOp2.getImm())
 | |
|     return false;
 | |
| 
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| bool PTXInstrInfo::
 | |
| DefinesPredicate(MachineInstr *MI,
 | |
|                  std::vector<MachineOperand> &Pred) const {
 | |
|   // If an instruction sets a predicate register, it defines a predicate.
 | |
| 
 | |
|   // TODO supprot 5-operand format of setp instruction
 | |
| 
 | |
|   if (MI->getNumOperands() < 1)
 | |
|     return false;
 | |
| 
 | |
|   const MachineOperand &MO = MI->getOperand(0);
 | |
| 
 | |
|   if (!MO.isReg() || RI.getRegClass(MO.getReg()) != &PTX::RegPredRegClass)
 | |
|     return false;
 | |
| 
 | |
|   Pred.push_back(MO);
 | |
|   Pred.push_back(MachineOperand::CreateImm(PTX::PRED_NORMAL));
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| // branch support
 | |
| 
 | |
| bool PTXInstrInfo::
 | |
| AnalyzeBranch(MachineBasicBlock &MBB,
 | |
|               MachineBasicBlock *&TBB,
 | |
|               MachineBasicBlock *&FBB,
 | |
|               SmallVectorImpl<MachineOperand> &Cond,
 | |
|               bool AllowModify) const {
 | |
|   // TODO implement cases when AllowModify is true
 | |
| 
 | |
|   if (MBB.empty())
 | |
|     return true;
 | |
| 
 | |
|   MachineBasicBlock::const_iterator iter = MBB.end();
 | |
|   const MachineInstr& instLast1 = *--iter;
 | |
|   const MCInstrDesc &desc1 = instLast1.getDesc();
 | |
|   // for special case that MBB has only 1 instruction
 | |
|   const bool IsSizeOne = MBB.size() == 1;
 | |
|   // if IsSizeOne is true, *--iter and instLast2 are invalid
 | |
|   // we put a dummy value in instLast2 and desc2 since they are used
 | |
|   const MachineInstr& instLast2 = IsSizeOne ? instLast1 : *--iter;
 | |
|   const MCInstrDesc &desc2 = IsSizeOne ? desc1 : instLast2.getDesc();
 | |
| 
 | |
|   DEBUG(dbgs() << "\n");
 | |
|   DEBUG(dbgs() << "AnalyzeBranch: opcode: " << instLast1.getOpcode() << "\n");
 | |
|   DEBUG(dbgs() << "AnalyzeBranch: MBB:    " << MBB.getName().str() << "\n");
 | |
|   DEBUG(dbgs() << "AnalyzeBranch: TBB:    " << TBB << "\n");
 | |
|   DEBUG(dbgs() << "AnalyzeBranch: FBB:    " << FBB << "\n");
 | |
| 
 | |
|   // this block ends with no branches
 | |
|   if (!IsAnyKindOfBranch(instLast1)) {
 | |
|     DEBUG(dbgs() << "AnalyzeBranch: ends with no branch\n");
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   // this block ends with only an unconditional branch
 | |
|   if (desc1.isUnconditionalBranch() &&
 | |
|       // when IsSizeOne is true, it "absorbs" the evaluation of instLast2
 | |
|       (IsSizeOne || !IsAnyKindOfBranch(instLast2))) {
 | |
|     DEBUG(dbgs() << "AnalyzeBranch: ends with only uncond branch\n");
 | |
|     TBB = GetBranchTarget(instLast1);
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   // this block ends with a conditional branch and
 | |
|   // it falls through to a successor block
 | |
|   if (desc1.isConditionalBranch() &&
 | |
|       IsAnySuccessorAlsoLayoutSuccessor(MBB)) {
 | |
|     DEBUG(dbgs() << "AnalyzeBranch: ends with cond branch and fall through\n");
 | |
|     TBB = GetBranchTarget(instLast1);
 | |
|     int i = instLast1.findFirstPredOperandIdx();
 | |
|     Cond.push_back(instLast1.getOperand(i));
 | |
|     Cond.push_back(instLast1.getOperand(i+1));
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   // when IsSizeOne is true, we are done
 | |
|   if (IsSizeOne)
 | |
|     return true;
 | |
| 
 | |
|   // this block ends with a conditional branch
 | |
|   // followed by an unconditional branch
 | |
|   if (desc2.isConditionalBranch() &&
 | |
|       desc1.isUnconditionalBranch()) {
 | |
|     DEBUG(dbgs() << "AnalyzeBranch: ends with cond and uncond branch\n");
 | |
|     TBB = GetBranchTarget(instLast2);
 | |
|     FBB = GetBranchTarget(instLast1);
 | |
|     int i = instLast2.findFirstPredOperandIdx();
 | |
|     Cond.push_back(instLast2.getOperand(i));
 | |
|     Cond.push_back(instLast2.getOperand(i+1));
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   // branch cannot be understood
 | |
|   DEBUG(dbgs() << "AnalyzeBranch: cannot be understood\n");
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| unsigned PTXInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
 | |
|   unsigned count = 0;
 | |
|   while (!MBB.empty())
 | |
|     if (IsAnyKindOfBranch(MBB.back())) {
 | |
|       MBB.pop_back();
 | |
|       ++count;
 | |
|     } else
 | |
|       break;
 | |
|   DEBUG(dbgs() << "RemoveBranch: MBB:   " << MBB.getName().str() << "\n");
 | |
|   DEBUG(dbgs() << "RemoveBranch: remove " << count << " branch inst\n");
 | |
|   return count;
 | |
| }
 | |
| 
 | |
| unsigned PTXInstrInfo::
 | |
| InsertBranch(MachineBasicBlock &MBB,
 | |
|              MachineBasicBlock *TBB,
 | |
|              MachineBasicBlock *FBB,
 | |
|              const SmallVectorImpl<MachineOperand> &Cond,
 | |
|              DebugLoc DL) const {
 | |
|   DEBUG(dbgs() << "InsertBranch: MBB: " << MBB.getName().str() << "\n");
 | |
|   DEBUG(if (TBB) dbgs() << "InsertBranch: TBB: " << TBB->getName().str()
 | |
|                         << "\n";
 | |
|         else     dbgs() << "InsertBranch: TBB: (NULL)\n");
 | |
|   DEBUG(if (FBB) dbgs() << "InsertBranch: FBB: " << FBB->getName().str()
 | |
|                         << "\n";
 | |
|         else     dbgs() << "InsertBranch: FBB: (NULL)\n");
 | |
|   DEBUG(dbgs() << "InsertBranch: Cond size: " << Cond.size() << "\n");
 | |
| 
 | |
|   assert(TBB && "TBB is NULL");
 | |
| 
 | |
|   if (FBB) {
 | |
|     BuildMI(&MBB, DL, get(PTX::BRAdp))
 | |
|       .addMBB(TBB).addReg(Cond[0].getReg()).addImm(Cond[1].getImm());
 | |
|     BuildMI(&MBB, DL, get(PTX::BRAd))
 | |
|       .addMBB(FBB).addReg(PTX::NoRegister).addImm(PTX::PRED_NORMAL);
 | |
|     return 2;
 | |
|   } else if (Cond.size()) {
 | |
|     BuildMI(&MBB, DL, get(PTX::BRAdp))
 | |
|       .addMBB(TBB).addReg(Cond[0].getReg()).addImm(Cond[1].getImm());
 | |
|     return 1;
 | |
|   } else {
 | |
|     BuildMI(&MBB, DL, get(PTX::BRAd))
 | |
|       .addMBB(TBB).addReg(PTX::NoRegister).addImm(PTX::PRED_NORMAL);
 | |
|     return 1;
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Memory operand folding for spills
 | |
| void PTXInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
 | |
|                                        MachineBasicBlock::iterator MII,
 | |
|                                      unsigned SrcReg, bool isKill, int FrameIdx,
 | |
|                                        const TargetRegisterClass *RC,
 | |
|                                        const TargetRegisterInfo *TRI) const {
 | |
|   MachineInstr& MI = *MII;
 | |
|   DebugLoc DL = MI.getDebugLoc();
 | |
| 
 | |
|   DEBUG(dbgs() << "storeRegToStackSlot: " << MI);
 | |
| 
 | |
|   int OpCode;
 | |
| 
 | |
|   // Select the appropriate opcode based on the register class
 | |
|   if (RC == PTX::RegI16RegisterClass) {
 | |
|     OpCode = PTX::STACKSTOREI16;
 | |
|   }  else if (RC == PTX::RegI32RegisterClass) {
 | |
|     OpCode = PTX::STACKSTOREI32;
 | |
|   }  else if (RC == PTX::RegI64RegisterClass) {
 | |
|     OpCode = PTX::STACKSTOREI32;
 | |
|   }  else if (RC == PTX::RegF32RegisterClass) {
 | |
|     OpCode = PTX::STACKSTOREF32;
 | |
|   }  else if (RC == PTX::RegF64RegisterClass) {
 | |
|     OpCode = PTX::STACKSTOREF64;
 | |
|   } else {
 | |
|     llvm_unreachable("Unknown PTX register class!");
 | |
|   }
 | |
| 
 | |
|   // Build the store instruction (really a mov)
 | |
|   MachineInstrBuilder MIB = BuildMI(MBB, MII, DL, get(OpCode));
 | |
|   MIB.addFrameIndex(FrameIdx);
 | |
|   MIB.addReg(SrcReg);
 | |
| 
 | |
|   AddDefaultPredicate(MIB);
 | |
| }
 | |
| 
 | |
| void PTXInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
 | |
|                                         MachineBasicBlock::iterator MII,
 | |
|                                         unsigned DestReg, int FrameIdx,
 | |
|                                         const TargetRegisterClass *RC,
 | |
|                                         const TargetRegisterInfo *TRI) const {
 | |
|   MachineInstr& MI = *MII;
 | |
|   DebugLoc DL = MI.getDebugLoc();
 | |
| 
 | |
|   DEBUG(dbgs() << "loadRegToStackSlot: " << MI);
 | |
| 
 | |
|   int OpCode;
 | |
| 
 | |
|   // Select the appropriate opcode based on the register class
 | |
|   if (RC == PTX::RegI16RegisterClass) {
 | |
|     OpCode = PTX::STACKLOADI16;
 | |
|   } else if (RC == PTX::RegI32RegisterClass) {
 | |
|     OpCode = PTX::STACKLOADI32;
 | |
|   } else if (RC == PTX::RegI64RegisterClass) {
 | |
|     OpCode = PTX::STACKLOADI32;
 | |
|   } else if (RC == PTX::RegF32RegisterClass) {
 | |
|     OpCode = PTX::STACKLOADF32;
 | |
|   } else if (RC == PTX::RegF64RegisterClass) {
 | |
|     OpCode = PTX::STACKLOADF64;
 | |
|   } else {
 | |
|     llvm_unreachable("Unknown PTX register class!");
 | |
|   }
 | |
| 
 | |
|   // Build the load instruction (really a mov)
 | |
|   MachineInstrBuilder MIB = BuildMI(MBB, MII, DL, get(OpCode));
 | |
|   MIB.addReg(DestReg);
 | |
|   MIB.addFrameIndex(FrameIdx);
 | |
| 
 | |
|   AddDefaultPredicate(MIB);
 | |
| }
 | |
| 
 | |
| // static helper routines
 | |
| 
 | |
| MachineSDNode *PTXInstrInfo::
 | |
| GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
 | |
|                   DebugLoc dl, EVT VT, SDValue Op1) {
 | |
|   SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
 | |
|   SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
 | |
|   SDValue ops[] = { Op1, predReg, predOp };
 | |
|   return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
 | |
| }
 | |
| 
 | |
| MachineSDNode *PTXInstrInfo::
 | |
| GetPTXMachineNode(SelectionDAG *DAG, unsigned Opcode,
 | |
|                   DebugLoc dl, EVT VT, SDValue Op1, SDValue Op2) {
 | |
|   SDValue predReg = DAG->getRegister(PTX::NoRegister, MVT::i1);
 | |
|   SDValue predOp = DAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
 | |
|   SDValue ops[] = { Op1, Op2, predReg, predOp };
 | |
|   return DAG->getMachineNode(Opcode, dl, VT, ops, array_lengthof(ops));
 | |
| }
 | |
| 
 | |
| void PTXInstrInfo::AddDefaultPredicate(MachineInstr *MI) {
 | |
|   if (MI->findFirstPredOperandIdx() == -1) {
 | |
|     MI->addOperand(MachineOperand::CreateReg(PTX::NoRegister, /*IsDef=*/false));
 | |
|     MI->addOperand(MachineOperand::CreateImm(PTX::PRED_NORMAL));
 | |
|   }
 | |
| }
 | |
| 
 | |
| bool PTXInstrInfo::IsAnyKindOfBranch(const MachineInstr& inst) {
 | |
|   const MCInstrDesc &desc = inst.getDesc();
 | |
|   return desc.isTerminator() || desc.isBranch() || desc.isIndirectBranch();
 | |
| }
 | |
| 
 | |
| bool PTXInstrInfo::
 | |
| IsAnySuccessorAlsoLayoutSuccessor(const MachineBasicBlock& MBB) {
 | |
|   for (MachineBasicBlock::const_succ_iterator
 | |
|       i = MBB.succ_begin(), e = MBB.succ_end(); i != e; ++i)
 | |
|     if (MBB.isLayoutSuccessor((const MachineBasicBlock*) &*i))
 | |
|       return true;
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| MachineBasicBlock *PTXInstrInfo::GetBranchTarget(const MachineInstr& inst) {
 | |
|   // FIXME So far all branch instructions put destination in 1st operand
 | |
|   const MachineOperand& target = inst.getOperand(0);
 | |
|   assert(target.isMBB() && "FIXME: detect branch target operand");
 | |
|   return target.getMBB();
 | |
| }
 | |
| 
 | |
| MCInstrInfo *createPTXMCInstrInfo() {
 | |
|   MCInstrInfo *X = new MCInstrInfo();
 | |
|   InitPTXMCInstrInfo(X);
 | |
|   return X;
 | |
| }
 | |
| 
 | |
| extern "C" void LLVMInitializePTXMCInstrInfo() {
 | |
|   TargetRegistry::RegisterMCInstrInfo(ThePTX32Target, createPTXMCInstrInfo);
 | |
|   TargetRegistry::RegisterMCInstrInfo(ThePTX64Target, createPTXMCInstrInfo);
 | |
| }
 |