Jannik Silvanus e044796132 [llvm-diff] Fix false-positive diffs on forward-referencing phi nodes
When a phi node references a variable defined in a basic block dominated
by the the basic block containing the phi node, llvm-diff currently cannot determine
whether the variable is equivalent, and thus treats the phi node as different
and reports a difference. This leads to false positive differences as demonstrated
by the loop.ll diff, for which llvm-diff reports a diff when comparing the file
with itself.

Fix that issue by adding the concept of *equivalence assumptions*.
When encountering a pair of values which can neither be proven to be equivalent
nor to be non-equivalent, instead optimistically assume equivalence, and store
somewhere that the equivalence of the currently compared basic blocks depends
on this assumption.

Later, once all BBs have been processed, check all made assumptions and report
blocks as different whose equivalence was depending on an incorrect assumption,
or an assumption we could not prove to be correct.

In order to preserve the original diff report order, also schedule diffs
of blocks already known to be different using the same mechanism, so all block
diffs are now generated at the very end of function diffing.

In case an incorrect assumption was made, all further shown equivalences between
old and new values implictly depend on the incorrect assumption. Some of these
may in fact be not equivalent, but these are neither reverted nor reported,
because they are considered indirect diffs caused by an earlier direct diff.

See inline comments for an argument why we do not run into issues caused by circular
proof dependencies.

Differential Revision: https://reviews.llvm.org/D137318
2022-11-09 20:40:47 +01:00

36 lines
1.2 KiB
LLVM

; Diff file with itself, assert no difference by return code
; RUN: llvm-diff %s %s
; Replace %newvar1 with %newvar2 in the phi node. This can only
; be detected to be different once BB1 has been processed.
; RUN: rm -f %t.ll
; RUN: cat %s | sed -e 's/ %newvar1, %BB1 / %newvar2, %BB1 /' > %t.ll
; RUN: not llvm-diff %s %t.ll 2>&1 | FileCheck --check-prefix DIFFERENT-VAR %s
; DIFFERENT-VAR: in function func:
; DIFFERENT-VAR-NEXT: in block %BB0:
; DIFFERENT-VAR-NEXT: > %var = phi i32 [ 0, %ENTRY ], [ %newvar2, %BB1 ]
; DIFFERENT-VAR-NEXT: < %var = phi i32 [ 0, %ENTRY ], [ %newvar1, %BB1 ]
define i32 @func() {
ENTRY:
br label %BB0
BB0:
; When diffing this phi node, we need to detect whether
; %newvar1 is equivalent, which is not known until BB1 has been processed.
%var = phi i32 [ 0, %ENTRY ], [ %newvar1, %BB1 ]
%cnd = icmp eq i32 %var, 0
br i1 %cnd, label %BB1, label %END
BB1:
%newvar1 = add i32 %var, 1
%newvar2 = add i32 %var, 2
br label %BB0
END:
; Equivalence of the ret depends on equivalence of %var.
; Even if %var differs, we do not report a diff here, because
; this is an indirect diff caused by another diff.
ret i32 %var
}