[llvm] r328004 - Add an analysis printer for must execute reasoning
Philip Reames via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 29 10:28:28 PDT 2018
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
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180329/74b9acfc/attachment.html>
More information about the llvm-commits
mailing list