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 180b57cec5SDimitry Andric #include "ConstantsContext.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric namespace llvm { 21349cc55cSDimitry Andric bool Operator::hasPoisonGeneratingFlags() const { 22349cc55cSDimitry Andric switch (getOpcode()) { 23349cc55cSDimitry Andric case Instruction::Add: 24349cc55cSDimitry Andric case Instruction::Sub: 25349cc55cSDimitry Andric case Instruction::Mul: 26349cc55cSDimitry Andric case Instruction::Shl: { 27349cc55cSDimitry Andric auto *OBO = cast<OverflowingBinaryOperator>(this); 28349cc55cSDimitry Andric return OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap(); 29349cc55cSDimitry Andric } 30349cc55cSDimitry Andric case Instruction::UDiv: 31349cc55cSDimitry Andric case Instruction::SDiv: 32349cc55cSDimitry Andric case Instruction::AShr: 33349cc55cSDimitry Andric case Instruction::LShr: 34349cc55cSDimitry Andric return cast<PossiblyExactOperator>(this)->isExact(); 35349cc55cSDimitry Andric case Instruction::GetElementPtr: { 36349cc55cSDimitry Andric auto *GEP = cast<GEPOperator>(this); 37349cc55cSDimitry Andric // Note: inrange exists on constexpr only 38*bdd1243dSDimitry Andric return GEP->isInBounds() || GEP->getInRangeIndex() != std::nullopt; 39349cc55cSDimitry Andric } 40349cc55cSDimitry Andric default: 410eae32dcSDimitry Andric if (const auto *FP = dyn_cast<FPMathOperator>(this)) 420eae32dcSDimitry Andric return FP->hasNoNaNs() || FP->hasNoInfs(); 43349cc55cSDimitry Andric return false; 44349cc55cSDimitry Andric } 45349cc55cSDimitry Andric } 46349cc55cSDimitry Andric 47*bdd1243dSDimitry Andric bool Operator::hasPoisonGeneratingFlagsOrMetadata() const { 48*bdd1243dSDimitry Andric if (hasPoisonGeneratingFlags()) 49*bdd1243dSDimitry Andric return true; 50*bdd1243dSDimitry Andric auto *I = dyn_cast<Instruction>(this); 51*bdd1243dSDimitry Andric return I && I->hasPoisonGeneratingMetadata(); 52*bdd1243dSDimitry Andric } 53*bdd1243dSDimitry Andric 540b57cec5SDimitry Andric Type *GEPOperator::getSourceElementType() const { 550b57cec5SDimitry Andric if (auto *I = dyn_cast<GetElementPtrInst>(this)) 560b57cec5SDimitry Andric return I->getSourceElementType(); 570b57cec5SDimitry Andric return cast<GetElementPtrConstantExpr>(this)->getSourceElementType(); 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric Type *GEPOperator::getResultElementType() const { 610b57cec5SDimitry Andric if (auto *I = dyn_cast<GetElementPtrInst>(this)) 620b57cec5SDimitry Andric return I->getResultElementType(); 630b57cec5SDimitry Andric return cast<GetElementPtrConstantExpr>(this)->getResultElementType(); 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric 665ffd83dbSDimitry Andric Align GEPOperator::getMaxPreservedAlignment(const DataLayout &DL) const { 675ffd83dbSDimitry Andric /// compute the worse possible offset for every level of the GEP et accumulate 685ffd83dbSDimitry Andric /// the minimum alignment into Result. 695ffd83dbSDimitry Andric 705ffd83dbSDimitry Andric Align Result = Align(llvm::Value::MaximumAlignment); 715ffd83dbSDimitry Andric for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this); 725ffd83dbSDimitry Andric GTI != GTE; ++GTI) { 73*bdd1243dSDimitry Andric uint64_t Offset; 745ffd83dbSDimitry Andric ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand()); 755ffd83dbSDimitry Andric 765ffd83dbSDimitry Andric if (StructType *STy = GTI.getStructTypeOrNull()) { 775ffd83dbSDimitry Andric const StructLayout *SL = DL.getStructLayout(STy); 785ffd83dbSDimitry Andric Offset = SL->getElementOffset(OpC->getZExtValue()); 795ffd83dbSDimitry Andric } else { 805ffd83dbSDimitry Andric assert(GTI.isSequential() && "should be sequencial"); 81*bdd1243dSDimitry Andric /// If the index isn't known, we take 1 because it is the index that will 825ffd83dbSDimitry Andric /// give the worse alignment of the offset. 83*bdd1243dSDimitry Andric const uint64_t ElemCount = OpC ? OpC->getZExtValue() : 1; 845ffd83dbSDimitry Andric Offset = DL.getTypeAllocSize(GTI.getIndexedType()) * ElemCount; 855ffd83dbSDimitry Andric } 865ffd83dbSDimitry Andric Result = Align(MinAlign(Offset, Result.value())); 875ffd83dbSDimitry Andric } 885ffd83dbSDimitry Andric return Result; 895ffd83dbSDimitry Andric } 905ffd83dbSDimitry Andric 915ffd83dbSDimitry Andric bool GEPOperator::accumulateConstantOffset( 925ffd83dbSDimitry Andric const DataLayout &DL, APInt &Offset, 935ffd83dbSDimitry Andric function_ref<bool(Value &, APInt &)> ExternalAnalysis) const { 940b57cec5SDimitry Andric assert(Offset.getBitWidth() == 950b57cec5SDimitry Andric DL.getIndexSizeInBits(getPointerAddressSpace()) && 960b57cec5SDimitry Andric "The offset bit width does not match DL specification."); 970eae32dcSDimitry Andric SmallVector<const Value *> Index(llvm::drop_begin(operand_values())); 98d409305fSDimitry Andric return GEPOperator::accumulateConstantOffset(getSourceElementType(), Index, 99d409305fSDimitry Andric DL, Offset, ExternalAnalysis); 100d409305fSDimitry Andric } 1010b57cec5SDimitry Andric 102d409305fSDimitry Andric bool GEPOperator::accumulateConstantOffset( 103d409305fSDimitry Andric Type *SourceType, ArrayRef<const Value *> Index, const DataLayout &DL, 104d409305fSDimitry Andric APInt &Offset, function_ref<bool(Value &, APInt &)> ExternalAnalysis) { 1055ffd83dbSDimitry Andric bool UsedExternalAnalysis = false; 1065ffd83dbSDimitry Andric auto AccumulateOffset = [&](APInt Index, uint64_t Size) -> bool { 1075ffd83dbSDimitry Andric Index = Index.sextOrTrunc(Offset.getBitWidth()); 1085ffd83dbSDimitry Andric APInt IndexedSize = APInt(Offset.getBitWidth(), Size); 1095ffd83dbSDimitry Andric // For array or vector indices, scale the index by the size of the type. 1105ffd83dbSDimitry Andric if (!UsedExternalAnalysis) { 1115ffd83dbSDimitry Andric Offset += Index * IndexedSize; 1125ffd83dbSDimitry Andric } else { 1135ffd83dbSDimitry Andric // External Analysis can return a result higher/lower than the value 1145ffd83dbSDimitry Andric // represents. We need to detect overflow/underflow. 1155ffd83dbSDimitry Andric bool Overflow = false; 1165ffd83dbSDimitry Andric APInt OffsetPlus = Index.smul_ov(IndexedSize, Overflow); 1175ffd83dbSDimitry Andric if (Overflow) 1185ffd83dbSDimitry Andric return false; 1195ffd83dbSDimitry Andric Offset = Offset.sadd_ov(OffsetPlus, Overflow); 1205ffd83dbSDimitry Andric if (Overflow) 1215ffd83dbSDimitry Andric return false; 1225ffd83dbSDimitry Andric } 1235ffd83dbSDimitry Andric return true; 1245ffd83dbSDimitry Andric }; 125d409305fSDimitry Andric auto begin = generic_gep_type_iterator<decltype(Index.begin())>::begin( 126d409305fSDimitry Andric SourceType, Index.begin()); 127d409305fSDimitry Andric auto end = generic_gep_type_iterator<decltype(Index.end())>::end(Index.end()); 128d409305fSDimitry Andric for (auto GTI = begin, GTE = end; GTI != GTE; ++GTI) { 1295ffd83dbSDimitry Andric // Scalable vectors are multiplied by a runtime constant. 1305ffd83dbSDimitry Andric bool ScalableType = false; 1315ffd83dbSDimitry Andric if (isa<ScalableVectorType>(GTI.getIndexedType())) 1325ffd83dbSDimitry Andric ScalableType = true; 1330b57cec5SDimitry Andric 1345ffd83dbSDimitry Andric Value *V = GTI.getOperand(); 1355ffd83dbSDimitry Andric StructType *STy = GTI.getStructTypeOrNull(); 1365ffd83dbSDimitry Andric // Handle ConstantInt if possible. 1375ffd83dbSDimitry Andric if (auto ConstOffset = dyn_cast<ConstantInt>(V)) { 1385ffd83dbSDimitry Andric if (ConstOffset->isZero()) 1395ffd83dbSDimitry Andric continue; 1405ffd83dbSDimitry Andric // if the type is scalable and the constant is not zero (vscale * n * 0 = 1415ffd83dbSDimitry Andric // 0) bailout. 1425ffd83dbSDimitry Andric if (ScalableType) 1435ffd83dbSDimitry Andric return false; 1440b57cec5SDimitry Andric // Handle a struct index, which adds its field offset to the pointer. 1455ffd83dbSDimitry Andric if (STy) { 1465ffd83dbSDimitry Andric unsigned ElementIdx = ConstOffset->getZExtValue(); 1470b57cec5SDimitry Andric const StructLayout *SL = DL.getStructLayout(STy); 1485ffd83dbSDimitry Andric // Element offset is in bytes. 1495ffd83dbSDimitry Andric if (!AccumulateOffset( 1505ffd83dbSDimitry Andric APInt(Offset.getBitWidth(), SL->getElementOffset(ElementIdx)), 1515ffd83dbSDimitry Andric 1)) 1525ffd83dbSDimitry Andric return false; 1535ffd83dbSDimitry Andric continue; 1545ffd83dbSDimitry Andric } 1555ffd83dbSDimitry Andric if (!AccumulateOffset(ConstOffset->getValue(), 1565ffd83dbSDimitry Andric DL.getTypeAllocSize(GTI.getIndexedType()))) 1575ffd83dbSDimitry Andric return false; 1580b57cec5SDimitry Andric continue; 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 1615ffd83dbSDimitry Andric // The operand is not constant, check if an external analysis was provided. 1625ffd83dbSDimitry Andric // External analsis is not applicable to a struct type. 1635ffd83dbSDimitry Andric if (!ExternalAnalysis || STy || ScalableType) 1645ffd83dbSDimitry Andric return false; 1655ffd83dbSDimitry Andric APInt AnalysisIndex; 1665ffd83dbSDimitry Andric if (!ExternalAnalysis(*V, AnalysisIndex)) 1675ffd83dbSDimitry Andric return false; 1685ffd83dbSDimitry Andric UsedExternalAnalysis = true; 1695ffd83dbSDimitry Andric if (!AccumulateOffset(AnalysisIndex, 1705ffd83dbSDimitry Andric DL.getTypeAllocSize(GTI.getIndexedType()))) 1715ffd83dbSDimitry Andric return false; 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric return true; 1740b57cec5SDimitry Andric } 175fe6060f1SDimitry Andric 176fe6060f1SDimitry Andric bool GEPOperator::collectOffset( 177fe6060f1SDimitry Andric const DataLayout &DL, unsigned BitWidth, 178fe6060f1SDimitry Andric MapVector<Value *, APInt> &VariableOffsets, 179fe6060f1SDimitry Andric APInt &ConstantOffset) const { 180fe6060f1SDimitry Andric assert(BitWidth == DL.getIndexSizeInBits(getPointerAddressSpace()) && 181fe6060f1SDimitry Andric "The offset bit width does not match DL specification."); 182fe6060f1SDimitry Andric 183fe6060f1SDimitry Andric auto CollectConstantOffset = [&](APInt Index, uint64_t Size) { 184fe6060f1SDimitry Andric Index = Index.sextOrTrunc(BitWidth); 185fe6060f1SDimitry Andric APInt IndexedSize = APInt(BitWidth, Size); 186fe6060f1SDimitry Andric ConstantOffset += Index * IndexedSize; 187fe6060f1SDimitry Andric }; 188fe6060f1SDimitry Andric 189fe6060f1SDimitry Andric for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this); 190fe6060f1SDimitry Andric GTI != GTE; ++GTI) { 191fe6060f1SDimitry Andric // Scalable vectors are multiplied by a runtime constant. 192fe6060f1SDimitry Andric bool ScalableType = isa<ScalableVectorType>(GTI.getIndexedType()); 193fe6060f1SDimitry Andric 194fe6060f1SDimitry Andric Value *V = GTI.getOperand(); 195fe6060f1SDimitry Andric StructType *STy = GTI.getStructTypeOrNull(); 196fe6060f1SDimitry Andric // Handle ConstantInt if possible. 197fe6060f1SDimitry Andric if (auto ConstOffset = dyn_cast<ConstantInt>(V)) { 198fe6060f1SDimitry Andric if (ConstOffset->isZero()) 199fe6060f1SDimitry Andric continue; 200fe6060f1SDimitry Andric // If the type is scalable and the constant is not zero (vscale * n * 0 = 201fe6060f1SDimitry Andric // 0) bailout. 202fe6060f1SDimitry Andric // TODO: If the runtime value is accessible at any point before DWARF 203fe6060f1SDimitry Andric // emission, then we could potentially keep a forward reference to it 204fe6060f1SDimitry Andric // in the debug value to be filled in later. 205fe6060f1SDimitry Andric if (ScalableType) 206fe6060f1SDimitry Andric return false; 207fe6060f1SDimitry Andric // Handle a struct index, which adds its field offset to the pointer. 208fe6060f1SDimitry Andric if (STy) { 209fe6060f1SDimitry Andric unsigned ElementIdx = ConstOffset->getZExtValue(); 210fe6060f1SDimitry Andric const StructLayout *SL = DL.getStructLayout(STy); 211fe6060f1SDimitry Andric // Element offset is in bytes. 212fe6060f1SDimitry Andric CollectConstantOffset(APInt(BitWidth, SL->getElementOffset(ElementIdx)), 213fe6060f1SDimitry Andric 1); 214fe6060f1SDimitry Andric continue; 215fe6060f1SDimitry Andric } 216fe6060f1SDimitry Andric CollectConstantOffset(ConstOffset->getValue(), 217fe6060f1SDimitry Andric DL.getTypeAllocSize(GTI.getIndexedType())); 218fe6060f1SDimitry Andric continue; 219fe6060f1SDimitry Andric } 220fe6060f1SDimitry Andric 221fe6060f1SDimitry Andric if (STy || ScalableType) 222fe6060f1SDimitry Andric return false; 223fe6060f1SDimitry Andric APInt IndexedSize = 224fe6060f1SDimitry Andric APInt(BitWidth, DL.getTypeAllocSize(GTI.getIndexedType())); 2251b3bef43SDimitry Andric // Insert an initial offset of 0 for V iff none exists already, then 2261b3bef43SDimitry Andric // increment the offset by IndexedSize. 227349cc55cSDimitry Andric if (!IndexedSize.isZero()) { 2281b3bef43SDimitry Andric VariableOffsets.insert({V, APInt(BitWidth, 0)}); 229fe6060f1SDimitry Andric VariableOffsets[V] += IndexedSize; 230fe6060f1SDimitry Andric } 2311b3bef43SDimitry Andric } 232fe6060f1SDimitry Andric return true; 233fe6060f1SDimitry Andric } 2344824e7fdSDimitry Andric 2354824e7fdSDimitry Andric void FastMathFlags::print(raw_ostream &O) const { 2364824e7fdSDimitry Andric if (all()) 2374824e7fdSDimitry Andric O << " fast"; 2384824e7fdSDimitry Andric else { 2394824e7fdSDimitry Andric if (allowReassoc()) 2404824e7fdSDimitry Andric O << " reassoc"; 2414824e7fdSDimitry Andric if (noNaNs()) 2424824e7fdSDimitry Andric O << " nnan"; 2434824e7fdSDimitry Andric if (noInfs()) 2444824e7fdSDimitry Andric O << " ninf"; 2454824e7fdSDimitry Andric if (noSignedZeros()) 2464824e7fdSDimitry Andric O << " nsz"; 2474824e7fdSDimitry Andric if (allowReciprocal()) 2484824e7fdSDimitry Andric O << " arcp"; 2494824e7fdSDimitry Andric if (allowContract()) 2504824e7fdSDimitry Andric O << " contract"; 2514824e7fdSDimitry Andric if (approxFunc()) 2524824e7fdSDimitry Andric O << " afn"; 2534824e7fdSDimitry Andric } 2544824e7fdSDimitry Andric } 2555ffd83dbSDimitry Andric } // namespace llvm 256