[llvm] r328004 - Add an analysis printer for must execute reasoning
Philip Reames via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 29 12:25:40 PDT 2018
Should be fixed in 328816.
On 03/29/2018 10:28 AM, Philip Reames via llvm-commits wrote:
>
> I'll have to look at the compiler errors to see what's used. I hadn't
> intended to leave any of the required functionality in Transforms and
> I'm confused as to what I might have missed. I'm hoping it's
> something minor.
>
>
> On 03/29/2018 10:24 AM, David Blaikie wrote:
>> Ah, sorry - I think I tested that first & found it was used. I forget
>> what the particular use was - but should be easy to reproduce &
>> hopefully there's some good fix for it. Happy to help with the
>> implementation or ideas about how to address it if you like.
>>
>> On Thu, Mar 29, 2018 at 10:15 AM Philip Reames
>> <listmail at philipreames.com <mailto:listmail at philipreames.com>> wrote:
>>
>>
>>
>> On 03/28/2018 04:16 PM, David Blaikie wrote:
>>>
>>>
>>> On Tue, Mar 20, 2018 at 10:11 AM Philip Reames via llvm-commits
>>> <llvm-commits at lists.llvm.org
>>> <mailto:llvm-commits at lists.llvm.org>> wrote:
>>>
>>> Author: reames
>>> Date: Tue Mar 20 10:09:21 2018
>>> New Revision: 328004
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=328004&view=rev
>>> Log:
>>> Add an analysis printer for must execute reasoning
>>>
>>> Many of our loop passes make use of so called "must execute"
>>> or "guaranteed to execute" facts to prove the legality of
>>> code motion. The basic notion is that we know (by
>>> assumption) an instruction didn't fault at it's original
>>> location, so if the location we move it to is strictly post
>>> dominated by the original, then we can't have introduced a
>>> new fault.
>>>
>>> At the moment, the testing for this logic is somewhat adhoc
>>> and done mostly through LICM. Since I'm working on that
>>> code, I want to improve the testing. This patch is the first
>>> step in that direction. It doesn't actually test the variant
>>> used by the loop passes - I need to move that to the
>>> Analysis library first - but instead exercises an alternate
>>> implementation used by SCEV. (I plan on merging both
>>> implementations.)
>>>
>>> Note: I'll be replacing the printing logic within this with
>>> an annotation based version in the near future. Anna
>>> suggested this in review, and it seems like a strictly
>>> better format.
>>>
>>> Differential Revision: https://reviews.llvm.org/D44524
>>>
>>>
>>> Added:
>>> llvm/trunk/lib/Analysis/MustExecute.cpp
>>> llvm/trunk/test/Analysis/MustExecute/
>>> llvm/trunk/test/Analysis/MustExecute/loop-header.ll
>>> Modified:
>>> llvm/trunk/include/llvm/Analysis/Passes.h
>>> llvm/trunk/include/llvm/InitializePasses.h
>>> llvm/trunk/include/llvm/LinkAllPasses.h
>>> llvm/trunk/lib/Analysis/Analysis.cpp
>>> llvm/trunk/lib/Analysis/CMakeLists.txt
>>>
>>> Modified: llvm/trunk/include/llvm/Analysis/Passes.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/Passes.h?rev=328004&r1=328003&r2=328004&view=diff
>>> ==============================================================================
>>> --- llvm/trunk/include/llvm/Analysis/Passes.h (original)
>>> +++ llvm/trunk/include/llvm/Analysis/Passes.h Tue Mar 20
>>> 10:09:21 2018
>>> @@ -96,6 +96,14 @@ namespace llvm {
>>> //
>>> FunctionPass *createMemDerefPrinter();
>>>
>>> +
>>> //===--------------------------------------------------------------------===//
>>> + //
>>> + // createMustExecutePrinter - This pass collects
>>> information about which
>>> + // instructions within a loop are guaranteed to execute
>>> if the loop header is
>>> + // entered and prints it with -analyze.
>>> + //
>>> + FunctionPass *createMustExecutePrinter();
>>> +
>>> }
>>>
>>> #endif
>>>
>>> Modified: llvm/trunk/include/llvm/InitializePasses.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=328004&r1=328003&r2=328004&view=diff
>>> ==============================================================================
>>> --- llvm/trunk/include/llvm/InitializePasses.h (original)
>>> +++ llvm/trunk/include/llvm/InitializePasses.h Tue Mar 20
>>> 10:09:21 2018
>>> @@ -268,6 +268,7 @@ void initializeMergedLoadStoreMotionLega
>>> void initializeMetaRenamerPass(PassRegistry&);
>>> void initializeModuleDebugInfoPrinterPass(PassRegistry&);
>>> void
>>> initializeModuleSummaryIndexWrapperPassPass(PassRegistry&);
>>> +void initializeMustExecutePrinterPass(PassRegistry&);
>>> void initializeNameAnonGlobalLegacyPassPass(PassRegistry&);
>>> void initializeNaryReassociateLegacyPassPass(PassRegistry&);
>>> void initializeNewGVNLegacyPassPass(PassRegistry&);
>>>
>>> Modified: llvm/trunk/include/llvm/LinkAllPasses.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=328004&r1=328003&r2=328004&view=diff
>>> ==============================================================================
>>> --- llvm/trunk/include/llvm/LinkAllPasses.h (original)
>>> +++ llvm/trunk/include/llvm/LinkAllPasses.h Tue Mar 20
>>> 10:09:21 2018
>>> @@ -207,6 +207,7 @@ namespace {
>>> (void) llvm::createRewriteSymbolsPass();
>>> (void) llvm::createStraightLineStrengthReducePass();
>>> (void) llvm::createMemDerefPrinter();
>>> + (void) llvm::createMustExecutePrinter();
>>> (void) llvm::createFloat2IntPass();
>>> (void) llvm::createEliminateAvailableExternallyPass();
>>> (void) llvm::createScalarizeMaskedMemIntrinPass();
>>>
>>> Modified: llvm/trunk/lib/Analysis/Analysis.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/Analysis.cpp?rev=328004&r1=328003&r2=328004&view=diff
>>> ==============================================================================
>>> --- llvm/trunk/lib/Analysis/Analysis.cpp (original)
>>> +++ llvm/trunk/lib/Analysis/Analysis.cpp Tue Mar 20 10:09:21
>>> 2018
>>> @@ -65,6 +65,7 @@ void llvm::initializeAnalysis(PassRegist
>>> initializeMemoryDependenceWrapperPassPass(Registry);
>>> initializeModuleDebugInfoPrinterPass(Registry);
>>> initializeModuleSummaryIndexWrapperPassPass(Registry);
>>> + initializeMustExecutePrinterPass(Registry);
>>> initializeObjCARCAAWrapperPassPass(Registry);
>>> initializeOptimizationRemarkEmitterWrapperPassPass(Registry);
>>> initializePostDominatorTreeWrapperPassPass(Registry);
>>>
>>> Modified: llvm/trunk/lib/Analysis/CMakeLists.txt
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CMakeLists.txt?rev=328004&r1=328003&r2=328004&view=diff
>>> ==============================================================================
>>> --- llvm/trunk/lib/Analysis/CMakeLists.txt (original)
>>> +++ llvm/trunk/lib/Analysis/CMakeLists.txt Tue Mar 20
>>> 10:09:21 2018
>>> @@ -58,6 +58,7 @@ add_llvm_library(LLVMAnalysis
>>> MemorySSAUpdater.cpp
>>> ModuleDebugInfoPrinter.cpp
>>> ModuleSummaryAnalysis.cpp
>>> + MustExecute.cpp
>>> ObjCARCAliasAnalysis.cpp
>>> ObjCARCAnalysisUtils.cpp
>>> ObjCARCInstKind.cpp
>>>
>>> Added: llvm/trunk/lib/Analysis/MustExecute.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/MustExecute.cpp?rev=328004&view=auto
>>> ==============================================================================
>>> --- llvm/trunk/lib/Analysis/MustExecute.cpp (added)
>>> +++ llvm/trunk/lib/Analysis/MustExecute.cpp Tue Mar 20
>>> 10:09:21 2018
>>> @@ -0,0 +1,102 @@
>>> +//===- MustExecute.cpp - Printer for isGuaranteedToExecute
>>> ----------------===//
>>> +//
>>> +// The LLVM Compiler Infrastructure
>>> +//
>>> +// This file is distributed under the University of
>>> Illinois Open Source
>>> +// License. See LICENSE.TXT for details.
>>> +//
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +#include "llvm/Analysis/LoopInfo.h"
>>> +#include "llvm/Analysis/Passes.h"
>>> +#include "llvm/Analysis/ValueTracking.h"
>>> +#include "llvm/IR/DataLayout.h"
>>> +#include "llvm/IR/InstIterator.h"
>>> +#include "llvm/IR/LLVMContext.h"
>>> +#include "llvm/IR/Module.h"
>>> +#include "llvm/Support/ErrorHandling.h"
>>> +#include "llvm/Support/raw_ostream.h"
>>> +#include "llvm/Transforms/Utils/LoopUtils.h"
>>>
>>>
>>> This looks like a circular/invalid dependency? Transforms depend
>>> on Analysis, not the other way around?
>>>
>>> Would be great to get this fixed - happy to help, if you've some
>>> ideas.
>>>
>>> Moving the whole LoopUtils isn't immediately possible, its
>>> implementation depends on BasicBlockUtils. (& also many of these
>>> utilities seem more for mutation, which isn't relevant to
>>> Analysis - so maybe it needs to be split up?)
>> I think this is just a stale header include. I'm building to
>> confirm now and if so will remove it.
>>>
>>> +using namespace llvm;
>>> +
>>> +namespace {
>>> + struct MustExecutePrinter : public FunctionPass {
>>> + DenseMap<Value*, SmallVector<Loop*, 4> > MustExec;
>>> + SmallVector<Value *, 4> Ordering;
>>> +
>>> + static char ID; // Pass identification, replacement for
>>> typeid
>>> + MustExecutePrinter() : FunctionPass(ID) {
>>> +
>>> initializeMustExecutePrinterPass(*PassRegistry::getPassRegistry());
>>> + }
>>> + void getAnalysisUsage(AnalysisUsage &AU) const override {
>>> + AU.setPreservesAll();
>>> + AU.addRequired<DominatorTreeWrapperPass>();
>>> + AU.addRequired<LoopInfoWrapperPass>();
>>> + }
>>> + bool runOnFunction(Function &F) override;
>>> + void print(raw_ostream &OS, const Module * = nullptr)
>>> const override;
>>> + void releaseMemory() override {
>>> + MustExec.clear();
>>> + Ordering.clear();
>>> + }
>>> + };
>>> +}
>>> +
>>> +char MustExecutePrinter::ID = 0;
>>> +INITIALIZE_PASS_BEGIN(MustExecutePrinter, "print-mustexecute",
>>> + "Instructions which execute on loop
>>> entry", false, true)
>>> +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
>>> +INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
>>> +INITIALIZE_PASS_END(MustExecutePrinter, "print-mustexecute",
>>> + "Instructions which execute on loop
>>> entry", false, true)
>>> +
>>> +FunctionPass *llvm::createMustExecutePrinter() {
>>> + return new MustExecutePrinter();
>>> +}
>>> +
>>> +bool isMustExecuteIn(Instruction &I, Loop *L, DominatorTree
>>> *DT) {
>>> + // TODO: move loop specific code to analysis
>>> + //LoopSafetyInfo LSI;
>>> + //computeLoopSafetyInfo(&LSI, L);
>>> + //return isGuaranteedToExecute(I, DT, L, &LSI);
>>> + return isGuaranteedToExecuteForEveryIteration(&I, L);
>>> +}
>>> +
>>> +bool MustExecutePrinter::runOnFunction(Function &F) {
>>> + auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
>>> + auto &DT =
>>> getAnalysis<DominatorTreeWrapperPass>().getDomTree();
>>> + for (auto &I: instructions(F)) {
>>> + Loop *L = LI.getLoopFor(I.getParent());
>>> + while (L) {
>>> + if (isMustExecuteIn(I, L, &DT)) {
>>> + if (!MustExec.count(&I))
>>> + Ordering.push_back(&I);
>>> + MustExec[&I].push_back(L);
>>> + }
>>> + L = L->getParentLoop();
>>> + };
>>> + }
>>> + return false;
>>> +}
>>> +
>>> +void MustExecutePrinter::print(raw_ostream &OS, const
>>> Module *M) const {
>>> + OS << "The following are guaranteed to execute (for the
>>> respective loops):\n";
>>> + for (Value *V: Ordering) {
>>> + V->printAsOperand(OS);
>>> + auto NumLoops = MustExec.lookup(V).size();
>>> + if (NumLoops > 1)
>>> + OS << "\t(mustexec in " << NumLoops << " loops: ";
>>> + else
>>> + OS << "\t(mustexec in: ";
>>> +
>>> + bool first = true;
>>> + for (const Loop *L : MustExec.lookup(V)) {
>>> + if (!first)
>>> + OS << ", ";
>>> + first = false;
>>> + OS << L->getHeader()->getName();
>>> + }
>>> + OS << ")\n";
>>> + }
>>> + OS << "\n";
>>> +}
>>>
>>> Added: llvm/trunk/test/Analysis/MustExecute/loop-header.ll
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/MustExecute/loop-header.ll?rev=328004&view=auto
>>> ==============================================================================
>>> --- llvm/trunk/test/Analysis/MustExecute/loop-header.ll (added)
>>> +++ llvm/trunk/test/Analysis/MustExecute/loop-header.ll Tue
>>> Mar 20 10:09:21 2018
>>> @@ -0,0 +1,80 @@
>>> +; RUN: opt -analyze -print-mustexecute %s
>>> +
>>> +; CHECK: Printing analysis 'Instructions which execute on
>>> loop entry' for function 'header_with_icf':
>>> +; CHECK: The following are guaranteed to execute (for the
>>> respective loops):
>>> +; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop
>>> ] (mustexec in: loop)
>>> +; CHECK: %v = load i32, i32* %p (mustexec in: loop)
>>> +; CHECK: call void @maythrow_and_use(i32 %v) (mustexec
>>> in: loop)
>>> +; CHECK-NOT: add
>>> +define i1 @header_with_icf(i32* noalias %p, i32 %high) {
>>> +entry:
>>> + br label %loop
>>> +
>>> +loop:
>>> + %iv = phi i32 [0, %entry], [%iv.next, %loop]
>>> + %v = load i32, i32* %p
>>> + call void @maythrow_and_use(i32 %v)
>>> + %iv.next = add nsw nuw i32 %iv, 1
>>> + %exit.test = icmp slt i32 %iv, %high
>>> + br i1 %exit.test, label %exit, label %loop
>>> +
>>> +exit:
>>> + ret i1 false
>>> +}
>>> +
>>> +; CHECK: Printing analysis 'Instructions which execute on
>>> loop entry' for function 'test':
>>> +; CHECK: The following are guaranteed to execute (for the
>>> respective loops):
>>> +; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.next, %next
>>> ] (mustexec in: loop)
>>> +; CHECK: %v = load i32, i32* %p (mustexec in: loop)
>>> +; CHECK: br label %next (mustexec in: loop)
>>> +define i1 @test(i32* noalias %p, i32 %high) {
>>> +entry:
>>> + br label %loop
>>> +
>>> +loop:
>>> + %iv = phi i32 [0, %entry], [%iv.next, %next]
>>> + %v = load i32, i32* %p
>>> + br label %next
>>> +next:
>>> + call void @maythrow_and_use(i32 %v)
>>> + %iv.next = add nsw nuw i32 %iv, 1
>>> + %exit.test = icmp slt i32 %iv, %high
>>> + br i1 %exit.test, label %exit, label %loop
>>> +
>>> +exit:
>>> + ret i1 false
>>> +}
>>> +
>>> +; CHECK: Printing analysis 'Instructions which execute on
>>> loop entry' for function 'nested':
>>> +; CHECK: The following are guaranteed to execute (for the
>>> respective loops):
>>> +; CHECK: %iv = phi i32 [ 0, %entry ], [ %iv.next, %next
>>> ] (mustexec in: loop)
>>> +; CHECK: br label %inner_loop (mustexec in: loop)
>>> +; FIXME: These three are also must execute for the outer loop.
>>> +; CHECK: %v = load i32, i32* %p (mustexec in:
>>> inner_loop)
>>> +; CHECK: %inner.test = icmp eq i32 %v, 0 (mustexec in:
>>> inner_loop)
>>> +; CHECK: br i1 %inner.test, label %inner_loop, label
>>> %next (mustexec in: inner_loop)
>>> +define i1 @nested(i32* noalias %p, i32 %high) {
>>> +entry:
>>> + br label %loop
>>> +
>>> +loop:
>>> + %iv = phi i32 [0, %entry], [%iv.next, %next]
>>> + br label %inner_loop
>>> +
>>> +inner_loop:
>>> + %v = load i32, i32* %p
>>> + %inner.test = icmp eq i32 %v, 0
>>> + br i1 %inner.test, label %inner_loop, label %next
>>> +
>>> +next:
>>> + call void @maythrow_and_use(i32 %v)
>>> + %iv.next = add nsw nuw i32 %iv, 1
>>> + %exit.test = icmp slt i32 %iv, %high
>>> + br i1 %exit.test, label %exit, label %loop
>>> +
>>> +exit:
>>> + ret i1 false
>>> +}
>>> +
>>> +
>>> +declare void @maythrow_and_use(i32)
>>>
>>>
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at lists.llvm.org <mailto:llvm-commits at lists.llvm.org>
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>>
>>
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180329/d8e5a564/attachment.html>
More information about the llvm-commits
mailing list