mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-04 05:17:07 +00:00 
			
		
		
		
	In some cases, we were losing track of live implicit registers which was creating dead defs and causing the scheduler to produce invalid code. NOTE: This is a candidate for the Mesa stable branch. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@175516 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			345 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			345 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//===-- AMDGPUIndirectAddressing.cpp - Indirect Adressing Support ---------===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
/// \file
 | 
						|
///
 | 
						|
/// Instructions can use indirect addressing to index the register file as if it
 | 
						|
/// were memory.  This pass lowers RegisterLoad and RegisterStore instructions
 | 
						|
/// to either a COPY or a MOV that uses indirect addressing.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "AMDGPU.h"
 | 
						|
#include "R600InstrInfo.h"
 | 
						|
#include "R600MachineFunctionInfo.h"
 | 
						|
#include "llvm/CodeGen/MachineFunction.h"
 | 
						|
#include "llvm/CodeGen/MachineFunctionPass.h"
 | 
						|
#include "llvm/CodeGen/MachineInstrBuilder.h"
 | 
						|
#include "llvm/CodeGen/MachineRegisterInfo.h"
 | 
						|
#include "llvm/Support/Debug.h"
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
namespace {
 | 
						|
 | 
						|
class AMDGPUIndirectAddressingPass : public MachineFunctionPass {
 | 
						|
 | 
						|
private:
 | 
						|
  static char ID;
 | 
						|
  const AMDGPUInstrInfo *TII;
 | 
						|
 | 
						|
  bool regHasExplicitDef(MachineRegisterInfo &MRI, unsigned Reg) const;
 | 
						|
 | 
						|
public:
 | 
						|
  AMDGPUIndirectAddressingPass(TargetMachine &tm) :
 | 
						|
    MachineFunctionPass(ID),
 | 
						|
    TII(static_cast<const AMDGPUInstrInfo*>(tm.getInstrInfo()))
 | 
						|
    { }
 | 
						|
 | 
						|
  virtual bool runOnMachineFunction(MachineFunction &MF);
 | 
						|
 | 
						|
  const char *getPassName() const { return "R600 Handle indirect addressing"; }
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
} // End anonymous namespace
 | 
						|
 | 
						|
char AMDGPUIndirectAddressingPass::ID = 0;
 | 
						|
 | 
						|
FunctionPass *llvm::createAMDGPUIndirectAddressingPass(TargetMachine &tm) {
 | 
						|
  return new AMDGPUIndirectAddressingPass(tm);
 | 
						|
}
 | 
						|
 | 
						|
bool AMDGPUIndirectAddressingPass::runOnMachineFunction(MachineFunction &MF) {
 | 
						|
  MachineRegisterInfo &MRI = MF.getRegInfo();
 | 
						|
 | 
						|
  int IndirectBegin = TII->getIndirectIndexBegin(MF);
 | 
						|
  int IndirectEnd = TII->getIndirectIndexEnd(MF);
 | 
						|
 | 
						|
  if (IndirectBegin == -1) {
 | 
						|
    // No indirect addressing, we can skip this pass
 | 
						|
    assert(IndirectEnd == -1);
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  // The map keeps track of the indirect address that is represented by
 | 
						|
  // each virtual register. The key is the register and the value is the
 | 
						|
  // indirect address it uses.
 | 
						|
  std::map<unsigned, unsigned> RegisterAddressMap;
 | 
						|
 | 
						|
  // First pass - Lower all of the RegisterStore instructions and track which
 | 
						|
  // registers are live.
 | 
						|
  for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
 | 
						|
                                                      BB != BB_E; ++BB) {
 | 
						|
    // This map keeps track of the current live indirect registers.
 | 
						|
    // The key is the address and the value is the register
 | 
						|
    std::map<unsigned, unsigned> LiveAddressRegisterMap;
 | 
						|
    MachineBasicBlock &MBB = *BB;
 | 
						|
 | 
						|
    for (MachineBasicBlock::iterator I = MBB.begin(), Next = llvm::next(I);
 | 
						|
                               I != MBB.end(); I = Next) {
 | 
						|
      Next = llvm::next(I);
 | 
						|
      MachineInstr &MI = *I;
 | 
						|
 | 
						|
      if (!TII->isRegisterStore(MI)) {
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      // Lower RegisterStore
 | 
						|
 | 
						|
      unsigned RegIndex = MI.getOperand(2).getImm();
 | 
						|
      unsigned Channel = MI.getOperand(3).getImm();
 | 
						|
      unsigned Address = TII->calculateIndirectAddress(RegIndex, Channel);
 | 
						|
      const TargetRegisterClass *IndirectStoreRegClass =
 | 
						|
                   TII->getIndirectAddrStoreRegClass(MI.getOperand(0).getReg());
 | 
						|
 | 
						|
      if (MI.getOperand(1).getReg() == AMDGPU::INDIRECT_BASE_ADDR) {
 | 
						|
        // Direct register access.
 | 
						|
        unsigned DstReg = MRI.createVirtualRegister(IndirectStoreRegClass);
 | 
						|
 | 
						|
        BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(AMDGPU::COPY), DstReg)
 | 
						|
                .addOperand(MI.getOperand(0));
 | 
						|
 | 
						|
        RegisterAddressMap[DstReg] = Address;
 | 
						|
        LiveAddressRegisterMap[Address] = DstReg;
 | 
						|
      } else {
 | 
						|
        // Indirect register access.
 | 
						|
        MachineInstrBuilder MOV = TII->buildIndirectWrite(BB, I,
 | 
						|
                                           MI.getOperand(0).getReg(), // Value
 | 
						|
                                           Address,
 | 
						|
                                           MI.getOperand(1).getReg()); // Offset
 | 
						|
        for (int i = IndirectBegin; i <= IndirectEnd; ++i) {
 | 
						|
          unsigned Addr = TII->calculateIndirectAddress(i, Channel);
 | 
						|
          unsigned DstReg = MRI.createVirtualRegister(IndirectStoreRegClass);
 | 
						|
          MOV.addReg(DstReg, RegState::Define | RegState::Implicit);
 | 
						|
          RegisterAddressMap[DstReg] = Addr;
 | 
						|
          LiveAddressRegisterMap[Addr] = DstReg;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      MI.eraseFromParent();
 | 
						|
    }
 | 
						|
 | 
						|
    // Update the live-ins of the succesor blocks
 | 
						|
    for (MachineBasicBlock::succ_iterator Succ = MBB.succ_begin(),
 | 
						|
                                          SuccEnd = MBB.succ_end();
 | 
						|
                                          SuccEnd != Succ; ++Succ) {
 | 
						|
      std::map<unsigned, unsigned>::const_iterator Key, KeyEnd;
 | 
						|
      for (Key = LiveAddressRegisterMap.begin(),
 | 
						|
           KeyEnd = LiveAddressRegisterMap.end(); KeyEnd != Key; ++Key) {
 | 
						|
        (*Succ)->addLiveIn(Key->second);
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Second pass - Lower the RegisterLoad instructions
 | 
						|
  for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
 | 
						|
                                                      BB != BB_E; ++BB) {
 | 
						|
    // Key is the address and the value is the register
 | 
						|
    std::map<unsigned, unsigned> LiveAddressRegisterMap;
 | 
						|
    MachineBasicBlock &MBB = *BB;
 | 
						|
 | 
						|
    MachineBasicBlock::livein_iterator LI = MBB.livein_begin();
 | 
						|
    while (LI != MBB.livein_end()) {
 | 
						|
      std::vector<unsigned> PhiRegisters;
 | 
						|
 | 
						|
      // Make sure this live in is used for indirect addressing
 | 
						|
      if (RegisterAddressMap.find(*LI) == RegisterAddressMap.end()) {
 | 
						|
        ++LI;
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      unsigned Address = RegisterAddressMap[*LI];
 | 
						|
      LiveAddressRegisterMap[Address] = *LI;
 | 
						|
      PhiRegisters.push_back(*LI);
 | 
						|
 | 
						|
      // Check if there are other live in registers which map to the same
 | 
						|
      // indirect address.
 | 
						|
      for (MachineBasicBlock::livein_iterator LJ = llvm::next(LI),
 | 
						|
                                              LE = MBB.livein_end();
 | 
						|
                                              LJ != LE; ++LJ) {
 | 
						|
        unsigned Reg = *LJ;
 | 
						|
        if (RegisterAddressMap.find(Reg) == RegisterAddressMap.end()) {
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
 | 
						|
        if (RegisterAddressMap[Reg] == Address) {
 | 
						|
          PhiRegisters.push_back(Reg);
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      if (PhiRegisters.size() == 1) {
 | 
						|
        // We don't need to insert a Phi instruction, so we can just add the
 | 
						|
        // registers to the live list for the block.
 | 
						|
        LiveAddressRegisterMap[Address] = *LI;
 | 
						|
        MBB.removeLiveIn(*LI);
 | 
						|
      } else {
 | 
						|
        // We need to insert a PHI, because we have the same address being
 | 
						|
        // written in multiple predecessor blocks.
 | 
						|
        const TargetRegisterClass *PhiDstClass =
 | 
						|
                   TII->getIndirectAddrStoreRegClass(*(PhiRegisters.begin()));
 | 
						|
        unsigned PhiDstReg = MRI.createVirtualRegister(PhiDstClass);
 | 
						|
        MachineInstrBuilder Phi = BuildMI(MBB, MBB.begin(),
 | 
						|
                                          MBB.findDebugLoc(MBB.begin()),
 | 
						|
                                          TII->get(AMDGPU::PHI), PhiDstReg);
 | 
						|
 | 
						|
        for (std::vector<unsigned>::const_iterator RI = PhiRegisters.begin(),
 | 
						|
                                                   RE = PhiRegisters.end();
 | 
						|
                                                   RI != RE; ++RI) {
 | 
						|
          unsigned Reg = *RI;
 | 
						|
          MachineInstr *DefInst = MRI.getVRegDef(Reg);
 | 
						|
          assert(DefInst);
 | 
						|
          MachineBasicBlock *RegBlock = DefInst->getParent();
 | 
						|
          Phi.addReg(Reg);
 | 
						|
          Phi.addMBB(RegBlock);
 | 
						|
          MBB.removeLiveIn(Reg);
 | 
						|
        }
 | 
						|
        RegisterAddressMap[PhiDstReg] = Address;
 | 
						|
        LiveAddressRegisterMap[Address] = PhiDstReg;
 | 
						|
      }
 | 
						|
      LI = MBB.livein_begin();
 | 
						|
    }
 | 
						|
 | 
						|
    for (MachineBasicBlock::iterator I = MBB.begin(), Next = llvm::next(I);
 | 
						|
                               I != MBB.end(); I = Next) {
 | 
						|
      Next = llvm::next(I);
 | 
						|
      MachineInstr &MI = *I;
 | 
						|
 | 
						|
      if (!TII->isRegisterLoad(MI)) {
 | 
						|
        if (MI.getOpcode() == AMDGPU::PHI) {
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
        // Check for indirect register defs
 | 
						|
        for (unsigned OpIdx = 0, NumOperands = MI.getNumOperands();
 | 
						|
                                 OpIdx < NumOperands; ++OpIdx) {
 | 
						|
          MachineOperand &MO = MI.getOperand(OpIdx);
 | 
						|
          if (MO.isReg() && MO.isDef() &&
 | 
						|
              RegisterAddressMap.find(MO.getReg()) != RegisterAddressMap.end()) {
 | 
						|
            unsigned Reg = MO.getReg();
 | 
						|
            unsigned LiveAddress = RegisterAddressMap[Reg];
 | 
						|
            // Chain the live-ins
 | 
						|
            if (LiveAddressRegisterMap.find(LiveAddress) !=
 | 
						|
                                                     RegisterAddressMap.end()) {
 | 
						|
              MI.addOperand(MachineOperand::CreateReg(
 | 
						|
                                  LiveAddressRegisterMap[LiveAddress],
 | 
						|
                                  false, // isDef
 | 
						|
                                  true,  // isImp
 | 
						|
                                  true));  // isKill
 | 
						|
            }
 | 
						|
            LiveAddressRegisterMap[LiveAddress] = Reg;
 | 
						|
          }
 | 
						|
        }
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      const TargetRegisterClass *SuperIndirectRegClass =
 | 
						|
                                                TII->getSuperIndirectRegClass();
 | 
						|
      const TargetRegisterClass *IndirectLoadRegClass =
 | 
						|
                                             TII->getIndirectAddrLoadRegClass();
 | 
						|
      unsigned IndirectReg = MRI.createVirtualRegister(SuperIndirectRegClass);
 | 
						|
 | 
						|
      unsigned RegIndex = MI.getOperand(2).getImm();
 | 
						|
      unsigned Channel = MI.getOperand(3).getImm();
 | 
						|
      unsigned Address = TII->calculateIndirectAddress(RegIndex, Channel);
 | 
						|
 | 
						|
      if (MI.getOperand(1).getReg() == AMDGPU::INDIRECT_BASE_ADDR) {
 | 
						|
        // Direct register access
 | 
						|
        unsigned Reg = LiveAddressRegisterMap[Address];
 | 
						|
        unsigned AddrReg = IndirectLoadRegClass->getRegister(Address);
 | 
						|
 | 
						|
        if (regHasExplicitDef(MRI, Reg)) {
 | 
						|
          // If the register we are reading from has an explicit def, then that
 | 
						|
          // means it was written via a direct register access (i.e. COPY
 | 
						|
          // or other instruction that doesn't use indirect addressing).  In
 | 
						|
          // this case we know where the value has been stored, so we can just
 | 
						|
          // issue a copy.
 | 
						|
          BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(AMDGPU::COPY),
 | 
						|
                  MI.getOperand(0).getReg())
 | 
						|
                  .addReg(Reg);
 | 
						|
        } else {
 | 
						|
          // If the register we are reading has an implicit def, then that
 | 
						|
          // means it was written by an indirect register access (i.e. An
 | 
						|
          // instruction that uses indirect addressing. 
 | 
						|
          BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(AMDGPU::COPY),
 | 
						|
                   MI.getOperand(0).getReg())
 | 
						|
                   .addReg(AddrReg)
 | 
						|
                   .addReg(Reg, RegState::Implicit);
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        // Indirect register access
 | 
						|
 | 
						|
        // Note on REQ_SEQUENCE instructons: You can't actually use the register
 | 
						|
        // it defines unless  you have an instruction that takes the defined
 | 
						|
        // register class as an operand.
 | 
						|
 | 
						|
        MachineInstrBuilder Sequence = BuildMI(MBB, I, MBB.findDebugLoc(I),
 | 
						|
                                               TII->get(AMDGPU::REG_SEQUENCE),
 | 
						|
                                               IndirectReg);
 | 
						|
        for (int i = IndirectBegin; i <= IndirectEnd; ++i) {
 | 
						|
          unsigned Addr = TII->calculateIndirectAddress(i, Channel);
 | 
						|
          if (LiveAddressRegisterMap.find(Addr) == LiveAddressRegisterMap.end()) {
 | 
						|
            continue;
 | 
						|
          }
 | 
						|
          unsigned Reg = LiveAddressRegisterMap[Addr];
 | 
						|
 | 
						|
          // We only need to use REG_SEQUENCE for explicit defs, since the
 | 
						|
          // register coalescer won't do anything with the implicit defs.
 | 
						|
          MachineInstr *DefInstr = MRI.getVRegDef(Reg);
 | 
						|
          if (!regHasExplicitDef(MRI, Reg)) {
 | 
						|
            continue;
 | 
						|
          }
 | 
						|
 | 
						|
          // Insert a REQ_SEQUENCE instruction to force the register allocator
 | 
						|
          // to allocate the virtual register to the correct physical register.
 | 
						|
          Sequence.addReg(LiveAddressRegisterMap[Addr]);
 | 
						|
          Sequence.addImm(TII->getRegisterInfo().getIndirectSubReg(Addr));
 | 
						|
        }
 | 
						|
        MachineInstrBuilder Mov = TII->buildIndirectRead(BB, I,
 | 
						|
                                           MI.getOperand(0).getReg(), // Value
 | 
						|
                                           Address,
 | 
						|
                                           MI.getOperand(1).getReg()); // Offset
 | 
						|
 | 
						|
 | 
						|
 | 
						|
        Mov.addReg(IndirectReg, RegState::Implicit | RegState::Kill);
 | 
						|
        Mov.addReg(LiveAddressRegisterMap[Address], RegState::Implicit);
 | 
						|
 | 
						|
      }
 | 
						|
      MI.eraseFromParent();
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
bool AMDGPUIndirectAddressingPass::regHasExplicitDef(MachineRegisterInfo &MRI,
 | 
						|
                                                  unsigned Reg) const {
 | 
						|
  MachineInstr *DefInstr = MRI.getVRegDef(Reg);
 | 
						|
 | 
						|
  if (!DefInstr) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (DefInstr->getOpcode() == AMDGPU::PHI) {
 | 
						|
    bool Explicit = false;
 | 
						|
    for (MachineInstr::const_mop_iterator I = DefInstr->operands_begin(),
 | 
						|
                                          E = DefInstr->operands_end();
 | 
						|
                                          I != E; ++I) {
 | 
						|
      const MachineOperand &MO = *I;
 | 
						|
      if (!MO.isReg() || MO.isDef()) {
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      Explicit = Explicit || regHasExplicitDef(MRI, MO.getReg());
 | 
						|
    }
 | 
						|
    return Explicit;
 | 
						|
  }
 | 
						|
 | 
						|
  return DefInstr->getOperand(0).isReg() &&
 | 
						|
         DefInstr->getOperand(0).getReg() == Reg;
 | 
						|
}
 |