forked from OSchip/llvm-project
[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:
parent
cae1b9fef2
commit
6aff5a7810
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue