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 { 22349cc55cSDimitry Andric bool Operator::hasPoisonGeneratingFlags() const { 23349cc55cSDimitry Andric switch (getOpcode()) { 24349cc55cSDimitry Andric case Instruction::Add: 25349cc55cSDimitry Andric case Instruction::Sub: 26349cc55cSDimitry Andric case Instruction::Mul: 27349cc55cSDimitry Andric case Instruction::Shl: { 28349cc55cSDimitry Andric auto *OBO = cast<OverflowingBinaryOperator>(this); 29349cc55cSDimitry Andric return OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap(); 30349cc55cSDimitry Andric } 31349cc55cSDimitry Andric case Instruction::UDiv: 32349cc55cSDimitry Andric case Instruction::SDiv: 33349cc55cSDimitry Andric case Instruction::AShr: 34349cc55cSDimitry Andric case Instruction::LShr: 35349cc55cSDimitry Andric return cast<PossiblyExactOperator>(this)->isExact(); 36349cc55cSDimitry Andric case Instruction::GetElementPtr: { 37349cc55cSDimitry Andric auto *GEP = cast<GEPOperator>(this); 38349cc55cSDimitry Andric // Note: inrange exists on constexpr only 39349cc55cSDimitry Andric return GEP->isInBounds() || GEP->getInRangeIndex() != None; 40349cc55cSDimitry Andric } 41349cc55cSDimitry Andric default: 42*0eae32dcSDimitry Andric if (const auto *FP = dyn_cast<FPMathOperator>(this)) 43*0eae32dcSDimitry Andric return FP->hasNoNaNs() || FP->hasNoInfs(); 44349cc55cSDimitry Andric return false; 45349cc55cSDimitry Andric } 46349cc55cSDimitry Andric } 47349cc55cSDimitry Andric 480b57cec5SDimitry Andric Type *GEPOperator::getSourceElementType() const { 490b57cec5SDimitry Andric if (auto *I = dyn_cast<GetElementPtrInst>(this)) 500b57cec5SDimitry Andric return I->getSourceElementType(); 510b57cec5SDimitry Andric return cast<GetElementPtrConstantExpr>(this)->getSourceElementType(); 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric Type *GEPOperator::getResultElementType() const { 550b57cec5SDimitry Andric if (auto *I = dyn_cast<GetElementPtrInst>(this)) 560b57cec5SDimitry Andric return I->getResultElementType(); 570b57cec5SDimitry Andric return cast<GetElementPtrConstantExpr>(this)->getResultElementType(); 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric 605ffd83dbSDimitry Andric Align GEPOperator::getMaxPreservedAlignment(const DataLayout &DL) const { 615ffd83dbSDimitry Andric /// compute the worse possible offset for every level of the GEP et accumulate 625ffd83dbSDimitry Andric /// the minimum alignment into Result. 635ffd83dbSDimitry Andric 645ffd83dbSDimitry Andric Align Result = Align(llvm::Value::MaximumAlignment); 655ffd83dbSDimitry Andric for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this); 665ffd83dbSDimitry Andric GTI != GTE; ++GTI) { 675ffd83dbSDimitry Andric int64_t Offset = 1; 685ffd83dbSDimitry Andric ConstantInt *OpC = dyn_cast<ConstantInt>(GTI.getOperand()); 695ffd83dbSDimitry Andric 705ffd83dbSDimitry Andric if (StructType *STy = GTI.getStructTypeOrNull()) { 715ffd83dbSDimitry Andric const StructLayout *SL = DL.getStructLayout(STy); 725ffd83dbSDimitry Andric Offset = SL->getElementOffset(OpC->getZExtValue()); 735ffd83dbSDimitry Andric } else { 745ffd83dbSDimitry Andric assert(GTI.isSequential() && "should be sequencial"); 755ffd83dbSDimitry Andric /// If the index isn't know we take 1 because it is the index that will 765ffd83dbSDimitry Andric /// give the worse alignment of the offset. 775ffd83dbSDimitry Andric int64_t ElemCount = 1; 785ffd83dbSDimitry Andric if (OpC) 795ffd83dbSDimitry Andric ElemCount = OpC->getZExtValue(); 805ffd83dbSDimitry Andric Offset = DL.getTypeAllocSize(GTI.getIndexedType()) * ElemCount; 815ffd83dbSDimitry Andric } 825ffd83dbSDimitry Andric Result = Align(MinAlign(Offset, Result.value())); 835ffd83dbSDimitry Andric } 845ffd83dbSDimitry Andric return Result; 855ffd83dbSDimitry Andric } 865ffd83dbSDimitry Andric 875ffd83dbSDimitry Andric bool GEPOperator::accumulateConstantOffset( 885ffd83dbSDimitry Andric const DataLayout &DL, APInt &Offset, 895ffd83dbSDimitry Andric function_ref<bool(Value &, APInt &)> ExternalAnalysis) const { 900b57cec5SDimitry Andric assert(Offset.getBitWidth() == 910b57cec5SDimitry Andric DL.getIndexSizeInBits(getPointerAddressSpace()) && 920b57cec5SDimitry Andric "The offset bit width does not match DL specification."); 93*0eae32dcSDimitry Andric SmallVector<const Value *> Index(llvm::drop_begin(operand_values())); 94d409305fSDimitry Andric return GEPOperator::accumulateConstantOffset(getSourceElementType(), Index, 95d409305fSDimitry Andric DL, Offset, ExternalAnalysis); 96d409305fSDimitry Andric } 970b57cec5SDimitry Andric 98d409305fSDimitry Andric bool GEPOperator::accumulateConstantOffset( 99d409305fSDimitry Andric Type *SourceType, ArrayRef<const Value *> Index, const DataLayout &DL, 100d409305fSDimitry Andric APInt &Offset, function_ref<bool(Value &, APInt &)> ExternalAnalysis) { 1015ffd83dbSDimitry Andric bool UsedExternalAnalysis = false; 1025ffd83dbSDimitry Andric auto AccumulateOffset = [&](APInt Index, uint64_t Size) -> bool { 1035ffd83dbSDimitry Andric Index = Index.sextOrTrunc(Offset.getBitWidth()); 1045ffd83dbSDimitry Andric APInt IndexedSize = APInt(Offset.getBitWidth(), Size); 1055ffd83dbSDimitry Andric // For array or vector indices, scale the index by the size of the type. 1065ffd83dbSDimitry Andric if (!UsedExternalAnalysis) { 1075ffd83dbSDimitry Andric Offset += Index * IndexedSize; 1085ffd83dbSDimitry Andric } else { 1095ffd83dbSDimitry Andric // External Analysis can return a result higher/lower than the value 1105ffd83dbSDimitry Andric // represents. We need to detect overflow/underflow. 1115ffd83dbSDimitry Andric bool Overflow = false; 1125ffd83dbSDimitry Andric APInt OffsetPlus = Index.smul_ov(IndexedSize, Overflow); 1135ffd83dbSDimitry Andric if (Overflow) 1145ffd83dbSDimitry Andric return false; 1155ffd83dbSDimitry Andric Offset = Offset.sadd_ov(OffsetPlus, Overflow); 1165ffd83dbSDimitry Andric if (Overflow) 1175ffd83dbSDimitry Andric return false; 1185ffd83dbSDimitry Andric } 1195ffd83dbSDimitry Andric return true; 1205ffd83dbSDimitry Andric }; 121d409305fSDimitry Andric auto begin = generic_gep_type_iterator<decltype(Index.begin())>::begin( 122d409305fSDimitry Andric SourceType, Index.begin()); 123d409305fSDimitry Andric auto end = generic_gep_type_iterator<decltype(Index.end())>::end(Index.end()); 124d409305fSDimitry Andric for (auto GTI = begin, GTE = end; GTI != GTE; ++GTI) { 1255ffd83dbSDimitry Andric // Scalable vectors are multiplied by a runtime constant. 1265ffd83dbSDimitry Andric bool ScalableType = false; 1275ffd83dbSDimitry Andric if (isa<ScalableVectorType>(GTI.getIndexedType())) 1285ffd83dbSDimitry Andric ScalableType = true; 1290b57cec5SDimitry Andric 1305ffd83dbSDimitry Andric Value *V = GTI.getOperand(); 1315ffd83dbSDimitry Andric StructType *STy = GTI.getStructTypeOrNull(); 1325ffd83dbSDimitry Andric // Handle ConstantInt if possible. 1335ffd83dbSDimitry Andric if (auto ConstOffset = dyn_cast<ConstantInt>(V)) { 1345ffd83dbSDimitry Andric if (ConstOffset->isZero()) 1355ffd83dbSDimitry Andric continue; 1365ffd83dbSDimitry Andric // if the type is scalable and the constant is not zero (vscale * n * 0 = 1375ffd83dbSDimitry Andric // 0) bailout. 1385ffd83dbSDimitry Andric if (ScalableType) 1395ffd83dbSDimitry Andric return false; 1400b57cec5SDimitry Andric // Handle a struct index, which adds its field offset to the pointer. 1415ffd83dbSDimitry Andric if (STy) { 1425ffd83dbSDimitry Andric unsigned ElementIdx = ConstOffset->getZExtValue(); 1430b57cec5SDimitry Andric const StructLayout *SL = DL.getStructLayout(STy); 1445ffd83dbSDimitry Andric // Element offset is in bytes. 1455ffd83dbSDimitry Andric if (!AccumulateOffset( 1465ffd83dbSDimitry Andric APInt(Offset.getBitWidth(), SL->getElementOffset(ElementIdx)), 1475ffd83dbSDimitry Andric 1)) 1485ffd83dbSDimitry Andric return false; 1495ffd83dbSDimitry Andric continue; 1505ffd83dbSDimitry Andric } 1515ffd83dbSDimitry Andric if (!AccumulateOffset(ConstOffset->getValue(), 1525ffd83dbSDimitry Andric DL.getTypeAllocSize(GTI.getIndexedType()))) 1535ffd83dbSDimitry Andric return false; 1540b57cec5SDimitry Andric continue; 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric 1575ffd83dbSDimitry Andric // The operand is not constant, check if an external analysis was provided. 1585ffd83dbSDimitry Andric // External analsis is not applicable to a struct type. 1595ffd83dbSDimitry Andric if (!ExternalAnalysis || STy || ScalableType) 1605ffd83dbSDimitry Andric return false; 1615ffd83dbSDimitry Andric APInt AnalysisIndex; 1625ffd83dbSDimitry Andric if (!ExternalAnalysis(*V, AnalysisIndex)) 1635ffd83dbSDimitry Andric return false; 1645ffd83dbSDimitry Andric UsedExternalAnalysis = true; 1655ffd83dbSDimitry Andric if (!AccumulateOffset(AnalysisIndex, 1665ffd83dbSDimitry Andric DL.getTypeAllocSize(GTI.getIndexedType()))) 1675ffd83dbSDimitry Andric return false; 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric return true; 1700b57cec5SDimitry Andric } 171fe6060f1SDimitry Andric 172fe6060f1SDimitry Andric bool GEPOperator::collectOffset( 173fe6060f1SDimitry Andric const DataLayout &DL, unsigned BitWidth, 174fe6060f1SDimitry Andric MapVector<Value *, APInt> &VariableOffsets, 175fe6060f1SDimitry Andric APInt &ConstantOffset) const { 176fe6060f1SDimitry Andric assert(BitWidth == DL.getIndexSizeInBits(getPointerAddressSpace()) && 177fe6060f1SDimitry Andric "The offset bit width does not match DL specification."); 178fe6060f1SDimitry Andric 179fe6060f1SDimitry Andric auto CollectConstantOffset = [&](APInt Index, uint64_t Size) { 180fe6060f1SDimitry Andric Index = Index.sextOrTrunc(BitWidth); 181fe6060f1SDimitry Andric APInt IndexedSize = APInt(BitWidth, Size); 182fe6060f1SDimitry Andric ConstantOffset += Index * IndexedSize; 183fe6060f1SDimitry Andric }; 184fe6060f1SDimitry Andric 185fe6060f1SDimitry Andric for (gep_type_iterator GTI = gep_type_begin(this), GTE = gep_type_end(this); 186fe6060f1SDimitry Andric GTI != GTE; ++GTI) { 187fe6060f1SDimitry Andric // Scalable vectors are multiplied by a runtime constant. 188fe6060f1SDimitry Andric bool ScalableType = isa<ScalableVectorType>(GTI.getIndexedType()); 189fe6060f1SDimitry Andric 190fe6060f1SDimitry Andric Value *V = GTI.getOperand(); 191fe6060f1SDimitry Andric StructType *STy = GTI.getStructTypeOrNull(); 192fe6060f1SDimitry Andric // Handle ConstantInt if possible. 193fe6060f1SDimitry Andric if (auto ConstOffset = dyn_cast<ConstantInt>(V)) { 194fe6060f1SDimitry Andric if (ConstOffset->isZero()) 195fe6060f1SDimitry Andric continue; 196fe6060f1SDimitry Andric // If the type is scalable and the constant is not zero (vscale * n * 0 = 197fe6060f1SDimitry Andric // 0) bailout. 198fe6060f1SDimitry Andric // TODO: If the runtime value is accessible at any point before DWARF 199fe6060f1SDimitry Andric // emission, then we could potentially keep a forward reference to it 200fe6060f1SDimitry Andric // in the debug value to be filled in later. 201fe6060f1SDimitry Andric if (ScalableType) 202fe6060f1SDimitry Andric return false; 203fe6060f1SDimitry Andric // Handle a struct index, which adds its field offset to the pointer. 204fe6060f1SDimitry Andric if (STy) { 205fe6060f1SDimitry Andric unsigned ElementIdx = ConstOffset->getZExtValue(); 206fe6060f1SDimitry Andric const StructLayout *SL = DL.getStructLayout(STy); 207fe6060f1SDimitry Andric // Element offset is in bytes. 208fe6060f1SDimitry Andric CollectConstantOffset(APInt(BitWidth, SL->getElementOffset(ElementIdx)), 209fe6060f1SDimitry Andric 1); 210fe6060f1SDimitry Andric continue; 211fe6060f1SDimitry Andric } 212fe6060f1SDimitry Andric CollectConstantOffset(ConstOffset->getValue(), 213fe6060f1SDimitry Andric DL.getTypeAllocSize(GTI.getIndexedType())); 214fe6060f1SDimitry Andric continue; 215fe6060f1SDimitry Andric } 216fe6060f1SDimitry Andric 217fe6060f1SDimitry Andric if (STy || ScalableType) 218fe6060f1SDimitry Andric return false; 219fe6060f1SDimitry Andric APInt IndexedSize = 220fe6060f1SDimitry Andric APInt(BitWidth, DL.getTypeAllocSize(GTI.getIndexedType())); 2211b3bef43SDimitry Andric // Insert an initial offset of 0 for V iff none exists already, then 2221b3bef43SDimitry Andric // increment the offset by IndexedSize. 223349cc55cSDimitry Andric if (!IndexedSize.isZero()) { 2241b3bef43SDimitry Andric VariableOffsets.insert({V, APInt(BitWidth, 0)}); 225fe6060f1SDimitry Andric VariableOffsets[V] += IndexedSize; 226fe6060f1SDimitry Andric } 2271b3bef43SDimitry Andric } 228fe6060f1SDimitry Andric return true; 229fe6060f1SDimitry Andric } 2304824e7fdSDimitry Andric 2314824e7fdSDimitry Andric void FastMathFlags::print(raw_ostream &O) const { 2324824e7fdSDimitry Andric if (all()) 2334824e7fdSDimitry Andric O << " fast"; 2344824e7fdSDimitry Andric else { 2354824e7fdSDimitry Andric if (allowReassoc()) 2364824e7fdSDimitry Andric O << " reassoc"; 2374824e7fdSDimitry Andric if (noNaNs()) 2384824e7fdSDimitry Andric O << " nnan"; 2394824e7fdSDimitry Andric if (noInfs()) 2404824e7fdSDimitry Andric O << " ninf"; 2414824e7fdSDimitry Andric if (noSignedZeros()) 2424824e7fdSDimitry Andric O << " nsz"; 2434824e7fdSDimitry Andric if (allowReciprocal()) 2444824e7fdSDimitry Andric O << " arcp"; 2454824e7fdSDimitry Andric if (allowContract()) 2464824e7fdSDimitry Andric O << " contract"; 2474824e7fdSDimitry Andric if (approxFunc()) 2484824e7fdSDimitry Andric O << " afn"; 2494824e7fdSDimitry Andric } 2504824e7fdSDimitry Andric } 2515ffd83dbSDimitry Andric } // namespace llvm 252