[GlobalISel] Add a G_BLOCK_ADDR opcode to handle IR blockaddress constants.

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

llvm-svn: 338335
This commit is contained in:
Amara Emerson 2018-07-31 00:08:50 +00:00
parent cae1b9fef2
commit 6aff5a7810
6 changed files with 44 additions and 1 deletions

View File

@ -942,6 +942,16 @@ public:
/// \return a MachineInstrBuilder for the newly created instruction.
MachineInstrBuilder buildAtomicRMWUmin(unsigned OldValRes, unsigned Addr,
unsigned Val, MachineMemOperand &MMO);
/// Build and insert \p Res = G_BLOCK_ADDR \p BA
///
/// G_BLOCK_ADDR computes the address of a basic block.
///
/// \pre setBasicBlock or setMI must have been called.
/// \pre \p Res must be a generic virtual register of a pointer type.
///
/// \return The newly created instruction.
MachineInstrBuilder buildBlockAddress(unsigned Res, const BlockAddress *BA);
};
/// A CRTP class that contains methods for building instructions that can

View File

@ -470,12 +470,15 @@ HANDLE_TARGET_OPCODE(G_BSWAP)
/// Generic AddressSpaceCast.
HANDLE_TARGET_OPCODE(G_ADDRSPACE_CAST)
/// Generic block address
HANDLE_TARGET_OPCODE(G_BLOCK_ADDR)
// TODO: Add more generic opcodes as we move along.
/// Marker for the end of the generic opcode.
/// This is used to check if an opcode is in the range of the
/// generic opcodes.
HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_ADDRSPACE_CAST)
HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_BLOCK_ADDR)
/// BUILTIN_OP_END - This must be the last enum value in this list.
/// The target-specific post-isel opcode values start here.

View File

@ -131,6 +131,13 @@ def G_ADDRSPACE_CAST : GenericInstruction {
let InOperandList = (ins type1:$src);
let hasSideEffects = 0;
}
def G_BLOCK_ADDR : GenericInstruction {
let OutOperandList = (outs type0:$dst);
let InOperandList = (ins unknown:$ba);
let hasSideEffects = 0;
}
//------------------------------------------------------------------------------
// Binary ops.
//------------------------------------------------------------------------------

View File

@ -1503,6 +1503,8 @@ bool IRTranslator::translate(const Constant &C, unsigned Reg) {
Ops.push_back(getOrCreateVReg(*CV->getOperand(i)));
}
EntryBuilder.buildMerge(Reg, Ops);
} else if (auto *BA = dyn_cast<BlockAddress>(&C)) {
EntryBuilder.buildBlockAddress(Reg, BA);
} else
return false;

View File

@ -809,6 +809,15 @@ MachineIRBuilderBase::buildAtomicRMWUmin(unsigned OldValRes, unsigned Addr,
MMO);
}
MachineInstrBuilder
MachineIRBuilderBase::buildBlockAddress(unsigned Res, const BlockAddress *BA) {
#ifndef NDEBUG
assert(getMRI()->getType(Res).isPointer() && "invalid res type");
#endif
return buildInstr(TargetOpcode::G_BLOCK_ADDR).addDef(Res).addBlockAddress(BA);
}
void MachineIRBuilderBase::validateTruncExt(unsigned Dst, unsigned Src,
bool IsExtend) {
#ifndef NDEBUG

View File

@ -2147,3 +2147,15 @@ define i32 @test_atomicrmw_umax(i256* %addr) {
%oldval.trunc = trunc i256 %oldval to i32
ret i32 %oldval.trunc
}
@addr = global i8* null
define void @test_blockaddress() {
; CHECK-LABEL: name: test_blockaddress
; CHECK: [[BADDR:%[0-9]+]]:_(p0) = G_BLOCK_ADDR blockaddress(@test_blockaddress, %ir-block.block)
; CHECK: G_STORE [[BADDR]](p0)
store i8* blockaddress(@test_blockaddress, %block), i8** @addr
indirectbr i8* blockaddress(@test_blockaddress, %block), [label %block]
block:
ret void
}