File: TransformArgCopy.h

package info (click to toggle)
intel-graphics-compiler 1.0.12504.6-1%2Bdeb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 83,912 kB
  • sloc: cpp: 910,147; lisp: 202,655; ansic: 15,197; python: 4,025; yacc: 2,241; lex: 1,570; pascal: 244; sh: 104; makefile: 25
file content (219 lines) | stat: -rw-r--r-- 7,154 bytes parent folder | download | duplicates (2)
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/*========================== begin_copyright_notice ============================

Copyright (C) 2022 Intel Corporation

SPDX-License-Identifier: MIT

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

#ifndef VC_UTILS_GENX_TRANSFORMARGCOPY_H
#define VC_UTILS_GENX_TRANSFORMARGCOPY_H

#include "vc/Utils/GenX/TypeSize.h"

#include <llvm/ADT/DenseMap.h>
#include <llvm/ADT/SetVector.h>
#include <llvm/ADT/SmallPtrSet.h>
#include <llvm/ADT/SmallVector.h>
#include <llvm/Analysis/CallGraph.h>
#include <llvm/IR/Argument.h>
#include <llvm/IR/Attributes.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/Instructions.h>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Type.h>
#include <llvm/IR/Value.h>

#include <vector>

namespace vc {

// Collect arguments that should be transformed.
llvm::SmallPtrSet<llvm::Argument *, 8>
collectArgsToTransform(llvm::Function &F, vc::TypeSizeWrapper MaxStructSize);

void replaceUsesWithinFunction(
    const llvm::SmallDenseMap<llvm::Value *, llvm::Value *> &GlobalsToReplace,
    llvm::Function *F);

struct TransformedFuncType {
  llvm::SmallVector<llvm::Type *, 8> Ret;
  llvm::SmallVector<llvm::Type *, 8> Args;
};

enum class ArgKind { General, CopyIn, CopyOut, CopyInOut };
enum class GlobalArgKind { ByValueIn, ByValueInOut, ByPointer };

struct GlobalArgInfo {
  llvm::GlobalVariable *GV;
  GlobalArgKind Kind;
};

struct GlobalArgsInfo {
  static constexpr int UndefIdx = -1;
  std::vector<GlobalArgInfo> Globals;
  int FirstGlobalArgIdx = UndefIdx;

  GlobalArgInfo getGlobalInfoForArgNo(int ArgIdx) const;
  llvm::GlobalVariable *getGlobalForArgNo(int ArgIdx) const {
    return getGlobalInfoForArgNo(ArgIdx).GV;
  }
};

// Data and helpers for ret to arg (both orig and new ones) connection.
// It doesn't contain ret info itself: ret_id is taken from position in vec.
// Check TransformedFuncInfo for more details.
class RetToArgLink {
  static constexpr int OmittedIdx = -1;
  const int NewIdx;
  const int OrigIdx;

  RetToArgLink(int NewIdxIn, int OrigIdxIn)
      : NewIdx{NewIdxIn}, OrigIdx{OrigIdxIn} {}

  // Check if the given idx is real one.
  static bool isRealIdx(int Idx);
  // Check if the given idx is omitted.
  static bool isOmittedIdx(int Idx);

public:
  // Create RetToArgLink for original return value.
  static RetToArgLink createForOrigRet();
  // Create RetToArgLink for global argument.
  // Global argument is a newly added one, thus it is omitted in
  // original call.
  static RetToArgLink createForGlobalArg(int NewIdx);
  // Create RetToArgLink for omitted argument.
  static RetToArgLink createForOmittedArg(int OrigIdx);
  // Create RetToArgLink with specific indices.
  static RetToArgLink createForLinkedArgs(int NewIdx, int OrigIdx);

  // Check if the link describes the original return value.
  bool isOrigRet() const;
  // Check if the link describes the global argument.
  bool isGlobalArg() const;
  // Check if the link describes the omitted argument.
  bool isOmittedArg() const;
  // Get new argument idx.
  int getNewIdx() const;
  // Get orig argument idx.
  int getOrigIdx() const;
};

// Information for existing original arg. OrigId is not stored here.
// Chech TransformedFuncInfo for more details.
class OrigArgInfo {
  static constexpr int OmittedIdx = -1;
  llvm::Type *TransformedOrigType;
  const ArgKind Kind;
  const int NewIdx;

public:
  OrigArgInfo(llvm::Type *TyIn, ArgKind KindIn, int NewIdxIn = OmittedIdx);

  // Check if the argument is omitted.
  bool isOmittedArg() const { return NewIdx == OmittedIdx; }
  // Get transformed original argument type.
  llvm::Type *getTransformedOrigType() const { return TransformedOrigType; }
  // Get argument kind.
  ArgKind getKind() const { return Kind; }
  // Get new argument idx.
  int getNewIdx() const;
};

struct ParameterAttrInfo {
  unsigned ArgIndex;
  llvm::Attribute::AttrKind Attr;
};

// Computing a new prototype for the function. E.g.
//
// i32 @foo(i32, <8 x i32>*) becomes {i32, <8 x i32>} @bar(i32, <8 x i32>)
//
class TransformedFuncInfo {
  TransformedFuncType NewFuncType;
  llvm::AttributeList Attrs;
  std::vector<ParameterAttrInfo> DiscardedParameterAttrs;
  std::vector<RetToArgLink> RetToArg;
  std::vector<OrigArgInfo> OrigArgs;
  GlobalArgsInfo GlobalArgs;

public:
  TransformedFuncInfo(llvm::Function &OrigFunc,
                      llvm::SmallPtrSetImpl<llvm::Argument *> &ArgsToTransform);
  void appendGlobals(llvm::SetVector<llvm::GlobalVariable *> &Globals);
  // Gather attributes for new function type according to transformations.
  llvm::AttributeList gatherAttributes(llvm::LLVMContext &Context,
                                       const llvm::AttributeList &AL) const;

  const TransformedFuncType &getType() const { return NewFuncType; }
  llvm::AttributeList getAttributes() const { return Attrs; }
  const std::vector<ParameterAttrInfo> &getDiscardedParameterAttrs() const {
    return DiscardedParameterAttrs;
  }
  const std::vector<RetToArgLink> &getRetToArgInfo() const { return RetToArg; }
  const std::vector<OrigArgInfo> &getOrigArgInfo() const { return OrigArgs; }
  const GlobalArgsInfo &getGlobalArgsInfo() const { return GlobalArgs; }

private:
  void
  fillOrigArgInfo(llvm::Function &OrigFunc,
                  llvm::SmallPtrSetImpl<llvm::Argument *> &ArgsToTransform);

  void inheritAttributes(llvm::Function &OrigFunc);

  // Sret may become inapplicable for transformed function.
  void discardStructRetAttr(llvm::LLVMContext &Context);

  void appendRetCopyOutInfo();
};

llvm::Function *createTransformedFuncDecl(llvm::Function &OrigFunc,
                                          const TransformedFuncInfo &TFuncInfo);

class FuncUsersUpdater {
  llvm::Function &OrigFunc;
  llvm::Function &NewFunc;
  const TransformedFuncInfo &NewFuncInfo;
  llvm::CallGraphNode &NewFuncCGN;
  llvm::CallGraph &CG;

public:
  FuncUsersUpdater(llvm::Function &OrigFuncIn, llvm::Function &NewFuncIn,
                   const TransformedFuncInfo &NewFuncInfoIn,
                   llvm::CallGraphNode &NewFuncCGNIn, llvm::CallGraph &CGIn)
      : OrigFunc{OrigFuncIn}, NewFunc{NewFuncIn}, NewFuncInfo{NewFuncInfoIn},
        NewFuncCGN{NewFuncCGNIn}, CG{CGIn} {}

  void run();

private:
  llvm::CallInst *updateFuncDirectUser(llvm::CallInst &OrigCall);
};

class FuncBodyTransfer {
  llvm::Function &OrigFunc;
  llvm::Function &NewFunc;
  const TransformedFuncInfo &NewFuncInfo;

public:
  FuncBodyTransfer(llvm::Function &OrigFuncIn, llvm::Function &NewFuncIn,
                   const TransformedFuncInfo &NewFuncInfoIn)
      : OrigFunc{OrigFuncIn}, NewFunc{NewFuncIn}, NewFuncInfo{NewFuncInfoIn} {}
  void run();

private:
  std::vector<llvm::Value *> handleTransformedFuncArgs();
  void handleTransformedFuncRet(
      llvm::ReturnInst &OrigRet,
      const std::vector<llvm::Value *> &OrigArgReplacements,
      std::vector<llvm::Value *> &LocalizedGlobals);
  void handleTransformedFuncRets(
      const std::vector<llvm::Value *> &OrigArgReplacements,
      std::vector<llvm::Value *> &LocalizedGlobals);
};

} // namespace vc

#endif // VC_UTILS_GENX_TRANSFORMARGCOPY_H