Commit 16f777f4 authored by Tyker's avatar Tyker
Browse files

[NFC] Add debug and stat counters to assume queries and assume builder

Summary:
Add debug counter and stats counter to assume queries and assume builder
here is the collected stats on a build of check-llvm + check-clang.
  "assume-builder.NumAssumeBuilt": 2720879,
  "assume-builder.NumAssumesMerged": 761396,
  "assume-builder.NumAssumesRemoved": 1576212,
  "assume-builder.NumBundlesInAssumes": 6518809,
  "assume-queries.NumAssumeQueries": 85566380,
  "assume-queries.NumUsefullAssumeQueries": 2727360,
the NumUsefullAssumeQueries stat is actually pessimistic because in a few places queries
ask to keep providing information to try to get better information. and this isn't counted
as a usefull query evem tho it can be usefull

Reviewers: jdoerfert

Reviewed By: jdoerfert

Subscribers: hiraditya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D83506
parent 00d97b75
Loading
Loading
Loading
Loading
+22 −3
Original line number Diff line number Diff line
@@ -6,17 +6,29 @@
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "assume-queries"

#include "llvm/Analysis/AssumeBundleQueries.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Support/DebugCounter.h"

using namespace llvm;
using namespace llvm::PatternMatch;

STATISTIC(NumAssumeQueries, "Number of Queries into an assume assume bundles");
STATISTIC(
    NumUsefullAssumeQueries,
    "Number of Queries into an assume assume bundles that were satisfied");

DEBUG_COUNTER(AssumeQueryCounter, "assume-queries-counter",
              "Controls which assumes gets created");

static bool bundleHasArgument(const CallBase::BundleOpInfo &BOI, unsigned Idx) {
  return BOI.End - BOI.Begin > Idx;
}
@@ -158,6 +170,9 @@ llvm::getKnowledgeForValue(const Value *V,
                           function_ref<bool(RetainedKnowledge, Instruction *,
                                             const CallBase::BundleOpInfo *)>
                               Filter) {
  NumAssumeQueries++;
  if (!DebugCounter::shouldExecute(AssumeQueryCounter))
    return RetainedKnowledge::none();
  if (AC) {
    for (AssumptionCache::ResultElem &Elem : AC->assumptionsFor(V)) {
      IntrinsicInst *II = cast_or_null<IntrinsicInst>(Elem.Assume);
@@ -166,21 +181,25 @@ llvm::getKnowledgeForValue(const Value *V,
      if (RetainedKnowledge RK = getKnowledgeFromBundle(
              *II, II->bundle_op_info_begin()[Elem.Index]))
        if (is_contained(AttrKinds, RK.AttrKind) &&
            Filter(RK, II, &II->bundle_op_info_begin()[Elem.Index]))
            Filter(RK, II, &II->bundle_op_info_begin()[Elem.Index])) {
          NumUsefullAssumeQueries++;
          return RK;
        }
    }
    return RetainedKnowledge::none();
  }
  for (auto &U : V->uses()) {
  for (const auto &U : V->uses()) {
    CallInst::BundleOpInfo* Bundle = getBundleFromUse(&U);
    if (!Bundle)
      continue;
    if (RetainedKnowledge RK =
            getKnowledgeFromBundle(*cast<CallInst>(U.getUser()), *Bundle))
      if (is_contained(AttrKinds, RK.AttrKind) &&
          Filter(RK, cast<Instruction>(U.getUser()), Bundle))
          Filter(RK, cast<Instruction>(U.getUser()), Bundle)) {
        NumUsefullAssumeQueries++;
        return RK;
      }
  }
  return RetainedKnowledge::none();
}

+22 −0
Original line number Diff line number Diff line
@@ -6,9 +6,12 @@
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "assume-builder"

#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AssumeBundleQueries.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/ValueTracking.h"
@@ -19,6 +22,7 @@
#include "llvm/IR/Module.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/DebugCounter.h"
#include "llvm/Transforms/Utils/Local.h"

using namespace llvm;
@@ -33,6 +37,16 @@ cl::opt<bool> EnableKnowledgeRetention(
    cl::desc(
        "enable preservation of attributes throughout code transformation"));

STATISTIC(NumAssumeBuilt, "Number of assume built by the assume builder");
STATISTIC(NumBundlesInAssumes, "Total number of Bundles in the assume built");
STATISTIC(NumAssumesMerged,
          "Number of assume merged by the assume simplify pass");
STATISTIC(NumAssumesRemoved,
          "Number of assume removed by the assume simplify pass");

DEBUG_COUNTER(BuildAssumeCounter, "assume-builder-counter",
              "Controls which assumes gets created");

