1c98f8835SCraig Topper //===-- Operator.cpp - Implement the LLVM operators -----------------------===//
2c98f8835SCraig Topper //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c98f8835SCraig Topper //
7c98f8835SCraig Topper //===----------------------------------------------------------------------===//
8c98f8835SCraig Topper //
9c98f8835SCraig Topper // This file implements the non-inline methods for the LLVM Operator classes.
10c98f8835SCraig Topper //
11c98f8835SCraig Topper //===----------------------------------------------------------------------===//
12c98f8835SCraig Topper
1360310f27SDavid Blaikie #include "llvm/IR/Operator.h"
14b5c2bfa8SCraig Topper #include "llvm/IR/DataLayout.h"
156f0d5224SDavid Blaikie #include "llvm/IR/GetElementPtrTypeIterator.h"
1660310f27SDavid Blaikie #include "llvm/IR/Instructions.h"
1760310f27SDavid Blaikie
1860310f27SDavid Blaikie #include "ConstantsContext.h"
1960310f27SDavid Blaikie
2060310f27SDavid Blaikie namespace llvm {
hasPoisonGeneratingFlags() const21425cbbc6SPhilip Reames bool Operator::hasPoisonGeneratingFlags() const {
22425cbbc6SPhilip Reames switch (getOpcode()) {
23425cbbc6SPhilip Reames case Instruction::Add:
24425cbbc6SPhilip Reames case Instruction::Sub:
25425cbbc6SPhilip Reames case Instruction::Mul:
26425cbbc6SPhilip Reames case Instruction::Shl: {
27425cbbc6SPhilip Reames auto *OBO = cast<OverflowingBinaryOperator>(this);
28425cbbc6SPhilip Reames return OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap();
29425cbbc6SPhilip Reames }
30425cbbc6SPhilip Reames case Instruction::UDiv:
31425cbbc6SPhilip Reames case Instruction::SDiv:
32425cbbc6SPhilip Reames case Instruction::AShr:
33425cbbc6SPhilip Reames case Instruction::LShr:
34425cbbc6SPhilip Reames return cast<PossiblyExactOperator>(this)->isExact();
35425cbbc6SPhilip Reames case Instruction::GetElementPtr: {
36425cbbc6SPhilip Reames auto *GEP = cast<GEPOperator>(this);
37425cbbc6SPhilip Reames // Note: inrange exists on constexpr only
38425cbbc6SPhilip Reames return GEP->isInBounds() || GEP->getInRangeIndex() != None;
39425cbbc6SPhilip Reames }
40425cbbc6SPhilip Reames default:
41423f1968SPhilip Reames if (const auto *FP = dyn_cast<FPMathOperator>(this))
42423f1968SPhilip Reames return FP->hasNoNaNs() || FP->hasNoInfs();
43425cbbc6SPhilip Reames return false;
44425cbbc6SPhilip Reames }
45425cbbc6SPhilip Reames }
46425cbbc6SPhilip Reames
getSourceElementType() const4760310f27SDavid Blaikie Type *GEPOperator::getSourceElementType() const {
4860310f27SDavid Blaikie if (auto *I = dyn_cast<GetElementPtrInst>(this))
4960310f27SDavid Blaikie return I->getSourceElementType();
5060310f27SDavid Blaikie return cast<GetElementPtrConstantExpr>(this)->getSourceElementType();
5160310f27SDavid Blaikie }
526f0d5224SDavid Blaikie
getResultElementType() const5319eb0310SEduard Burtescu Type *GEPOperator::getResultElementType() const {
5419eb0310SEduard Burtescu if (auto *I = dyn_cast<GetElementPtrInst>(this))
5519eb0310SEduard Burtescu return I->getResultElementType();
5619eb0310SEduard Burtescu return cast<GetElementPtrConstantExpr>(this)->getResultElementType();
5719eb0310SEduard Burtescu }
5819eb0310SEduard Burtescu
getMaxPreservedAlignment(const DataLayout & DL) const59b7338fb1STyker Align GEPOperator::getMaxPreservedAlignment(const DataLayout &DL) const {
60b7338fb1STyker /// compute the worse possible offset for every level of the GEP et accumulate
61b7338fb1STyker /// the minimum alignment into Result.
62b7338fb1STyker
63b7338fb1STyker Align Result = Align(llvm::Value::MaximumAlignment);
64b7338fb1STyker for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);
65b7338fb1STyker GTI != GTE; ++GTI) {
66b7338fb1STyker int64_t Offset = 1;
67b7338fb1STyker ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand());
68b7338fb1STyker
69b7338fb1STyker if (StructType *STy = GTI.getStructTypeOrNull()) {
70b7338fb1STyker const StructLayout *SL = DL.getStructLayout(STy);
71b7338fb1STyker Offset = SL->getElementOffset(OpC->getZExtValue());
72b7338fb1STyker } else {
73b7338fb1STyker assert(GTI.isSequential() && "should be sequencial");
74b7338fb1STyker /// If the index isn't know we take 1 because it is the index that will
75b7338fb1STyker /// give the worse alignment of the offset.
76b7338fb1STyker int64_t ElemCount = 1;
77b7338fb1STyker if (OpC)
78b7338fb1STyker ElemCount = OpC->getZExtValue();
79b7338fb1STyker Offset = DL.getTypeAllocSize(GTI.getIndexedType()) * ElemCount;
80b7338fb1STyker }
81b7338fb1STyker Result = Align(MinAlign(Offset, Result.value()));
82b7338fb1STyker }
83b7338fb1STyker return Result;
84b7338fb1STyker }
85b7338fb1STyker
accumulateConstantOffset(const DataLayout & DL,APInt & Offset,function_ref<bool (Value &,APInt &)> ExternalAnalysis) const86e5780776SKuter Dinel bool GEPOperator::accumulateConstantOffset(
87e5780776SKuter Dinel const DataLayout &DL, APInt &Offset,
88e5780776SKuter Dinel function_ref<bool(Value &, APInt &)> ExternalAnalysis) const {
896f0d5224SDavid Blaikie assert(Offset.getBitWidth() ==
90945b7e5aSElena Demikhovsky DL.getIndexSizeInBits(getPointerAddressSpace()) &&
91945b7e5aSElena Demikhovsky "The offset bit width does not match DL specification.");
92*500c4b68SKazu Hirata SmallVector<const Value *> Index(llvm::drop_begin(operand_values()));
9340862b1aSWilliam S. Moses return GEPOperator::accumulateConstantOffset(getSourceElementType(), Index,
9440862b1aSWilliam S. Moses DL, Offset, ExternalAnalysis);
9540862b1aSWilliam S. Moses }
966f0d5224SDavid Blaikie
accumulateConstantOffset(Type * SourceType,ArrayRef<const Value * > Index,const DataLayout & DL,APInt & Offset,function_ref<bool (Value &,APInt &)> ExternalAnalysis)9740862b1aSWilliam S. Moses bool GEPOperator::accumulateConstantOffset(
9840862b1aSWilliam S. Moses Type *SourceType, ArrayRef<const Value *> Index, const DataLayout &DL,
9940862b1aSWilliam S. Moses APInt &Offset, function_ref<bool(Value &, APInt &)> ExternalAnalysis) {
100e5780776SKuter Dinel bool UsedExternalAnalysis = false;
101e5780776SKuter Dinel auto AccumulateOffset = [&](APInt Index, uint64_t Size) -> bool {
102e5780776SKuter Dinel Index = Index.sextOrTrunc(Offset.getBitWidth());
103e5780776SKuter Dinel APInt IndexedSize = APInt(Offset.getBitWidth(), Size);
104e5780776SKuter Dinel // For array or vector indices, scale the index by the size of the type.
105e5780776SKuter Dinel if (!UsedExternalAnalysis) {
106e5780776SKuter Dinel Offset += Index * IndexedSize;
107e5780776SKuter Dinel } else {
108e5780776SKuter Dinel // External Analysis can return a result higher/lower than the value
109e5780776SKuter Dinel // represents. We need to detect overflow/underflow.
110e5780776SKuter Dinel bool Overflow = false;
111e5780776SKuter Dinel APInt OffsetPlus = Index.smul_ov(IndexedSize, Overflow);
112e5780776SKuter Dinel if (Overflow)
113e5780776SKuter Dinel return false;
114e5780776SKuter Dinel Offset = Offset.sadd_ov(OffsetPlus, Overflow);
115e5780776SKuter Dinel if (Overflow)
116e5780776SKuter Dinel return false;
117e5780776SKuter Dinel }
118e5780776SKuter Dinel return true;
119e5780776SKuter Dinel };
12040862b1aSWilliam S. Moses auto begin = generic_gep_type_iterator<decltype(Index.begin())>::begin(
12140862b1aSWilliam S. Moses SourceType, Index.begin());
12240862b1aSWilliam S. Moses auto end = generic_gep_type_iterator<decltype(Index.end())>::end(Index.end());
12340862b1aSWilliam S. Moses for (auto GTI = begin, GTE = end; GTI != GTE; ++GTI) {
124e5780776SKuter Dinel // Scalable vectors are multiplied by a runtime constant.
125e5780776SKuter Dinel bool ScalableType = false;
1263ecced16SChristopher Tetreault if (isa<ScalableVectorType>(GTI.getIndexedType()))
127e5780776SKuter Dinel ScalableType = true;
128ef64ba83SSander de Smalen
129e5780776SKuter Dinel Value *V = GTI.getOperand();
130e5780776SKuter Dinel StructType *STy = GTI.getStructTypeOrNull();
131e5780776SKuter Dinel // Handle ConstantInt if possible.
132e5780776SKuter Dinel if (auto ConstOffset = dyn_cast<ConstantInt>(V)) {
133e5780776SKuter Dinel if (ConstOffset->isZero())
134e5780776SKuter Dinel continue;
135e5780776SKuter Dinel // if the type is scalable and the constant is not zero (vscale * n * 0 =
136e5780776SKuter Dinel // 0) bailout.
137e5780776SKuter Dinel if (ScalableType)
138e5780776SKuter Dinel return false;
1396f0d5224SDavid Blaikie // Handle a struct index, which adds its field offset to the pointer.
140e5780776SKuter Dinel if (STy) {
141e5780776SKuter Dinel unsigned ElementIdx = ConstOffset->getZExtValue();
1426f0d5224SDavid Blaikie const StructLayout *SL = DL.getStructLayout(STy);
143e5780776SKuter Dinel // Element offset is in bytes.
144e5780776SKuter Dinel if (!AccumulateOffset(
145e5780776SKuter Dinel APInt(Offset.getBitWidth(), SL->getElementOffset(ElementIdx)),
146e5780776SKuter Dinel 1))
147e5780776SKuter Dinel return false;
148e5780776SKuter Dinel continue;
149e5780776SKuter Dinel }
150e5780776SKuter Dinel if (!AccumulateOffset(ConstOffset->getValue(),
151e5780776SKuter Dinel DL.getTypeAllocSize(GTI.getIndexedType())))
152e5780776SKuter Dinel return false;
1536f0d5224SDavid Blaikie continue;
1546f0d5224SDavid Blaikie }
1556f0d5224SDavid Blaikie
156e5780776SKuter Dinel // The operand is not constant, check if an external analysis was provided.
157e5780776SKuter Dinel // External analsis is not applicable to a struct type.
158e5780776SKuter Dinel if (!ExternalAnalysis || STy || ScalableType)
159e5780776SKuter Dinel return false;
160e5780776SKuter Dinel APInt AnalysisIndex;
161e5780776SKuter Dinel if (!ExternalAnalysis(*V, AnalysisIndex))
162e5780776SKuter Dinel return false;
163e5780776SKuter Dinel UsedExternalAnalysis = true;
164e5780776SKuter Dinel if (!AccumulateOffset(AnalysisIndex,
165e5780776SKuter Dinel DL.getTypeAllocSize(GTI.getIndexedType())))
166e5780776SKuter Dinel return false;
1676f0d5224SDavid Blaikie }
1686f0d5224SDavid Blaikie return true;
1696f0d5224SDavid Blaikie }
170c7270567SStephen Tozer
collectOffset(const DataLayout & DL,unsigned BitWidth,MapVector<Value *,APInt> & VariableOffsets,APInt & ConstantOffset) const171c7270567SStephen Tozer bool GEPOperator::collectOffset(
172c7270567SStephen Tozer const DataLayout &DL, unsigned BitWidth,
173c7270567SStephen Tozer MapVector<Value *, APInt> &VariableOffsets,
174c7270567SStephen Tozer APInt &ConstantOffset) const {
175c7270567SStephen Tozer assert(BitWidth == DL.getIndexSizeInBits(getPointerAddressSpace()) &&
176c7270567SStephen Tozer "The offset bit width does not match DL specification.");
177c7270567SStephen Tozer
178c7270567SStephen Tozer auto CollectConstantOffset = [&](APInt Index, uint64_t Size) {
179c7270567SStephen Tozer Index = Index.sextOrTrunc(BitWidth);
180c7270567SStephen Tozer APInt IndexedSize = APInt(BitWidth, Size);
181c7270567SStephen Tozer ConstantOffset += Index * IndexedSize;
182c7270567SStephen Tozer };
183c7270567SStephen Tozer
184c7270567SStephen Tozer for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);
185c7270567SStephen Tozer GTI != GTE; ++GTI) {
186c7270567SStephen Tozer // Scalable vectors are multiplied by a runtime constant.
187c7270567SStephen Tozer bool ScalableType = isa<ScalableVectorType>(GTI.getIndexedType());
188c7270567SStephen Tozer
189c7270567SStephen Tozer Value *V = GTI.getOperand();
190c7270567SStephen Tozer StructType *STy = GTI.getStructTypeOrNull();
191c7270567SStephen Tozer // Handle ConstantInt if possible.
192c7270567SStephen Tozer if (auto ConstOffset = dyn_cast<ConstantInt>(V)) {
193c7270567SStephen Tozer if (ConstOffset->isZero())
194c7270567SStephen Tozer continue;
195c7270567SStephen Tozer // If the type is scalable and the constant is not zero (vscale * n * 0 =
196c7270567SStephen Tozer // 0) bailout.
197c7270567SStephen Tozer // TODO: If the runtime value is accessible at any point before DWARF
198c7270567SStephen Tozer // emission, then we could potentially keep a forward reference to it
199c7270567SStephen Tozer // in the debug value to be filled in later.
200c7270567SStephen Tozer if (ScalableType)
201c7270567SStephen Tozer return false;
202c7270567SStephen Tozer // Handle a struct index, which adds its field offset to the pointer.
203c7270567SStephen Tozer if (STy) {
204c7270567SStephen Tozer unsigned ElementIdx = ConstOffset->getZExtValue();
205c7270567SStephen Tozer const StructLayout *SL = DL.getStructLayout(STy);
206c7270567SStephen Tozer // Element offset is in bytes.
207c7270567SStephen Tozer CollectConstantOffset(APInt(BitWidth, SL->getElementOffset(ElementIdx)),
208c7270567SStephen Tozer 1);
209c7270567SStephen Tozer continue;
210c7270567SStephen Tozer }
211c7270567SStephen Tozer CollectConstantOffset(ConstOffset->getValue(),
212c7270567SStephen Tozer DL.getTypeAllocSize(GTI.getIndexedType()));
213c7270567SStephen Tozer continue;
214c7270567SStephen Tozer }
215c7270567SStephen Tozer
216c7270567SStephen Tozer if (STy || ScalableType)
217c7270567SStephen Tozer return false;
218c7270567SStephen Tozer APInt IndexedSize =
219c7270567SStephen Tozer APInt(BitWidth, DL.getTypeAllocSize(GTI.getIndexedType()));
220b9ca73e1SStephen Tozer // Insert an initial offset of 0 for V iff none exists already, then
221b9ca73e1SStephen Tozer // increment the offset by IndexedSize.
222b9ca73e1SStephen Tozer if (!IndexedSize.isZero()) {
223b9ca73e1SStephen Tozer VariableOffsets.insert({V, APInt(BitWidth, 0)});
224c7270567SStephen Tozer VariableOffsets[V] += IndexedSize;
225c7270567SStephen Tozer }
226b9ca73e1SStephen Tozer }
227c7270567SStephen Tozer return true;
228c7270567SStephen Tozer }
22999107401SRosie Sumpter
print(raw_ostream & O) const23099107401SRosie Sumpter void FastMathFlags::print(raw_ostream &O) const {
23199107401SRosie Sumpter if (all())
23299107401SRosie Sumpter O << " fast";
23399107401SRosie Sumpter else {
23499107401SRosie Sumpter if (allowReassoc())
23599107401SRosie Sumpter O << " reassoc";
23699107401SRosie Sumpter if (noNaNs())
23799107401SRosie Sumpter O << " nnan";
23899107401SRosie Sumpter if (noInfs())
23999107401SRosie Sumpter O << " ninf";
24099107401SRosie Sumpter if (noSignedZeros())
24199107401SRosie Sumpter O << " nsz";
24299107401SRosie Sumpter if (allowReciprocal())
24399107401SRosie Sumpter O << " arcp";
24499107401SRosie Sumpter if (allowContract())
24599107401SRosie Sumpter O << " contract";
24699107401SRosie Sumpter if (approxFunc())
24799107401SRosie Sumpter O << " afn";
24899107401SRosie Sumpter }
24999107401SRosie Sumpter }
2508b52037cSSimon Pilgrim } // namespace llvm
251