LLVM  15.0.0git
Operator.cpp
Go to the documentation of this file.
1 //===-- Operator.cpp - Implement the LLVM operators -----------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the non-inline methods for the LLVM Operator classes.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/IR/Operator.h"
14 #include "llvm/IR/DataLayout.h"
16 #include "llvm/IR/Instructions.h"
17 
18 #include "ConstantsContext.h"
19 
20 namespace llvm {
22  switch (getOpcode()) {
23  case Instruction::Add:
24  case Instruction::Sub:
25  case Instruction::Mul:
26  case Instruction::Shl: {
27  auto *OBO = cast<OverflowingBinaryOperator>(this);
28  return OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap();
29  }
30  case Instruction::UDiv:
31  case Instruction::SDiv:
32  case Instruction::AShr:
33  case Instruction::LShr:
34  return cast<PossiblyExactOperator>(this)->isExact();
35  case Instruction::GetElementPtr: {
36  auto *GEP = cast<GEPOperator>(this);
37  // Note: inrange exists on constexpr only
38  return GEP->isInBounds() || GEP->getInRangeIndex() != None;
39  }
40  default:
41  if (const auto *FP = dyn_cast<FPMathOperator>(this))
42  return FP->hasNoNaNs() || FP->hasNoInfs();
43  return false;
44  }
45 }
46 
48  if (auto *I = dyn_cast<GetElementPtrInst>(this))
49  return I->getSourceElementType();
50  return cast<GetElementPtrConstantExpr>(this)->getSourceElementType();
51 }
52 
54  if (auto *I = dyn_cast<GetElementPtrInst>(this))
55  return I->getResultElementType();
56  return cast<GetElementPtrConstantExpr>(this)->getResultElementType();
57 }
58 
60  /// compute the worse possible offset for every level of the GEP et accumulate
61  /// the minimum alignment into Result.
62 
64  for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);
65  GTI != GTE; ++GTI) {
66  int64_t Offset = 1;
67  ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand());
68 
69  if (StructType *STy = GTI.getStructTypeOrNull()) {
70  const StructLayout *SL = DL.getStructLayout(STy);
71  Offset = SL->getElementOffset(OpC->getZExtValue());
72  } else {
73  assert(GTI.isSequential() && "should be sequencial");
74  /// If the index isn't know we take 1 because it is the index that will
75  /// give the worse alignment of the offset.
76  int64_t ElemCount = 1;
77  if (OpC)
78  ElemCount = OpC->getZExtValue();
79  Offset = DL.getTypeAllocSize(GTI.getIndexedType()) * ElemCount;
80  }
81  Result = Align(MinAlign(Offset, Result.value()));
82  }
83  return Result;
84 }
85 
87  const DataLayout &DL, APInt &Offset,
88  function_ref<bool(Value &, APInt &)> ExternalAnalysis) const {
89  assert(Offset.getBitWidth() ==
90  DL.getIndexSizeInBits(getPointerAddressSpace()) &&
91  "The offset bit width does not match DL specification.");
94  DL, Offset, ExternalAnalysis);
95 }
96 
98  Type *SourceType, ArrayRef<const Value *> Index, const DataLayout &DL,
99  APInt &Offset, function_ref<bool(Value &, APInt &)> ExternalAnalysis) {
100  bool UsedExternalAnalysis = false;
101  auto AccumulateOffset = [&](APInt Index, uint64_t Size) -> bool {
102  Index = Index.sextOrTrunc(Offset.getBitWidth());
103  APInt IndexedSize = APInt(Offset.getBitWidth(), Size);
104  // For array or vector indices, scale the index by the size of the type.
105  if (!UsedExternalAnalysis) {
106  Offset += Index * IndexedSize;
107  } else {
108  // External Analysis can return a result higher/lower than the value
109  // represents. We need to detect overflow/underflow.
110  bool Overflow = false;
111  APInt OffsetPlus = Index.smul_ov(IndexedSize, Overflow);
112  if (Overflow)
113  return false;
114  Offset = Offset.sadd_ov(OffsetPlus, Overflow);
115  if (Overflow)
116  return false;
117  }
118  return true;
119  };
120  auto begin = generic_gep_type_iterator<decltype(Index.begin())>::begin(
121  SourceType, Index.begin());
122  auto end = generic_gep_type_iterator<decltype(Index.end())>::end(Index.end());
123  for (auto GTI = begin, GTE = end; GTI != GTE; ++GTI) {
124  // Scalable vectors are multiplied by a runtime constant.
125  bool ScalableType = false;
126  if (isa<ScalableVectorType>(GTI.getIndexedType()))
127  ScalableType = true;
128 
129  Value *V = GTI.getOperand();
130  StructType *STy = GTI.getStructTypeOrNull();
131  // Handle ConstantInt if possible.
132  if (auto ConstOffset = dyn_cast<ConstantInt>(V)) {
133  if (ConstOffset->isZero())
134  continue;
135  // if the type is scalable and the constant is not zero (vscale * n * 0 =
136  // 0) bailout.
137  if (ScalableType)
138  return false;
139  // Handle a struct index, which adds its field offset to the pointer.
140  if (STy) {
141  unsigned ElementIdx = ConstOffset->getZExtValue();
142  const StructLayout *SL = DL.getStructLayout(STy);
143  // Element offset is in bytes.
144  if (!AccumulateOffset(
145  APInt(Offset.getBitWidth(), SL->getElementOffset(ElementIdx)),
146  1))
147  return false;
148  continue;
149  }
150  if (!AccumulateOffset(ConstOffset->getValue(),
151  DL.getTypeAllocSize(GTI.getIndexedType())))
152  return false;
153  continue;
154  }
155 
156  // The operand is not constant, check if an external analysis was provided.
157  // External analsis is not applicable to a struct type.
158  if (!ExternalAnalysis || STy || ScalableType)
159  return false;
160  APInt AnalysisIndex;
161  if (!ExternalAnalysis(*V, AnalysisIndex))
162  return false;
163  UsedExternalAnalysis = true;
164  if (!AccumulateOffset(AnalysisIndex,
165  DL.getTypeAllocSize(GTI.getIndexedType())))
166  return false;
167  }
168  return true;
169 }
170 
172  const DataLayout &DL, unsigned BitWidth,
173  MapVector<Value *, APInt> &VariableOffsets,
174  APInt &ConstantOffset) const {
175  assert(BitWidth == DL.getIndexSizeInBits(getPointerAddressSpace()) &&
176  "The offset bit width does not match DL specification.");
177 
178  auto CollectConstantOffset = [&](APInt Index, uint64_t Size) {
179  Index = Index.sextOrTrunc(BitWidth);
180  APInt IndexedSize = APInt(BitWidth, Size);
181  ConstantOffset += Index * IndexedSize;
182  };
183 
184  for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);
185  GTI != GTE; ++GTI) {
186  // Scalable vectors are multiplied by a runtime constant.
187  bool ScalableType = isa<ScalableVectorType>(GTI.getIndexedType());
188 
189  Value *V = GTI.getOperand();
190  StructType *STy = GTI.getStructTypeOrNull();
191  // Handle ConstantInt if possible.
192  if (auto ConstOffset = dyn_cast<ConstantInt>(V)) {
193  if (ConstOffset->isZero())
194  continue;
195  // If the type is scalable and the constant is not zero (vscale * n * 0 =
196  // 0) bailout.
197  // TODO: If the runtime value is accessible at any point before DWARF
198  // emission, then we could potentially keep a forward reference to it
199  // in the debug value to be filled in later.
200  if (ScalableType)
201  return false;
202  // Handle a struct index, which adds its field offset to the pointer.
203  if (STy) {
204  unsigned ElementIdx = ConstOffset->getZExtValue();
205  const StructLayout *SL = DL.getStructLayout(STy);
206  // Element offset is in bytes.
207  CollectConstantOffset(APInt(BitWidth, SL->getElementOffset(ElementIdx)),
208  1);
209  continue;
210  }
211  CollectConstantOffset(ConstOffset->getValue(),
212  DL.getTypeAllocSize(GTI.getIndexedType()));
213  continue;
214  }
215 
216  if (STy || ScalableType)
217  return false;
218  APInt IndexedSize =
219  APInt(BitWidth, DL.getTypeAllocSize(GTI.getIndexedType()));
220  // Insert an initial offset of 0 for V iff none exists already, then
221  // increment the offset by IndexedSize.
222  if (!IndexedSize.isZero()) {
223  VariableOffsets.insert({V, APInt(BitWidth, 0)});
224  VariableOffsets[V] += IndexedSize;
225  }
226  }
227  return true;
228 }
229 
231  if (all())
232  O << " fast";
233  else {
234  if (allowReassoc())
235  O << " reassoc";
236  if (noNaNs())
237  O << " nnan";
238  if (noInfs())
239  O << " ninf";
240  if (noSignedZeros())
241  O << " nsz";
242  if (allowReciprocal())
243  O << " arcp";
244  if (allowContract())
245  O << " contract";
246  if (approxFunc())
247  O << " afn";
248  }
249 }
250 } // namespace llvm
CmpMode::FP
@ FP
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::drop_begin
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition: STLExtras.h:280
llvm::DataLayout
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:113
llvm::generic_gep_type_iterator
Definition: GetElementPtrTypeIterator.h:31
llvm::Value::MaximumAlignment
static constexpr uint64_t MaximumAlignment
Definition: Value.h:793
GetElementPtrTypeIterator.h
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1185
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::sys::path::end
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:235
llvm::sys::path::begin
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:226
llvm::FastMathFlags::noSignedZeros
bool noSignedZeros() const
Definition: FMF.h:69
llvm::MapVector
This class implements a map that also provides access to all stored values in a deterministic order.
Definition: MapVector.h:37
Operator.h
llvm::gep_type_begin
gep_type_iterator gep_type_begin(const User *GEP)
Definition: GetElementPtrTypeIterator.h:123
llvm::FastMathFlags::noNaNs
bool noNaNs() const
Definition: FMF.h:67
llvm::gep_type_end
gep_type_iterator gep_type_end(const User *GEP)
Definition: GetElementPtrTypeIterator.h:130
llvm::ConstantInt
This is the shared class of boolean and integer constants.
Definition: Constants.h:79
llvm::MinAlign
constexpr uint64_t MinAlign(uint64_t A, uint64_t B)
A and B are either alignments or offsets.
Definition: MathExtras.h:699
llvm::GEPOperator::getResultElementType
Type * getResultElementType() const
Definition: Operator.cpp:53
llvm::FastMathFlags::approxFunc
bool approxFunc() const
Definition: FMF.h:72
llvm::APInt::isZero
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition: APInt.h:359
llvm::FastMathFlags::print
void print(raw_ostream &O) const
Print fast-math flags to O.
Definition: Operator.cpp:230
llvm::FastMathFlags::allowReassoc
bool allowReassoc() const
Flag queries.
Definition: FMF.h:66
llvm::FastMathFlags::allowReciprocal
bool allowReciprocal() const
Definition: FMF.h:70
llvm::Operator::getOpcode
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
Definition: Operator.h:42
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:54
llvm::GEPOperator::getMaxPreservedAlignment
Align getMaxPreservedAlignment(const DataLayout &DL) const
Compute the maximum alignment that this GEP is garranteed to preserve.
Definition: Operator.cpp:59
Align
uint64_t Align
Definition: ELFObjHandler.cpp:81
llvm::Align
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
llvm::None
const NoneType None
Definition: None.h:24
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLFunctionalExtras.h:36
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:239
llvm::FastMathFlags::noInfs
bool noInfs() const
Definition: FMF.h:68
uint64_t
llvm::StructLayout
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
Definition: DataLayout.h:622
I
#define I(x, y, z)
Definition: MD5.cpp:58
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ConstantsContext.h
llvm::Operator::hasPoisonGeneratingFlags
bool hasPoisonGeneratingFlags() const
Return true if this operator has flags which may cause this operator to evaluate to poison despite ha...
Definition: Operator.cpp:21
llvm::APInt
Class for arbitrary precision integers.
Definition: APInt.h:75
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
llvm::MapVector::insert
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition: MapVector.h:118
Mul
BinaryOperator * Mul
Definition: X86PartialReduction.cpp:70
DataLayout.h
llvm::StructType
Class to represent struct types.
Definition: DerivedTypes.h:213
DL
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Definition: AArch64SLSHardening.cpp:76
llvm::ConstantInt::getZExtValue
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition: Constants.h:142
llvm::GEPOperator::getPointerAddressSpace
unsigned getPointerAddressSpace() const
Method to return the address space of the pointer operand.
Definition: Operator.h:435
llvm::StructLayout::getElementOffset
uint64_t getElementOffset(unsigned Idx) const
Definition: DataLayout.h:652
llvm::GEPOperator::accumulateConstantOffset
bool accumulateConstantOffset(const DataLayout &DL, APInt &Offset, function_ref< bool(Value &, APInt &)> ExternalAnalysis=nullptr) const
Accumulate the constant address offset of this GEP if possible.
Definition: Operator.cpp:86
llvm::BitWidth
constexpr unsigned BitWidth
Definition: BitmaskEnum.h:147
llvm::GEPOperator::collectOffset
bool collectOffset(const DataLayout &DL, unsigned BitWidth, MapVector< Value *, APInt > &VariableOffsets, APInt &ConstantOffset) const
Collect the offset of this GEP as a map of Values to their associated APInt multipliers,...
Definition: Operator.cpp:171
llvm::User::operand_values
iterator_range< value_op_iterator > operand_values()
Definition: User.h:266
llvm::MCID::Add
@ Add
Definition: MCInstrDesc.h:185
Instructions.h
llvm::GEPOperator::getSourceElementType
Type * getSourceElementType() const
Definition: Operator.cpp:47
llvm::FastMathFlags::all
bool all() const
Definition: FMF.h:60
GEP
Hexagon Common GEP
Definition: HexagonCommonGEP.cpp:172
llvm::FastMathFlags::allowContract
bool allowContract() const
Definition: FMF.h:71
llvm::Value
LLVM Value Representation.
Definition: Value.h:74