diff options
Diffstat (limited to 'llvm/lib/IR')
-rw-r--r-- | llvm/lib/IR/AsmWriter.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/IR/Assumptions.cpp | 22 | ||||
-rw-r--r-- | llvm/lib/IR/Attributes.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/IR/AutoUpgrade.cpp | 38 | ||||
-rw-r--r-- | llvm/lib/IR/ConstantFold.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/IR/ConstantRange.cpp | 42 | ||||
-rw-r--r-- | llvm/lib/IR/Constants.cpp | 20 | ||||
-rw-r--r-- | llvm/lib/IR/Core.cpp | 10 | ||||
-rw-r--r-- | llvm/lib/IR/DataLayout.cpp | 52 | ||||
-rw-r--r-- | llvm/lib/IR/DebugInfo.cpp | 71 | ||||
-rw-r--r-- | llvm/lib/IR/DebugInfoMetadata.cpp | 10 | ||||
-rw-r--r-- | llvm/lib/IR/Globals.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/IR/IRBuilder.cpp | 20 | ||||
-rw-r--r-- | llvm/lib/IR/Instruction.cpp | 32 | ||||
-rw-r--r-- | llvm/lib/IR/Instructions.cpp | 52 | ||||
-rw-r--r-- | llvm/lib/IR/IntrinsicInst.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/IR/LLVMContextImpl.h | 27 | ||||
-rw-r--r-- | llvm/lib/IR/Mangler.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/IR/ProfDataUtils.cpp | 12 | ||||
-rw-r--r-- | llvm/lib/IR/RuntimeLibcalls.cpp | 194 | ||||
-rw-r--r-- | llvm/lib/IR/Type.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/IR/Value.cpp | 49 | ||||
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 124 |
23 files changed, 452 insertions, 361 deletions
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index e5a4e1e..094678f 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -88,6 +88,8 @@ using namespace llvm; +// See https://llvm.org/docs/DebuggingLLVM.html for why these flags are useful. + static cl::opt<bool> PrintInstAddrs("print-inst-addrs", cl::Hidden, cl::desc("Print addresses of instructions when dumping")); @@ -1163,7 +1165,7 @@ int SlotTracker::processIndex() { std::vector<StringRef> ModulePaths; for (auto &[ModPath, _] : TheIndex->modulePaths()) ModulePaths.push_back(ModPath); - llvm::sort(ModulePaths.begin(), ModulePaths.end()); + llvm::sort(ModulePaths); for (auto &ModPath : ModulePaths) CreateModulePathSlot(ModPath); diff --git a/llvm/lib/IR/Assumptions.cpp b/llvm/lib/IR/Assumptions.cpp index 6adbbc4..f8bbcb3 100644 --- a/llvm/lib/IR/Assumptions.cpp +++ b/llvm/lib/IR/Assumptions.cpp @@ -101,12 +101,16 @@ bool llvm::addAssumptions(CallBase &CB, return ::addAssumptionsImpl(CB, Assumptions); } -StringSet<> llvm::KnownAssumptionStrings({ - "omp_no_openmp", // OpenMP 5.1 - "omp_no_openmp_routines", // OpenMP 5.1 - "omp_no_parallelism", // OpenMP 5.1 - "omp_no_openmp_constructs", // OpenMP 6.0 - "ompx_spmd_amenable", // OpenMPOpt extension - "ompx_no_call_asm", // OpenMPOpt extension - "ompx_aligned_barrier", // OpenMPOpt extension -}); +StringSet<> &llvm::getKnownAssumptionStrings() { + static StringSet<> Object({ + "omp_no_openmp", // OpenMP 5.1 + "omp_no_openmp_routines", // OpenMP 5.1 + "omp_no_parallelism", // OpenMP 5.1 + "omp_no_openmp_constructs", // OpenMP 6.0 + "ompx_spmd_amenable", // OpenMPOpt extension + "ompx_no_call_asm", // OpenMPOpt extension + "ompx_aligned_barrier", // OpenMPOpt extension + }); + + return Object; +} diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp index d1fbcb9..4ac2ebd 100644 --- a/llvm/lib/IR/Attributes.cpp +++ b/llvm/lib/IR/Attributes.cpp @@ -954,6 +954,19 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C, return get(C, B); } +AttributeSet AttributeSet::addAttributes(LLVMContext &C, + const AttrBuilder &B) const { + if (!hasAttributes()) + return get(C, B); + + if (!B.hasAttributes()) + return *this; + + AttrBuilder Merged(C, *this); + Merged.merge(B); + return get(C, Merged); +} + AttributeSet AttributeSet::removeAttribute(LLVMContext &C, Attribute::AttrKind Kind) const { if (!hasAttribute(Kind)) return *this; diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp index 7159107..7ea9c6d 100644 --- a/llvm/lib/IR/AutoUpgrade.cpp +++ b/llvm/lib/IR/AutoUpgrade.cpp @@ -1311,14 +1311,15 @@ static bool upgradeIntrinsicFunction1(Function *F, Function *&NewFn, } break; case 'l': - if (Name.starts_with("lifetime.start") || - Name.starts_with("lifetime.end")) { - // Unless remangling is required, do not upgrade the function declaration, - // but do upgrade the calls. - if (auto Result = llvm::Intrinsic::remangleIntrinsicFunction(F)) - NewFn = *Result; - else - NewFn = F; + if ((Name.starts_with("lifetime.start") || + Name.starts_with("lifetime.end")) && + F->arg_size() == 2) { + Intrinsic::ID IID = Name.starts_with("lifetime.start") + ? Intrinsic::lifetime_start + : Intrinsic::lifetime_end; + rename(F); + NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID, + F->getArg(0)->getType()); return true; } break; @@ -5133,21 +5134,20 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) { case Intrinsic::lifetime_start: case Intrinsic::lifetime_end: { - Value *Size = CI->getArgOperand(0); - Value *Ptr = CI->getArgOperand(1); - if (isa<AllocaInst>(Ptr)) { + if (CI->arg_size() != 2) { DefaultCase(); return; } + Value *Ptr = CI->getArgOperand(1); // Try to strip pointer casts, such that the lifetime works on an alloca. Ptr = Ptr->stripPointerCasts(); if (isa<AllocaInst>(Ptr)) { // Don't use NewFn, as we might have looked through an addrspacecast. if (NewFn->getIntrinsicID() == Intrinsic::lifetime_start) - NewCall = Builder.CreateLifetimeStart(Ptr, cast<ConstantInt>(Size)); + NewCall = Builder.CreateLifetimeStart(Ptr); else - NewCall = Builder.CreateLifetimeEnd(Ptr, cast<ConstantInt>(Size)); + NewCall = Builder.CreateLifetimeEnd(Ptr); break; } @@ -5381,6 +5381,16 @@ bool static upgradeSingleNVVMAnnotation(GlobalValue *GV, StringRef K, upgradeNVVMFnVectorAttr("nvvm.cluster_dim", K[0], GV, V); return true; } + if (K == "grid_constant") { + const auto Attr = Attribute::get(GV->getContext(), "nvvm.grid_constant"); + for (const auto &Op : cast<MDNode>(V)->operands()) { + // For some reason, the index is 1-based in the metadata. Good thing we're + // able to auto-upgrade it! + const auto Index = mdconst::extract<ConstantInt>(Op)->getZExtValue() - 1; + cast<Function>(GV)->addParamAttr(Index, Attr); + } + return true; + } return false; } @@ -5391,7 +5401,7 @@ void llvm::UpgradeNVVMAnnotations(Module &M) { return; SmallVector<MDNode *, 8> NewNodes; - SmallSet<const MDNode *, 8> SeenNodes; + SmallPtrSet<const MDNode *, 8> SeenNodes; for (MDNode *MD : NamedMD->operands()) { if (!SeenNodes.insert(MD).second) continue; diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp index d4ad21e..6b202ba 100644 --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -254,6 +254,7 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, return FoldBitCast(V, DestTy); case Instruction::AddrSpaceCast: case Instruction::IntToPtr: + case Instruction::PtrToAddr: case Instruction::PtrToInt: return nullptr; } diff --git a/llvm/lib/IR/ConstantRange.cpp b/llvm/lib/IR/ConstantRange.cpp index e09c139..b454c9a 100644 --- a/llvm/lib/IR/ConstantRange.cpp +++ b/llvm/lib/IR/ConstantRange.cpp @@ -829,6 +829,7 @@ ConstantRange ConstantRange::castOp(Instruction::CastOps CastOp, case Instruction::FPTrunc: case Instruction::FPExt: case Instruction::IntToPtr: + case Instruction::PtrToAddr: case Instruction::PtrToInt: case Instruction::AddrSpaceCast: // Conservatively return getFull set. @@ -871,7 +872,8 @@ ConstantRange ConstantRange::signExtend(uint32_t DstTySize) const { return ConstantRange(Lower.sext(DstTySize), Upper.sext(DstTySize)); } -ConstantRange ConstantRange::truncate(uint32_t DstTySize) const { +ConstantRange ConstantRange::truncate(uint32_t DstTySize, + unsigned NoWrapKind) const { assert(getBitWidth() > DstTySize && "Not a value truncation"); if (isEmptySet()) return getEmpty(DstTySize); @@ -885,22 +887,36 @@ ConstantRange ConstantRange::truncate(uint32_t DstTySize) const { // We use the non-wrapped set code to analyze the [Lower, MaxValue) part, and // then we do the union with [MaxValue, Upper) if (isUpperWrapped()) { - // If Upper is greater than or equal to MaxValue(DstTy), it covers the whole - // truncated range. - if (Upper.getActiveBits() > DstTySize || Upper.countr_one() == DstTySize) + // If Upper is greater than MaxValue(DstTy), it covers the whole truncated + // range. + if (Upper.getActiveBits() > DstTySize) return getFull(DstTySize); - Union = ConstantRange(APInt::getMaxValue(DstTySize),Upper.trunc(DstTySize)); - UpperDiv.setAllBits(); - - // Union covers the MaxValue case, so return if the remaining range is just - // MaxValue(DstTy). - if (LowerDiv == UpperDiv) - return Union; + // For nuw the two parts are: [0, Upper) \/ [Lower, MaxValue(DstTy)] + if (NoWrapKind & TruncInst::NoUnsignedWrap) { + Union = ConstantRange(APInt::getZero(DstTySize), Upper.trunc(DstTySize)); + UpperDiv = APInt::getOneBitSet(getBitWidth(), DstTySize); + } else { + // If Upper is equal to MaxValue(DstTy), it covers the whole truncated + // range. + if (Upper.countr_one() == DstTySize) + return getFull(DstTySize); + Union = + ConstantRange(APInt::getMaxValue(DstTySize), Upper.trunc(DstTySize)); + UpperDiv.setAllBits(); + // Union covers the MaxValue case, so return if the remaining range is + // just MaxValue(DstTy). + if (LowerDiv == UpperDiv) + return Union; + } } // Chop off the most significant bits that are past the destination bitwidth. if (LowerDiv.getActiveBits() > DstTySize) { + // For trunc nuw if LowerDiv is greater than MaxValue(DstTy), the range is + // outside the whole truncated range. + if (NoWrapKind & TruncInst::NoUnsignedWrap) + return Union; // Mask to just the signficant bits and subtract from LowerDiv/UpperDiv. APInt Adjust = LowerDiv & APInt::getBitsSetFrom(getBitWidth(), DstTySize); LowerDiv -= Adjust; @@ -912,6 +928,10 @@ ConstantRange ConstantRange::truncate(uint32_t DstTySize) const { return ConstantRange(LowerDiv.trunc(DstTySize), UpperDiv.trunc(DstTySize)).unionWith(Union); + if (!LowerDiv.isZero() && NoWrapKind & TruncInst::NoUnsignedWrap) + return ConstantRange(LowerDiv.trunc(DstTySize), APInt::getZero(DstTySize)) + .unionWith(Union); + // The truncated value wraps around. Check if we can do better than fullset. if (UpperDivWidth == DstTySize + 1) { // Clear the MSB so that UpperDiv wraps around. diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index a3c725b..c7e3113a 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -1567,6 +1567,7 @@ Constant *ConstantExpr::getWithOperands(ArrayRef<Constant *> Ops, Type *Ty, case Instruction::SIToFP: case Instruction::FPToUI: case Instruction::FPToSI: + case Instruction::PtrToAddr: case Instruction::PtrToInt: case Instruction::IntToPtr: case Instruction::BitCast: @@ -2223,6 +2224,8 @@ Constant *ConstantExpr::getCast(unsigned oc, Constant *C, Type *Ty, llvm_unreachable("Invalid cast opcode"); case Instruction::Trunc: return getTrunc(C, Ty, OnlyIfReduced); + case Instruction::PtrToAddr: + return getPtrToAddr(C, Ty, OnlyIfReduced); case Instruction::PtrToInt: return getPtrToInt(C, Ty, OnlyIfReduced); case Instruction::IntToPtr: @@ -2280,6 +2283,20 @@ Constant *ConstantExpr::getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced) { return getFoldedCast(Instruction::Trunc, C, Ty, OnlyIfReduced); } +Constant *ConstantExpr::getPtrToAddr(Constant *C, Type *DstTy, + bool OnlyIfReduced) { + assert(C->getType()->isPtrOrPtrVectorTy() && + "PtrToAddr source must be pointer or pointer vector"); + assert(DstTy->isIntOrIntVectorTy() && + "PtrToAddr destination must be integer or integer vector"); + assert(isa<VectorType>(C->getType()) == isa<VectorType>(DstTy)); + if (isa<VectorType>(C->getType())) + assert(cast<VectorType>(C->getType())->getElementCount() == + cast<VectorType>(DstTy)->getElementCount() && + "Invalid cast between a different number of vector elements"); + return getFoldedCast(Instruction::PtrToAddr, C, DstTy, OnlyIfReduced); +} + Constant *ConstantExpr::getPtrToInt(Constant *C, Type *DstTy, bool OnlyIfReduced) { assert(C->getType()->isPtrOrPtrVectorTy() && @@ -2435,6 +2452,7 @@ bool ConstantExpr::isDesirableCastOp(unsigned Opcode) { case Instruction::FPToSI: return false; case Instruction::Trunc: + case Instruction::PtrToAddr: case Instruction::PtrToInt: case Instruction::IntToPtr: case Instruction::BitCast: @@ -2457,6 +2475,7 @@ bool ConstantExpr::isSupportedCastOp(unsigned Opcode) { case Instruction::FPToSI: return false; case Instruction::Trunc: + case Instruction::PtrToAddr: case Instruction::PtrToInt: case Instruction::IntToPtr: case Instruction::BitCast: @@ -3401,6 +3420,7 @@ Instruction *ConstantExpr::getAsInstruction() const { switch (getOpcode()) { case Instruction::Trunc: + case Instruction::PtrToAddr: case Instruction::PtrToInt: case Instruction::IntToPtr: case Instruction::BitCast: diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index f7ef4aa..8b5965b 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -2186,6 +2186,11 @@ void LLVMGlobalSetMetadata(LLVMValueRef Global, unsigned Kind, unwrap<GlobalObject>(Global)->setMetadata(Kind, unwrap<MDNode>(MD)); } +void LLVMGlobalAddMetadata(LLVMValueRef Global, unsigned Kind, + LLVMMetadataRef MD) { + unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD)); +} + void LLVMGlobalEraseMetadata(LLVMValueRef Global, unsigned Kind) { unwrap<GlobalObject>(Global)->eraseMetadata(Kind); } @@ -2194,6 +2199,11 @@ void LLVMGlobalClearMetadata(LLVMValueRef Global) { unwrap<GlobalObject>(Global)->clearMetadata(); } +void LLVMGlobalAddDebugInfo(LLVMValueRef Global, LLVMMetadataRef GVE) { + unwrap<GlobalVariable>(Global)->addDebugInfo( + unwrap<DIGlobalVariableExpression>(GVE)); +} + /*--.. Operations on global variables ......................................--*/ LLVMValueRef LLVMAddGlobal(LLVMModuleRef M, LLVMTypeRef Ty, const char *Name) { diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp index dbd6d81..2cf96f8 100644 --- a/llvm/lib/IR/DataLayout.cpp +++ b/llvm/lib/IR/DataLayout.cpp @@ -694,7 +694,12 @@ void DataLayout::setPointerSpec(uint32_t AddrSpace, uint32_t BitWidth, Align DataLayout::getIntegerAlignment(uint32_t BitWidth, bool abi_or_pref) const { - auto I = lower_bound(IntSpecs, BitWidth, LessPrimitiveBitWidth()); + auto I = IntSpecs.begin(); + for (; I != IntSpecs.end(); ++I) { + if (I->BitWidth >= BitWidth) + break; + } + // If we don't have an exact match, use alignment of next larger integer // type. If there is none, use alignment of largest integer type by going // back one element. @@ -839,6 +844,44 @@ Align DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const { } } +TypeSize DataLayout::getTypeAllocSize(Type *Ty) const { + switch (Ty->getTypeID()) { + case Type::ArrayTyID: { + // The alignment of the array is the alignment of the element, so there + // is no need for further adjustment. + auto *ATy = cast<ArrayType>(Ty); + return ATy->getNumElements() * getTypeAllocSize(ATy->getElementType()); + } + case Type::StructTyID: { + const StructLayout *Layout = getStructLayout(cast<StructType>(Ty)); + TypeSize Size = Layout->getSizeInBytes(); + + if (cast<StructType>(Ty)->isPacked()) + return Size; + + Align A = std::max(StructABIAlignment, Layout->getAlignment()); + return alignTo(Size, A.value()); + } + case Type::IntegerTyID: { + unsigned BitWidth = Ty->getIntegerBitWidth(); + TypeSize Size = TypeSize::getFixed(divideCeil(BitWidth, 8)); + Align A = getIntegerAlignment(BitWidth, /*ABI=*/true); + return alignTo(Size, A.value()); + } + case Type::PointerTyID: { + unsigned AS = Ty->getPointerAddressSpace(); + TypeSize Size = TypeSize::getFixed(getPointerSize(AS)); + return alignTo(Size, getPointerABIAlignment(AS).value()); + } + case Type::TargetExtTyID: { + Type *LayoutTy = cast<TargetExtType>(Ty)->getLayoutType(); + return getTypeAllocSize(LayoutTy); + } + default: + return alignTo(getTypeStoreSize(Ty), getABITypeAlign(Ty).value()); + } +} + Align DataLayout::getABITypeAlign(Type *Ty) const { return getAlignment(Ty, true); } @@ -926,12 +969,13 @@ static APInt getElementIndex(TypeSize ElemSize, APInt &Offset) { return APInt::getZero(BitWidth); } - APInt Index = Offset.sdiv(ElemSize); - Offset -= Index * ElemSize; + uint64_t FixedElemSize = ElemSize.getFixedValue(); + APInt Index = Offset.sdiv(FixedElemSize); + Offset -= Index * FixedElemSize; if (Offset.isNegative()) { // Prefer a positive remaining offset to allow struct indexing. --Index; - Offset += ElemSize; + Offset += FixedElemSize; assert(Offset.isNonNegative() && "Remaining offset shouldn't be negative"); } return Index; diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index ab8ecee..b468d92 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -755,7 +755,7 @@ private: return getReplacementMDNode(N); }; - // Seperate recursive doRemap and operator [] into 2 lines to avoid + // Separate recursive doRemap and operator [] into 2 lines to avoid // out-of-order evaluations since both of them can access the same memory // location in map Replacements. auto Value = doRemap(N); @@ -1896,29 +1896,8 @@ AssignmentInstRange at::getAssignmentInsts(DIAssignID *ID) { return make_range(MapIt->second.begin(), MapIt->second.end()); } -AssignmentMarkerRange at::getAssignmentMarkers(DIAssignID *ID) { - assert(ID && "Expected non-null ID"); - LLVMContext &Ctx = ID->getContext(); - - auto *IDAsValue = MetadataAsValue::getIfExists(Ctx, ID); - - // The ID is only used wrapped in MetadataAsValue(ID), so lets check that - // one of those already exists first. - if (!IDAsValue) - return make_range(Value::user_iterator(), Value::user_iterator()); - - return make_range(IDAsValue->user_begin(), IDAsValue->user_end()); -} - void at::deleteAssignmentMarkers(const Instruction *Inst) { - auto Range = getAssignmentMarkers(Inst); - SmallVector<DbgVariableRecord *> DVRAssigns = getDVRAssignmentMarkers(Inst); - if (Range.empty() && DVRAssigns.empty()) - return; - SmallVector<DbgAssignIntrinsic *> ToDelete(Range.begin(), Range.end()); - for (auto *DAI : ToDelete) - DAI->eraseFromParent(); - for (auto *DVR : DVRAssigns) + for (auto *DVR : getDVRAssignmentMarkers(Inst)) DVR->eraseFromParent(); } @@ -1936,31 +1915,21 @@ void at::RAUW(DIAssignID *Old, DIAssignID *New) { } void at::deleteAll(Function *F) { - SmallVector<DbgAssignIntrinsic *, 12> ToDelete; - SmallVector<DbgVariableRecord *, 12> DPToDelete; for (BasicBlock &BB : *F) { for (Instruction &I : BB) { - for (DbgVariableRecord &DVR : filterDbgVars(I.getDbgRecordRange())) + for (DbgVariableRecord &DVR : + make_early_inc_range(filterDbgVars(I.getDbgRecordRange()))) if (DVR.isDbgAssign()) - DPToDelete.push_back(&DVR); - if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(&I)) - ToDelete.push_back(DAI); - else - I.setMetadata(LLVMContext::MD_DIAssignID, nullptr); + DVR.eraseFromParent(); + + I.setMetadata(LLVMContext::MD_DIAssignID, nullptr); } } - for (auto *DAI : ToDelete) - DAI->eraseFromParent(); - for (auto *DVR : DPToDelete) - DVR->eraseFromParent(); } -/// FIXME: Remove this wrapper function and call -/// DIExpression::calculateFragmentIntersect directly. -template <typename T> -bool calculateFragmentIntersectImpl( +bool at::calculateFragmentIntersect( const DataLayout &DL, const Value *Dest, uint64_t SliceOffsetInBits, - uint64_t SliceSizeInBits, const T *AssignRecord, + uint64_t SliceSizeInBits, const DbgVariableRecord *AssignRecord, std::optional<DIExpression::FragmentInfo> &Result) { // No overlap if this DbgRecord describes a killed location. if (AssignRecord->isKillAddress()) @@ -1989,26 +1958,6 @@ bool calculateFragmentIntersectImpl( BitExtractOffsetInBits, VarFrag, Result, OffsetFromLocationInBits); } -/// FIXME: Remove this wrapper function and call -/// DIExpression::calculateFragmentIntersect directly. -bool at::calculateFragmentIntersect( - const DataLayout &DL, const Value *Dest, uint64_t SliceOffsetInBits, - uint64_t SliceSizeInBits, const DbgAssignIntrinsic *DbgAssign, - std::optional<DIExpression::FragmentInfo> &Result) { - return calculateFragmentIntersectImpl(DL, Dest, SliceOffsetInBits, - SliceSizeInBits, DbgAssign, Result); -} - -/// FIXME: Remove this wrapper function and call -/// DIExpression::calculateFragmentIntersect directly. -bool at::calculateFragmentIntersect( - const DataLayout &DL, const Value *Dest, uint64_t SliceOffsetInBits, - uint64_t SliceSizeInBits, const DbgVariableRecord *DVRAssign, - std::optional<DIExpression::FragmentInfo> &Result) { - return calculateFragmentIntersectImpl(DL, Dest, SliceOffsetInBits, - SliceSizeInBits, DVRAssign, Result); -} - /// Update inlined instructions' DIAssignID metadata. We need to do this /// otherwise a function inlined more than once into the same function /// will cause DIAssignID to be shared by many instructions. @@ -2029,8 +1978,6 @@ void at::remapAssignID(DenseMap<DIAssignID *, DIAssignID *> &Map, } if (auto *ID = I.getMetadata(LLVMContext::MD_DIAssignID)) I.setMetadata(LLVMContext::MD_DIAssignID, GetNewID(ID)); - else if (auto *DAI = dyn_cast<DbgAssignIntrinsic>(&I)) - DAI->setAssignId(GetNewID(DAI->getAssignID())); } /// Collect constant properies (base, size, offset) of \p StoreDest. diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index f1d4549..96065ed 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -57,15 +57,9 @@ DebugVariable::DebugVariable(const DbgVariableRecord *DVR) DILocation::DILocation(LLVMContext &C, StorageType Storage, unsigned Line, unsigned Column, uint64_t AtomGroup, uint8_t AtomRank, ArrayRef<Metadata *> MDs, bool ImplicitCode) - : MDNode(C, DILocationKind, Storage, MDs) -#ifdef EXPERIMENTAL_KEY_INSTRUCTIONS - , - AtomGroup(AtomGroup), AtomRank(AtomRank) -#endif -{ -#ifdef EXPERIMENTAL_KEY_INSTRUCTIONS + : MDNode(C, DILocationKind, Storage, MDs), AtomGroup(AtomGroup), + AtomRank(AtomRank) { assert(AtomRank <= 7 && "AtomRank number should fit in 3 bits"); -#endif if (AtomGroup) C.updateDILocationAtomGroupWaterline(AtomGroup + 1); diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp index 7b799c7..11d33e2 100644 --- a/llvm/lib/IR/Globals.cpp +++ b/llvm/lib/IR/Globals.cpp @@ -404,6 +404,7 @@ findBaseObject(const Constant *C, DenseSet<const GlobalAlias *> &Aliases, return findBaseObject(CE->getOperand(0), Aliases, Op); } case Instruction::IntToPtr: + case Instruction::PtrToAddr: case Instruction::PtrToInt: case Instruction::BitCast: case Instruction::GetElementPtr: diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index 49c6dc7..614c3a9 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -411,28 +411,16 @@ CallInst *IRBuilderBase::CreateFPMinimumReduce(Value *Src) { return getReductionIntrinsic(Intrinsic::vector_reduce_fminimum, Src); } -CallInst *IRBuilderBase::CreateLifetimeStart(Value *Ptr, ConstantInt *Size) { +CallInst *IRBuilderBase::CreateLifetimeStart(Value *Ptr) { assert(isa<PointerType>(Ptr->getType()) && "lifetime.start only applies to pointers."); - if (!Size) - Size = getInt64(-1); - else - assert(Size->getType() == getInt64Ty() && - "lifetime.start requires the size to be an i64"); - Value *Ops[] = { Size, Ptr }; - return CreateIntrinsic(Intrinsic::lifetime_start, {Ptr->getType()}, Ops); + return CreateIntrinsic(Intrinsic::lifetime_start, {Ptr->getType()}, {Ptr}); } -CallInst *IRBuilderBase::CreateLifetimeEnd(Value *Ptr, ConstantInt *Size) { +CallInst *IRBuilderBase::CreateLifetimeEnd(Value *Ptr) { assert(isa<PointerType>(Ptr->getType()) && "lifetime.end only applies to pointers."); - if (!Size) - Size = getInt64(-1); - else - assert(Size->getType() == getInt64Ty() && - "lifetime.end requires the size to be an i64"); - Value *Ops[] = { Size, Ptr }; - return CreateIntrinsic(Intrinsic::lifetime_end, {Ptr->getType()}, Ops); + return CreateIntrinsic(Intrinsic::lifetime_end, {Ptr->getType()}, {Ptr}); } CallInst *IRBuilderBase::CreateInvariantStart(Value *Ptr, ConstantInt *Size) { diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp index 763cc18..5e87b5f 100644 --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -26,9 +26,18 @@ #include "llvm/IR/Operator.h" #include "llvm/IR/ProfDataUtils.h" #include "llvm/IR/Type.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" using namespace llvm; +// FIXME: Flag used for an ablation performance test, Issue #147390. Placing it +// here because referencing IR should be feasible from anywhere. Will be +// removed after the ablation test. +cl::opt<bool> ProfcheckDisableMetadataFixes( + "profcheck-disable-metadata-fixes", cl::Hidden, cl::init(false), + cl::desc( + "Disable metadata propagation fixes discovered through Issue #147390")); + InsertPosition::InsertPosition(Instruction *InsertBefore) : InsertAt(InsertBefore ? InsertBefore->getIterator() : InstListType::iterator()) {} @@ -543,14 +552,19 @@ void Instruction::dropUBImplyingAttrsAndUnknownMetadata( CB->removeRetAttrs(UBImplyingAttributes); } -void Instruction::dropUBImplyingAttrsAndMetadata() { +void Instruction::dropUBImplyingAttrsAndMetadata(ArrayRef<unsigned> Keep) { // !annotation metadata does not impact semantics. // !range, !nonnull and !align produce poison, so they are safe to speculate. // !noundef and various AA metadata must be dropped, as it generally produces // immediate undefined behavior. - unsigned KnownIDs[] = {LLVMContext::MD_annotation, LLVMContext::MD_range, - LLVMContext::MD_nonnull, LLVMContext::MD_align}; - dropUBImplyingAttrsAndUnknownMetadata(KnownIDs); + static const unsigned KnownIDs[] = { + LLVMContext::MD_annotation, LLVMContext::MD_range, + LLVMContext::MD_nonnull, LLVMContext::MD_align}; + SmallVector<unsigned> KeepIDs; + KeepIDs.reserve(Keep.size() + std::size(KnownIDs)); + append_range(KeepIDs, KnownIDs); + append_range(KeepIDs, Keep); + dropUBImplyingAttrsAndUnknownMetadata(KeepIDs); } bool Instruction::hasUBImplyingAttrs() const { @@ -817,6 +831,7 @@ const char *Instruction::getOpcodeName(unsigned OpCode) { case UIToFP: return "uitofp"; case SIToFP: return "sitofp"; case IntToPtr: return "inttoptr"; + case PtrToAddr: return "ptrtoaddr"; case PtrToInt: return "ptrtoint"; case BitCast: return "bitcast"; case AddrSpaceCast: return "addrspacecast"; @@ -942,14 +957,13 @@ bool Instruction::isIdenticalToWhenDefined(const Instruction *I, // We have two instructions of identical opcode and #operands. Check to see // if all operands are the same. - if (!std::equal(op_begin(), op_end(), I->op_begin())) + if (!equal(operands(), I->operands())) return false; // WARNING: this logic must be kept in sync with EliminateDuplicatePHINodes()! - if (const PHINode *thisPHI = dyn_cast<PHINode>(this)) { - const PHINode *otherPHI = cast<PHINode>(I); - return std::equal(thisPHI->block_begin(), thisPHI->block_end(), - otherPHI->block_begin()); + if (const PHINode *Phi = dyn_cast<PHINode>(this)) { + const PHINode *OtherPhi = cast<PHINode>(I); + return equal(Phi->blocks(), OtherPhi->blocks()); } return this->hasSameSpecialState(I, /*IgnoreAlignment=*/false, diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index b896382..a1751c0 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -2798,6 +2798,7 @@ bool CastInst::isNoopCast(Instruction::CastOps Opcode, return false; case Instruction::BitCast: return true; // BitCast never modifies bits. + case Instruction::PtrToAddr: case Instruction::PtrToInt: return DL.getIntPtrType(SrcTy)->getScalarSizeInBits() == DestTy->getScalarSizeInBits(); @@ -2855,26 +2856,29 @@ unsigned CastInst::isEliminableCastPair( // same reason. const unsigned numCastOps = Instruction::CastOpsEnd - Instruction::CastOpsBegin; + // clang-format off static const uint8_t CastResults[numCastOps][numCastOps] = { - // T F F U S F F P I B A -+ - // R Z S P P I I T P 2 N T S | - // U E E 2 2 2 2 R E I T C C +- secondOp - // N X X U S F F N X N 2 V V | - // C T T I I P P C T T P T T -+ - { 1, 0, 0,99,99, 0, 0,99,99,99, 0, 3, 0}, // Trunc -+ - { 8, 1, 9,99,99, 2,17,99,99,99, 2, 3, 0}, // ZExt | - { 8, 0, 1,99,99, 0, 2,99,99,99, 0, 3, 0}, // SExt | - { 0, 0, 0,99,99, 0, 0,99,99,99, 0, 3, 0}, // FPToUI | - { 0, 0, 0,99,99, 0, 0,99,99,99, 0, 3, 0}, // FPToSI | - { 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // UIToFP +- firstOp - { 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // SIToFP | - { 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // FPTrunc | - { 99,99,99, 2, 2,99,99, 8, 2,99,99, 4, 0}, // FPExt | - { 1, 0, 0,99,99, 0, 0,99,99,99, 7, 3, 0}, // PtrToInt | - { 99,99,99,99,99,99,99,99,99,11,99,15, 0}, // IntToPtr | - { 5, 5, 5, 0, 0, 5, 5, 0, 0,16, 5, 1,14}, // BitCast | - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,13,12}, // AddrSpaceCast -+ + // T F F U S F F P P I B A -+ + // R Z S P P I I T P 2 2 N T S | + // U E E 2 2 2 2 R E I A T C C +- secondOp + // N X X U S F F N X N D 2 V V | + // C T T I I P P C T T R P T T -+ + { 1, 0, 0,99,99, 0, 0,99,99,99,99, 0, 3, 0}, // Trunc -+ + { 8, 1, 9,99,99, 2,17,99,99,99,99, 2, 3, 0}, // ZExt | + { 8, 0, 1,99,99, 0, 2,99,99,99,99, 0, 3, 0}, // SExt | + { 0, 0, 0,99,99, 0, 0,99,99,99,99, 0, 3, 0}, // FPToUI | + { 0, 0, 0,99,99, 0, 0,99,99,99,99, 0, 3, 0}, // FPToSI | + { 99,99,99, 0, 0,99,99, 0, 0,99,99,99, 4, 0}, // UIToFP +- firstOp + { 99,99,99, 0, 0,99,99, 0, 0,99,99,99, 4, 0}, // SIToFP | + { 99,99,99, 0, 0,99,99, 0, 0,99,99,99, 4, 0}, // FPTrunc | + { 99,99,99, 2, 2,99,99, 8, 2,99,99,99, 4, 0}, // FPExt | + { 1, 0, 0,99,99, 0, 0,99,99,99,99, 7, 3, 0}, // PtrToInt | + { 1, 0, 0,99,99, 0, 0,99,99,99,99, 0, 3, 0}, // PtrToAddr | + { 99,99,99,99,99,99,99,99,99,11,99,99,15, 0}, // IntToPtr | + { 5, 5, 5, 0, 0, 5, 5, 0, 0,16,16, 5, 1,14}, // BitCast | + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,13,12}, // AddrSpaceCast -+ }; + // clang-format on // TODO: This logic could be encoded into the table above and handled in the // switch below. @@ -3046,6 +3050,7 @@ CastInst *CastInst::Create(Instruction::CastOps op, Value *S, Type *Ty, case SIToFP: return new SIToFPInst (S, Ty, Name, InsertBefore); case FPToUI: return new FPToUIInst (S, Ty, Name, InsertBefore); case FPToSI: return new FPToSIInst (S, Ty, Name, InsertBefore); + case PtrToAddr: return new PtrToAddrInst (S, Ty, Name, InsertBefore); case PtrToInt: return new PtrToIntInst (S, Ty, Name, InsertBefore); case IntToPtr: return new IntToPtrInst (S, Ty, Name, InsertBefore); case BitCast: @@ -3347,6 +3352,7 @@ CastInst::castIsValid(Instruction::CastOps op, Type *SrcTy, Type *DstTy) { case Instruction::FPToSI: return SrcTy->isFPOrFPVectorTy() && DstTy->isIntOrIntVectorTy() && SrcEC == DstEC; + case Instruction::PtrToAddr: case Instruction::PtrToInt: if (SrcEC != DstEC) return false; @@ -3460,6 +3466,12 @@ PtrToIntInst::PtrToIntInst(Value *S, Type *Ty, const Twine &Name, assert(castIsValid(getOpcode(), S, Ty) && "Illegal PtrToInt"); } +PtrToAddrInst::PtrToAddrInst(Value *S, Type *Ty, const Twine &Name, + InsertPosition InsertBefore) + : CastInst(Ty, PtrToAddr, S, Name, InsertBefore) { + assert(castIsValid(getOpcode(), S, Ty) && "Illegal PtrToAddr"); +} + IntToPtrInst::IntToPtrInst(Value *S, Type *Ty, const Twine &Name, InsertPosition InsertBefore) : CastInst(Ty, IntToPtr, S, Name, InsertBefore) { @@ -4427,6 +4439,10 @@ PtrToIntInst *PtrToIntInst::cloneImpl() const { return new PtrToIntInst(getOperand(0), getType()); } +PtrToAddrInst *PtrToAddrInst::cloneImpl() const { + return new PtrToAddrInst(getOperand(0), getType()); +} + IntToPtrInst *IntToPtrInst::cloneImpl() const { return new IntToPtrInst(getOperand(0), getType()); } diff --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp index b1d3339..23a4d1b 100644 --- a/llvm/lib/IR/IntrinsicInst.cpp +++ b/llvm/lib/IR/IntrinsicInst.cpp @@ -448,6 +448,7 @@ VPIntrinsic::getMemoryPointerParamPos(Intrinsic::ID VPID) { case Intrinsic::experimental_vp_strided_store: return 1; case Intrinsic::vp_load: + case Intrinsic::vp_load_ff: case Intrinsic::vp_gather: case Intrinsic::experimental_vp_strided_load: return 0; @@ -671,6 +672,10 @@ Function *VPIntrinsic::getOrInsertDeclarationForParams( VPFunc = Intrinsic::getOrInsertDeclaration( M, VPID, {ReturnType, Params[0]->getType()}); break; + case Intrinsic::vp_load_ff: + VPFunc = Intrinsic::getOrInsertDeclaration( + M, VPID, {ReturnType->getStructElementType(0), Params[0]->getType()}); + break; case Intrinsic::experimental_vp_strided_load: VPFunc = Intrinsic::getOrInsertDeclaration( M, VPID, {ReturnType, Params[0]->getType(), Params[1]->getType()}); diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index aa2a60e..e03f993 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -312,10 +312,8 @@ template <> struct MDNodeKeyImpl<MDTuple> : MDNodeOpsKey { template <> struct MDNodeKeyImpl<DILocation> { Metadata *Scope; Metadata *InlinedAt; -#ifdef EXPERIMENTAL_KEY_INSTRUCTIONS uint64_t AtomGroup : 61; uint64_t AtomRank : 3; -#endif unsigned Line; uint16_t Column; bool ImplicitCode; @@ -323,36 +321,24 @@ template <> struct MDNodeKeyImpl<DILocation> { MDNodeKeyImpl(unsigned Line, uint16_t Column, Metadata *Scope, Metadata *InlinedAt, bool ImplicitCode, uint64_t AtomGroup, uint8_t AtomRank) - : Scope(Scope), InlinedAt(InlinedAt), -#ifdef EXPERIMENTAL_KEY_INSTRUCTIONS - AtomGroup(AtomGroup), AtomRank(AtomRank), -#endif - Line(Line), Column(Column), ImplicitCode(ImplicitCode) { - } + : Scope(Scope), InlinedAt(InlinedAt), AtomGroup(AtomGroup), + AtomRank(AtomRank), Line(Line), Column(Column), + ImplicitCode(ImplicitCode) {} MDNodeKeyImpl(const DILocation *L) : Scope(L->getRawScope()), InlinedAt(L->getRawInlinedAt()), -#ifdef EXPERIMENTAL_KEY_INSTRUCTIONS AtomGroup(L->getAtomGroup()), AtomRank(L->getAtomRank()), -#endif Line(L->getLine()), Column(L->getColumn()), - ImplicitCode(L->isImplicitCode()) { - } + ImplicitCode(L->isImplicitCode()) {} bool isKeyOf(const DILocation *RHS) const { return Line == RHS->getLine() && Column == RHS->getColumn() && Scope == RHS->getRawScope() && InlinedAt == RHS->getRawInlinedAt() && - ImplicitCode == RHS->isImplicitCode() -#ifdef EXPERIMENTAL_KEY_INSTRUCTIONS - && AtomGroup == RHS->getAtomGroup() && - AtomRank == RHS->getAtomRank(); -#else - ; -#endif + ImplicitCode == RHS->isImplicitCode() && + AtomGroup == RHS->getAtomGroup() && AtomRank == RHS->getAtomRank(); } unsigned getHashValue() const { -#ifdef EXPERIMENTAL_KEY_INSTRUCTIONS // Hashing AtomGroup and AtomRank substantially impacts performance whether // Key Instructions is enabled or not. We can't detect whether it's enabled // here cheaply; avoiding hashing zero values is a good approximation. This @@ -363,7 +349,6 @@ template <> struct MDNodeKeyImpl<DILocation> { if (AtomGroup || AtomRank) return hash_combine(Line, Column, Scope, InlinedAt, ImplicitCode, AtomGroup, (uint8_t)AtomRank); -#endif return hash_combine(Line, Column, Scope, InlinedAt, ImplicitCode); } }; diff --git a/llvm/lib/IR/Mangler.cpp b/llvm/lib/IR/Mangler.cpp index 010bd15..ca6a480 100644 --- a/llvm/lib/IR/Mangler.cpp +++ b/llvm/lib/IR/Mangler.cpp @@ -292,6 +292,9 @@ void llvm::emitLinkerFlagsForUsedCOFF(raw_ostream &OS, const GlobalValue *GV, } std::optional<std::string> llvm::getArm64ECMangledFunctionName(StringRef Name) { + assert(!Name.empty() && + "getArm64ECMangledFunctionName requires non-empty name"); + if (Name[0] != '?') { // For non-C++ symbols, prefix the name with "#" unless it's already // mangled. diff --git a/llvm/lib/IR/ProfDataUtils.cpp b/llvm/lib/IR/ProfDataUtils.cpp index b1b5f67..d24263f 100644 --- a/llvm/lib/IR/ProfDataUtils.cpp +++ b/llvm/lib/IR/ProfDataUtils.cpp @@ -270,6 +270,18 @@ void setBranchWeights(Instruction &I, ArrayRef<uint32_t> Weights, I.setMetadata(LLVMContext::MD_prof, BranchWeights); } +SmallVector<uint32_t> downscaleWeights(ArrayRef<uint64_t> Weights, + std::optional<uint64_t> KnownMaxCount) { + uint64_t MaxCount = KnownMaxCount.has_value() ? KnownMaxCount.value() + : *llvm::max_element(Weights); + assert(MaxCount > 0 && "Bad max count"); + uint64_t Scale = calculateCountScale(MaxCount); + SmallVector<uint32_t> DownscaledWeights; + for (const auto &ECI : Weights) + DownscaledWeights.push_back(scaleBranchCount(ECI, Scale)); + return DownscaledWeights; +} + void scaleProfData(Instruction &I, uint64_t S, uint64_t T) { assert(T != 0 && "Caller should guarantee"); auto *ProfileData = I.getMetadata(LLVMContext::MD_prof); diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp index 1ca5878..4fe5714 100644 --- a/llvm/lib/IR/RuntimeLibcalls.cpp +++ b/llvm/lib/IR/RuntimeLibcalls.cpp @@ -8,65 +8,22 @@ #include "llvm/IR/RuntimeLibcalls.h" #include "llvm/ADT/StringTable.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/xxhash.h" +#include "llvm/TargetParser/ARMTargetParser.h" + +#define DEBUG_TYPE "runtime-libcalls-info" using namespace llvm; using namespace RTLIB; #define GET_INIT_RUNTIME_LIBCALL_NAMES #define GET_SET_TARGET_RUNTIME_LIBCALL_SETS +#define DEFINE_GET_LOOKUP_LIBCALL_IMPL_NAME #include "llvm/IR/RuntimeLibcalls.inc" #undef GET_INIT_RUNTIME_LIBCALL_NAMES #undef GET_SET_TARGET_RUNTIME_LIBCALL_SETS - -static void setARMLibcallNames(RuntimeLibcallsInfo &Info, const Triple &TT, - FloatABI::ABIType FloatABIType, - EABI EABIVersion) { - static const RTLIB::LibcallImpl AAPCS_Libcalls[] = { - RTLIB::__aeabi_dadd, RTLIB::__aeabi_ddiv, - RTLIB::__aeabi_dmul, RTLIB::__aeabi_dsub, - RTLIB::__aeabi_dcmpeq__oeq, RTLIB::__aeabi_dcmpeq__une, - RTLIB::__aeabi_dcmplt, RTLIB::__aeabi_dcmple, - RTLIB::__aeabi_dcmpge, RTLIB::__aeabi_dcmpgt, - RTLIB::__aeabi_dcmpun, RTLIB::__aeabi_fadd, - RTLIB::__aeabi_fdiv, RTLIB::__aeabi_fmul, - RTLIB::__aeabi_fsub, RTLIB::__aeabi_fcmpeq__oeq, - RTLIB::__aeabi_fcmpeq__une, RTLIB::__aeabi_fcmplt, - RTLIB::__aeabi_fcmple, RTLIB::__aeabi_fcmpge, - RTLIB::__aeabi_fcmpgt, RTLIB::__aeabi_fcmpun, - RTLIB::__aeabi_d2iz, RTLIB::__aeabi_d2uiz, - RTLIB::__aeabi_d2lz, RTLIB::__aeabi_d2ulz, - RTLIB::__aeabi_f2iz, RTLIB::__aeabi_f2uiz, - RTLIB::__aeabi_f2lz, RTLIB::__aeabi_f2ulz, - RTLIB::__aeabi_d2f, RTLIB::__aeabi_d2h, - RTLIB::__aeabi_f2d, RTLIB::__aeabi_i2d, - RTLIB::__aeabi_ui2d, RTLIB::__aeabi_l2d, - RTLIB::__aeabi_ul2d, RTLIB::__aeabi_i2f, - RTLIB::__aeabi_ui2f, RTLIB::__aeabi_l2f, - RTLIB::__aeabi_ul2f, RTLIB::__aeabi_lmul, - RTLIB::__aeabi_llsl, RTLIB::__aeabi_llsr, - RTLIB::__aeabi_lasr, RTLIB::__aeabi_idiv__i8, - RTLIB::__aeabi_idiv__i16, RTLIB::__aeabi_idiv__i32, - RTLIB::__aeabi_idivmod, RTLIB::__aeabi_uidivmod, - RTLIB::__aeabi_ldivmod, RTLIB::__aeabi_uidiv__i8, - RTLIB::__aeabi_uidiv__i16, RTLIB::__aeabi_uidiv__i32, - RTLIB::__aeabi_uldivmod, RTLIB::__aeabi_f2h, - RTLIB::__aeabi_d2h, RTLIB::__aeabi_h2f, - RTLIB::__aeabi_memcpy, RTLIB::__aeabi_memmove, - RTLIB::__aeabi_memset, RTLIB::__aeabi_memcpy4, - RTLIB::__aeabi_memcpy8, RTLIB::__aeabi_memmove4, - RTLIB::__aeabi_memmove8, RTLIB::__aeabi_memset4, - RTLIB::__aeabi_memset8, RTLIB::__aeabi_memclr, - RTLIB::__aeabi_memclr4, RTLIB::__aeabi_memclr8}; - - for (RTLIB::LibcallImpl Impl : AAPCS_Libcalls) - Info.setLibcallImplCallingConv(Impl, CallingConv::ARM_AAPCS); -} - -void RTLIB::RuntimeLibcallsInfo::initDefaultLibCallImpls() { - std::memcpy(LibcallImpls, DefaultLibcallImpls, sizeof(LibcallImpls)); - static_assert(sizeof(LibcallImpls) == sizeof(DefaultLibcallImpls), - "libcall array size should match"); -} +#undef DEFINE_GET_LOOKUP_LIBCALL_IMPL_NAME /// Set default libcall names. If a target wants to opt-out of a libcall it /// should be placed here. @@ -74,114 +31,57 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT, ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, EABI EABIVersion, StringRef ABIName) { - setTargetRuntimeLibcallSets(TT, FloatABI); - - // Early exit for targets that have fully ported to tablegen. - if (TT.isAMDGPU() || TT.isNVPTX() || TT.isWasm()) - return; + setTargetRuntimeLibcallSets(TT, ExceptionModel, FloatABI, EABIVersion, + ABIName); - if (TT.isX86() || TT.isVE() || TT.isARM() || TT.isThumb()) { - if (ExceptionModel == ExceptionHandling::SjLj) - setLibcallImpl(RTLIB::UNWIND_RESUME, RTLIB::_Unwind_SjLj_Resume); - } - - // A few names are different on particular architectures or environments. - if (TT.isOSDarwin()) { - // For f16/f32 conversions, Darwin uses the standard naming scheme, - // instead of the gnueabi-style __gnu_*_ieee. - // FIXME: What about other targets? - setLibcallImpl(RTLIB::FPEXT_F16_F32, RTLIB::__extendhfsf2); - setLibcallImpl(RTLIB::FPROUND_F32_F16, RTLIB::__truncsfhf2); - - if (!darwinHasExp10(TT)) { - setLibcallImpl(RTLIB::EXP10_F32, RTLIB::Unsupported); - setLibcallImpl(RTLIB::EXP10_F64, RTLIB::Unsupported); + if (TT.isARM() || TT.isThumb()) { + // The half <-> float conversion functions are always soft-float on + // non-watchos platforms, but are needed for some targets which use a + // hard-float calling convention by default. + if (!TT.isWatchABI()) { + if (isAAPCS_ABI(TT, ABIName)) { + setLibcallImplCallingConv(RTLIB::impl___truncsfhf2, + CallingConv::ARM_AAPCS); + setLibcallImplCallingConv(RTLIB::impl___truncdfhf2, + CallingConv::ARM_AAPCS); + setLibcallImplCallingConv(RTLIB::impl___extendhfsf2, + CallingConv::ARM_AAPCS); + } else { + setLibcallImplCallingConv(RTLIB::impl___truncsfhf2, + CallingConv::ARM_APCS); + setLibcallImplCallingConv(RTLIB::impl___truncdfhf2, + CallingConv::ARM_APCS); + setLibcallImplCallingConv(RTLIB::impl___extendhfsf2, + CallingConv::ARM_APCS); + } } - } - if (TT.isOSOpenBSD()) { - setLibcallImpl(RTLIB::STACKPROTECTOR_CHECK_FAIL, RTLIB::Unsupported); - setLibcallImpl(RTLIB::STACK_SMASH_HANDLER, RTLIB::__stack_smash_handler); - } - - // Skip default manual processing for targets that have been mostly ported to - // tablegen for now. Eventually the rest of this should be deleted. - if (TT.isX86() || TT.isAArch64() || TT.isWasm() || TT.isPPC()) return; - - if (TT.isARM() || TT.isThumb()) { - setARMLibcallNames(*this, TT, FloatABI, EABIVersion); - return; - } - - if (hasSinCos(TT)) { - setLibcallImpl(RTLIB::SINCOS_F32, RTLIB::sincosf); - setLibcallImpl(RTLIB::SINCOS_F64, RTLIB::sincos); - setLibcallImpl(RTLIB::SINCOS_F128, RTLIB::sincos_f128); - } - - setLibcallImpl(RTLIB::EXP10_F32, RTLIB::exp10f); - setLibcallImpl(RTLIB::EXP10_F64, RTLIB::exp10); - setLibcallImpl(RTLIB::EXP10_F128, RTLIB::exp10l_f128); - - // These libcalls are only available in compiler-rt, not libgcc. - if (TT.isArch64Bit()) { - setLibcallImpl(RTLIB::SHL_I128, RTLIB::__ashlti3); - setLibcallImpl(RTLIB::SRL_I128, RTLIB::__lshrti3); - setLibcallImpl(RTLIB::SRA_I128, RTLIB::__ashrti3); - setLibcallImpl(RTLIB::MUL_I128, RTLIB::__multi3); - setLibcallImpl(RTLIB::MULO_I64, RTLIB::__mulodi4); - } - - if (TT.getArch() == Triple::ArchType::msp430) { - setLibcallImplCallingConv(RTLIB::__mspabi_mpyll, - CallingConv::MSP430_BUILTIN); } } -RTLIB::LibcallImpl -RuntimeLibcallsInfo::getSupportedLibcallImpl(StringRef FuncName) const { - const ArrayRef<uint16_t> RuntimeLibcallNameOffsets( - RuntimeLibcallNameOffsetTable); - - iterator_range<ArrayRef<uint16_t>::const_iterator> Range = - getRecognizedLibcallImpls(FuncName); - - for (auto I = Range.begin(); I != Range.end(); ++I) { - RTLIB::LibcallImpl Impl = - static_cast<RTLIB::LibcallImpl>(I - RuntimeLibcallNameOffsets.begin()); - - // FIXME: This should not depend on looking up ImplToLibcall, only the list - // of libcalls for the module. - RTLIB::LibcallImpl Recognized = LibcallImpls[ImplToLibcall[Impl]]; - if (Recognized != RTLIB::Unsupported) - return Recognized; +LLVM_ATTRIBUTE_ALWAYS_INLINE +iota_range<RTLIB::LibcallImpl> +RuntimeLibcallsInfo::libcallImplNameHit(uint16_t NameOffsetEntry, + uint16_t StrOffset) { + int NumAliases = 1; + for (uint16_t Entry : ArrayRef(RuntimeLibcallNameOffsetTable) + .drop_front(NameOffsetEntry + 1)) { + if (Entry != StrOffset) + break; + ++NumAliases; } - return RTLIB::Unsupported; + RTLIB::LibcallImpl ImplStart = static_cast<RTLIB::LibcallImpl>( + &RuntimeLibcallNameOffsetTable[NameOffsetEntry] - + &RuntimeLibcallNameOffsetTable[0]); + return enum_seq(ImplStart, + static_cast<RTLIB::LibcallImpl>(ImplStart + NumAliases)); } -iterator_range<ArrayRef<uint16_t>::const_iterator> -RuntimeLibcallsInfo::getRecognizedLibcallImpls(StringRef FuncName) { - StringTable::Iterator It = lower_bound(RuntimeLibcallImplNameTable, FuncName); - if (It == RuntimeLibcallImplNameTable.end() || *It != FuncName) - return iterator_range(ArrayRef<uint16_t>()); - - uint16_t IndexVal = It.offset().value(); - const ArrayRef<uint16_t> TableRef(RuntimeLibcallNameOffsetTable); - - ArrayRef<uint16_t>::const_iterator E = TableRef.end(); - ArrayRef<uint16_t>::const_iterator EntriesBegin = - std::lower_bound(TableRef.begin(), E, IndexVal); - ArrayRef<uint16_t>::const_iterator EntriesEnd = EntriesBegin; - - while (EntriesEnd != E && *EntriesEnd == IndexVal) - ++EntriesEnd; - - assert(EntriesBegin != E && - "libcall found in name table but not offset table"); - - return make_range(EntriesBegin, EntriesEnd); +bool RuntimeLibcallsInfo::isAAPCS_ABI(const Triple &TT, StringRef ABIName) { + const ARM::ARMABI TargetABI = ARM::computeTargetABI(TT, ABIName); + return TargetABI == ARM::ARM_ABI_AAPCS || TargetABI == ARM::ARM_ABI_AAPCS16; } bool RuntimeLibcallsInfo::darwinHasExp10(const Triple &TT) { diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp index 9c34662..9db48e8 100644 --- a/llvm/lib/IR/Type.cpp +++ b/llvm/lib/IR/Type.cpp @@ -1036,7 +1036,8 @@ static TargetTypeInfo getTargetTypeInfo(const TargetExtType *Ty) { // DirectX resources if (Name.starts_with("dx.")) return TargetTypeInfo(PointerType::get(C, 0), TargetExtType::CanBeGlobal, - TargetExtType::CanBeLocal); + TargetExtType::CanBeLocal, + TargetExtType::IsTokenLike); // Opaque types in the AMDGPU name space. if (Name == "amdgcn.named.barrier") { @@ -1054,6 +1055,14 @@ static TargetTypeInfo getTargetTypeInfo(const TargetExtType *Ty) { return TargetTypeInfo(Type::getVoidTy(C)); } +bool Type::isTokenLikeTy() const { + if (isTokenTy()) + return true; + if (auto *TT = dyn_cast<TargetExtType>(this)) + return TT->hasProperty(TargetExtType::Property::IsTokenLike); + return false; +} + Type *TargetExtType::getLayoutType() const { return getTargetTypeInfo(this).LayoutType; } diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp index 129ca4a..4e8f359 100644 --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -747,34 +747,28 @@ const Value *Value::stripAndAccumulateConstantOffsets( // means when we construct GEPOffset, we need to use the size // of GEP's pointer type rather than the size of the original // pointer type. - unsigned CurBitWidth = DL.getIndexTypeSizeInBits(V->getType()); - if (CurBitWidth == BitWidth) { - if (!GEP->accumulateConstantOffset(DL, Offset, ExternalAnalysis)) - return V; - } else { - APInt GEPOffset(CurBitWidth, 0); - if (!GEP->accumulateConstantOffset(DL, GEPOffset, ExternalAnalysis)) - return V; + APInt GEPOffset(DL.getIndexTypeSizeInBits(V->getType()), 0); + if (!GEP->accumulateConstantOffset(DL, GEPOffset, ExternalAnalysis)) + return V; - // Stop traversal if the pointer offset wouldn't fit in the bit-width - // provided by the Offset argument. This can happen due to AddrSpaceCast - // stripping. - if (GEPOffset.getSignificantBits() > BitWidth) - return V; + // Stop traversal if the pointer offset wouldn't fit in the bit-width + // provided by the Offset argument. This can happen due to AddrSpaceCast + // stripping. + if (GEPOffset.getSignificantBits() > BitWidth) + return V; - // External Analysis can return a result higher/lower than the value - // represents. We need to detect overflow/underflow. - APInt GEPOffsetST = GEPOffset.sextOrTrunc(BitWidth); - if (!ExternalAnalysis) { - Offset += GEPOffsetST; - } else { - bool Overflow = false; - APInt OldOffset = Offset; - Offset = Offset.sadd_ov(GEPOffsetST, Overflow); - if (Overflow) { - Offset = OldOffset; - return V; - } + // External Analysis can return a result higher/lower than the value + // represents. We need to detect overflow/underflow. + APInt GEPOffsetST = GEPOffset.sextOrTrunc(BitWidth); + if (!ExternalAnalysis) { + Offset += GEPOffsetST; + } else { + bool Overflow = false; + APInt OldOffset = Offset; + Offset = Offset.sadd_ov(GEPOffsetST, Overflow); + if (Overflow) { + Offset = OldOffset; + return V; } } V = GEP->getPointerOperand(); @@ -842,6 +836,9 @@ bool Value::canBeFreed() const { return false; } + if (isa<IntToPtrInst>(this) && getMetadata(LLVMContext::MD_nofree)) + return false; + const Function *F = nullptr; if (auto *I = dyn_cast<Instruction>(this)) F = I->getFunction(); diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 3ff9895..b285150 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -55,7 +55,6 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" @@ -527,6 +526,7 @@ private: void visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty); void visitNoaliasAddrspaceMetadata(Instruction &I, MDNode *Range, Type *Ty); void visitDereferenceableMetadata(Instruction &I, MDNode *MD); + void visitNofreeMetadata(Instruction &I, MDNode *MD); void visitProfMetadata(Instruction &I, MDNode *MD); void visitCallStackMetadata(MDNode *MD); void visitMemProfMetadata(Instruction &I, MDNode *MD); @@ -566,6 +566,8 @@ private: void visitUIToFPInst(UIToFPInst &I); void visitSIToFPInst(SIToFPInst &I); void visitIntToPtrInst(IntToPtrInst &I); + void checkPtrToAddr(Type *SrcTy, Type *DestTy, const Value &V); + void visitPtrToAddrInst(PtrToAddrInst &I); void visitPtrToIntInst(PtrToIntInst &I); void visitBitCastInst(BitCastInst &I); void visitAddrSpaceCastInst(AddrSpaceCastInst &I); @@ -834,6 +836,7 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) { &GV); Check(GV.getInitializer()->getType()->isSized(), "Global variable initializer must be sized", &GV); + visitConstantExprsRecursively(GV.getInitializer()); // If the global has common linkage, it must have a zero initializer and // cannot be constant. if (GV.hasCommonLinkage()) { @@ -1296,9 +1299,11 @@ void Verifier::visitDIDerivedType(const DIDerivedType &N) { if (N.getTag() == dwarf::DW_TAG_set_type) { if (auto *T = N.getRawBaseType()) { auto *Enum = dyn_cast_or_null<DICompositeType>(T); + auto *Subrange = dyn_cast_or_null<DISubrangeType>(T); auto *Basic = dyn_cast_or_null<DIBasicType>(T); CheckDI( (Enum && Enum->getTag() == dwarf::DW_TAG_enumeration_type) || + (Subrange && Subrange->getTag() == dwarf::DW_TAG_subrange_type) || (Basic && (Basic->getEncoding() == dwarf::DW_ATE_unsigned || Basic->getEncoding() == dwarf::DW_ATE_signed || Basic->getEncoding() == dwarf::DW_ATE_unsigned_char || @@ -2610,6 +2615,8 @@ void Verifier::visitConstantExpr(const ConstantExpr *CE) { Check(CastInst::castIsValid(Instruction::BitCast, CE->getOperand(0), CE->getType()), "Invalid bitcast", CE); + else if (CE->getOpcode() == Instruction::PtrToAddr) + checkPtrToAddr(CE->getOperand(0)->getType(), CE->getType(), *CE); } void Verifier::visitConstantPtrAuth(const ConstantPtrAuth *CPA) { @@ -3002,7 +3009,7 @@ void Verifier::visitFunction(const Function &F) { if (!IsIntrinsic) { Check(!Arg.getType()->isMetadataTy(), "Function takes metadata but isn't an intrinsic", &Arg, &F); - Check(!Arg.getType()->isTokenTy(), + Check(!Arg.getType()->isTokenLikeTy(), "Function takes token but isn't an intrinsic", &Arg, &F); Check(!Arg.getType()->isX86_AMXTy(), "Function takes x86_amx but isn't an intrinsic", &Arg, &F); @@ -3016,7 +3023,7 @@ void Verifier::visitFunction(const Function &F) { } if (!IsIntrinsic) { - Check(!F.getReturnType()->isTokenTy(), + Check(!F.getReturnType()->isTokenLikeTy(), "Function returns a token but isn't an intrinsic", &F); Check(!F.getReturnType()->isX86_AMXTy(), "Function returns a x86_amx but isn't an intrinsic", &F); @@ -3532,6 +3539,28 @@ void Verifier::visitFPToSIInst(FPToSIInst &I) { visitInstruction(I); } +void Verifier::checkPtrToAddr(Type *SrcTy, Type *DestTy, const Value &V) { + Check(SrcTy->isPtrOrPtrVectorTy(), "PtrToAddr source must be pointer", V); + Check(DestTy->isIntOrIntVectorTy(), "PtrToAddr result must be integral", V); + Check(SrcTy->isVectorTy() == DestTy->isVectorTy(), "PtrToAddr type mismatch", + V); + + if (SrcTy->isVectorTy()) { + auto *VSrc = cast<VectorType>(SrcTy); + auto *VDest = cast<VectorType>(DestTy); + Check(VSrc->getElementCount() == VDest->getElementCount(), + "PtrToAddr vector length mismatch", V); + } + + Type *AddrTy = DL.getAddressType(SrcTy); + Check(AddrTy == DestTy, "PtrToAddr result must be address width", V); +} + +void Verifier::visitPtrToAddrInst(PtrToAddrInst &I) { + checkPtrToAddr(I.getOperand(0)->getType(), I.getType(), I); + visitInstruction(I); +} + void Verifier::visitPtrToIntInst(PtrToIntInst &I) { // Get the source and destination types Type *SrcTy = I.getOperand(0)->getType(); @@ -3547,7 +3576,7 @@ void Verifier::visitPtrToIntInst(PtrToIntInst &I) { auto *VSrc = cast<VectorType>(SrcTy); auto *VDest = cast<VectorType>(DestTy); Check(VSrc->getElementCount() == VDest->getElementCount(), - "PtrToInt Vector width mismatch", &I); + "PtrToInt Vector length mismatch", &I); } visitInstruction(I); @@ -3567,7 +3596,7 @@ void Verifier::visitIntToPtrInst(IntToPtrInst &I) { auto *VSrc = cast<VectorType>(SrcTy); auto *VDest = cast<VectorType>(DestTy); Check(VSrc->getElementCount() == VDest->getElementCount(), - "IntToPtr Vector width mismatch", &I); + "IntToPtr Vector length mismatch", &I); } visitInstruction(I); } @@ -3608,7 +3637,7 @@ void Verifier::visitPHINode(PHINode &PN) { "PHI nodes not grouped at top of basic block!", &PN, PN.getParent()); // Check that a PHI doesn't yield a Token. - Check(!PN.getType()->isTokenTy(), "PHI nodes cannot have token type!"); + Check(!PN.getType()->isTokenLikeTy(), "PHI nodes cannot have token type!"); // Check that all of the values of the PHI node have the same type as the // result. @@ -3813,14 +3842,14 @@ void Verifier::visitCallBase(CallBase &Call) { for (Type *ParamTy : FTy->params()) { Check(!ParamTy->isMetadataTy(), "Function has metadata parameter but isn't an intrinsic", Call); - Check(!ParamTy->isTokenTy(), + Check(!ParamTy->isTokenLikeTy(), "Function has token parameter but isn't an intrinsic", Call); } } // Verify that indirect calls don't return tokens. if (!Call.getCalledFunction()) { - Check(!FTy->getReturnType()->isTokenTy(), + Check(!FTy->getReturnType()->isTokenLikeTy(), "Return type cannot be token for indirect call!"); Check(!FTy->getReturnType()->isX86_AMXTy(), "Return type cannot be x86_amx for indirect call!"); @@ -4609,7 +4638,7 @@ void Verifier::visitEHPadPredecessors(Instruction &I) { } // The edge may exit from zero or more nested pads. - SmallSet<Value *, 8> Seen; + SmallPtrSet<Value *, 8> Seen; for (;; FromPad = getParentPad(FromPad)) { Check(FromPad != ToPad, "EH pad cannot handle exceptions raised within it", FromPad, TI); @@ -4737,7 +4766,7 @@ void Verifier::visitFuncletPadInst(FuncletPadInst &FPI) { User *FirstUser = nullptr; Value *FirstUnwindPad = nullptr; SmallVector<FuncletPadInst *, 8> Worklist({&FPI}); - SmallSet<FuncletPadInst *, 8> Seen; + SmallPtrSet<FuncletPadInst *, 8> Seen; while (!Worklist.empty()) { FuncletPadInst *CurrentPad = Worklist.pop_back_val(); @@ -4995,6 +5024,13 @@ void Verifier::visitDereferenceableMetadata(Instruction& I, MDNode* MD) { &I); } +void Verifier::visitNofreeMetadata(Instruction &I, MDNode *MD) { + Check(I.getType()->isPointerTy(), "nofree applies only to pointer types", &I); + Check((isa<IntToPtrInst>(I)), "nofree applies only to inttoptr instruction", + &I); + Check(MD->getNumOperands() == 0, "nofree metadata must be empty", &I); +} + void Verifier::visitProfMetadata(Instruction &I, MDNode *MD) { auto GetBranchingTerminatorNumOperands = [&]() { unsigned ExpectedNumOperands = 0; @@ -5470,6 +5506,9 @@ void Verifier::visitInstruction(Instruction &I) { if (MDNode *MD = I.getMetadata(LLVMContext::MD_dereferenceable_or_null)) visitDereferenceableMetadata(I, MD); + if (MDNode *MD = I.getMetadata(LLVMContext::MD_nofree)) + visitNofreeMetadata(I, MD); + if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa)) TBAAVerifyHelper.visitTBAAMetadata(I, TBAA); @@ -6612,6 +6651,36 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { "Value for inactive lanes must be a VGPR function argument", &Call); break; } + case Intrinsic::amdgcn_call_whole_wave: { + auto F = dyn_cast<Function>(Call.getArgOperand(0)); + Check(F, "Indirect whole wave calls are not allowed", &Call); + + CallingConv::ID CC = F->getCallingConv(); + Check(CC == CallingConv::AMDGPU_Gfx_WholeWave, + "Callee must have the amdgpu_gfx_whole_wave calling convention", + &Call); + + Check(!F->isVarArg(), "Variadic whole wave calls are not allowed", &Call); + + Check(Call.arg_size() == F->arg_size(), + "Call argument count must match callee argument count", &Call); + + // The first argument of the call is the callee, and the first argument of + // the callee is the active mask. The rest of the arguments must match. + Check(F->arg_begin()->getType()->isIntegerTy(1), + "Callee must have i1 as its first argument", &Call); + for (auto [CallArg, FuncArg] : + drop_begin(zip_equal(Call.args(), F->args()))) { + Check(CallArg->getType() == FuncArg.getType(), + "Argument types must match", &Call); + + // Check that inreg attributes match between call site and function + Check(Call.paramHasAttr(FuncArg.getArgNo(), Attribute::InReg) == + FuncArg.hasInRegAttr(), + "Argument inreg attributes must match", &Call); + } + break; + } case Intrinsic::amdgcn_s_prefetch_data: { Check( AMDGPU::isFlatGlobalAddrSpace( @@ -6668,7 +6737,9 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { "invalid vector type for format", &Call, Src1, Call.getArgOperand(5)); break; } - case Intrinsic::amdgcn_wmma_f32_16x16x128_f8f6f4: { + case Intrinsic::amdgcn_wmma_f32_16x16x128_f8f6f4: + case Intrinsic::amdgcn_wmma_scale_f32_16x16x128_f8f6f4: + case Intrinsic::amdgcn_wmma_scale16_f32_16x16x128_f8f6f4: { Value *Src0 = Call.getArgOperand(1); Value *Src1 = Call.getArgOperand(3); @@ -6716,6 +6787,28 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { "invalid vector type for format", &Call, Src1, Call.getArgOperand(2)); break; } + case Intrinsic::amdgcn_cooperative_atomic_load_32x4B: + case Intrinsic::amdgcn_cooperative_atomic_load_16x8B: + case Intrinsic::amdgcn_cooperative_atomic_load_8x16B: + case Intrinsic::amdgcn_cooperative_atomic_store_32x4B: + case Intrinsic::amdgcn_cooperative_atomic_store_16x8B: + case Intrinsic::amdgcn_cooperative_atomic_store_8x16B: { + // Check we only use this intrinsic on the FLAT or GLOBAL address spaces. + Value *PtrArg = Call.getArgOperand(0); + const unsigned AS = PtrArg->getType()->getPointerAddressSpace(); + Check(AS == AMDGPUAS::FLAT_ADDRESS || AS == AMDGPUAS::GLOBAL_ADDRESS, + "cooperative atomic intrinsics require a generic or global pointer", + &Call, PtrArg); + + // Last argument must be a MD string + auto *Op = cast<MetadataAsValue>(Call.getArgOperand(Call.arg_size() - 1)); + MDNode *MD = cast<MDNode>(Op->getMetadata()); + Check((MD->getNumOperands() == 1) && isa<MDString>(MD->getOperand(0)), + "cooperative atomic intrinsics require that the last argument is a " + "metadata string", + &Call, Op); + break; + } case Intrinsic::nvvm_setmaxnreg_inc_sync_aligned_u32: case Intrinsic::nvvm_setmaxnreg_dec_sync_aligned_u32: { Value *V = Call.getArgOperand(0); @@ -6769,10 +6862,13 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { break; } case Intrinsic::lifetime_start: - case Intrinsic::lifetime_end: - Check(isa<AllocaInst>(Call.getArgOperand(1)), - "llvm.lifetime.start/end can only be used on alloca", &Call); + case Intrinsic::lifetime_end: { + Value *Ptr = Call.getArgOperand(0); + Check(isa<AllocaInst>(Ptr) || isa<PoisonValue>(Ptr), + "llvm.lifetime.start/end can only be used on alloca or poison", + &Call); break; + } }; // Verify that there aren't any unmediated control transfers between funclets. |