LLVM  12.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 #include "llvm/IR/Type.h"
18 
19 #include "ConstantsContext.h"
20 
21 namespace llvm {
23  if (auto *I = dyn_cast<GetElementPtrInst>(this))
24  return I->getSourceElementType();
25  return cast<GetElementPtrConstantExpr>(this)->getSourceElementType();
26 }
27 
29  if (auto *I = dyn_cast<GetElementPtrInst>(this))
30  return I->getResultElementType();
31  return cast<GetElementPtrConstantExpr>(this)->getResultElementType();
32 }
33 
35  /// compute the worse possible offset for every level of the GEP et accumulate
36  /// the minimum alignment into Result.
37 
39  for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);
40  GTI != GTE; ++GTI) {
41  int64_t Offset = 1;
42  ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand());
43 
44  if (StructType *STy = GTI.getStructTypeOrNull()) {
45  const StructLayout *SL = DL.getStructLayout(STy);
46  Offset = SL->getElementOffset(OpC->getZExtValue());
47  } else {
48  assert(GTI.isSequential() && "should be sequencial");
49  /// If the index isn't know we take 1 because it is the index that will
50  /// give the worse alignment of the offset.
51  int64_t ElemCount = 1;
52  if (OpC)
53  ElemCount = OpC->getZExtValue();
54  Offset = DL.getTypeAllocSize(GTI.getIndexedType()) * ElemCount;
55  }
56  Result = Align(MinAlign(Offset, Result.value()));
57  }
58  return Result;
59 }
60 
62  const DataLayout &DL, APInt &Offset,
63  function_ref<bool(Value &, APInt &)> ExternalAnalysis) const {
64  assert(Offset.getBitWidth() ==
66  "The offset bit width does not match DL specification.");
67 
68  bool UsedExternalAnalysis = false;
69  auto AccumulateOffset = [&](APInt Index, uint64_t Size) -> bool {
70  Index = Index.sextOrTrunc(Offset.getBitWidth());
71  APInt IndexedSize = APInt(Offset.getBitWidth(), Size);
72  // For array or vector indices, scale the index by the size of the type.
73  if (!UsedExternalAnalysis) {
74  Offset += Index * IndexedSize;
75  } else {
76  // External Analysis can return a result higher/lower than the value
77  // represents. We need to detect overflow/underflow.
78  bool Overflow = false;
79  APInt OffsetPlus = Index.smul_ov(IndexedSize, Overflow);
80  if (Overflow)
81  return false;
82  Offset = Offset.sadd_ov(OffsetPlus, Overflow);
83  if (Overflow)
84  return false;
85  }
86  return true;
87  };
88 
89  for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);
90  GTI != GTE; ++GTI) {
91  // Scalable vectors are multiplied by a runtime constant.
92  bool ScalableType = false;
93  if (isa<ScalableVectorType>(GTI.getIndexedType()))
94  ScalableType = true;
95 
96  Value *V = GTI.getOperand();
97  StructType *STy = GTI.getStructTypeOrNull();
98  // Handle ConstantInt if possible.
99  if (auto ConstOffset = dyn_cast<ConstantInt>(V)) {
100  if (ConstOffset->isZero())
101  continue;
102  // if the type is scalable and the constant is not zero (vscale * n * 0 =
103  // 0) bailout.
104  if (ScalableType)
105  return false;
106  // Handle a struct index, which adds its field offset to the pointer.
107  if (STy) {
108  unsigned ElementIdx = ConstOffset->getZExtValue();
109  const StructLayout *SL = DL.getStructLayout(STy);
110  // Element offset is in bytes.
111  if (!AccumulateOffset(
112  APInt(Offset.getBitWidth(), SL->getElementOffset(ElementIdx)),
113  1))
114  return false;
115  continue;
116  }
117  if (!AccumulateOffset(ConstOffset->getValue(),
118  DL.getTypeAllocSize(GTI.getIndexedType())))
119  return false;
120  continue;
121  }
122 
123  // The operand is not constant, check if an external analysis was provided.
124  // External analsis is not applicable to a struct type.
125  if (!ExternalAnalysis || STy || ScalableType)
126  return false;
127  APInt AnalysisIndex;
128  if (!ExternalAnalysis(*V, AnalysisIndex))
129  return false;
130  UsedExternalAnalysis = true;
131  if (!AccumulateOffset(AnalysisIndex,
132  DL.getTypeAllocSize(GTI.getIndexedType())))
133  return false;
134  }
135  return true;
136 }
137 } // namespace llvm
A parsed version of the target data layout string in and methods for querying it. ...
Definition: DataLayout.h:111
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
LLVM_NODISCARD std::enable_if_t< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
Definition: Casting.h:334
unsigned getIndexSizeInBits(unsigned AS) const
Size in bits of index used for address calculation in getelementptr.
Definition: DataLayout.h:406
This class represents lattice values for constants.
Definition: AllocatorList.h:23
const StructLayout * getStructLayout(StructType *Ty) const
Returns a StructLayout object, indicating the alignment of the struct, its size, and the offsets of i...
Definition: DataLayout.cpp:621
gep_type_iterator gep_type_end(const User *GEP)
unsigned getPointerAddressSpace() const
Method to return the address space of the pointer operand.
Definition: Operator.h:506
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLExtras.h:176
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition: APInt.h:1569
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
Definition: DataLayout.h:613
Class to represent struct types.
Definition: DerivedTypes.h:218
static const unsigned MaximumAlignment
Definition: Value.h:689
APInt sextOrTrunc(unsigned width) const
Sign extend or truncate to width.
Definition: APInt.cpp:961
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:61
uint64_t value() const
This is a hole in the type system and should not be abused.
Definition: Alignment.h:85
constexpr uint64_t MinAlign(uint64_t A, uint64_t B)
A and B are either alignments or offsets.
Definition: MathExtras.h:673
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
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
Definition: DataLayout.h:490
Align getMaxPreservedAlignment(const DataLayout &DL) const
Compute the maximum alignment that this GEP is garranteed to preserve.
Definition: Operator.cpp:34
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
This is the shared class of boolean and integer constants.
Definition: Constants.h:77
Class for arbitrary precision integers.
Definition: APInt.h:69
Type * getResultElementType() const
Definition: Operator.cpp:28
uint64_t getElementOffset(unsigned Idx) const
Definition: DataLayout.h:635
APInt smul_ov(const APInt &RHS, bool &Overflow) const
Definition: APInt.cpp:1986
#define I(x, y, z)
Definition: MD5.cpp:59
uint32_t Size
Definition: Profile.cpp:46
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
APInt sadd_ov(const APInt &RHS, bool &Overflow) const
Definition: APInt.cpp:1954
LLVM Value Representation.
Definition: Value.h:74
Type * getSourceElementType() const
Definition: Operator.cpp:22
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
gep_type_iterator gep_type_begin(const User *GEP)