Adding a printer pass for printing the LVI cache values after transformations
that use LVI.
This will help us in identifying cases where LVI
invariants are violated, or transforms that leave LVI in an incorrect state.
Right now, I have added two test cases to show that the printer pass is working.
I will be adding more test cases in a later change, once this change is
checked in upstream.
Details
Diff Detail
- Build Status
Buildable 4692 Build 4692: arc lint + arc unit
Event Timeline
It's worth noting for others that the motivation for the change is a bug we found in JumpThreading LVI cache invalidation. The bug is easily triggered with our downstream changes, but is difficult to trigger it upstream. We need the printer pass to write an isolated upstream test case for this problem.
include/llvm/Analysis/LazyValueInfo.h | ||
---|---|---|
101 | Here and below - /// doxygen documentation comment | |
102 | Here and below - just printCache? | |
lib/Analysis/LazyValueInfo.cpp | ||
449 | For the sake of completeness you might also want to print overdefined cache. |
Yes, the motivation is the bug :)
It is *easier* to trigger the bug upstream with printer pass after jump-threading. This pass will also help in uncovering/testing any other LVI caching issues or LVI broken invariants. Also, we can easily print the LVI cache within any pass (using LVI) as LVI->printLazyValueInfoCache(errs()).
include/llvm/Analysis/LazyValueInfo.h | ||
---|---|---|
102 | Works for me |
include/llvm/Analysis/LazyValueInfo.h | ||
---|---|---|
102 | Both overdefined and latticevaluecache are defined within the LVICache. So, left as printCache itself. |
include/llvm/Analysis/LazyValueInfo.h | ||
---|---|---|
102 | What's the reason for datalayout? | |
lib/Analysis/LazyValueInfo.cpp | ||
444 | FWIW: I would generally recommend you do this as an annotation to the basic blocks/values, using the asm printer interface, and adding them as comments. This would produce output similar to print-predicateinfo, print-memoryssa, etc, where the values are right above the instructions they belong to. This usually makes it significantly easier to test and understand what is going on, IME. I have not looked at this specific case, of course. But, for example, the iteration order here is *completely* undefined, meaning you have to be prepared for the output to appear in any order. | |
448 | BB's don't always have names, i would use BV.first->printAsOperand(), which will also handle the nameless ones properly. | |
1858 | You should add a new PM version of this as well. | |
1871 | I do not believe we normally print to errs for printing passes. |
include/llvm/Analysis/LazyValueInfo.h | ||
---|---|---|
102 | We need it here for getting the LazyValueInfoImpl within this function. I don't think we have any other way for getting the datalayout. see: getImpl(PImpl, AC, &DL, DT).printCache(OS); | |
lib/Analysis/LazyValueInfo.cpp | ||
444 | Yes, since the order would be completely undefined, I used the CHECK-DAG part here along with the CHECK-LABEL. | |
1871 | So, couple of ones still print to errs, like the AliasSetPrinter (that's the one I followed for this). It looks like most printing passes print to dbgs(), I can change to that. |
include/llvm/Analysis/LazyValueInfo.h | ||
---|---|---|
102 | Oh, yeah, this is just silly. I would just add it to the class LazyValueInfo interface, since everything else is there. |
Hi folks,
Daniel added a suggestion regarding the printing of the LVI:
FWIW: I would generally recommend you do this as an annotation to the basic blocks/values, using the asm printer interface, and adding them as comments. This would produce output similar to print-predicateinfo, print-memoryssa, etc, where the values are right above the instructions they belong to. This usually makes it significantly easier to test and understand what is going on, IME.
I had a look at the print-predicateinfo, and agree with Daniel - adding annotations as comments before the instruction makes it easier to see what's the transformation (along with the LVI values). However, in the LVI case, an instruction would have a list of LatticeValues corresponding to different basic blocks. Also, the LatticeValueCache structure enables printing the annotation per instruction (the cache key is ssa value). The overdefined cache structure enables printing per basic block. So, the print would be something like this:
For test2 example (see annotations added as comments):
entry: ; ' i32 %n ' is overdefined br label %loop loop ; %iv2 = phi i32 [ %n, %entry ], [ %iv2.next, %backedge ] ' is overdefined ; 'constantrange<0, -2147483647>' at the beginning of 'loop' ; 'constantrange<0, -2147483648>' at the beginning of 'backedge' %iv = phi i32 [0, %entry], [%iv.next, %backedge] <-- the values corresponding to the `%iv` per basic block, are annotated before the instruction. %iv2 = phi i32 [%n, %entry], [%iv2.next, %backedge] %cnd1 = icmp sge i32 %iv, 0 %cnd2 = icmp sgt i32 %iv2, 0 %cnd = and i1 %cnd1, %cnd2 br i1 %cnd, label %backedge, label %exit backedge: ; 'constantrange<1, -2147483647>' at the beginning of 'backedge' %iv.next = add nsw i32 %iv, 1 %iv2.next = sub nsw i32 %iv2, 1 %cont1 = icmp slt i32 %iv.next, 400 %cont2 = icmp sgt i32 %iv2.next, 0 %cont = and i1 %cont1, %cont2 br i1 %cont, label %loop, label %exit exit: ret i8 0
I think it looks clearer than the CHECK-DAG and CHECK-LABEL combination I have for test2 currently.
Does this look better?
include/llvm/Analysis/LazyValueInfo.h | ||
---|---|---|
102 | Thanks, added as a separate NFC. |
Updated the pass to use the AseemblyAnnotationWriter.
Addressed other review comments.
Tests updated accordingly.
I have not yet added the new pass manager version, I'll add for review once this is completed.
(The new pass manager version of the LVIPrinter compiles, but it does not use the existing LVI object, I'll debug that on the side.
Don't want to block this review on that issue).
Review for the updated version. The previous LGTMed version did not return the annotation as comments.
Thanks Daniel!
I'll submit a follow on patch (directly) for capturing lattice values of the function's arguments. Just realized while adding some test cases that the AssemblyAnnotationWriter only prints info for instructions and basic blocks.
Here and below - /// doxygen documentation comment