diff --git a/llvm/test/tools/llvm-diff/callbr.ll b/llvm/test/tools/llvm-diff/callbr.ll new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-diff/callbr.ll @@ -0,0 +1,39 @@ +; RUN: not llvm-diff %s %s 2>&1 | FileCheck %s + +define void @foo() { +entry: + callbr void asm sideeffect "", "X,X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %return), i8* blockaddress(@foo, %t_no)) + to label %asm.fallthrough [label %return, label %t_no] + +asm.fallthrough: + br label %return + +t_no: + br label %return + +return: + ret void +} + +; CHECK: in function bar: +; CHECK-NOT: in function foo: +; CHECK-NEXT: in block %entry: +; CHECK-NEXT: > callbr void asm sideeffect "", "X,X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %t_no), i8* blockaddress(@foo, %return)) +; CHECK-NEXT: to label %asm.fallthrough [label %return, label %t_no] +; CHECK-NEXT: < callbr void asm sideeffect "", "X,X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %t_no), i8* blockaddress(@foo, %return)) +; CHECK-NEXT: to label %asm.fallthrough [label %return, label %t_no] + +define void @bar() { +entry: + callbr void asm sideeffect "", "X,X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %t_no), i8* blockaddress(@foo, %return)) + to label %asm.fallthrough [label %return, label %t_no] + +asm.fallthrough: + br label %return + +t_no: + br label %return + +return: + ret void +} diff --git a/llvm/tools/llvm-diff/DifferenceEngine.cpp b/llvm/tools/llvm-diff/DifferenceEngine.cpp --- a/llvm/tools/llvm-diff/DifferenceEngine.cpp +++ b/llvm/tools/llvm-diff/DifferenceEngine.cpp @@ -287,6 +287,27 @@ } return false; + } else if (isa(L)) { + const CallBrInst &LI = cast(*L); + const CallBrInst &RI = cast(*R); + if (LI.getNumIndirectDests() != RI.getNumIndirectDests()) { + if (Complain) + Engine.log("callbr # of indirect destinations differ"); + return true; + } + + // Perform the "try unify" step so that we can equate the indirect + // destinations before checking the call site. + for (unsigned I = 0; I < LI.getNumIndirectDests(); I++) + tryUnify(LI.getIndirectDest(I), RI.getIndirectDest(I)); + + if (diffCallSites(LI, RI, Complain)) + return true; + + if (TryUnify) + tryUnify(LI.getDefaultDest(), RI.getDefaultDest()); + return false; + } else if (isa(L)) { const BranchInst *LI = cast(L); const BranchInst *RI = cast(R);