namespace {

bool isUsefullToPreserve(Attribute::AttrKind Kind) {
@@ -204,6 +218,8 @@ struct AssumeBuilderState {
  IntrinsicInst *build() {
    if (AssumedKnowledgeMap.empty())
      return nullptr;
    if (!DebugCounter::shouldExecute(BuildAssumeCounter))
      return nullptr;
    Function *FnAssume = Intrinsic::getDeclaration(M, Intrinsic::assume);
    LLVMContext &C = M->getContext();
    SmallVector<OperandBundleDef, 8> OpBundle;
@@ -220,7 +236,9 @@ struct AssumeBuilderState {
      OpBundle.push_back(OperandBundleDefT<Value *>(
          std::string(Attribute::getNameFromAttrKind(MapElem.first.second)),
          Args));
      NumBundlesInAssumes++;
    }
    NumAssumeBuilt++;
    return cast<IntrinsicInst>(CallInst::Create(
        FnAssume, ArrayRef<Value *>({ConstantInt::getTrue(C)}), OpBundle));
  }
@@ -328,6 +346,10 @@ struct AssumeSimplify {
          (!ForceCleanup && !isAssumeWithEmptyBundle(*Assume)))
        continue;
      MadeChange = true;
      if (ForceCleanup)
        NumAssumesMerged++;
      else
        NumAssumesRemoved++;
      Assume->eraseFromParent();
    }
    CleanupToDo.clear();
+110 −0
Original line number Diff line number Diff line
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -instcombine --debug-counter=assume-queries-counter-skip=0,assume-queries-counter-count=1 -S | FileCheck %s --check-prefixes=SAME,COUNTER1
; RUN: opt < %s -instcombine --debug-counter=assume-queries-counter-skip=1,assume-queries-counter-count=2 -S | FileCheck %s --check-prefixes=SAME,COUNTER2
; RUN: opt < %s -instcombine --debug-counter=assume-queries-counter-skip=2,assume-queries-counter-count=1 -S | FileCheck %s --check-prefixes=SAME,COUNTER3

declare i1 @get_val()
declare void @llvm.assume(i1)

define dso_local i1 @test1(i32* readonly %0) {
; COUNTER1-LABEL: @test1(
; COUNTER1-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[TMP0:%.*]]) ]
; COUNTER1-NEXT:    ret i1 false
;
; COUNTER2-LABEL: @test1(
; COUNTER2-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[TMP0:%.*]]) ]
; COUNTER2-NEXT:    [[TMP2:%.*]] = icmp eq i32* [[TMP0]], null
; COUNTER2-NEXT:    ret i1 [[TMP2]]
;
; COUNTER3-LABEL: @test1(
; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[TMP0:%.*]]) ]
; COUNTER3-NEXT:    [[TMP2:%.*]] = icmp eq i32* [[TMP0]], null
; COUNTER3-NEXT:    ret i1 [[TMP2]]
;
  call void @llvm.assume(i1 true) ["nonnull"(i32* %0)]
  %2 = icmp eq i32* %0, null
  ret i1 %2
}

define dso_local i1 @test2(i32* readonly %0) {
; COUNTER1-LABEL: @test2(
; COUNTER1-NEXT:    [[TMP2:%.*]] = icmp eq i32* [[TMP0:%.*]], null
; COUNTER1-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[TMP0]]) ]
; COUNTER1-NEXT:    ret i1 [[TMP2]]
;
; COUNTER2-LABEL: @test2(
; COUNTER2-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[TMP0:%.*]]) ]
; COUNTER2-NEXT:    ret i1 false
;
; COUNTER3-LABEL: @test2(
; COUNTER3-NEXT:    [[TMP2:%.*]] = icmp eq i32* [[TMP0:%.*]], null
; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[TMP0]]) ]
; COUNTER3-NEXT:    ret i1 [[TMP2]]
;
  %2 = icmp eq i32* %0, null
  call void @llvm.assume(i1 true) ["nonnull"(i32* %0)]
  ret i1 %2
}

