LLVM  11.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  const DataLayout &DL, APInt &Offset,
36  function_ref<bool(Value &, APInt &)> ExternalAnalysis) const {
37  assert(Offset.getBitWidth() ==
39  "The offset bit width does not match DL specification.");
40 
41  bool UsedExternalAnalysis = false;
42  auto AccumulateOffset = [&](APInt Index, uint64_t Size) -> bool {
43  Index = Index.sextOrTrunc(Offset.getBitWidth());
44  APInt IndexedSize = APInt(Offset.getBitWidth(), Size);
45  // For array or vector indices, scale the index by the size of the type.
46  if (!UsedExternalAnalysis) {
47  Offset += Index * IndexedSize;
48  } else {
49  // External Analysis can return a result higher/lower than the value
50  // represents. We need to detect overflow/underflow.
51  bool Overflow = false;
52  APInt OffsetPlus = Index.smul_ov(IndexedSize, Overflow);
53  if (Overflow)
54  return false;
55  Offset = Offset.sadd_ov(OffsetPlus, Overflow);
56  if (Overflow)
57  return false;
58  }
59  return true;
60  };
61 
62  for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);
63  GTI != GTE; ++GTI) {
64  // Scalable vectors are multiplied by a runtime constant.
65  bool ScalableType = false;
66  if (isa<ScalableVectorType>(GTI.getIndexedType()))
67  ScalableType = true;
68 
69  Value *V = GTI.getOperand();
70  StructType *STy = GTI.getStructTypeOrNull();
71  // Handle ConstantInt if possible.
72  if (auto ConstOffset = dyn_cast<ConstantInt>(V)) {
73  if (ConstOffset->isZero())
74  continue;
75  // if the type is scalable and the constant is not zero (vscale * n * 0 =
76  // 0) bailout.
77  if (ScalableType)
78  return false;
79  // Handle a struct index, which adds its field offset to the pointer.
80  if (STy) {
81  unsigned ElementIdx = ConstOffset->getZExtValue();
82  const StructLayout *SL = DL.getStructLayout(STy);
83  // Element offset is in bytes.
84  if (!AccumulateOffset(
85  APInt(Offset.getBitWidth(), SL->getElementOffset(ElementIdx)),
86  1))
87  return false;
88  continue;
89  }
90  if (!AccumulateOffset(ConstOffset->getValue(),
91  DL.getTypeAllocSize(GTI.getIndexedType())))
92  return false;
93  continue;
94  }
95 
96  // The operand is not constant, check if an external analysis was provided.
97  // External analsis is not applicable to a struct type.
98  if (!ExternalAnalysis || STy || ScalableType)
99  return false;
100  APInt AnalysisIndex;
101  if (!ExternalAnalysis(*V, AnalysisIndex))
102  return false;
103  UsedExternalAnalysis = true;
104  if (!AccumulateOffset(AnalysisIndex,
105  DL.getTypeAllocSize(GTI.getIndexedType())))
106  return false;
107  }
108  return true;
109 }
110 }
A parsed version of the target data layout string in and methods for querying it. ...
Definition: DataLayout.h:111
unsigned getIndexSizeInBits(unsigned AS) const
Size in bits of index used for address calculation in getelementptr.
Definition: DataLayout.h:402
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:616
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:1566
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
Definition: DataLayout.h:596
Class to represent struct types.
Definition: DerivedTypes.h:218
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:34
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:486
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:618
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
gep_type_iterator gep_type_begin(const User *GEP)