xref: /freebsd/contrib/llvm-project/llvm/lib/IR/Operator.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
10b57cec5SDimitry Andric //===-- Operator.cpp - Implement the LLVM operators -----------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the non-inline methods for the LLVM Operator classes.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/IR/Operator.h"
140b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
150b57cec5SDimitry Andric #include "llvm/IR/GetElementPtrTypeIterator.h"
160b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
170b57cec5SDimitry Andric #include "llvm/IR/Type.h"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #include "ConstantsContext.h"
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric namespace llvm {
220b57cec5SDimitry Andric Type *GEPOperator::getSourceElementType() const {
230b57cec5SDimitry Andric   if (auto *I = dyn_cast<GetElementPtrInst>(this))
240b57cec5SDimitry Andric     return I->getSourceElementType();
250b57cec5SDimitry Andric   return cast<GetElementPtrConstantExpr>(this)->getSourceElementType();
260b57cec5SDimitry Andric }
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric Type *GEPOperator::getResultElementType() const {
290b57cec5SDimitry Andric   if (auto *I = dyn_cast<GetElementPtrInst>(this))
300b57cec5SDimitry Andric     return I->getResultElementType();
310b57cec5SDimitry Andric   return cast<GetElementPtrConstantExpr>(this)->getResultElementType();
320b57cec5SDimitry Andric }
330b57cec5SDimitry Andric 
34*5ffd83dbSDimitry Andric Align GEPOperator::getMaxPreservedAlignment(const DataLayout &DL) const {
35*5ffd83dbSDimitry Andric   /// compute the worse possible offset for every level of the GEP et accumulate
36*5ffd83dbSDimitry Andric   /// the minimum alignment into Result.
37*5ffd83dbSDimitry Andric 
38*5ffd83dbSDimitry Andric   Align Result = Align(llvm::Value::MaximumAlignment);
39*5ffd83dbSDimitry Andric   for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);
40*5ffd83dbSDimitry Andric        GTI != GTE; ++GTI) {
41*5ffd83dbSDimitry Andric     int64_t Offset = 1;
42*5ffd83dbSDimitry Andric     ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand());
43*5ffd83dbSDimitry Andric 
44*5ffd83dbSDimitry Andric     if (StructType *STy = GTI.getStructTypeOrNull()) {
45*5ffd83dbSDimitry Andric       const StructLayout *SL = DL.getStructLayout(STy);
46*5ffd83dbSDimitry Andric       Offset = SL->getElementOffset(OpC->getZExtValue());
47*5ffd83dbSDimitry Andric     } else {
48*5ffd83dbSDimitry Andric       assert(GTI.isSequential() && "should be sequencial");
49*5ffd83dbSDimitry Andric       /// If the index isn't know we take 1 because it is the index that will
50*5ffd83dbSDimitry Andric       /// give the worse alignment of the offset.
51*5ffd83dbSDimitry Andric       int64_t ElemCount = 1;
52*5ffd83dbSDimitry Andric       if (OpC)
53*5ffd83dbSDimitry Andric         ElemCount = OpC->getZExtValue();
54*5ffd83dbSDimitry Andric       Offset = DL.getTypeAllocSize(GTI.getIndexedType()) * ElemCount;
55*5ffd83dbSDimitry Andric     }
56*5ffd83dbSDimitry Andric     Result = Align(MinAlign(Offset, Result.value()));
57*5ffd83dbSDimitry Andric   }
58*5ffd83dbSDimitry Andric   return Result;
59*5ffd83dbSDimitry Andric }
60*5ffd83dbSDimitry Andric 
61*5ffd83dbSDimitry Andric bool GEPOperator::accumulateConstantOffset(
62*5ffd83dbSDimitry Andric     const DataLayout &DL, APInt &Offset,
63*5ffd83dbSDimitry Andric     function_ref<bool(Value &, APInt &)> ExternalAnalysis) const {
640b57cec5SDimitry Andric    assert(Offset.getBitWidth() ==
650b57cec5SDimitry Andric               DL.getIndexSizeInBits(getPointerAddressSpace()) &&
660b57cec5SDimitry Andric           "The offset bit width does not match DL specification.");
670b57cec5SDimitry Andric 
68*5ffd83dbSDimitry Andric   bool UsedExternalAnalysis = false;
69*5ffd83dbSDimitry Andric   auto AccumulateOffset = [&](APInt Index, uint64_t Size) -> bool {
70*5ffd83dbSDimitry Andric     Index = Index.sextOrTrunc(Offset.getBitWidth());
71*5ffd83dbSDimitry Andric     APInt IndexedSize = APInt(Offset.getBitWidth(), Size);
72*5ffd83dbSDimitry Andric     // For array or vector indices, scale the index by the size of the type.
73*5ffd83dbSDimitry Andric     if (!UsedExternalAnalysis) {
74*5ffd83dbSDimitry Andric       Offset += Index * IndexedSize;
75*5ffd83dbSDimitry Andric     } else {
76*5ffd83dbSDimitry Andric       // External Analysis can return a result higher/lower than the value
77*5ffd83dbSDimitry Andric       // represents. We need to detect overflow/underflow.
78*5ffd83dbSDimitry Andric       bool Overflow = false;
79*5ffd83dbSDimitry Andric       APInt OffsetPlus = Index.smul_ov(IndexedSize, Overflow);
80*5ffd83dbSDimitry Andric       if (Overflow)
81*5ffd83dbSDimitry Andric         return false;
82*5ffd83dbSDimitry Andric       Offset = Offset.sadd_ov(OffsetPlus, Overflow);
83*5ffd83dbSDimitry Andric       if (Overflow)
84*5ffd83dbSDimitry Andric         return false;
85*5ffd83dbSDimitry Andric     }
86*5ffd83dbSDimitry Andric     return true;
87*5ffd83dbSDimitry Andric   };
88*5ffd83dbSDimitry Andric 
890b57cec5SDimitry Andric   for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this);
900b57cec5SDimitry Andric        GTI != GTE; ++GTI) {
91*5ffd83dbSDimitry Andric     // Scalable vectors are multiplied by a runtime constant.
92*5ffd83dbSDimitry Andric     bool ScalableType = false;
93*5ffd83dbSDimitry Andric     if (isa<ScalableVectorType>(GTI.getIndexedType()))
94*5ffd83dbSDimitry Andric       ScalableType = true;
950b57cec5SDimitry Andric 
96*5ffd83dbSDimitry Andric     Value *V = GTI.getOperand();
97*5ffd83dbSDimitry Andric     StructType *STy = GTI.getStructTypeOrNull();
98*5ffd83dbSDimitry Andric     // Handle ConstantInt if possible.
99*5ffd83dbSDimitry Andric     if (auto ConstOffset = dyn_cast<ConstantInt>(V)) {
100*5ffd83dbSDimitry Andric       if (ConstOffset->isZero())
101*5ffd83dbSDimitry Andric         continue;
102*5ffd83dbSDimitry Andric       // if the type is scalable and the constant is not zero (vscale * n * 0 =
103*5ffd83dbSDimitry Andric       // 0) bailout.
104*5ffd83dbSDimitry Andric       if (ScalableType)
105*5ffd83dbSDimitry Andric         return false;
1060b57cec5SDimitry Andric       // Handle a struct index, which adds its field offset to the pointer.
107*5ffd83dbSDimitry Andric       if (STy) {
108*5ffd83dbSDimitry Andric         unsigned ElementIdx = ConstOffset->getZExtValue();
1090b57cec5SDimitry Andric         const StructLayout *SL = DL.getStructLayout(STy);
110*5ffd83dbSDimitry Andric         // Element offset is in bytes.
111*5ffd83dbSDimitry Andric         if (!AccumulateOffset(
112*5ffd83dbSDimitry Andric                 APInt(Offset.getBitWidth(), SL->getElementOffset(ElementIdx)),
113*5ffd83dbSDimitry Andric                 1))
114*5ffd83dbSDimitry Andric           return false;
115*5ffd83dbSDimitry Andric         continue;
116*5ffd83dbSDimitry Andric       }
117*5ffd83dbSDimitry Andric       if (!AccumulateOffset(ConstOffset->getValue(),
118*5ffd83dbSDimitry Andric                             DL.getTypeAllocSize(GTI.getIndexedType())))
119*5ffd83dbSDimitry Andric         return false;
1200b57cec5SDimitry Andric       continue;
1210b57cec5SDimitry Andric     }
1220b57cec5SDimitry Andric 
123*5ffd83dbSDimitry Andric     // The operand is not constant, check if an external analysis was provided.
124*5ffd83dbSDimitry Andric     // External analsis is not applicable to a struct type.
125*5ffd83dbSDimitry Andric     if (!ExternalAnalysis || STy || ScalableType)
126*5ffd83dbSDimitry Andric       return false;
127*5ffd83dbSDimitry Andric     APInt AnalysisIndex;
128*5ffd83dbSDimitry Andric     if (!ExternalAnalysis(*V, AnalysisIndex))
129*5ffd83dbSDimitry Andric       return false;
130*5ffd83dbSDimitry Andric     UsedExternalAnalysis = true;
131*5ffd83dbSDimitry Andric     if (!AccumulateOffset(AnalysisIndex,
132*5ffd83dbSDimitry Andric                           DL.getTypeAllocSize(GTI.getIndexedType())))
133*5ffd83dbSDimitry Andric       return false;
1340b57cec5SDimitry Andric   }
1350b57cec5SDimitry Andric   return true;
1360b57cec5SDimitry Andric }
137*5ffd83dbSDimitry Andric } // namespace llvm
138