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