diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp --- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp +++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp @@ -443,7 +443,7 @@ if (&BB == &F.getEntryBlock() || DTU->isBBPendingDeletion(&BB)) continue; - if (pred_empty(&BB)) { + if (pred_empty(&BB) && !BB.hasAddressTaken()) { // When processBlock makes BB unreachable it doesn't bother to fix up // the instructions in it. We must remove BB to prevent invalid IR. LLVM_DEBUG(dbgs() << " JT: Deleting dead block '" << BB.getName() diff --git a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp --- a/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -97,9 +97,12 @@ // Make sure that all predecessors of each dead block is also dead. SmallPtrSet Dead(BBs.begin(), BBs.end()); assert(Dead.size() == BBs.size() && "Duplicating blocks?"); - for (auto *BB : Dead) + for (auto *BB : Dead) { + assert(!BB->hasAddressTaken() && + "Can not delete blocks with their addresses taken."); for (BasicBlock *Pred : predecessors(BB)) assert(Dead.count(Pred) && "All predecessors must be dead!"); + } #endif SmallVector Updates; @@ -124,11 +127,24 @@ (void)BB/* Mark all reachable blocks */; // Collect all dead blocks. - std::vector DeadBlocks; + std::vector DeadBlocks; for (BasicBlock &BB : F) - if (!Reachable.count(&BB)) + if (!Reachable.count(&BB)) { DeadBlocks.push_back(&BB); + if (!BB.hasAddressTaken()) + continue; + + // Taking an address of a block does not make the block live, + // but we also don't like to delete blocks with their addresses taken. + // So, make it so that the address is no longer taken. + for (User *U : make_early_inc_range(BB.users())) + if (auto *C = dyn_cast(U)) { + C->replaceAllUsesWith(UndefValue::get(U->getType())); + C->destroyConstant(); + } + } + // Delete the dead blocks. DeleteDeadBlocks(DeadBlocks, DTU, KeepOneInputPHIs); diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp --- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -6713,8 +6713,9 @@ // Remove basic blocks that have no predecessors (except the entry block)... // or that just have themself as a predecessor. These are unreachable. - if ((pred_empty(BB) && BB != &BB->getParent()->getEntryBlock()) || - BB->getSinglePredecessor() == BB) { + if (((pred_empty(BB) && BB != &BB->getParent()->getEntryBlock()) || + BB->getSinglePredecessor() == BB) && + !BB->hasAddressTaken()) { LLVM_DEBUG(dbgs() << "Removing BB: \n" << *BB); DeleteDeadBlock(BB, DTU); return true; diff --git a/llvm/test/CodeGen/RISCV/codemodel-lowering.ll b/llvm/test/CodeGen/RISCV/codemodel-lowering.ll --- a/llvm/test/CodeGen/RISCV/codemodel-lowering.ll +++ b/llvm/test/CodeGen/RISCV/codemodel-lowering.ll @@ -31,25 +31,35 @@ define void @lower_blockaddress() nounwind { ; RV32I-SMALL-LABEL: lower_blockaddress: -; RV32I-SMALL: # %bb.0: +; RV32I-SMALL: # %bb.0: # %entry +; RV32I-SMALL-NEXT: .Ltmp0: # Block address taken +; RV32I-SMALL-NEXT: # %bb.1: # %end ; RV32I-SMALL-NEXT: lui a0, %hi(addr) -; RV32I-SMALL-NEXT: addi a1, zero, 1 +; RV32I-SMALL-NEXT: lui a1, %hi(.Ltmp0) +; RV32I-SMALL-NEXT: addi a1, a1, %lo(.Ltmp0) ; RV32I-SMALL-NEXT: sw a1, %lo(addr)(a0) ; RV32I-SMALL-NEXT: ret ; ; RV32I-MEDIUM-LABEL: lower_blockaddress: -; RV32I-MEDIUM: # %bb.0: -; RV32I-MEDIUM-NEXT: .LBB1_1: # Label of block must be emitted +; RV32I-MEDIUM: # %bb.0: # %entry +; RV32I-MEDIUM-NEXT: .Ltmp0: # Block address taken +; RV32I-MEDIUM-NEXT: # %bb.1: # %end +; RV32I-MEDIUM-NEXT: .LBB1_2: # %end +; RV32I-MEDIUM-NEXT: # Label of block must be emitted ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(addr) -; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.LBB1_1) -; RV32I-MEDIUM-NEXT: addi a1, zero, 1 +; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.LBB1_2) +; RV32I-MEDIUM-NEXT: .LBB1_3: # %end +; RV32I-MEDIUM-NEXT: # Label of block must be emitted +; RV32I-MEDIUM-NEXT: auipc a1, %pcrel_hi(.Ltmp0) +; RV32I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.LBB1_3) ; RV32I-MEDIUM-NEXT: sw a1, 0(a0) ; RV32I-MEDIUM-NEXT: ret - store volatile i8* blockaddress(@lower_blockaddress, %block), i8** @addr - ret void +entry: + br label %end -block: - unreachable +end: + store volatile i8* blockaddress(@lower_blockaddress, %end), i8** @addr + ret void } ; Check lowering of blockaddress that forces a displacement to be added @@ -58,15 +68,15 @@ ; RV32I-SMALL-LABEL: lower_blockaddress_displ: ; RV32I-SMALL: # %bb.0: # %entry ; RV32I-SMALL-NEXT: addi sp, sp, -16 -; RV32I-SMALL-NEXT: lui a1, %hi(.Ltmp0) -; RV32I-SMALL-NEXT: addi a1, a1, %lo(.Ltmp0) +; RV32I-SMALL-NEXT: lui a1, %hi(.Ltmp1) +; RV32I-SMALL-NEXT: addi a1, a1, %lo(.Ltmp1) ; RV32I-SMALL-NEXT: addi a2, zero, 101 ; RV32I-SMALL-NEXT: sw a1, 8(sp) ; RV32I-SMALL-NEXT: blt a0, a2, .LBB2_3 ; RV32I-SMALL-NEXT: # %bb.1: # %if.then ; RV32I-SMALL-NEXT: lw a0, 8(sp) ; RV32I-SMALL-NEXT: jr a0 -; RV32I-SMALL-NEXT: .Ltmp0: # Block address taken +; RV32I-SMALL-NEXT: .Ltmp1: # Block address taken ; RV32I-SMALL-NEXT: .LBB2_2: # %return ; RV32I-SMALL-NEXT: addi a0, zero, 4 ; RV32I-SMALL-NEXT: addi sp, sp, 16 @@ -81,7 +91,7 @@ ; RV32I-MEDIUM-NEXT: addi sp, sp, -16 ; RV32I-MEDIUM-NEXT: .LBB2_4: # %entry ; RV32I-MEDIUM-NEXT: # Label of block must be emitted -; RV32I-MEDIUM-NEXT: auipc a1, %pcrel_hi(.Ltmp0) +; RV32I-MEDIUM-NEXT: auipc a1, %pcrel_hi(.Ltmp1) ; RV32I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.LBB2_4) ; RV32I-MEDIUM-NEXT: addi a2, zero, 101 ; RV32I-MEDIUM-NEXT: sw a1, 8(sp) @@ -89,7 +99,7 @@ ; RV32I-MEDIUM-NEXT: # %bb.1: # %if.then ; RV32I-MEDIUM-NEXT: lw a0, 8(sp) ; RV32I-MEDIUM-NEXT: jr a0 -; RV32I-MEDIUM-NEXT: .Ltmp0: # Block address taken +; RV32I-MEDIUM-NEXT: .Ltmp1: # Block address taken ; RV32I-MEDIUM-NEXT: .LBB2_2: # %return ; RV32I-MEDIUM-NEXT: addi a0, zero, 4 ; RV32I-MEDIUM-NEXT: addi sp, sp, 16 diff --git a/llvm/test/CodeGen/WebAssembly/indirectbr.ll b/llvm/test/CodeGen/WebAssembly/indirectbr.ll --- a/llvm/test/CodeGen/WebAssembly/indirectbr.ll +++ b/llvm/test/CodeGen/WebAssembly/indirectbr.ll @@ -32,7 +32,6 @@ ; CHECK-NEXT: .int32 ; CHECK-NEXT: .int32 ; CHECK-NEXT: .int32 -; CHECK-NEXT: .int32 define void @test1(i32* readonly %p, i32* %sink) #0 {