LLVM  6.0.0svn
Macros | Functions | Variables
SIFixSGPRCopies.cpp File Reference

Copies from VGPR to SGPR registers are illegal and the register coalescer will sometimes generate these illegal copies in situations like this: More...

#include "AMDGPU.h"
#include "AMDGPUSubtarget.h"
#include "SIInstrInfo.h"
#include "SIRegisterInfo.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Pass.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include <cassert>
#include <cstdint>
#include <iterator>
#include <list>
#include <map>
#include <tuple>
#include <utility>
Include dependency graph for SIFixSGPRCopies.cpp:

Go to the source code of this file.

Macros

#define DEBUG_TYPE   "si-fix-sgpr-copies"
 

Functions

 INITIALIZE_PASS_BEGIN (SIFixSGPRCopies, DEBUG_TYPE, "SI Fix SGPR copies", false, false) INITIALIZE_PASS_END(SIFixSGPRCopies
 
static bool hasVGPROperands (const MachineInstr &MI, const SIRegisterInfo *TRI)
 
static std::pair< const TargetRegisterClass *, const TargetRegisterClass * > getCopyRegClasses (const MachineInstr &Copy, const SIRegisterInfo &TRI, const MachineRegisterInfo &MRI)
 
static bool isVGPRToSGPRCopy (const TargetRegisterClass *SrcRC, const TargetRegisterClass *DstRC, const SIRegisterInfo &TRI)
 
static bool isSGPRToVGPRCopy (const TargetRegisterClass *SrcRC, const TargetRegisterClass *DstRC, const SIRegisterInfo &TRI)
 
static bool tryChangeVGPRtoSGPRinCopy (MachineInstr &MI, const SIRegisterInfo *TRI, const SIInstrInfo *TII)
 
static bool foldVGPRCopyIntoRegSequence (MachineInstr &MI, const SIRegisterInfo *TRI, const SIInstrInfo *TII, MachineRegisterInfo &MRI)
 
static bool phiHasVGPROperands (const MachineInstr &PHI, const MachineRegisterInfo &MRI, const SIRegisterInfo *TRI, const SIInstrInfo *TII)
 
static bool phiHasBreakDef (const MachineInstr &PHI, const MachineRegisterInfo &MRI, SmallSet< unsigned, 8 > &Visited)
 
static bool hasTerminatorThatModifiesExec (const MachineBasicBlock &MBB, const TargetRegisterInfo &TRI)
 
static bool isSafeToFoldImmIntoCopy (const MachineInstr *Copy, const MachineInstr *MoveImm, const SIInstrInfo *TII, unsigned &SMovOp, int64_t &Imm)
 
template<class UnaryPredicate >
bool searchPredecessors (const MachineBasicBlock *MBB, const MachineBasicBlock *CutOff, UnaryPredicate Predicate)
 
static bool predsHasDivergentTerminator (MachineBasicBlock *MBB, const TargetRegisterInfo *TRI)
 
static bool isReachable (const MachineInstr *From, const MachineInstr *To, const MachineBasicBlock *CutOff, MachineDominatorTree &MDT)
 
static bool hoistAndMergeSGPRInits (unsigned Reg, const MachineRegisterInfo &MRI, MachineDominatorTree &MDT)
 

Variables

static cl::opt< boolEnableM0Merge ("amdgpu-enable-merge-m0", cl::desc("Merge and hoist M0 initializations"), cl::init(false))
 
 DEBUG_TYPE
 
SI Fix SGPR copies
 
SI Fix SGPR false
 

Detailed Description

Copies from VGPR to SGPR registers are illegal and the register coalescer will sometimes generate these illegal copies in situations like this:

Register Class <vsrc> is the union of <vgpr> and <sgpr>

BB0: vreg0 <sgpr> = SCALAR_INST vreg1 <vsrc> = COPY vreg0 <sgpr> ... BRANCH cond BB1, BB2 BB1: vreg2 <vgpr> = VECTOR_INST vreg3 <vsrc> = COPY vreg2 <vgpr> BB2: vreg4 <vsrc> = PHI vreg1 <vsrc>, <BB#0>, vreg3 <vrsc>, <BB#1> vreg5 <vgpr> = VECTOR_INST vreg4 <vsrc>

The coalescer will begin at BB0 and eliminate its copy, then the resulting code will look like this:

BB0: vreg0 <sgpr> = SCALAR_INST ... BRANCH cond BB1, BB2 BB1: vreg2 <vgpr> = VECTOR_INST vreg3 <vsrc> = COPY vreg2 <vgpr> BB2: vreg4 <sgpr> = PHI vreg0 <sgpr>, <BB#0>, vreg3 <vsrc>, <BB#1> vreg5 <vgpr> = VECTOR_INST vreg4 <sgpr>

Now that the result of the PHI instruction is an SGPR, the register allocator is now forced to constrain the register class of vreg3 to <sgpr> so we end up with final code like this:

BB0: vreg0 <sgpr> = SCALAR_INST ... BRANCH cond BB1, BB2 BB1: vreg2 <vgpr> = VECTOR_INST vreg3 <sgpr> = COPY vreg2 <vgpr> BB2: vreg4 <sgpr> = PHI vreg0 <sgpr>, <BB#0>, vreg3 <sgpr>, <BB#1> vreg5 <vgpr> = VECTOR_INST vreg4 <sgpr>

Now this code contains an illegal copy from a VGPR to an SGPR.

In order to avoid this problem, this pass searches for PHI instructions which define a <vsrc> register and constrains its definition class to <vgpr> if the user of the PHI's definition register is a vector instruction. If the PHI's definition class is constrained to <vgpr> then the coalescer will be unable to perform the COPY removal from the above example which ultimately led to the creation of an illegal COPY.

Definition in file SIFixSGPRCopies.cpp.

Macro Definition Documentation

◆ DEBUG_TYPE

#define DEBUG_TYPE   "si-fix-sgpr-copies"

Definition at line 101 of file SIFixSGPRCopies.cpp.

Function Documentation

◆ foldVGPRCopyIntoRegSequence()

static bool foldVGPRCopyIntoRegSequence ( MachineInstr MI,
const SIRegisterInfo TRI,
const SIInstrInfo TII,
MachineRegisterInfo MRI 
)
static

◆ getCopyRegClasses()

static std::pair<const TargetRegisterClass *, const TargetRegisterClass *> getCopyRegClasses ( const MachineInstr Copy,
const SIRegisterInfo TRI,
const MachineRegisterInfo MRI 
)
static

◆ hasTerminatorThatModifiesExec()

static bool hasTerminatorThatModifiesExec ( const MachineBasicBlock MBB,
const TargetRegisterInfo TRI 
)
static

◆ hasVGPROperands()

static bool hasVGPROperands ( const MachineInstr MI,
const SIRegisterInfo TRI 
)
static

◆ hoistAndMergeSGPRInits()

static bool hoistAndMergeSGPRInits ( unsigned  Reg,
const MachineRegisterInfo MRI,
MachineDominatorTree MDT 
)
static

Definition at line 446 of file SIFixSGPRCopies.cpp.

References llvm::MachineInstr::addImplicitDefUseOperands(), llvm::any_of(), assert(), llvm::MachineBasicBlock::begin(), llvm::MachineFunction::begin(), C, llvm::MachineOperand::ChangeToImmediate(), llvm::MachineRegisterInfo::clearKillFlags(), llvm::dbgs(), DEBUG, llvm::MachineRegisterInfo::def_instructions(), DefMI, llvm::MachineDominatorTree::dominates(), E, EnableM0Merge, llvm::MachineBasicBlock::end(), llvm::MachineFunction::end(), llvm::MachineInstr::eraseFromParent(), llvm::MachineDominatorTree::findNearestCommonDominator(), foldVGPRCopyIntoRegSequence(), getCopyRegClasses(), llvm::MachineOperand::getImm(), llvm::SISubtarget::getInstrInfo(), llvm::MachineOperand::getMBB(), llvm::MachineBasicBlock::getNumber(), llvm::MachineInstr::getNumExplicitOperands(), llvm::MachineInstr::getOpcode(), llvm::MachineInstr::getOperand(), llvm::SIInstrInfo::getOpRegClass(), llvm::TargetMachine::getOptLevel(), llvm::MachineInstr::getParent(), llvm::MachineBasicBlock::getParent(), llvm::MachineOperand::getReg(), llvm::MachineFunction::getRegInfo(), llvm::SISubtarget::getRegisterInfo(), llvm::MachineFunction::getSubtarget(), llvm::MachineFunction::getTarget(), hasVGPROperands(), llvm::SIRegisterInfo::hasVGPRs(), I, isReachable(), isSafeToFoldImmIntoCopy(), llvm::SIRegisterInfo::isSGPRClass(), isSGPRToVGPRCopy(), isVGPRToSGPRCopy(), llvm::TargetRegisterInfo::isVirtualRegister(), MI, llvm::SIInstrInfo::moveToVALU(), MRI, llvm::CodeGenOpt::None, phiHasBreakDef(), phiHasVGPROperands(), predsHasDivergentTerminator(), llvm::MachineDominatorTree::properlyDominates(), llvm::SmallVectorTemplateBase< T, isPodLike< T >::value >::push_back(), llvm::MachineInstr::setDesc(), llvm::ARM_MB::ST, TII, tryChangeVGPRtoSGPRinCopy(), and llvm::SIInstrFlags::WQM.

◆ INITIALIZE_PASS_BEGIN()

INITIALIZE_PASS_BEGIN ( SIFixSGPRCopies  ,
DEBUG_TYPE  ,
"SI Fix SGPR copies ,
false  ,
false   
)

◆ isReachable()

static bool isReachable ( const MachineInstr From,
const MachineInstr To,
const MachineBasicBlock CutOff,
MachineDominatorTree MDT 
)
static

◆ isSafeToFoldImmIntoCopy()

static bool isSafeToFoldImmIntoCopy ( const MachineInstr Copy,
const MachineInstr MoveImm,
const SIInstrInfo TII,
unsigned SMovOp,
int64_t &  Imm 
)
static

◆ isSGPRToVGPRCopy()

static bool isSGPRToVGPRCopy ( const TargetRegisterClass SrcRC,
const TargetRegisterClass DstRC,
const SIRegisterInfo TRI 
)
static

◆ isVGPRToSGPRCopy()

static bool isVGPRToSGPRCopy ( const TargetRegisterClass SrcRC,
const TargetRegisterClass DstRC,
const SIRegisterInfo TRI 
)
static

◆ phiHasBreakDef()

static bool phiHasBreakDef ( const MachineInstr PHI,
const MachineRegisterInfo MRI,
SmallSet< unsigned, 8 > &  Visited 
)
static

◆ phiHasVGPROperands()

static bool phiHasVGPROperands ( const MachineInstr PHI,
const MachineRegisterInfo MRI,
const SIRegisterInfo TRI,
const SIInstrInfo TII 
)
static

◆ predsHasDivergentTerminator()

static bool predsHasDivergentTerminator ( MachineBasicBlock MBB,
const TargetRegisterInfo TRI 
)
static

Definition at line 412 of file SIFixSGPRCopies.cpp.

References hasTerminatorThatModifiesExec(), and searchPredecessors().

Referenced by hoistAndMergeSGPRInits().

◆ searchPredecessors()

template<class UnaryPredicate >
bool searchPredecessors ( const MachineBasicBlock MBB,
const MachineBasicBlock CutOff,
UnaryPredicate  Predicate 
)

◆ tryChangeVGPRtoSGPRinCopy()

static bool tryChangeVGPRtoSGPRinCopy ( MachineInstr MI,
const SIRegisterInfo TRI,
const SIInstrInfo TII 
)
static

Variable Documentation

◆ copies

SI Fix SGPR copies

Definition at line 135 of file SIFixSGPRCopies.cpp.

◆ DEBUG_TYPE

DEBUG_TYPE

Definition at line 135 of file SIFixSGPRCopies.cpp.

◆ EnableM0Merge

cl::opt<bool> EnableM0Merge("amdgpu-enable-merge-m0", cl::desc("Merge and hoist M0 initializations"), cl::init(false))
static

Referenced by hoistAndMergeSGPRInits().

◆ false

SI Fix SGPR false

Definition at line 135 of file SIFixSGPRCopies.cpp.