define dso_local i32 @test4(i32* readonly %0, i1 %cond) {
; COUNTER1-LABEL: @test4(
; COUNTER1-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP0:%.*]], i32 4) ]
; COUNTER1-NEXT:    br i1 [[COND:%.*]], label [[A:%.*]], label [[B:%.*]]
; COUNTER1:       B:
; COUNTER1-NEXT:    br label [[A]]
; COUNTER1:       A:
; COUNTER1-NEXT:    [[TMP2:%.*]] = icmp eq i32* [[TMP0]], null
; COUNTER1-NEXT:    br i1 [[TMP2]], label [[TMP5:%.*]], label [[TMP3:%.*]]
; COUNTER1:       3:
; COUNTER1-NEXT:    [[TMP4:%.*]] = load i32, i32* [[TMP0]], align 4
; COUNTER1-NEXT:    br label [[TMP5]]
; COUNTER1:       5:
; COUNTER1-NEXT:    [[TMP6:%.*]] = phi i32 [ [[TMP4]], [[TMP3]] ], [ 0, [[A]] ]
; COUNTER1-NEXT:    ret i32 [[TMP6]]
;
; COUNTER2-LABEL: @test4(
; COUNTER2-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP0:%.*]], i32 4) ]
; COUNTER2-NEXT:    br i1 [[COND:%.*]], label [[A:%.*]], label [[B:%.*]]
; COUNTER2:       B:
; COUNTER2-NEXT:    br label [[A]]
; COUNTER2:       A:
; COUNTER2-NEXT:    br i1 false, label [[TMP4:%.*]], label [[TMP2:%.*]]
; COUNTER2:       2:
; COUNTER2-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP0]], align 4
; COUNTER2-NEXT:    br label [[TMP4]]
; COUNTER2:       4:
; COUNTER2-NEXT:    [[TMP5:%.*]] = phi i32 [ [[TMP3]], [[TMP2]] ], [ 0, [[A]] ]
; COUNTER2-NEXT:    ret i32 [[TMP5]]
;
; COUNTER3-LABEL: @test4(
; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP0:%.*]], i32 4) ]
; COUNTER3-NEXT:    br i1 [[COND:%.*]], label [[A:%.*]], label [[B:%.*]]
; COUNTER3:       B:
; COUNTER3-NEXT:    br label [[A]]
; COUNTER3:       A:
; COUNTER3-NEXT:    br i1 false, label [[TMP4:%.*]], label [[TMP2:%.*]]
; COUNTER3:       2:
; COUNTER3-NEXT:    [[TMP3:%.*]] = load i32, i32* [[TMP0]], align 4
; COUNTER3-NEXT:    br label [[TMP4]]
; COUNTER3:       4:
; COUNTER3-NEXT:    [[TMP5:%.*]] = phi i32 [ [[TMP3]], [[TMP2]] ], [ 0, [[A]] ]
; COUNTER3-NEXT:    ret i32 [[TMP5]]
;
  call void @llvm.assume(i1 true) ["dereferenceable"(i32* %0, i32 4)]
  br i1 %cond, label %A, label %B

B:
  br label %A

A:
  %2 = icmp eq i32* %0, null
  br i1 %2, label %5, label %3

3:                                                ; preds = %1
  %4 = load i32, i32* %0, align 4
  br label %5

5:                                                ; preds = %1, %3
  %6 = phi i32 [ %4, %3 ], [ 0, %A ]
  ret i32 %6
}
+79 −0
Original line number Diff line number Diff line
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
; RUN: opt -passes='assume-builder,verify' --enable-knowledge-retention --debug-counter=assume-builder-counter-skip=5,assume-builder-counter-count=1 -S %s | FileCheck %s --check-prefixes=COUNTER1
; RUN: opt -passes='assume-builder,verify' --enable-knowledge-retention --debug-counter=assume-builder-counter-skip=1,assume-builder-counter-count=3 -S %s | FileCheck %s --check-prefixes=COUNTER2
; RUN: opt -passes='assume-builder,verify' --enable-knowledge-retention --debug-counter=assume-builder-counter-skip=2,assume-builder-counter-count=200 -S %s | FileCheck %s --check-prefixes=COUNTER3

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"

declare void @func(i32*, i32*)
declare void @func_cold(i32*) cold willreturn nounwind
declare void @func_strbool(i32*) "no-jump-tables"
declare void @func_many(i32*) "no-jump-tables" nounwind "less-precise-fpmad" willreturn norecurse
declare void @func_argattr(i32* align 8, i32* nonnull) nounwind
declare void @may_throw()

