File: ScalarArgAsPointer.hpp

package info (click to toggle)
intel-graphics-compiler2 2.16.0-2
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 106,644 kB
  • sloc: cpp: 805,640; lisp: 287,672; ansic: 16,414; python: 3,952; yacc: 2,588; lex: 1,666; pascal: 313; sh: 186; makefile: 35
file content (138 lines) | stat: -rw-r--r-- 5,501 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*========================== begin_copyright_notice ============================

Copyright (C) 2022-2023 Intel Corporation

SPDX-License-Identifier: MIT

============================= end_copyright_notice ===========================*/

#pragma once

#include "Compiler/MetaDataUtilsWrapper.h"

#include "common/LLVMWarningsPush.hpp"
#include <llvm/Pass.h>
#include <llvm/IR/InstVisitor.h>
#include "common/LLVMWarningsPop.hpp"

namespace IGC {
/// @brief  Pass to analyze if scalar (byval) kernel argument is used for access to global memory.
///         This includes explicit scalar arguments casted to pointers:
///
///             kernel void f(long addr) {
///                 *((global int*) addr) += 1;
///             }
///
///         Or pointers in structs (implicit arguments):
///
///             struct S { int* ptr };
///             kernel void f(struct S s) {
///                 *(s.ptr) += 1;
///             }
///
///         To parse implicit arguments this pass must be run after ResolveAggregateArguments.

/// IMPORTANT!!!
/// Please bump up INDIRECT_ACCESS_DETECTION_VERSION when introducing any functional fixes in this pass.

class ScalarArgAsPointerAnalysis : public llvm::ModulePass, public llvm::InstVisitor<ScalarArgAsPointerAnalysis> {
public:
  // Pass identification, replacement for typeid
  static char ID;

  /// @brief  Constructor
  ScalarArgAsPointerAnalysis();

  /// @brief  Destructor
  ~ScalarArgAsPointerAnalysis() {}

  /// @brief  Provides name of pass
  virtual llvm::StringRef getPassName() const override { return "ScalarArgAsPointerAnalysis"; }

  void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { AU.addRequired<MetaDataUtilsWrapper>(); }

  /// @brief   Main entry point. Runs on all kernel functions in the given module, analyzes them and
  ///          creates metadata with scalar kernel arguments (both explicit and implicit) used to
  ///          access global memory.
  /// @param   M module to analyze.
  /// @returns True if metadata was modified.
  virtual bool runOnModule(llvm::Module &M) override;

  void visitStoreInst(llvm::StoreInst &I);
  void visitLoadInst(llvm::LoadInst &I);
  void visitCallInst(llvm::CallInst &I);

private:
  using ArgSet = llvm::SmallPtrSet<llvm::Argument *, 2>;

  void visitGenIntrinsic(llvm::GenIntrinsicInst &I);

  /// @brief    Analyzes kernel function and saves result in function metadata.
  /// @param    F function to analyze.
  /// @returns  True if function metadata was updated.
  bool analyzeFunction(llvm::Function &F);

  /// @brief  Common entrypoint for load/store visitors - traces back destination pointer to kernel
  ///         arguments and saves them to common list.
  /// @param  V destination pointer.
  void analyzePointer(llvm::Value *V);

  void analyzeValue(llvm::Value *V);

  /// @brief    Returns a set of matching kernel arguments. Returns null if load/store:
  ///             (1) is indirect, or
  ///             (2) uses pointer kernel argument
  /// @param    I instruction to trace back.
  /// @returns  Set of matching kernel arguments.
  const std::shared_ptr<ArgSet> findArgs(llvm::Instruction *I);

  /// @brief    Called by findArgs to analyzes instruction's operands. Returns null if load/store:
  ///             (1) is indirect, or
  ///             (2) uses pointer kernel argument
  /// @param    op operand to trace back.
  /// @returns  Set of matching kernel arguments.
  const std::shared_ptr<ArgSet> analyzeOperand(llvm::Value *op);

  llvm::Argument *analyzeGlobal(llvm::GlobalValue *V);

  /// @brief  Checks if instruction stores kernel argument, and if true, traces back to
  ///         alloca instruction (with offset). This is required for decomposed structs
  ///         that are copied into private memory.
  /// @param  SI visited store instruction.
  void analyzeStoredArg(llvm::StoreInst &I);

  /// @brief    Searches for kernel argument stored in allocated memory. Required for
  ///           decomposed structs that are copied into private memory. Can return more
  ///           than one argument if load instruction uses variable offset.
  /// @param    LI load instruction to check.
  /// @param    args output list of kernel arguments.
  /// @returns  true if kernel argument found or false if instruction doesn't trace back to alloca.
  bool findStoredArgs(llvm::LoadInst &LI, ArgSet &args);

  /// @brief    Traces pointer of load/store instruction back to alloca instruction.
  /// @param    V input load/store pointer.
  /// @param    AI output alloca instruction.
  /// @param    GEPI output GEP instruction (offset from alloca to value V).
  /// @returns  true if traced back to alloca.
  bool findAllocaWithOffset(llvm::Value *V, llvm::AllocaInst *&AI, llvm::GetElementPtrInst *&GEPI);

  /// @brief Combined set of all matching arguments found in currently analyzed function.
  ArgSet m_matchingArgs;

  /// @brief Cached results for visited instructions.
  // TODO: Should memory footprint be deemed acceptable,
  //       switch to holding the argument sets by value.
  llvm::DenseMap<llvm::Instruction *, std::shared_ptr<ArgSet>> m_visitedInst;

  /// @brief Mapping of basePtr + offset to kernel argument.
  llvm::DenseMap<std::pair<llvm::AllocaInst *, uint64_t>, llvm::Argument *> m_allocas;

  /// @brief Data layout of currently analyzed module.
  const llvm::DataLayout *DL = nullptr;

  IGC::IGCMD::MetaDataUtils *MDU = nullptr;

  llvm::Function *m_currentFunction = nullptr;
};

} // namespace IGC