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 } 30*0fca6ea1SDimitry Andric case Instruction::Trunc: { 31*0fca6ea1SDimitry Andric if (auto *TI = dyn_cast<TruncInst>(this)) 32*0fca6ea1SDimitry Andric return TI->hasNoUnsignedWrap() || TI->hasNoSignedWrap(); 33*0fca6ea1SDimitry Andric return false; 34*0fca6ea1SDimitry Andric } 35349cc55cSDimitry Andric case Instruction::UDiv: 36349cc55cSDimitry Andric case Instruction::SDiv: 37349cc55cSDimitry Andric case Instruction::AShr: 38349cc55cSDimitry Andric case Instruction::LShr: 39349cc55cSDimitry Andric return cast<PossiblyExactOperator>(this)->isExact(); 405f757f3fSDimitry Andric case Instruction::Or: 415f757f3fSDimitry Andric return cast<PossiblyDisjointInst>(this)->isDisjoint(); 42349cc55cSDimitry Andric case Instruction::GetElementPtr: { 43349cc55cSDimitry Andric auto *GEP = cast<GEPOperator>(this); 44349cc55cSDimitry Andric // Note: inrange exists on constexpr only 45*0fca6ea1SDimitry Andric return GEP->getNoWrapFlags() != GEPNoWrapFlags::none() || 46*0fca6ea1SDimitry Andric GEP->getInRange() != std::nullopt; 47349cc55cSDimitry Andric } 48*0fca6ea1SDimitry Andric case Instruction::UIToFP: 495f757f3fSDimitry Andric case Instruction::ZExt: 505f757f3fSDimitry Andric if (auto *NNI = dyn_cast<PossiblyNonNegInst>(this)) 515f757f3fSDimitry Andric return NNI->hasNonNeg(); 525f757f3fSDimitry Andric return false; 53349cc55cSDimitry Andric default: 540eae32dcSDimitry Andric if (const auto *FP = dyn_cast<FPMathOperator>(this)) 550eae32dcSDimitry Andric return FP->hasNoNaNs() || FP->hasNoInfs(); 56349cc55cSDimitry Andric return false; 57349cc55cSDimitry Andric } 58349cc55cSDimitry Andric } 59349cc55cSDimitry Andric 60*0fca6ea1SDimitry Andric bool Operator::hasPoisonGeneratingAnnotations() const { 61bdd1243dSDimitry Andric if (hasPoisonGeneratingFlags()) 62bdd1243dSDimitry Andric return true; 63bdd1243dSDimitry Andric auto *I = dyn_cast<Instruction>(this); 64*0fca6ea1SDimitry Andric return I && (I->hasPoisonGeneratingReturnAttributes() || 65*0fca6ea1SDimitry Andric I->hasPoisonGeneratingMetadata()); 66bdd1243dSDimitry Andric } 67bdd1243dSDimitry Andric 680b57cec5SDimitry Andric Type *GEPOperator::getSourceElementType() const { 690b57cec5SDimitry Andric if (auto *I = dyn_cast<GetElementPtrInst>(this)) 700b57cec5SDimitry Andric return I->getSourceElementType(); 710b57cec5SDimitry Andric return cast<GetElementPtrConstantExpr>(this)->getSourceElementType(); 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric Type *GEPOperator::getResultElementType() const { 750b57cec5SDimitry Andric if (auto *I = dyn_cast<GetElementPtrInst>(this)) 760b57cec5SDimitry Andric return I->getResultElementType(); 770b57cec5SDimitry Andric return cast<GetElementPtrConstantExpr>(this)->getResultElementType(); 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric 80*0fca6ea1SDimitry Andric std::optional<ConstantRange> GEPOperator::getInRange() const { 81*0fca6ea1SDimitry Andric if (auto *CE = dyn_cast<GetElementPtrConstantExpr>(this)) 82*0fca6ea1SDimitry Andric return CE->getInRange(); 83*0fca6ea1SDimitry Andric return std::nullopt; 84*0fca6ea1SDimitry Andric } 85*0fca6ea1SDimitry Andric 865ffd83dbSDimitry Andric Align GEPOperator::getMaxPreservedAlignment(const DataLayout &DL) const { 875ffd83dbSDimitry Andric /// compute the worse possible offset for every level of the GEP et accumulate 885ffd83dbSDimitry Andric /// the minimum alignment into Result. 895ffd83dbSDimitry Andric 905ffd83dbSDimitry Andric Align Result = Align(llvm::Value::MaximumAlignment); 915ffd83dbSDimitry Andric for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this); 925ffd83dbSDimitry Andric GTI != GTE; ++GTI) { 93bdd1243dSDimitry Andric uint64_t Offset; 945ffd83dbSDimitry Andric ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand()); 955ffd83dbSDimitry Andric 965ffd83dbSDimitry Andric if (StructType *STy = GTI.getStructTypeOrNull()) { 975ffd83dbSDimitry Andric const StructLayout *SL = DL.getStructLayout(STy); 985ffd83dbSDimitry Andric Offset = SL->getElementOffset(OpC->getZExtValue()); 995ffd83dbSDimitry Andric } else { 1005ffd83dbSDimitry Andric assert(GTI.isSequential() && "should be sequencial"); 101bdd1243dSDimitry Andric /// If the index isn't known, we take 1 because it is the index that will 1025ffd83dbSDimitry Andric /// give the worse alignment of the offset. 103bdd1243dSDimitry Andric const uint64_t ElemCount = OpC ? OpC->getZExtValue() : 1; 1041db9f3b2SDimitry Andric Offset = GTI.getSequentialElementStride(DL) * ElemCount; 1055ffd83dbSDimitry Andric } 1065ffd83dbSDimitry Andric Result = Align(MinAlign(Offset, Result.value())); 1075ffd83dbSDimitry Andric } 1085ffd83dbSDimitry Andric return Result; 1095ffd83dbSDimitry Andric } 1105ffd83dbSDimitry Andric 1115ffd83dbSDimitry Andric bool GEPOperator::accumulateConstantOffset( 1125ffd83dbSDimitry Andric const DataLayout &DL, APInt &Offset, 1135ffd83dbSDimitry Andric function_ref<bool(Value &, APInt &)> ExternalAnalysis) const { 1140b57cec5SDimitry Andric assert(Offset.getBitWidth() == 1150b57cec5SDimitry Andric DL.getIndexSizeInBits(getPointerAddressSpace()) && 1160b57cec5SDimitry Andric "The offset bit width does not match DL specification."); 1170eae32dcSDimitry Andric SmallVector<const Value *> Index(llvm::drop_begin(operand_values())); 118d409305fSDimitry Andric return GEPOperator::accumulateConstantOffset(getSourceElementType(), Index, 119d409305fSDimitry Andric DL, Offset, ExternalAnalysis); 120d409305fSDimitry Andric } 1210b57cec5SDimitry Andric 122d409305fSDimitry Andric bool GEPOperator::accumulateConstantOffset( 123d409305fSDimitry Andric Type *SourceType, ArrayRef<const Value *> Index, const DataLayout &DL, 124d409305fSDimitry Andric APInt &Offset, function_ref<bool(Value &, APInt &)> ExternalAnalysis) { 125*0fca6ea1SDimitry Andric // Fast path for canonical getelementptr i8 form. 126*0fca6ea1SDimitry Andric if (SourceType->isIntegerTy(8) && !ExternalAnalysis) { 127*0fca6ea1SDimitry Andric if (auto *CI = dyn_cast<ConstantInt>(Index.front())) { 128*0fca6ea1SDimitry Andric Offset += CI->getValue().sextOrTrunc(Offset.getBitWidth()); 129*0fca6ea1SDimitry Andric return true; 130*0fca6ea1SDimitry Andric } 131*0fca6ea1SDimitry Andric return false; 132*0fca6ea1SDimitry Andric } 133*0fca6ea1SDimitry Andric 1345ffd83dbSDimitry Andric bool UsedExternalAnalysis = false; 1355ffd83dbSDimitry Andric auto AccumulateOffset = [&](APInt Index, uint64_t Size) -> bool { 1365ffd83dbSDimitry Andric Index = Index.sextOrTrunc(Offset.getBitWidth()); 1375ffd83dbSDimitry Andric APInt IndexedSize = APInt(Offset.getBitWidth(), Size); 1385ffd83dbSDimitry Andric // For array or vector indices, scale the index by the size of the type. 1395ffd83dbSDimitry Andric if (!UsedExternalAnalysis) { 1405ffd83dbSDimitry Andric Offset += Index * IndexedSize; 1415ffd83dbSDimitry Andric } else { 1425ffd83dbSDimitry Andric // External Analysis can return a result higher/lower than the value 1435ffd83dbSDimitry Andric // represents. We need to detect overflow/underflow. 1445ffd83dbSDimitry Andric bool Overflow = false; 1455ffd83dbSDimitry Andric APInt OffsetPlus = Index.smul_ov(IndexedSize, Overflow); 1465ffd83dbSDimitry Andric if (Overflow) 1475ffd83dbSDimitry Andric return false; 1485ffd83dbSDimitry Andric Offset = Offset.sadd_ov(OffsetPlus, Overflow); 1495ffd83dbSDimitry Andric if (Overflow) 1505ffd83dbSDimitry Andric return false; 1515ffd83dbSDimitry Andric } 1525ffd83dbSDimitry Andric return true; 1535ffd83dbSDimitry Andric }; 154d409305fSDimitry Andric auto begin = generic_gep_type_iterator<decltype(Index.begin())>::begin( 155d409305fSDimitry Andric SourceType, Index.begin()); 156d409305fSDimitry Andric auto end = generic_gep_type_iterator<decltype(Index.end())>::end(Index.end()); 157d409305fSDimitry Andric for (auto GTI = begin, GTE = end; GTI != GTE; ++GTI) { 1585ffd83dbSDimitry Andric // Scalable vectors are multiplied by a runtime constant. 1595f757f3fSDimitry Andric bool ScalableType = GTI.getIndexedType()->isScalableTy(); 1600b57cec5SDimitry Andric 1615ffd83dbSDimitry Andric Value *V = GTI.getOperand(); 1625ffd83dbSDimitry Andric StructType *STy = GTI.getStructTypeOrNull(); 1635ffd83dbSDimitry Andric // Handle ConstantInt if possible. 1645ffd83dbSDimitry Andric if (auto ConstOffset = dyn_cast<ConstantInt>(V)) { 1655ffd83dbSDimitry Andric if (ConstOffset->isZero()) 1665ffd83dbSDimitry Andric continue; 1675ffd83dbSDimitry Andric // if the type is scalable and the constant is not zero (vscale * n * 0 = 1685ffd83dbSDimitry Andric // 0) bailout. 1695ffd83dbSDimitry Andric if (ScalableType) 1705ffd83dbSDimitry Andric return false; 1710b57cec5SDimitry Andric // Handle a struct index, which adds its field offset to the pointer. 1725ffd83dbSDimitry Andric if (STy) { 1735ffd83dbSDimitry Andric unsigned ElementIdx = ConstOffset->getZExtValue(); 1740b57cec5SDimitry Andric const StructLayout *SL = DL.getStructLayout(STy); 1755ffd83dbSDimitry Andric // Element offset is in bytes. 1765ffd83dbSDimitry Andric if (!AccumulateOffset( 1775ffd83dbSDimitry Andric APInt(Offset.getBitWidth(), SL->getElementOffset(ElementIdx)), 1785ffd83dbSDimitry Andric 1)) 1795ffd83dbSDimitry Andric return false; 1805ffd83dbSDimitry Andric continue; 1815ffd83dbSDimitry Andric } 1825ffd83dbSDimitry Andric if (!AccumulateOffset(ConstOffset->getValue(), 1831db9f3b2SDimitry Andric GTI.getSequentialElementStride(DL))) 1845ffd83dbSDimitry Andric return false; 1850b57cec5SDimitry Andric continue; 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric 1885ffd83dbSDimitry Andric // The operand is not constant, check if an external analysis was provided. 1895ffd83dbSDimitry Andric // External analsis is not applicable to a struct type. 1905ffd83dbSDimitry Andric if (!ExternalAnalysis || STy || ScalableType) 1915ffd83dbSDimitry Andric return false; 1925ffd83dbSDimitry Andric APInt AnalysisIndex; 1935ffd83dbSDimitry Andric if (!ExternalAnalysis(*V, AnalysisIndex)) 1945ffd83dbSDimitry Andric return false; 1955ffd83dbSDimitry Andric UsedExternalAnalysis = true; 1961db9f3b2SDimitry Andric if (!AccumulateOffset(AnalysisIndex, GTI.getSequentialElementStride(DL))) 1975ffd83dbSDimitry Andric return false; 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric return true; 2000b57cec5SDimitry Andric } 201fe6060f1SDimitry Andric 202fe6060f1SDimitry Andric bool GEPOperator::collectOffset( 203fe6060f1SDimitry Andric const DataLayout &DL, unsigned BitWidth, 204fe6060f1SDimitry Andric MapVector<Value *, APInt> &VariableOffsets, 205fe6060f1SDimitry Andric APInt &ConstantOffset) const { 206fe6060f1SDimitry Andric assert(BitWidth == DL.getIndexSizeInBits(getPointerAddressSpace()) && 207fe6060f1SDimitry Andric "The offset bit width does not match DL specification."); 208fe6060f1SDimitry Andric 209fe6060f1SDimitry Andric auto CollectConstantOffset = [&](APInt Index, uint64_t Size) { 210fe6060f1SDimitry Andric Index = Index.sextOrTrunc(BitWidth); 211fe6060f1SDimitry Andric APInt IndexedSize = APInt(BitWidth, Size); 212fe6060f1SDimitry Andric ConstantOffset += Index * IndexedSize; 213fe6060f1SDimitry Andric }; 214fe6060f1SDimitry Andric 215fe6060f1SDimitry Andric for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this); 216fe6060f1SDimitry Andric GTI != GTE; ++GTI) { 217fe6060f1SDimitry Andric // Scalable vectors are multiplied by a runtime constant. 2185f757f3fSDimitry Andric bool ScalableType = GTI.getIndexedType()->isScalableTy(); 219fe6060f1SDimitry Andric 220fe6060f1SDimitry Andric Value *V = GTI.getOperand(); 221fe6060f1SDimitry Andric StructType *STy = GTI.getStructTypeOrNull(); 222fe6060f1SDimitry Andric // Handle ConstantInt if possible. 223fe6060f1SDimitry Andric if (auto ConstOffset = dyn_cast<ConstantInt>(V)) { 224fe6060f1SDimitry Andric if (ConstOffset->isZero()) 225fe6060f1SDimitry Andric continue; 226fe6060f1SDimitry Andric // If the type is scalable and the constant is not zero (vscale * n * 0 = 227fe6060f1SDimitry Andric // 0) bailout. 228fe6060f1SDimitry Andric // TODO: If the runtime value is accessible at any point before DWARF 229fe6060f1SDimitry Andric // emission, then we could potentially keep a forward reference to it 230fe6060f1SDimitry Andric // in the debug value to be filled in later. 231fe6060f1SDimitry Andric if (ScalableType) 232fe6060f1SDimitry Andric return false; 233fe6060f1SDimitry Andric // Handle a struct index, which adds its field offset to the pointer. 234fe6060f1SDimitry Andric if (STy) { 235fe6060f1SDimitry Andric unsigned ElementIdx = ConstOffset->getZExtValue(); 236fe6060f1SDimitry Andric const StructLayout *SL = DL.getStructLayout(STy); 237fe6060f1SDimitry Andric // Element offset is in bytes. 238fe6060f1SDimitry Andric CollectConstantOffset(APInt(BitWidth, SL->getElementOffset(ElementIdx)), 239fe6060f1SDimitry Andric 1); 240fe6060f1SDimitry Andric continue; 241fe6060f1SDimitry Andric } 242fe6060f1SDimitry Andric CollectConstantOffset(ConstOffset->getValue(), 2431db9f3b2SDimitry Andric GTI.getSequentialElementStride(DL)); 244fe6060f1SDimitry Andric continue; 245fe6060f1SDimitry Andric } 246fe6060f1SDimitry Andric 247fe6060f1SDimitry Andric if (STy || ScalableType) 248fe6060f1SDimitry Andric return false; 2491db9f3b2SDimitry Andric APInt IndexedSize = APInt(BitWidth, GTI.getSequentialElementStride(DL)); 2501b3bef43SDimitry Andric // Insert an initial offset of 0 for V iff none exists already, then 2511b3bef43SDimitry Andric // increment the offset by IndexedSize. 252349cc55cSDimitry Andric if (!IndexedSize.isZero()) { 2535f757f3fSDimitry Andric auto *It = VariableOffsets.insert({V, APInt(BitWidth, 0)}).first; 2545f757f3fSDimitry Andric It->second += IndexedSize; 255fe6060f1SDimitry Andric } 2561b3bef43SDimitry Andric } 257fe6060f1SDimitry Andric return true; 258fe6060f1SDimitry Andric } 2594824e7fdSDimitry Andric 2604824e7fdSDimitry Andric void FastMathFlags::print(raw_ostream &O) const { 2614824e7fdSDimitry Andric if (all()) 2624824e7fdSDimitry Andric O << " fast"; 2634824e7fdSDimitry Andric else { 2644824e7fdSDimitry Andric if (allowReassoc()) 2654824e7fdSDimitry Andric O << " reassoc"; 2664824e7fdSDimitry Andric if (noNaNs()) 2674824e7fdSDimitry Andric O << " nnan"; 2684824e7fdSDimitry Andric if (noInfs()) 2694824e7fdSDimitry Andric O << " ninf"; 2704824e7fdSDimitry Andric if (noSignedZeros()) 2714824e7fdSDimitry Andric O << " nsz"; 2724824e7fdSDimitry Andric if (allowReciprocal()) 2734824e7fdSDimitry Andric O << " arcp"; 2744824e7fdSDimitry Andric if (allowContract()) 2754824e7fdSDimitry Andric O << " contract"; 2764824e7fdSDimitry Andric if (approxFunc()) 2774824e7fdSDimitry Andric O << " afn"; 2784824e7fdSDimitry Andric } 2794824e7fdSDimitry Andric } 2805ffd83dbSDimitry Andric } // namespace llvm 281