define void @test(i32* %P, i32* %P1, i32* %P2, i32* %P3) {
; COUNTER1-LABEL: define {{[^@]+}}@test
; COUNTER1-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i32* [[P2:%.*]], i32* [[P3:%.*]])
; COUNTER1-NEXT:    call void @func(i32* nonnull dereferenceable(16) [[P]], i32* null)
; COUNTER1-NEXT:    call void @func(i32* dereferenceable(12) [[P1]], i32* nonnull [[P]])
; COUNTER1-NEXT:    call void @func_cold(i32* dereferenceable(12) [[P1]]) #5
; COUNTER1-NEXT:    call void @func_cold(i32* dereferenceable(12) [[P1]])
; COUNTER1-NEXT:    call void @func(i32* [[P1]], i32* [[P]])
; COUNTER1-NEXT:    call void @func_strbool(i32* [[P1]])
; COUNTER1-NEXT:    call void @func(i32* dereferenceable(32) [[P]], i32* dereferenceable(8) [[P]])
; COUNTER1-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[P1]], i64 8) ]
; COUNTER1-NEXT:    call void @func_many(i32* align 8 [[P1]])
; COUNTER1-NEXT:    call void @func_argattr(i32* [[P2]], i32* [[P3]])
; COUNTER1-NEXT:    call void @func(i32* nonnull [[P1]], i32* nonnull [[P]])
; COUNTER1-NEXT:    ret void
;
; COUNTER2-LABEL: define {{[^@]+}}@test
; COUNTER2-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i32* [[P2:%.*]], i32* [[P3:%.*]])
; COUNTER2-NEXT:    call void @func(i32* nonnull dereferenceable(16) [[P]], i32* null)
; COUNTER2-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 12), "nonnull"(i32* [[P]]) ]
; COUNTER2-NEXT:    call void @func(i32* dereferenceable(12) [[P1]], i32* nonnull [[P]])
; COUNTER2-NEXT:    call void @llvm.assume(i1 true) [ "cold"() ]
; COUNTER2-NEXT:    call void @func_cold(i32* dereferenceable(12) [[P1]]) #5
; COUNTER2-NEXT:    call void @llvm.assume(i1 true) [ "cold"() ]
; COUNTER2-NEXT:    call void @func_cold(i32* dereferenceable(12) [[P1]])
; COUNTER2-NEXT:    call void @func(i32* [[P1]], i32* [[P]])
; COUNTER2-NEXT:    call void @func_strbool(i32* [[P1]])
; COUNTER2-NEXT:    call void @func(i32* dereferenceable(32) [[P]], i32* dereferenceable(8) [[P]])
; COUNTER2-NEXT:    call void @func_many(i32* align 8 [[P1]])
; COUNTER2-NEXT:    call void @func_argattr(i32* [[P2]], i32* [[P3]])
; COUNTER2-NEXT:    call void @func(i32* nonnull [[P1]], i32* nonnull [[P]])
; COUNTER2-NEXT:    ret void
;
; COUNTER3-LABEL: define {{[^@]+}}@test
; COUNTER3-SAME: (i32* [[P:%.*]], i32* [[P1:%.*]], i32* [[P2:%.*]], i32* [[P3:%.*]])
; COUNTER3-NEXT:    call void @func(i32* nonnull dereferenceable(16) [[P]], i32* null)
; COUNTER3-NEXT:    call void @func(i32* dereferenceable(12) [[P1]], i32* nonnull [[P]])
; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P1]], i64 12), "cold"() ]
; COUNTER3-NEXT:    call void @func_cold(i32* dereferenceable(12) [[P1]]) #5
; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "cold"() ]
; COUNTER3-NEXT:    call void @func_cold(i32* dereferenceable(12) [[P1]])
; COUNTER3-NEXT:    call void @func(i32* [[P1]], i32* [[P]])
; COUNTER3-NEXT:    call void @func_strbool(i32* [[P1]])
; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[P]], i64 32) ]
; COUNTER3-NEXT:    call void @func(i32* dereferenceable(32) [[P]], i32* dereferenceable(8) [[P]])
; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[P1]], i64 8) ]
; COUNTER3-NEXT:    call void @func_many(i32* align 8 [[P1]])
; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[P2]], i64 8), "nonnull"(i32* [[P3]]) ]
; COUNTER3-NEXT:    call void @func_argattr(i32* [[P2]], i32* [[P3]])
; COUNTER3-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P1]]), "nonnull"(i32* [[P]]) ]
; COUNTER3-NEXT:    call void @func(i32* nonnull [[P1]], i32* nonnull [[P]])
; COUNTER3-NEXT:    ret void
;
  call void @func(i32* nonnull dereferenceable(16) %P, i32* null)
  call void @func(i32* dereferenceable(12) %P1, i32* nonnull %P)
  call void @func_cold(i32* dereferenceable(12) %P1) cold
  call void @func_cold(i32* dereferenceable(12) %P1)
  call void @func(i32* %P1, i32* %P)
  call void @func_strbool(i32* %P1)
  call void @func(i32* dereferenceable(32) %P, i32* dereferenceable(8) %P)
  call void @func_many(i32* align 8 %P1)
  call void @func_argattr(i32* %P2, i32* %P3)
  call void @func(i32* nonnull %P1, i32* nonnull %P)
  ret void
}