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(); 35*5f757f3fSDimitry Andric case Instruction::Or: 36*5f757f3fSDimitry Andric return cast<PossiblyDisjointInst>(this)->isDisjoint(); 37349cc55cSDimitry Andric case Instruction::GetElementPtr: { 38349cc55cSDimitry Andric auto *GEP = cast<GEPOperator>(this); 39349cc55cSDimitry Andric // Note: inrange exists on constexpr only 40bdd1243dSDimitry Andric return GEP->isInBounds() || GEP->getInRangeIndex() != std::nullopt; 41349cc55cSDimitry Andric } 42*5f757f3fSDimitry Andric case Instruction::ZExt: 43*5f757f3fSDimitry Andric if (auto *NNI = dyn_cast<PossiblyNonNegInst>(this)) 44*5f757f3fSDimitry Andric return NNI->hasNonNeg(); 45*5f757f3fSDimitry Andric return false; 46349cc55cSDimitry Andric default: 470eae32dcSDimitry Andric if (const auto *FP = dyn_cast<FPMathOperator>(this)) 480eae32dcSDimitry Andric return FP->hasNoNaNs() || FP->hasNoInfs(); 49349cc55cSDimitry Andric return false; 50349cc55cSDimitry Andric } 51349cc55cSDimitry Andric } 52349cc55cSDimitry Andric 53bdd1243dSDimitry Andric bool Operator::hasPoisonGeneratingFlagsOrMetadata() const { 54bdd1243dSDimitry Andric if (hasPoisonGeneratingFlags()) 55bdd1243dSDimitry Andric return true; 56bdd1243dSDimitry Andric auto *I = dyn_cast<Instruction>(this); 57bdd1243dSDimitry Andric return I && I->hasPoisonGeneratingMetadata(); 58bdd1243dSDimitry Andric } 59bdd1243dSDimitry Andric 600b57cec5SDimitry Andric Type *GEPOperator::getSourceElementType() const { 610b57cec5SDimitry Andric if (auto *I = dyn_cast<GetElementPtrInst>(this)) 620b57cec5SDimitry Andric return I->getSourceElementType(); 630b57cec5SDimitry Andric return cast<GetElementPtrConstantExpr>(this)->getSourceElementType(); 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric Type *GEPOperator::getResultElementType() const { 670b57cec5SDimitry Andric if (auto *I = dyn_cast<GetElementPtrInst>(this)) 680b57cec5SDimitry Andric return I->getResultElementType(); 690b57cec5SDimitry Andric return cast<GetElementPtrConstantExpr>(this)->getResultElementType(); 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 725ffd83dbSDimitry Andric Align GEPOperator::getMaxPreservedAlignment(const DataLayout &DL) const { 735ffd83dbSDimitry Andric /// compute the worse possible offset for every level of the GEP et accumulate 745ffd83dbSDimitry Andric /// the minimum alignment into Result. 755ffd83dbSDimitry Andric 765ffd83dbSDimitry Andric Align Result = Align(llvm::Value::MaximumAlignment); 775ffd83dbSDimitry Andric for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this); 785ffd83dbSDimitry Andric GTI != GTE; ++GTI) { 79bdd1243dSDimitry Andric uint64_t Offset; 805ffd83dbSDimitry Andric ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand()); 815ffd83dbSDimitry Andric 825ffd83dbSDimitry Andric if (StructType *STy = GTI.getStructTypeOrNull()) { 835ffd83dbSDimitry Andric const StructLayout *SL = DL.getStructLayout(STy); 845ffd83dbSDimitry Andric Offset = SL->getElementOffset(OpC->getZExtValue()); 855ffd83dbSDimitry Andric } else { 865ffd83dbSDimitry Andric assert(GTI.isSequential() && "should be sequencial"); 87bdd1243dSDimitry Andric /// If the index isn't known, we take 1 because it is the index that will 885ffd83dbSDimitry Andric /// give the worse alignment of the offset. 89bdd1243dSDimitry Andric const uint64_t ElemCount = OpC ? OpC->getZExtValue() : 1; 905ffd83dbSDimitry Andric Offset = DL.getTypeAllocSize(GTI.getIndexedType()) * ElemCount; 915ffd83dbSDimitry Andric } 925ffd83dbSDimitry Andric Result = Align(MinAlign(Offset, Result.value())); 935ffd83dbSDimitry Andric } 945ffd83dbSDimitry Andric return Result; 955ffd83dbSDimitry Andric } 965ffd83dbSDimitry Andric 975ffd83dbSDimitry Andric bool GEPOperator::accumulateConstantOffset( 985ffd83dbSDimitry Andric const DataLayout &DL, APInt &Offset, 995ffd83dbSDimitry Andric function_ref<bool(Value &, APInt &)> ExternalAnalysis) const { 1000b57cec5SDimitry Andric assert(Offset.getBitWidth() == 1010b57cec5SDimitry Andric DL.getIndexSizeInBits(getPointerAddressSpace()) && 1020b57cec5SDimitry Andric "The offset bit width does not match DL specification."); 1030eae32dcSDimitry Andric SmallVector<const Value *> Index(llvm::drop_begin(operand_values())); 104d409305fSDimitry Andric return GEPOperator::accumulateConstantOffset(getSourceElementType(), Index, 105d409305fSDimitry Andric DL, Offset, ExternalAnalysis); 106d409305fSDimitry Andric } 1070b57cec5SDimitry Andric 108d409305fSDimitry Andric bool GEPOperator::accumulateConstantOffset( 109d409305fSDimitry Andric Type *SourceType, ArrayRef<const Value *> Index, const DataLayout &DL, 110d409305fSDimitry Andric APInt &Offset, function_ref<bool(Value &, APInt &)> ExternalAnalysis) { 1115ffd83dbSDimitry Andric bool UsedExternalAnalysis = false; 1125ffd83dbSDimitry Andric auto AccumulateOffset = [&](APInt Index, uint64_t Size) -> bool { 1135ffd83dbSDimitry Andric Index = Index.sextOrTrunc(Offset.getBitWidth()); 1145ffd83dbSDimitry Andric APInt IndexedSize = APInt(Offset.getBitWidth(), Size); 1155ffd83dbSDimitry Andric // For array or vector indices, scale the index by the size of the type. 1165ffd83dbSDimitry Andric if (!UsedExternalAnalysis) { 1175ffd83dbSDimitry Andric Offset += Index * IndexedSize; 1185ffd83dbSDimitry Andric } else { 1195ffd83dbSDimitry Andric // External Analysis can return a result higher/lower than the value 1205ffd83dbSDimitry Andric // represents. We need to detect overflow/underflow. 1215ffd83dbSDimitry Andric bool Overflow = false; 1225ffd83dbSDimitry Andric APInt OffsetPlus = Index.smul_ov(IndexedSize, Overflow); 1235ffd83dbSDimitry Andric if (Overflow) 1245ffd83dbSDimitry Andric return false; 1255ffd83dbSDimitry Andric Offset = Offset.sadd_ov(OffsetPlus, Overflow); 1265ffd83dbSDimitry Andric if (Overflow) 1275ffd83dbSDimitry Andric return false; 1285ffd83dbSDimitry Andric } 1295ffd83dbSDimitry Andric return true; 1305ffd83dbSDimitry Andric }; 131d409305fSDimitry Andric auto begin = generic_gep_type_iterator<decltype(Index.begin())>::begin( 132d409305fSDimitry Andric SourceType, Index.begin()); 133d409305fSDimitry Andric auto end = generic_gep_type_iterator<decltype(Index.end())>::end(Index.end()); 134d409305fSDimitry Andric for (auto GTI = begin, GTE = end; GTI != GTE; ++GTI) { 1355ffd83dbSDimitry Andric // Scalable vectors are multiplied by a runtime constant. 136*5f757f3fSDimitry Andric bool ScalableType = GTI.getIndexedType()->isScalableTy(); 1370b57cec5SDimitry Andric 1385ffd83dbSDimitry Andric Value *V = GTI.getOperand(); 1395ffd83dbSDimitry Andric StructType *STy = GTI.getStructTypeOrNull(); 1405ffd83dbSDimitry Andric // Handle ConstantInt if possible. 1415ffd83dbSDimitry Andric if (auto ConstOffset = dyn_cast<ConstantInt>(V)) { 1425ffd83dbSDimitry Andric if (ConstOffset->isZero()) 1435ffd83dbSDimitry Andric continue; 1445ffd83dbSDimitry Andric // if the type is scalable and the constant is not zero (vscale * n * 0 = 1455ffd83dbSDimitry Andric // 0) bailout. 1465ffd83dbSDimitry Andric if (ScalableType) 1475ffd83dbSDimitry Andric return false; 1480b57cec5SDimitry Andric // Handle a struct index, which adds its field offset to the pointer. 1495ffd83dbSDimitry Andric if (STy) { 1505ffd83dbSDimitry Andric unsigned ElementIdx = ConstOffset->getZExtValue(); 1510b57cec5SDimitry Andric const StructLayout *SL = DL.getStructLayout(STy); 1525ffd83dbSDimitry Andric // Element offset is in bytes. 1535ffd83dbSDimitry Andric if (!AccumulateOffset( 1545ffd83dbSDimitry Andric APInt(Offset.getBitWidth(), SL->getElementOffset(ElementIdx)), 1555ffd83dbSDimitry Andric 1)) 1565ffd83dbSDimitry Andric return false; 1575ffd83dbSDimitry Andric continue; 1585ffd83dbSDimitry Andric } 1595ffd83dbSDimitry Andric if (!AccumulateOffset(ConstOffset->getValue(), 1605ffd83dbSDimitry Andric DL.getTypeAllocSize(GTI.getIndexedType()))) 1615ffd83dbSDimitry Andric return false; 1620b57cec5SDimitry Andric continue; 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric 1655ffd83dbSDimitry Andric // The operand is not constant, check if an external analysis was provided. 1665ffd83dbSDimitry Andric // External analsis is not applicable to a struct type. 1675ffd83dbSDimitry Andric if (!ExternalAnalysis || STy || ScalableType) 1685ffd83dbSDimitry Andric return false; 1695ffd83dbSDimitry Andric APInt AnalysisIndex; 1705ffd83dbSDimitry Andric if (!ExternalAnalysis(*V, AnalysisIndex)) 1715ffd83dbSDimitry Andric return false; 1725ffd83dbSDimitry Andric UsedExternalAnalysis = true; 1735ffd83dbSDimitry Andric if (!AccumulateOffset(AnalysisIndex, 1745ffd83dbSDimitry Andric DL.getTypeAllocSize(GTI.getIndexedType()))) 1755ffd83dbSDimitry Andric return false; 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric return true; 1780b57cec5SDimitry Andric } 179fe6060f1SDimitry Andric 180fe6060f1SDimitry Andric bool GEPOperator::collectOffset( 181fe6060f1SDimitry Andric const DataLayout &DL, unsigned BitWidth, 182fe6060f1SDimitry Andric MapVector<Value *, APInt> &VariableOffsets, 183fe6060f1SDimitry Andric APInt &ConstantOffset) const { 184fe6060f1SDimitry Andric assert(BitWidth == DL.getIndexSizeInBits(getPointerAddressSpace()) && 185fe6060f1SDimitry Andric "The offset bit width does not match DL specification."); 186fe6060f1SDimitry Andric 187fe6060f1SDimitry Andric auto CollectConstantOffset = [&](APInt Index, uint64_t Size) { 188fe6060f1SDimitry Andric Index = Index.sextOrTrunc(BitWidth); 189fe6060f1SDimitry Andric APInt IndexedSize = APInt(BitWidth, Size); 190fe6060f1SDimitry Andric ConstantOffset += Index * IndexedSize; 191fe6060f1SDimitry Andric }; 192fe6060f1SDimitry Andric 193fe6060f1SDimitry Andric for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this); 194fe6060f1SDimitry Andric GTI != GTE; ++GTI) { 195fe6060f1SDimitry Andric // Scalable vectors are multiplied by a runtime constant. 196*5f757f3fSDimitry Andric bool ScalableType = GTI.getIndexedType()->isScalableTy(); 197fe6060f1SDimitry Andric 198fe6060f1SDimitry Andric Value *V = GTI.getOperand(); 199fe6060f1SDimitry Andric StructType *STy = GTI.getStructTypeOrNull(); 200fe6060f1SDimitry Andric // Handle ConstantInt if possible. 201fe6060f1SDimitry Andric if (auto ConstOffset = dyn_cast<ConstantInt>(V)) { 202fe6060f1SDimitry Andric if (ConstOffset->isZero()) 203fe6060f1SDimitry Andric continue; 204fe6060f1SDimitry Andric // If the type is scalable and the constant is not zero (vscale * n * 0 = 205fe6060f1SDimitry Andric // 0) bailout. 206fe6060f1SDimitry Andric // TODO: If the runtime value is accessible at any point before DWARF 207fe6060f1SDimitry Andric // emission, then we could potentially keep a forward reference to it 208fe6060f1SDimitry Andric // in the debug value to be filled in later. 209fe6060f1SDimitry Andric if (ScalableType) 210fe6060f1SDimitry Andric return false; 211fe6060f1SDimitry Andric // Handle a struct index, which adds its field offset to the pointer. 212fe6060f1SDimitry Andric if (STy) { 213fe6060f1SDimitry Andric unsigned ElementIdx = ConstOffset->getZExtValue(); 214fe6060f1SDimitry Andric const StructLayout *SL = DL.getStructLayout(STy); 215fe6060f1SDimitry Andric // Element offset is in bytes. 216fe6060f1SDimitry Andric CollectConstantOffset(APInt(BitWidth, SL->getElementOffset(ElementIdx)), 217fe6060f1SDimitry Andric 1); 218fe6060f1SDimitry Andric continue; 219fe6060f1SDimitry Andric } 220fe6060f1SDimitry Andric CollectConstantOffset(ConstOffset->getValue(), 221fe6060f1SDimitry Andric DL.getTypeAllocSize(GTI.getIndexedType())); 222fe6060f1SDimitry Andric continue; 223fe6060f1SDimitry Andric } 224fe6060f1SDimitry Andric 225fe6060f1SDimitry Andric if (STy || ScalableType) 226fe6060f1SDimitry Andric return false; 227fe6060f1SDimitry Andric APInt IndexedSize = 228fe6060f1SDimitry Andric APInt(BitWidth, DL.getTypeAllocSize(GTI.getIndexedType())); 2291b3bef43SDimitry Andric // Insert an initial offset of 0 for V iff none exists already, then 2301b3bef43SDimitry Andric // increment the offset by IndexedSize. 231349cc55cSDimitry Andric if (!IndexedSize.isZero()) { 232*5f757f3fSDimitry Andric auto *It = VariableOffsets.insert({V, APInt(BitWidth, 0)}).first; 233*5f757f3fSDimitry Andric It->second += IndexedSize; 234fe6060f1SDimitry Andric } 2351b3bef43SDimitry Andric } 236fe6060f1SDimitry Andric return true; 237fe6060f1SDimitry Andric } 2384824e7fdSDimitry Andric 2394824e7fdSDimitry Andric void FastMathFlags::print(raw_ostream &O) const { 2404824e7fdSDimitry Andric if (all()) 2414824e7fdSDimitry Andric O << " fast"; 2424824e7fdSDimitry Andric else { 2434824e7fdSDimitry Andric if (allowReassoc()) 2444824e7fdSDimitry Andric O << " reassoc"; 2454824e7fdSDimitry Andric if (noNaNs()) 2464824e7fdSDimitry Andric O << " nnan"; 2474824e7fdSDimitry Andric if (noInfs()) 2484824e7fdSDimitry Andric O << " ninf"; 2494824e7fdSDimitry Andric if (noSignedZeros()) 2504824e7fdSDimitry Andric O << " nsz"; 2514824e7fdSDimitry Andric if (allowReciprocal()) 2524824e7fdSDimitry Andric O << " arcp"; 2534824e7fdSDimitry Andric if (allowContract()) 2544824e7fdSDimitry Andric O << " contract"; 2554824e7fdSDimitry Andric if (approxFunc()) 2564824e7fdSDimitry Andric O << " afn"; 2574824e7fdSDimitry Andric } 2584824e7fdSDimitry Andric } 2595ffd83dbSDimitry Andric } // namespace llvm 260