Index: include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h =================================================================== --- include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -942,6 +942,17 @@ /// \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. + /// \pre \p BA must be an IR block address value. + /// + /// \return The newly created instruction. + MachineInstrBuilder buildBlockAddress(unsigned Res, const BlockAddress *BA); }; /// A CRTP class that contains methods for building instructions that can Index: include/llvm/Support/TargetOpcodes.def =================================================================== --- include/llvm/Support/TargetOpcodes.def +++ include/llvm/Support/TargetOpcodes.def @@ -470,12 +470,15 @@ /// 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. Index: include/llvm/Target/GenericOpcodes.td =================================================================== --- include/llvm/Target/GenericOpcodes.td +++ include/llvm/Target/GenericOpcodes.td @@ -131,6 +131,13 @@ 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. //------------------------------------------------------------------------------ Index: lib/CodeGen/GlobalISel/IRTranslator.cpp =================================================================== --- lib/CodeGen/GlobalISel/IRTranslator.cpp +++ lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -1503,6 +1503,8 @@ Ops.push_back(getOrCreateVReg(*CV->getOperand(i))); } EntryBuilder.buildMerge(Reg, Ops); + } else if (auto *BA = dyn_cast(&C)) { + EntryBuilder.buildBlockAddress(Reg, BA); } else return false; Index: lib/CodeGen/GlobalISel/MachineIRBuilder.cpp =================================================================== --- lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -809,6 +809,15 @@ MMO); } +MachineInstrBuilder +MachineIRBuilderBase::buildBlockAddress(unsigned Res, const BlockAddress *BA) { +#ifndef NDEBUG + assert(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 Index: test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll =================================================================== --- test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll +++ test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -2147,3 +2147,15 @@ %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 +}