GlobalISel: Handle llvm.read_register

Compared to the attempt in bdcc6d3d26,
this uses intermediate generic instructions.
This commit is contained in:
Matt Arsenault 2019-12-27 19:26:51 -05:00 committed by Matt Arsenault
parent f33f3d98e9
commit 0ea3c7291f
7 changed files with 59 additions and 2 deletions

View File

@ -240,6 +240,7 @@ public:
LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI); LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI);
LegalizeResult lowerBswap(MachineInstr &MI); LegalizeResult lowerBswap(MachineInstr &MI);
LegalizeResult lowerBitreverse(MachineInstr &MI); LegalizeResult lowerBitreverse(MachineInstr &MI);
LegalizeResult lowerReadRegister(MachineInstr &MI);
private: private:
MachineRegisterInfo &MRI; MachineRegisterInfo &MRI;

View File

@ -614,12 +614,16 @@ HANDLE_TARGET_OPCODE(G_JUMP_TABLE)
/// Generic dynamic stack allocation. /// Generic dynamic stack allocation.
HANDLE_TARGET_OPCODE(G_DYN_STACKALLOC) HANDLE_TARGET_OPCODE(G_DYN_STACKALLOC)
// TODO: Add more generic opcodes as we move along. /// read_register intrinsic
HANDLE_TARGET_OPCODE(G_READ_REGISTER)
/// write_register intrinsic
HANDLE_TARGET_OPCODE(G_WRITE_REGISTER)
/// Marker for the end of the generic opcode. /// Marker for the end of the generic opcode.
/// This is used to check if an opcode is in the range of the /// This is used to check if an opcode is in the range of the
/// generic opcodes. /// generic opcodes.
HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_DYN_STACKALLOC) HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_WRITE_REGISTER)
/// BUILTIN_OP_END - This must be the last enum value in this list. /// BUILTIN_OP_END - This must be the last enum value in this list.
/// The target-specific post-isel opcode values start here. /// The target-specific post-isel opcode values start here.

View File

@ -1012,6 +1012,26 @@ def G_BRJT : GenericInstruction {
let isTerminator = 1; let isTerminator = 1;
} }
def G_READ_REGISTER : GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins unknown:$register);
let hasSideEffects = 1;
// Assume convergent. It's probably not worth the effort of somehow
// modeling convergent and nonconvergent register accesses.
let isConvergent = 1;
}
def G_WRITE_REGISTER : GenericInstruction {
let OutOperandList = (outs);
let InOperandList = (ins unknown:$register, type0:$value);
let hasSideEffects = 1;
// Assume convergent. It's probably not worth the effort of somehow
// modeling convergent and nonconvergent register accesses.
let isConvergent = 1;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Vector ops // Vector ops
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------

View File

@ -1526,6 +1526,13 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
case Intrinsic::sideeffect: case Intrinsic::sideeffect:
// Discard annotate attributes, assumptions, and artificial side-effects. // Discard annotate attributes, assumptions, and artificial side-effects.
return true; return true;
case Intrinsic::read_register: {
Value *Arg = CI.getArgOperand(0);
MIRBuilder.buildInstr(TargetOpcode::G_READ_REGISTER)
.addDef(getOrCreateVReg(CI))
.addMetadata(cast<MDNode>(cast<MetadataAsValue>(Arg)->getMetadata()));
return true;
}
} }
return false; return false;
} }

View File

@ -2317,6 +2317,8 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT Ty) {
return lowerBswap(MI); return lowerBswap(MI);
case G_BITREVERSE: case G_BITREVERSE:
return lowerBitreverse(MI); return lowerBitreverse(MI);
case G_READ_REGISTER:
return lowerReadRegister(MI);
} }
} }
@ -4469,3 +4471,22 @@ LegalizerHelper::lowerBitreverse(MachineInstr &MI) {
MI.eraseFromParent(); MI.eraseFromParent();
return Legalized; return Legalized;
} }
LegalizerHelper::LegalizeResult
LegalizerHelper::lowerReadRegister(MachineInstr &MI) {
Register Dst = MI.getOperand(0).getReg();
const LLT Ty = MRI.getType(Dst);
const MDString *RegStr = cast<MDString>(
cast<MDNode>(MI.getOperand(1).getMetadata())->getOperand(0));
MachineFunction &MF = MIRBuilder.getMF();
const TargetSubtargetInfo &STI = MF.getSubtarget();
const TargetLowering *TLI = STI.getTargetLowering();
Register Reg = TLI->getRegisterByName(RegStr->getString().data(), Ty, MF);
if (!Reg.isValid())
return UnableToLegalize;
MIRBuilder.buildCopy(Dst, Reg);
MI.eraseFromParent();
return Legalized;
}

View File

@ -1116,6 +1116,8 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_,
getActionDefinitionsBuilder(G_SEXT_INREG).lower(); getActionDefinitionsBuilder(G_SEXT_INREG).lower();
getActionDefinitionsBuilder({G_READ_REGISTER, G_WRITE_REGISTER}).lower();
getActionDefinitionsBuilder(G_READCYCLECOUNTER) getActionDefinitionsBuilder(G_READCYCLECOUNTER)
.legalFor({S64}); .legalFor({S64});

View File

@ -0,0 +1,2 @@
; Runs original SDAG test with -global-isel
; RUN: llc -global-isel -mtriple=amdgcn-amd-amdhsa -mcpu=bonaire -verify-machineinstrs < %S/../read_register.ll | FileCheck -enable-var-scope %S/../read_register.ll