File: AlignmentAnalysis.hpp

package info (click to toggle)
intel-graphics-compiler2 2.16.0-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • 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 (102 lines) | stat: -rw-r--r-- 4,059 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
/*========================== begin_copyright_notice ============================

Copyright (C) 2017-2021 Intel Corporation

SPDX-License-Identifier: MIT

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

#pragma once

#include "common/LLVMWarningsPush.hpp"
#include <llvm/Pass.h>
#include <llvm/ADT/MapVector.h>
#include <llvm/IR/DataLayout.h>
#include <llvm/IR/InstVisitor.h>
#include "common/LLVMWarningsPop.hpp"
#include "llvmWrapper/Support/Alignment.h"

namespace IGC {

/// @brief  This pass correctly sets the alignment of all loads
///         and stores according to OpenCL rules.
///         It perform a data-flow analysis to keep track of the highest power
///         of 2 that divides a value.
///         This tracking is performed for integers and for pointers, and is
///         based on the assumption that global variables and kernel arguments
///         are always aligned on their data type.
///         The result is an underapproximation of the actual alignment, so it
///         is always safe.
class AlignmentAnalysis : public llvm::FunctionPass, public llvm::InstVisitor<AlignmentAnalysis, llvm::Align> {
public:
  // Pass identification, replacement for typeid
  static char ID;

  /// @brief  Constructor
  AlignmentAnalysis();

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

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

  virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { AU.setPreservesCFG(); }

  /// @brief  Main entry point.
  virtual bool runOnFunction(llvm::Function &F) override;

  // @ brief Instruction visitors
  llvm::Align visitInstruction(llvm::Instruction &I);
  llvm::Align visitAllocaInst(llvm::AllocaInst &I);
  llvm::Align visitIntToPtrInst(llvm::IntToPtrInst &I);
  llvm::Align visitPtrToIntInst(llvm::PtrToIntInst &I);
  llvm::Align visitSelectInst(llvm::SelectInst &I);
  llvm::Align visitGetElementPtrInst(llvm::GetElementPtrInst &I);
  llvm::Align visitPHINode(llvm::PHINode &I);
  llvm::Align visitBitCastInst(llvm::BitCastInst &I);
  llvm::Align visitAdd(llvm::BinaryOperator &I);
  llvm::Align visitMul(llvm::BinaryOperator &I);
  llvm::Align visitShl(llvm::BinaryOperator &I);
  llvm::Align visitAnd(llvm::BinaryOperator &I);
  llvm::Align visitTruncInst(llvm::TruncInst &I);
  llvm::Align visitZExtInst(llvm::ZExtInst &I);
  llvm::Align visitSExtInst(llvm::SExtInst &I);
  llvm::Align visitCallInst(llvm::CallInst &I);

  bool SetInstAlignment(llvm::Instruction &I);
  bool SetInstAlignment(llvm::LoadInst &I);
  bool SetInstAlignment(llvm::StoreInst &I);
  bool SetInstAlignment(llvm::MemSetInst &I);
  bool SetInstAlignment(llvm::MemCpyInst &I);
  bool SetInstAlignment(llvm::MemMoveInst &I);

protected:
  // Check if the function has OpenCL metadata that specifies the alignment of
  // its arguments. If it does, set the LLVM alignment attribute of the
  // arguments accordingly. This is helpful for passes like InferAlignment.
  void setArgumentAlignmentBasedOnOptionalMetadata(llvm::Function &F);

  /// @breif Evaluates the alignment of I based on its operands.
  ///        For Load and Store instructions, also sets the alignment
  ///        of the operation itself.
  /// @param I The instruction to process
  bool processInstruction(llvm::Instruction *I);

  /// @brief Returns the alignment for V, if it is known.
  ///        Otherwise, returns the maximum alignment.
  /// @param V the value the alignment of which we're interested in
  llvm::Align getAlignValue(llvm::Value *V) const;

  /// @brief Returns the alignment of a constant integer.
  ///        This is normally 1 << ctz(C) (the highest power of 2 that divides C),
  ///        except when C is 0, when it is the max alignment
  llvm::Align getConstantAlignment(uint64_t C) const;

  /// @brief This map stores the known alignment of every value.
  llvm::MapVector<llvm::Value *, llvm::Align> m_alignmentMap;

  const llvm::DataLayout *m_DL = nullptr;
};

} // namespace IGC