File: GenXAlignmentInfo.h

package info (click to toggle)
intel-graphics-compiler 1.0.17791.18-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 102,312 kB
  • sloc: cpp: 935,343; lisp: 286,143; ansic: 16,196; python: 3,279; yacc: 2,487; lex: 1,642; pascal: 300; sh: 174; makefile: 27
file content (144 lines) | stat: -rw-r--r-- 5,028 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
139
140
141
142
143
144
/*========================== begin_copyright_notice ============================

Copyright (C) 2017-2023 Intel Corporation

SPDX-License-Identifier: MIT

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

//
/// genx::AlignmentInfo : alignment information
/// -------------------------------------------
///
/// AlignmentInfo is a cache of information on the alignment of instruction
/// values in a function. It does not persist between passes.
///
/// A pass that needs alignment information constructs an AlignmentInfo at
/// the start of the pass, and then calls the ``get`` method each time it wants
/// alignment information for a particular instruction value. AlignmentInfo
/// calculates it if it is not already in its cache, which probably involves
/// also calculating the alignment of other instructions that the given one
/// depends on.
///
/// This cacheing and lazy calculation is done instead of having a separate
/// analysis pass because alignment is needed for only a small subset of values
/// in a function.
///
/// The alignment is returned as an *Alignment* object with three fields:
/// *ConstBits*, if ConstBits is not 0x7fffffff, alignment is a known
/// bit-pattern, otherwise *LogAlign* and *ExtraBits* (where 0 <= ExtraBits < (1
/// << LogAlign)), stating that the value is known to be A << LogAlign |
/// ExtraBits for some A.
///
/// For a vector value, the alignment information is for element 0.
///
/// The calculation uses a worklist algorithm that can cope with phi nodes and
/// loops. So, for example, a variable (used as an indirect region index) that
/// starts at 10 then is incremented by 8 inside a loop is correctly calculated
/// to be 8A+2 for some A.
///
//===----------------------------------------------------------------------===//

#ifndef GENXALIGNMENTINFO_H
#define GENXALIGNMENTINFO_H

#include "GenX.h"
#include "IgnoreRAUWValueMap.h"
#include "Probe/Assertion.h"

namespace llvm {
  class raw_ostream;

namespace genx {

// Alignment : the alignment of a value
class Alignment {
  unsigned LogAlign;
  unsigned ExtraBits;
  unsigned ConstBits;

  static constexpr unsigned MaskForUnknown = 0x7fffffff;
  static constexpr unsigned UnsignedAllOnes = 0xffffffff;

public:
  // No-arg constructor sets to uncomputed state.
  Alignment() { setUncomputed(); }
  // Constructor given LogAlign and ExtraBits fields.
  Alignment(unsigned LogAlign, unsigned ExtraBits)
      : LogAlign(LogAlign), ExtraBits(ExtraBits), ConstBits(MaskForUnknown) {}
  // Constructor given literal value.
  Alignment(unsigned C);
  // Constructor given Constant.
  Alignment(Constant *C);

  // Get an unknown alignment
  static Alignment getUnknown() { return Alignment(0, 0); }
  // Merge two Alignments
  Alignment merge(Alignment Other) const;
  // Add one Alignment with another Alignment
  Alignment add(Alignment Other) const;
  // Mul one Alignment with another Alignment
  Alignment mul(Alignment Other) const;
  // Logical and Alignment with constant integer
  Alignment logicalAnd(ConstantInt *CI) const;
  // Logical or Alignment with constant integer
  Alignment logicalOr(ConstantInt *CI) const;

  // accessors
  bool isUncomputed() const { return LogAlign == UnsignedAllOnes; }
  bool isUnknown() const {
    return LogAlign == 0 && ConstBits == MaskForUnknown;
  }
  bool isConstant() const {
    return !isUncomputed() && ConstBits != MaskForUnknown;
  }
  unsigned getLogAlign() const { IGC_ASSERT(!isUncomputed()); return LogAlign; }
  unsigned getExtraBits() const { IGC_ASSERT(!isUncomputed()); return ExtraBits; }
  int64_t getConstBits() const { IGC_ASSERT(isConstant()); return ConstBits; }
  // comparison
  bool operator==(const Alignment &Rhs) const {
    return (LogAlign == Rhs.LogAlign &&
            ExtraBits == Rhs.ExtraBits &&
            ConstBits == Rhs.ConstBits);
  }
  static Alignment getAlignmentForConstant(Constant *C);
  // Debug dump/print
  void dump() const;
  void print(raw_ostream &OS) const;
private:
  void setUncomputed() {
    LogAlign = UnsignedAllOnes;
    ExtraBits = 0;
    ConstBits = MaskForUnknown;
  }
  // Type alias for std::min and std::max functions.
  using SelectFunction = const unsigned &(*)(const unsigned &,
                                             const unsigned &);
  Alignment logicalOp(ConstantInt *CI, SelectFunction F) const;
};

// AlignmentInfo : cache of alignment of instructions in a function
class AlignmentInfo {
  ValueMap<const Value *, Alignment,
          IgnoreRAUWValueMapConfig<const Value *>> InstMap;
public:
  // AlignmentInfo constructor
  AlignmentInfo() {}
  // Clear the cache of value alignments
  void clear() { InstMap.clear(); }
  // get the alignment of a Value
  Alignment get(Value *V);
public:
  // return an Alignment for a value
  Alignment getFromInstMap(Value *V);
};

inline raw_ostream &operator<<(raw_ostream &OS, const Alignment &A) {
  A.print(OS);
  return OS;
}

} // end namespace genx
} // end namespace llvm

#endif /* GENXALIGNMENTINFO_H */