diff --git a/llvm/unittests/IR/InstructionsTest.cpp b/llvm/unittests/IR/InstructionsTest.cpp --- a/llvm/unittests/IR/InstructionsTest.cpp +++ b/llvm/unittests/IR/InstructionsTest.cpp @@ -1377,26 +1377,35 @@ FNeg->deleteValue(); } +void VerifyCallBr(const CallBrInst &CBI, const BasicBlock &Expected, + const std::string &F) { + BlockAddress *IndirectBA = BlockAddress::get(CBI.getIndirectDest(0)); + BlockAddress *ArgBA = cast(CBI.getArgOperand(0)); + EXPECT_EQ(IndirectBA, ArgBA) + << "After " << F << ", callbr had an indirect destination of '" + << CBI.getIndirectDest(0)->getName() << "', but a argument of '" + << ArgBA->getBasicBlock()->getName() << "'. These should always match:\n" + << CBI; + EXPECT_EQ(IndirectBA->getBasicBlock(), &Expected); + EXPECT_EQ(ArgBA->getBasicBlock(), &Expected); +} + TEST(InstructionsTest, CallBrInstruction) { LLVMContext Context; std::unique_ptr M = parseIR(Context, R"( define void @foo() { entry: - callbr void asm sideeffect "// XXX: ${0:l}", "X"(i8* blockaddress(@foo, %branch_test.exit)) + callbr void asm sideeffect "", "X"(i8* blockaddress(@foo, %branch_test.exit)) to label %land.rhs.i [label %branch_test.exit] land.rhs.i: br label %branch_test.exit branch_test.exit: - %0 = phi i1 [ true, %entry ], [ false, %land.rhs.i ] - br i1 %0, label %if.end, label %if.then + br label %if.then if.then: ret void - -if.end: - ret void } )"); Function *Foo = M->getFunction("foo"); @@ -1416,16 +1425,11 @@ // Further, test that changing the indirect destination updates the arg // operand to use the block address of the new indirect destination basic // block. This is a critical invariant of CallBrInst. - BlockAddress *IndirectBA = BlockAddress::get(CBI.getIndirectDest(0)); - BlockAddress *ArgBA = cast(CBI.getArgOperand(0)); - EXPECT_EQ(IndirectBA, ArgBA) - << "After setting the indirect destination, callbr had an indirect " - "destination of '" - << CBI.getIndirectDest(0)->getName() << "', but a argument of '" - << ArgBA->getBasicBlock()->getName() << "'. These should always match:\n" - << CBI; - EXPECT_EQ(IndirectBA->getBasicBlock(), &IfThen); - EXPECT_EQ(ArgBA->getBasicBlock(), &IfThen); + VerifyCallBr(CBI, IfThen, "CallBrInst::setIndirectDest()"); + + // Now try changing it back with User::replaceUsesOfWith(). + CBI.replaceUsesOfWith(CBI.getIndirectDest(0), &BranchTestExit); + VerifyCallBr(CBI, BranchTestExit, "User::replaceUsesOfWith()"); } TEST(InstructionsTest, UnaryOperator) {