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 345ffd83dbSDimitry Andric Align GEPOperator::getMaxPreservedAlignment(const DataLayout &DL) const { 355ffd83dbSDimitry Andric /// compute the worse possible offset for every level of the GEP et accumulate 365ffd83dbSDimitry Andric /// the minimum alignment into Result. 375ffd83dbSDimitry Andric 385ffd83dbSDimitry Andric Align Result = Align(llvm::Value::MaximumAlignment); 395ffd83dbSDimitry Andric for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this); 405ffd83dbSDimitry Andric GTI != GTE; ++GTI) { 415ffd83dbSDimitry Andric int64_t Offset = 1; 425ffd83dbSDimitry Andric ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand()); 435ffd83dbSDimitry Andric 445ffd83dbSDimitry Andric if (StructType *STy = GTI.getStructTypeOrNull()) { 455ffd83dbSDimitry Andric const StructLayout *SL = DL.getStructLayout(STy); 465ffd83dbSDimitry Andric Offset = SL->getElementOffset(OpC->getZExtValue()); 475ffd83dbSDimitry Andric } else { 485ffd83dbSDimitry Andric assert(GTI.isSequential() && "should be sequencial"); 495ffd83dbSDimitry Andric /// If the index isn't know we take 1 because it is the index that will 505ffd83dbSDimitry Andric /// give the worse alignment of the offset. 515ffd83dbSDimitry Andric int64_t ElemCount = 1; 525ffd83dbSDimitry Andric if (OpC) 535ffd83dbSDimitry Andric ElemCount = OpC->getZExtValue(); 545ffd83dbSDimitry Andric Offset = DL.getTypeAllocSize(GTI.getIndexedType()) * ElemCount; 555ffd83dbSDimitry Andric } 565ffd83dbSDimitry Andric Result = Align(MinAlign(Offset, Result.value())); 575ffd83dbSDimitry Andric } 585ffd83dbSDimitry Andric return Result; 595ffd83dbSDimitry Andric } 605ffd83dbSDimitry Andric 615ffd83dbSDimitry Andric bool GEPOperator::accumulateConstantOffset( 625ffd83dbSDimitry Andric const DataLayout &DL, APInt &Offset, 635ffd83dbSDimitry 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."); 67*d409305fSDimitry Andric SmallVector<const Value *> Index(value_op_begin() + 1, value_op_end()); 68*d409305fSDimitry Andric return GEPOperator::accumulateConstantOffset(getSourceElementType(), Index, 69*d409305fSDimitry Andric DL, Offset, ExternalAnalysis); 70*d409305fSDimitry Andric } 710b57cec5SDimitry Andric 72*d409305fSDimitry Andric bool GEPOperator::accumulateConstantOffset( 73*d409305fSDimitry Andric Type *SourceType, ArrayRef<const Value *> Index, const DataLayout &DL, 74*d409305fSDimitry Andric APInt &Offset, function_ref<bool(Value &, APInt &)> ExternalAnalysis) { 755ffd83dbSDimitry Andric bool UsedExternalAnalysis = false; 765ffd83dbSDimitry Andric auto AccumulateOffset = [&](APInt Index, uint64_t Size) -> bool { 775ffd83dbSDimitry Andric Index = Index.sextOrTrunc(Offset.getBitWidth()); 785ffd83dbSDimitry Andric APInt IndexedSize = APInt(Offset.getBitWidth(), Size); 795ffd83dbSDimitry Andric // For array or vector indices, scale the index by the size of the type. 805ffd83dbSDimitry Andric if (!UsedExternalAnalysis) { 815ffd83dbSDimitry Andric Offset += Index * IndexedSize; 825ffd83dbSDimitry Andric } else { 835ffd83dbSDimitry Andric // External Analysis can return a result higher/lower than the value 845ffd83dbSDimitry Andric // represents. We need to detect overflow/underflow. 855ffd83dbSDimitry Andric bool Overflow = false; 865ffd83dbSDimitry Andric APInt OffsetPlus = Index.smul_ov(IndexedSize, Overflow); 875ffd83dbSDimitry Andric if (Overflow) 885ffd83dbSDimitry Andric return false; 895ffd83dbSDimitry Andric Offset = Offset.sadd_ov(OffsetPlus, Overflow); 905ffd83dbSDimitry Andric if (Overflow) 915ffd83dbSDimitry Andric return false; 925ffd83dbSDimitry Andric } 935ffd83dbSDimitry Andric return true; 945ffd83dbSDimitry Andric }; 95*d409305fSDimitry Andric auto begin = generic_gep_type_iterator<decltype(Index.begin())>::begin( 96*d409305fSDimitry Andric SourceType, Index.begin()); 97*d409305fSDimitry Andric auto end = generic_gep_type_iterator<decltype(Index.end())>::end(Index.end()); 98*d409305fSDimitry Andric for (auto GTI = begin, GTE = end; GTI != GTE; ++GTI) { 995ffd83dbSDimitry Andric // Scalable vectors are multiplied by a runtime constant. 1005ffd83dbSDimitry Andric bool ScalableType = false; 1015ffd83dbSDimitry Andric if (isa<ScalableVectorType>(GTI.getIndexedType())) 1025ffd83dbSDimitry Andric ScalableType = true; 1030b57cec5SDimitry Andric 1045ffd83dbSDimitry Andric Value *V = GTI.getOperand(); 1055ffd83dbSDimitry Andric StructType *STy = GTI.getStructTypeOrNull(); 1065ffd83dbSDimitry Andric // Handle ConstantInt if possible. 1075ffd83dbSDimitry Andric if (auto ConstOffset = dyn_cast<ConstantInt>(V)) { 1085ffd83dbSDimitry Andric if (ConstOffset->isZero()) 1095ffd83dbSDimitry Andric continue; 1105ffd83dbSDimitry Andric // if the type is scalable and the constant is not zero (vscale * n * 0 = 1115ffd83dbSDimitry Andric // 0) bailout. 1125ffd83dbSDimitry Andric if (ScalableType) 1135ffd83dbSDimitry Andric return false; 1140b57cec5SDimitry Andric // Handle a struct index, which adds its field offset to the pointer. 1155ffd83dbSDimitry Andric if (STy) { 1165ffd83dbSDimitry Andric unsigned ElementIdx = ConstOffset->getZExtValue(); 1170b57cec5SDimitry Andric const StructLayout *SL = DL.getStructLayout(STy); 1185ffd83dbSDimitry Andric // Element offset is in bytes. 1195ffd83dbSDimitry Andric if (!AccumulateOffset( 1205ffd83dbSDimitry Andric APInt(Offset.getBitWidth(), SL->getElementOffset(ElementIdx)), 1215ffd83dbSDimitry Andric 1)) 1225ffd83dbSDimitry Andric return false; 1235ffd83dbSDimitry Andric continue; 1245ffd83dbSDimitry Andric } 1255ffd83dbSDimitry Andric if (!AccumulateOffset(ConstOffset->getValue(), 1265ffd83dbSDimitry Andric DL.getTypeAllocSize(GTI.getIndexedType()))) 1275ffd83dbSDimitry Andric return false; 1280b57cec5SDimitry Andric continue; 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 1315ffd83dbSDimitry Andric // The operand is not constant, check if an external analysis was provided. 1325ffd83dbSDimitry Andric // External analsis is not applicable to a struct type. 1335ffd83dbSDimitry Andric if (!ExternalAnalysis || STy || ScalableType) 1345ffd83dbSDimitry Andric return false; 1355ffd83dbSDimitry Andric APInt AnalysisIndex; 1365ffd83dbSDimitry Andric if (!ExternalAnalysis(*V, AnalysisIndex)) 1375ffd83dbSDimitry Andric return false; 1385ffd83dbSDimitry Andric UsedExternalAnalysis = true; 1395ffd83dbSDimitry Andric if (!AccumulateOffset(AnalysisIndex, 1405ffd83dbSDimitry Andric DL.getTypeAllocSize(GTI.getIndexedType()))) 1415ffd83dbSDimitry Andric return false; 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric return true; 1440b57cec5SDimitry Andric } 1455ffd83dbSDimitry Andric } // namespace llvm 146