diff --git a/llvm/test/tools/llvm-diff/phinode.ll b/llvm/test/tools/llvm-diff/phinode.ll new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-diff/phinode.ll @@ -0,0 +1,28 @@ +; RUN: rm -f %t.ll +; RUN: cat %s | sed -e 's/ 0, %2 / 1, %2 /' > %t.ll +; RUN: not llvm-diff %s %t.ll 2>&1 | FileCheck %s + +; CHECK: in function foo: +; CHECK-NEXT: in block %6 / %6: +; CHECK-NEXT: > %7 = phi i32 [ 1, %2 ], [ -1, %1 ] +; CHECK-NEXT: > ret i32 %7 +; CHECK-NEXT: < %7 = phi i32 [ 0, %2 ], [ -1, %1 ] +; CHECK-NEXT: < ret i32 %7 +define i32 @foo(i32 %0) #0 { + callbr void asm sideeffect "", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@foo, %6)) + to label %2 [label %6] + +2: + %3 = icmp eq i32 %0, 0 + br i1 %3, label %6, label %4 + +4: + br label %5 + +5: + br label %5 + +6: + %7 = phi i32 [ 0, %2 ], [ -1, %1 ] + ret i32 %7 +} diff --git a/llvm/tools/llvm-diff/lib/DifferenceEngine.cpp b/llvm/tools/llvm-diff/lib/DifferenceEngine.cpp --- a/llvm/tools/llvm-diff/lib/DifferenceEngine.cpp +++ b/llvm/tools/llvm-diff/lib/DifferenceEngine.cpp @@ -269,15 +269,35 @@ } else if (isa(L)) { return diffCallSites(cast(*L), cast(*R), Complain); } else if (isa(L)) { - // FIXME: implement. + const PHINode &LI = cast(*L); + const PHINode &RI = cast(*R); // This is really weird; type uniquing is broken? - if (L->getType() != R->getType()) { - if (!L->getType()->isPointerTy() || !R->getType()->isPointerTy()) { + if (LI.getType() != RI.getType()) { + if (!LI.getType()->isPointerTy() || !RI.getType()->isPointerTy()) { if (Complain) Engine.log("different phi types"); return true; } } + + if (LI.getNumIncomingValues() != RI.getNumIncomingValues()) { + if (Complain) + Engine.log("PHI node # of incoming values differ"); + return true; + } + + for (unsigned I = 0; I < LI.getNumIncomingValues(); ++I) { + if (TryUnify) + tryUnify(LI.getIncomingBlock(I), RI.getIncomingBlock(I)); + + if (!equivalentAsOperands(LI.getIncomingValue(I), + RI.getIncomingValue(I))) { + if (Complain) + Engine.log("PHI node incoming values differ"); + return true; + } + } + return false; // Terminators.