Skip to content

Commit

Permalink
[AMDGPU] Divergence driven ISel. Assign register class for cross blo…
Browse files Browse the repository at this point in the history
…ck values according to the divergence.

    Details: To make instruction selection really divergence driven it is necessary to assign
             the correct register classes to the cross block values beforehand. For the divergent targets
             same value type requires different register classes dependent on the value divergence.

    Reviewers: rampitec, nhaehnle

    Differential Revision: https://reviews.llvm.org/D59990

    This commit was reverted because of the build failure.
    The reason was mlformed patch.
    Build failure fixed.

llvm-svn: 361741
  • Loading branch information
alex-t committed May 26, 2019
1 parent c2493ce commit ba447ba
Show file tree
Hide file tree
Showing 49 changed files with 413 additions and 303 deletions.
11 changes: 7 additions & 4 deletions llvm/include/llvm/CodeGen/FunctionLoweringInfo.h
Expand Up @@ -13,14 +13,14 @@

#ifndef LLVM_CODEGEN_FUNCTIONLOWERINGINFO_H
#define LLVM_CODEGEN_FUNCTIONLOWERINGINFO_H

#include "llvm/ADT/APInt.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/LegacyDivergenceAnalysis.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
Expand Down Expand Up @@ -57,6 +57,7 @@ class FunctionLoweringInfo {
const TargetLowering *TLI;
MachineRegisterInfo *RegInfo;
BranchProbabilityInfo *BPI;
const LegacyDivergenceAnalysis *DA;
/// CanLowerReturn - true iff the function's return value can be lowered to
/// registers.
bool CanLowerReturn;
Expand Down Expand Up @@ -198,9 +199,11 @@ class FunctionLoweringInfo {
return ValueMap.count(V);
}

unsigned CreateReg(MVT VT);
unsigned CreateReg(MVT VT, bool isDivergent = false);

unsigned CreateRegs(const Value *V);

unsigned CreateRegs(Type *Ty);
unsigned CreateRegs(Type *Ty, bool isDivergent = false);

unsigned InitializeRegForValue(const Value *V) {
// Tokens never live in vregs.
Expand All @@ -209,7 +212,7 @@ class FunctionLoweringInfo {
unsigned &R = ValueMap[V];
assert(R == 0 && "Already initialized this value register!");
assert(VirtReg2Value.empty());
return R = CreateRegs(V->getType());
return R = CreateRegs(V);
}

/// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/CodeGen/SelectionDAG.h
Expand Up @@ -406,6 +406,7 @@ class SelectionDAG {
const TargetLowering &getTargetLoweringInfo() const { return *TLI; }
const TargetLibraryInfo &getLibInfo() const { return *LibInfo; }
const SelectionDAGTargetInfo &getSelectionDAGInfo() const { return *TSI; }
const LegacyDivergenceAnalysis *getDivergenceAnalysis() const { return DA; }
LLVMContext *getContext() const {return Context; }
OptimizationRemarkEmitter &getORE() const { return *ORE; }

Expand Down
11 changes: 10 additions & 1 deletion llvm/include/llvm/CodeGen/TargetLowering.h
Expand Up @@ -636,12 +636,21 @@ class TargetLoweringBase {

/// Return the register class that should be used for the specified value
/// type.
virtual const TargetRegisterClass *getRegClassFor(MVT VT) const {
virtual const TargetRegisterClass *getRegClassFor(MVT VT, bool isDivergent = false) const {
(void)isDivergent;
const TargetRegisterClass *RC = RegClassForVT[VT.SimpleTy];
assert(RC && "This value type is not natively supported!");
return RC;
}

/// Allows target to decide about the register class of the
/// specific value that is live outside the defining block.
/// Returns true if the value needs uniform register class.
virtual bool requiresUniformRegister(MachineFunction &MF,
const Value *) const {
return false;
}

/// Return the 'representative' register class for the specified value
/// type.
///
Expand Down
5 changes: 5 additions & 0 deletions llvm/include/llvm/CodeGen/TargetRegisterInfo.h
Expand Up @@ -520,6 +520,11 @@ class TargetRegisterInfo : public MCRegisterInfo {
/// function. Used by MachineRegisterInfo::isConstantPhysReg().
virtual bool isConstantPhysReg(unsigned PhysReg) const { return false; }

/// Returns true if the register class is considered divergent.
virtual bool isDivergentRegClass(const TargetRegisterClass *RC) const {
return false;
}

/// Physical registers that may be modified within a function but are
/// guaranteed to be restored before any uses. This is useful for targets that
/// have call sequences where a GOT register may be updated by the caller
Expand Down
6 changes: 4 additions & 2 deletions llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Expand Up @@ -13919,9 +13919,11 @@ struct LoadedSlice {
assert(DAG && "Missing context");
const TargetLowering &TLI = DAG->getTargetLoweringInfo();
EVT ResVT = Use->getValueType(0);
const TargetRegisterClass *ResRC = TLI.getRegClassFor(ResVT.getSimpleVT());
const TargetRegisterClass *ResRC =
TLI.getRegClassFor(ResVT.getSimpleVT(), Use->isDivergent());
const TargetRegisterClass *ArgRC =
TLI.getRegClassFor(Use->getOperand(0).getValueType().getSimpleVT());
TLI.getRegClassFor(Use->getOperand(0).getValueType().getSimpleVT(),
Use->getOperand(0)->isDivergent());
if (ArgRC == ResRC || !TLI.isOperationLegal(ISD::LOAD, ResVT))
return false;

Expand Down
14 changes: 10 additions & 4 deletions llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
Expand Up @@ -85,6 +85,7 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
RegInfo = &MF->getRegInfo();
const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering();
unsigned StackAlign = TFI->getStackAlignment();
DA = DAG->getDivergenceAnalysis();

// Check whether the function can return without sret-demotion.
SmallVector<ISD::OutputArg, 4> Outs;
Expand Down Expand Up @@ -345,9 +346,9 @@ void FunctionLoweringInfo::clear() {
}

/// CreateReg - Allocate a single virtual register for the given type.
unsigned FunctionLoweringInfo::CreateReg(MVT VT) {
unsigned FunctionLoweringInfo::CreateReg(MVT VT, bool isDivergent) {
return RegInfo->createVirtualRegister(
MF->getSubtarget().getTargetLowering()->getRegClassFor(VT));
MF->getSubtarget().getTargetLowering()->getRegClassFor(VT, isDivergent));
}

/// CreateRegs - Allocate the appropriate number of virtual registers of
Expand All @@ -357,7 +358,7 @@ unsigned FunctionLoweringInfo::CreateReg(MVT VT) {
/// In the case that the given value has struct or array type, this function
/// will assign registers for each member or element.
///
unsigned FunctionLoweringInfo::CreateRegs(Type *Ty) {
unsigned FunctionLoweringInfo::CreateRegs(Type *Ty, bool isDivergent) {
const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();

SmallVector<EVT, 4> ValueVTs;
Expand All @@ -370,13 +371,18 @@ unsigned FunctionLoweringInfo::CreateRegs(Type *Ty) {

unsigned NumRegs = TLI->getNumRegisters(Ty->getContext(), ValueVT);
for (unsigned i = 0; i != NumRegs; ++i) {
unsigned R = CreateReg(RegisterVT);
unsigned R = CreateReg(RegisterVT, isDivergent);
if (!FirstReg) FirstReg = R;
}
}
return FirstReg;
}

unsigned FunctionLoweringInfo::CreateRegs(const Value *V) {
return CreateRegs(V->getType(), DA && !TLI->requiresUniformRegister(*MF, V) &&
DA->isDivergent(V));
}

/// GetLiveOutRegInfo - Gets LiveOutInfo for a register, returning NULL if the
/// register is a PHI destination and the PHI's LiveOutInfo is not valid. If
/// the register's LiveOutInfo is for a smaller bit width, it is extended to
Expand Down
33 changes: 19 additions & 14 deletions llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp
Expand Up @@ -105,7 +105,7 @@ EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone, bool IsCloned,

// Stick to the preferred register classes for legal types.
if (TLI->isTypeLegal(VT))
UseRC = TLI->getRegClassFor(VT);
UseRC = TLI->getRegClassFor(VT, Node->isDivergent());

if (!IsClone && !IsCloned)
for (SDNode *User : Node->uses()) {
Expand Down Expand Up @@ -164,7 +164,7 @@ EmitCopyFromReg(SDNode *Node, unsigned ResNo, bool IsClone, bool IsCloned,
"Incompatible phys register def and uses!");
DstRC = UseRC;
} else {
DstRC = TLI->getRegClassFor(VT);
DstRC = TLI->getRegClassFor(VT, Node->isDivergent());
}

// If all uses are reading from the src physical register and copying the
Expand Down Expand Up @@ -225,8 +225,9 @@ void InstrEmitter::CreateVirtualRegisters(SDNode *Node,
// type correctly. For example, a 64-bit float (X86::FR64) can't live in
// the 32-bit float super-class (X86::FR32).
if (i < NumResults && TLI->isTypeLegal(Node->getSimpleValueType(i))) {
const TargetRegisterClass *VTRC =
TLI->getRegClassFor(Node->getSimpleValueType(i));
const TargetRegisterClass *VTRC = TLI->getRegClassFor(
Node->getSimpleValueType(i),
(Node->isDivergent() || (RC && TRI->isDivergentRegClass(RC))));
if (RC)
VTRC = TRI->getCommonSubClass(RC, VTRC);
if (VTRC)
Expand Down Expand Up @@ -289,8 +290,8 @@ unsigned InstrEmitter::getVR(SDValue Op,
// IMPLICIT_DEF can produce any type of result so its MCInstrDesc
// does not include operand register class info.
if (!VReg) {
const TargetRegisterClass *RC =
TLI->getRegClassFor(Op.getSimpleValueType());
const TargetRegisterClass *RC = TLI->getRegClassFor(
Op.getSimpleValueType(), Op.getNode()->isDivergent());
VReg = MRI->createVirtualRegister(RC);
}
BuildMI(*MBB, InsertPos, Op.getDebugLoc(),
Expand Down Expand Up @@ -395,11 +396,15 @@ void InstrEmitter::AddOperand(MachineInstrBuilder &MIB,
} else if (RegisterSDNode *R = dyn_cast<RegisterSDNode>(Op)) {
unsigned VReg = R->getReg();
MVT OpVT = Op.getSimpleValueType();
const TargetRegisterClass *OpRC =
TLI->isTypeLegal(OpVT) ? TLI->getRegClassFor(OpVT) : nullptr;
const TargetRegisterClass *IIRC =
II ? TRI->getAllocatableClass(TII->getRegClass(*II, IIOpNum, TRI, *MF))
: nullptr;
const TargetRegisterClass *OpRC =
TLI->isTypeLegal(OpVT)
? TLI->getRegClassFor(OpVT,
Op.getNode()->isDivergent() ||
(IIRC && TRI->isDivergentRegClass(IIRC)))
: nullptr;

if (OpRC && IIRC && OpRC != IIRC &&
TargetRegisterInfo::isVirtualRegister(VReg)) {
Expand Down Expand Up @@ -464,7 +469,7 @@ void InstrEmitter::AddOperand(MachineInstrBuilder &MIB,
}

unsigned InstrEmitter::ConstrainForSubReg(unsigned VReg, unsigned SubIdx,
MVT VT, const DebugLoc &DL) {
MVT VT, bool isDivergent, const DebugLoc &DL) {
const TargetRegisterClass *VRC = MRI->getRegClass(VReg);
const TargetRegisterClass *RC = TRI->getSubClassWithSubReg(VRC, SubIdx);

Expand All @@ -479,7 +484,7 @@ unsigned InstrEmitter::ConstrainForSubReg(unsigned VReg, unsigned SubIdx,

// VReg couldn't be reasonably constrained. Emit a COPY to a new virtual
// register instead.
RC = TRI->getSubClassWithSubReg(TLI->getRegClassFor(VT), SubIdx);
RC = TRI->getSubClassWithSubReg(TLI->getRegClassFor(VT, isDivergent), SubIdx);
assert(RC && "No legal register class for VT supports that SubIdx");
unsigned NewReg = MRI->createVirtualRegister(RC);
BuildMI(*MBB, InsertPos, DL, TII->get(TargetOpcode::COPY), NewReg)
Expand Down Expand Up @@ -514,7 +519,7 @@ void InstrEmitter::EmitSubregNode(SDNode *Node,
// classes.
unsigned SubIdx = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
const TargetRegisterClass *TRC =
TLI->getRegClassFor(Node->getSimpleValueType(0));
TLI->getRegClassFor(Node->getSimpleValueType(0), Node->isDivergent());

unsigned Reg;
MachineInstr *DefMI;
Expand Down Expand Up @@ -548,8 +553,7 @@ void InstrEmitter::EmitSubregNode(SDNode *Node,
if (TargetRegisterInfo::isVirtualRegister(Reg))
Reg = ConstrainForSubReg(Reg, SubIdx,
Node->getOperand(0).getSimpleValueType(),
Node->getDebugLoc());

Node->isDivergent(), Node->getDebugLoc());
// Create the destreg if it is missing.
if (VRBase == 0)
VRBase = MRI->createVirtualRegister(TRC);
Expand Down Expand Up @@ -584,7 +588,8 @@ void InstrEmitter::EmitSubregNode(SDNode *Node,
//
// There is no constraint on the %src register class.
//
const TargetRegisterClass *SRC = TLI->getRegClassFor(Node->getSimpleValueType(0));
const TargetRegisterClass *SRC =
TLI->getRegClassFor(Node->getSimpleValueType(0), Node->isDivergent());
SRC = TRI->getSubClassWithSubReg(SRC, SubIdx);
assert(SRC && "No register class supports VT and SubIdx for INSERT_SUBREG");

Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/SelectionDAG/InstrEmitter.h
Expand Up @@ -83,7 +83,7 @@ class LLVM_LIBRARY_VISIBILITY InstrEmitter {
/// supports SubIdx sub-registers. Emit a copy if that isn't possible.
/// Return the virtual register to use.
unsigned ConstrainForSubReg(unsigned VReg, unsigned SubIdx, MVT VT,
const DebugLoc &DL);
bool isDivergent, const DebugLoc &DL);

/// EmitSubregNode - Generate machine code for subreg nodes.
///
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Expand Up @@ -9844,7 +9844,7 @@ SelectionDAGBuilder::HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) {
if (const Constant *C = dyn_cast<Constant>(PHIOp)) {
unsigned &RegOut = ConstantsOut[C];
if (RegOut == 0) {
RegOut = FuncInfo.CreateRegs(C->getType());
RegOut = FuncInfo.CreateRegs(C);
CopyValueToVirtualRegister(C, RegOut);
}
Reg = RegOut;
Expand All @@ -9857,7 +9857,7 @@ SelectionDAGBuilder::HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB) {
assert(isa<AllocaInst>(PHIOp) &&
FuncInfo.StaticAllocaMap.count(cast<AllocaInst>(PHIOp)) &&
"Didn't codegen value into a register!??");
Reg = FuncInfo.CreateRegs(PHIOp->getType());
Reg = FuncInfo.CreateRegs(PHIOp);
CopyValueToVirtualRegister(PHIOp, Reg);
}
}
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
Expand Up @@ -1485,7 +1485,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
!Inst->use_empty()) {
unsigned &R = FuncInfo->ValueMap[Inst];
if (!R)
R = FuncInfo->CreateRegs(Inst->getType());
R = FuncInfo->CreateRegs(Inst);
}

bool HadTailCall = false;
Expand Down

0 comments on commit ba447ba

Please sign in to comment.