summaryrefslogtreecommitdiff
path: root/llvm/lib/IR
diff options
context:
space:
mode:
authorMingming Liu <mingmingl@google.com>2025-09-10 15:25:31 -0700
committerGitHub <noreply@github.com>2025-09-10 15:25:31 -0700
commit1417dafa1db9cb1b2b09438aa9f53ea5ab6e36e2 (patch)
tree57f4b1f313c8cf74eed8819870f39c36ea263c68 /llvm/lib/IR
parent898b813bc8a6d0276bf0f4769f5f2f64b34e632d (diff)
parentb8cefcb601ddaa18482555c4ff363c01a270c2fe (diff)
Merge branch 'main' into users/mingmingl-llvm/samplefdo-profile-formatusers/mingmingl-llvm/samplefdo-profile-format
Diffstat (limited to 'llvm/lib/IR')
-rw-r--r--llvm/lib/IR/AsmWriter.cpp2
-rw-r--r--llvm/lib/IR/Assumptions.cpp22
-rw-r--r--llvm/lib/IR/Attributes.cpp13
-rw-r--r--llvm/lib/IR/AutoUpgrade.cpp114
-rw-r--r--llvm/lib/IR/DataLayout.cpp53
-rw-r--r--llvm/lib/IR/DebugInfo.cpp4
-rw-r--r--llvm/lib/IR/DebugLoc.cpp15
-rw-r--r--llvm/lib/IR/Module.cpp2
-rw-r--r--llvm/lib/IR/ProfDataUtils.cpp12
-rw-r--r--llvm/lib/IR/RuntimeLibcalls.cpp18
-rw-r--r--llvm/lib/IR/Type.cpp11
-rw-r--r--llvm/lib/IR/Value.cpp3
-rw-r--r--llvm/lib/IR/Verifier.cpp73
13 files changed, 280 insertions, 62 deletions
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index dc6d599fa958..094678f32af2 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"));
diff --git a/llvm/lib/IR/Assumptions.cpp b/llvm/lib/IR/Assumptions.cpp
index 6adbbc4a63b0..f8bbcb32231c 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 d1fbcb9e893a..4ac2ebd55dca 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 e200f3626e69..8d8120ac9ed9 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -48,6 +48,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/NVPTXAddrSpace.h"
#include "llvm/Support/Regex.h"
+#include "llvm/Support/TimeProfiler.h"
#include "llvm/TargetParser/Triple.h"
#include <cstdint>
#include <cstring>
@@ -106,6 +107,24 @@ static bool upgradeX86MaskedFPCompare(Function *F, Intrinsic::ID IID,
return true;
}
+// Upgrade the declaration of multiply and add bytes intrinsics whose input
+// arguments' types have changed from vectors of i32 to vectors of i8
+static bool upgradeX86MultiplyAddBytes(Function *F, Intrinsic::ID IID,
+ Function *&NewFn) {
+ // check if input argument type is a vector of i8
+ Type *Arg1Type = F->getFunctionType()->getParamType(1);
+ Type *Arg2Type = F->getFunctionType()->getParamType(2);
+ if (Arg1Type->isVectorTy() &&
+ cast<VectorType>(Arg1Type)->getElementType()->isIntegerTy(8) &&
+ Arg2Type->isVectorTy() &&
+ cast<VectorType>(Arg2Type)->getElementType()->isIntegerTy(8))
+ return false;
+
+ rename(F);
+ NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), IID);
+ return true;
+}
+
static bool upgradeX86BF16Intrinsic(Function *F, Intrinsic::ID IID,
Function *&NewFn) {
if (F->getReturnType()->getScalarType()->isBFloatTy())
@@ -545,19 +564,34 @@ static bool upgradeX86IntrinsicFunction(Function *F, StringRef Name,
if (ID != Intrinsic::not_intrinsic)
return upgradeX86IntrinsicsWith8BitMask(F, ID, NewFn);
- if (Name.consume_front("avx512.mask.cmp.")) {
- // Added in 7.0
- ID = StringSwitch<Intrinsic::ID>(Name)
- .Case("pd.128", Intrinsic::x86_avx512_mask_cmp_pd_128)
- .Case("pd.256", Intrinsic::x86_avx512_mask_cmp_pd_256)
- .Case("pd.512", Intrinsic::x86_avx512_mask_cmp_pd_512)
- .Case("ps.128", Intrinsic::x86_avx512_mask_cmp_ps_128)
- .Case("ps.256", Intrinsic::x86_avx512_mask_cmp_ps_256)
- .Case("ps.512", Intrinsic::x86_avx512_mask_cmp_ps_512)
- .Default(Intrinsic::not_intrinsic);
- if (ID != Intrinsic::not_intrinsic)
- return upgradeX86MaskedFPCompare(F, ID, NewFn);
- return false; // No other 'x86.avx523.mask.cmp.*'.
+ if (Name.consume_front("avx512.")) {
+ if (Name.consume_front("mask.cmp.")) {
+ // Added in 7.0
+ ID = StringSwitch<Intrinsic::ID>(Name)
+ .Case("pd.128", Intrinsic::x86_avx512_mask_cmp_pd_128)
+ .Case("pd.256", Intrinsic::x86_avx512_mask_cmp_pd_256)
+ .Case("pd.512", Intrinsic::x86_avx512_mask_cmp_pd_512)
+ .Case("ps.128", Intrinsic::x86_avx512_mask_cmp_ps_128)
+ .Case("ps.256", Intrinsic::x86_avx512_mask_cmp_ps_256)
+ .Case("ps.512", Intrinsic::x86_avx512_mask_cmp_ps_512)
+ .Default(Intrinsic::not_intrinsic);
+ if (ID != Intrinsic::not_intrinsic)
+ return upgradeX86MaskedFPCompare(F, ID, NewFn);
+ } else if (Name.starts_with("vpdpbusd.") ||
+ Name.starts_with("vpdpbusds.")) {
+ // Added in 21.1
+ ID = StringSwitch<Intrinsic::ID>(Name)
+ .Case("vpdpbusd.128", Intrinsic::x86_avx512_vpdpbusd_128)
+ .Case("vpdpbusd.256", Intrinsic::x86_avx512_vpdpbusd_256)
+ .Case("vpdpbusd.512", Intrinsic::x86_avx512_vpdpbusd_512)
+ .Case("vpdpbusds.128", Intrinsic::x86_avx512_vpdpbusds_128)
+ .Case("vpdpbusds.256", Intrinsic::x86_avx512_vpdpbusds_256)
+ .Case("vpdpbusds.512", Intrinsic::x86_avx512_vpdpbusds_512)
+ .Default(Intrinsic::not_intrinsic);
+ if (ID != Intrinsic::not_intrinsic)
+ return upgradeX86MultiplyAddBytes(F, ID, NewFn);
+ }
+ return false; // No other 'x86.avx512.*'.
}
if (Name.consume_front("avx512bf16.")) {
@@ -4148,6 +4182,32 @@ static Value *upgradeX86IntrinsicCall(StringRef Name, CallBase *CI, Function *F,
Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
CI->getArgOperand(2)};
+
+ // Input arguments types were incorrectly set to vectors of i32 before but
+ // they should be vectors of i8. Insert bit cast when encountering the old
+ // types
+ if (Args[1]->getType()->isVectorTy() &&
+ cast<VectorType>(Args[1]->getType())
+ ->getElementType()
+ ->isIntegerTy(32) &&
+ Args[2]->getType()->isVectorTy() &&
+ cast<VectorType>(Args[2]->getType())
+ ->getElementType()
+ ->isIntegerTy(32)) {
+ Type *NewArgType = nullptr;
+ if (VecWidth == 128)
+ NewArgType = VectorType::get(Builder.getInt8Ty(), 16, false);
+ else if (VecWidth == 256)
+ NewArgType = VectorType::get(Builder.getInt8Ty(), 32, false);
+ else if (VecWidth == 512)
+ NewArgType = VectorType::get(Builder.getInt8Ty(), 64, false);
+ else
+ llvm_unreachable("Unexpected vector bit width");
+
+ Args[1] = Builder.CreateBitCast(Args[1], NewArgType);
+ Args[2] = Builder.CreateBitCast(Args[2], NewArgType);
+ }
+
Rep = Builder.CreateIntrinsic(IID, Args);
Value *PassThru = ZeroMask ? ConstantAggregateZero::get(CI->getType())
: CI->getArgOperand(0);
@@ -5155,6 +5215,23 @@ void llvm::UpgradeIntrinsicCall(CallBase *CI, Function *NewFn) {
CI->eraseFromParent();
return;
}
+
+ case Intrinsic::x86_avx512_vpdpbusd_128:
+ case Intrinsic::x86_avx512_vpdpbusd_256:
+ case Intrinsic::x86_avx512_vpdpbusd_512:
+ case Intrinsic::x86_avx512_vpdpbusds_128:
+ case Intrinsic::x86_avx512_vpdpbusds_256:
+ case Intrinsic::x86_avx512_vpdpbusds_512: {
+ unsigned NumElts = CI->getType()->getPrimitiveSizeInBits() / 8;
+ Value *Args[] = {CI->getArgOperand(0), CI->getArgOperand(1),
+ CI->getArgOperand(2)};
+ Type *NewArgType = VectorType::get(Builder.getInt8Ty(), NumElts, false);
+ Args[1] = Builder.CreateBitCast(Args[1], NewArgType);
+ Args[2] = Builder.CreateBitCast(Args[2], NewArgType);
+
+ NewCall = Builder.CreateCall(NewFn, Args);
+ break;
+ }
}
assert(NewCall && "Should have either set this variable or returned through "
"the default case");
@@ -5256,6 +5333,7 @@ bool llvm::UpgradeDebugInfo(Module &M) {
if (DisableAutoUpgradeDebugInfo)
return false;
+ llvm::TimeTraceScope timeScope("Upgrade debug info");
// We need to get metadata before the module is verified (i.e., getModuleFlag
// makes assumptions that we haven't verified yet). Carefully extract the flag
// from the metadata.
@@ -5381,6 +5459,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;
}
diff --git a/llvm/lib/IR/DataLayout.cpp b/llvm/lib/IR/DataLayout.cpp
index dbd6d81ad2e2..ed629d4e5ea2 100644
--- a/llvm/lib/IR/DataLayout.cpp
+++ b/llvm/lib/IR/DataLayout.cpp
@@ -187,7 +187,6 @@ const char *DataLayout::getManglingComponent(const Triple &T) {
// Default primitive type specifications.
// NOTE: These arrays must be sorted by type bit width.
constexpr DataLayout::PrimitiveSpec DefaultIntSpecs[] = {
- {1, Align::Constant<1>(), Align::Constant<1>()}, // i1:8:8
{8, Align::Constant<1>(), Align::Constant<1>()}, // i8:8:8
{16, Align::Constant<2>(), Align::Constant<2>()}, // i16:16:16
{32, Align::Constant<4>(), Align::Constant<4>()}, // i32:32:32
@@ -694,7 +693,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 +843,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 +968,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 8e523bcf7960..166521a27664 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -36,6 +36,7 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/TimeProfiler.h"
#include <algorithm>
#include <cassert>
#include <optional>
@@ -563,6 +564,7 @@ bool llvm::stripDebugInfo(Function &F) {
}
bool llvm::StripDebugInfo(Module &M) {
+ llvm::TimeTraceScope timeScope("Strip debug info");
bool Changed = false;
for (NamedMDNode &NMD : llvm::make_early_inc_range(M.named_metadata())) {
@@ -755,7 +757,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);
diff --git a/llvm/lib/IR/DebugLoc.cpp b/llvm/lib/IR/DebugLoc.cpp
index 79c5b896f8f2..01dafcab94ce 100644
--- a/llvm/lib/IR/DebugLoc.cpp
+++ b/llvm/lib/IR/DebugLoc.cpp
@@ -181,10 +181,19 @@ DebugLoc DebugLoc::getMergedLocations(ArrayRef<DebugLoc> Locs) {
return Merged;
}
DebugLoc DebugLoc::getMergedLocation(DebugLoc LocA, DebugLoc LocB) {
- if (!LocA)
- return LocA;
- if (!LocB)
+ if (!LocA || !LocB) {
+ // If coverage tracking is enabled, prioritize returning empty non-annotated
+ // locations to empty annotated locations.
+#if LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE
+ if (!LocA && LocA.getKind() == DebugLocKind::Normal)
+ return LocA;
+ if (!LocB && LocB.getKind() == DebugLocKind::Normal)
+ return LocB;
+#endif // LLVM_ENABLE_DEBUGLOC_TRACKING_COVERAGE
+ if (!LocA)
+ return LocA;
return LocB;
+ }
return DILocation::getMergedLocation(LocA, LocB);
}
diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp
index 70d364176062..30b5e48652b2 100644
--- a/llvm/lib/IR/Module.cpp
+++ b/llvm/lib/IR/Module.cpp
@@ -44,6 +44,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/RandomNumberGenerator.h"
+#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/VersionTuple.h"
#include <cassert>
#include <cstdint>
@@ -478,6 +479,7 @@ Error Module::materializeAll() {
}
Error Module::materializeMetadata() {
+ llvm::TimeTraceScope timeScope("Materialize metadata");
if (!Materializer)
return Error::success();
return Materializer->materializeMetadata();
diff --git a/llvm/lib/IR/ProfDataUtils.cpp b/llvm/lib/IR/ProfDataUtils.cpp
index d24263f8b3bd..b41256f59909 100644
--- a/llvm/lib/IR/ProfDataUtils.cpp
+++ b/llvm/lib/IR/ProfDataUtils.cpp
@@ -250,7 +250,15 @@ void setExplicitlyUnknownBranchWeights(Instruction &I) {
MDB.createString(MDProfLabels::UnknownBranchWeightsMarker)));
}
-bool isExplicitlyUnknownBranchWeightsMetadata(const MDNode &MD) {
+void setExplicitlyUnknownFunctionEntryCount(Function &F) {
+ MDBuilder MDB(F.getContext());
+ F.setMetadata(
+ LLVMContext::MD_prof,
+ MDNode::get(F.getContext(),
+ MDB.createString(MDProfLabels::UnknownBranchWeightsMarker)));
+}
+
+bool isExplicitlyUnknownProfileMetadata(const MDNode &MD) {
if (MD.getNumOperands() != 1)
return false;
return MD.getOperand(0).equalsStr(MDProfLabels::UnknownBranchWeightsMarker);
@@ -260,7 +268,7 @@ bool hasExplicitlyUnknownBranchWeights(const Instruction &I) {
auto *MD = I.getMetadata(LLVMContext::MD_prof);
if (!MD)
return false;
- return isExplicitlyUnknownBranchWeightsMetadata(*MD);
+ return isExplicitlyUnknownProfileMetadata(*MD);
}
void setBranchWeights(Instruction &I, ArrayRef<uint32_t> Weights,
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index 3c324f2fe0d8..4fe5714a74e3 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -40,13 +40,19 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
// hard-float calling convention by default.
if (!TT.isWatchABI()) {
if (isAAPCS_ABI(TT, ABIName)) {
- setLibcallImplCallingConv(RTLIB::__truncsfhf2, CallingConv::ARM_AAPCS);
- setLibcallImplCallingConv(RTLIB::__truncdfhf2, CallingConv::ARM_AAPCS);
- setLibcallImplCallingConv(RTLIB::__extendhfsf2, CallingConv::ARM_AAPCS);
+ setLibcallImplCallingConv(RTLIB::impl___truncsfhf2,
+ CallingConv::ARM_AAPCS);
+ setLibcallImplCallingConv(RTLIB::impl___truncdfhf2,
+ CallingConv::ARM_AAPCS);
+ setLibcallImplCallingConv(RTLIB::impl___extendhfsf2,
+ CallingConv::ARM_AAPCS);
} else {
- setLibcallImplCallingConv(RTLIB::__truncsfhf2, CallingConv::ARM_APCS);
- setLibcallImplCallingConv(RTLIB::__truncdfhf2, CallingConv::ARM_APCS);
- setLibcallImplCallingConv(RTLIB::__extendhfsf2, CallingConv::ARM_APCS);
+ setLibcallImplCallingConv(RTLIB::impl___truncsfhf2,
+ CallingConv::ARM_APCS);
+ setLibcallImplCallingConv(RTLIB::impl___truncdfhf2,
+ CallingConv::ARM_APCS);
+ setLibcallImplCallingConv(RTLIB::impl___extendhfsf2,
+ CallingConv::ARM_APCS);
}
}
diff --git a/llvm/lib/IR/Type.cpp b/llvm/lib/IR/Type.cpp
index 9c3466234035..9db48e8f6a96 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 5928c89029b8..4e8f359481b8 100644
--- a/llvm/lib/IR/Value.cpp
+++ b/llvm/lib/IR/Value.cpp
@@ -836,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 4eb4b58d022e..81a53722f489 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -119,6 +119,7 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/ModRef.h"
+#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
@@ -399,6 +400,7 @@ public:
bool hasBrokenDebugInfo() const { return BrokenDebugInfo; }
bool verify(const Function &F) {
+ llvm::TimeTraceScope timeScope("Verifier");
assert(F.getParent() == &M &&
"An instance of this class only works with a specific module!");
@@ -526,6 +528,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);
@@ -1298,9 +1301,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 ||
@@ -2443,16 +2448,6 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, AttributeList Attrs,
CheckFailed("invalid value for 'frame-pointer' attribute: " + FP, V);
}
- // Check EVEX512 feature.
- if (TT.isX86() && MaxParameterWidth >= 512) {
- Attribute TargetFeaturesAttr = Attrs.getFnAttr("target-features");
- if (TargetFeaturesAttr.isValid()) {
- StringRef TF = TargetFeaturesAttr.getValueAsString();
- Check(!TF.contains("+avx512f") || !TF.contains("-evex512"),
- "512-bit vector arguments require 'evex512' for AVX512", V);
- }
- }
-
checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-prefix", V);
checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-entry", V);
if (Attrs.hasFnAttr("patchable-function-entry-section"))
@@ -2526,12 +2521,11 @@ void Verifier::verifyFunctionMetadata(
for (const auto &Pair : MDs) {
if (Pair.first == LLVMContext::MD_prof) {
MDNode *MD = Pair.second;
- if (isExplicitlyUnknownBranchWeightsMetadata(*MD)) {
- CheckFailed("'unknown' !prof metadata should appear only on "
- "instructions supporting the 'branch_weights' metadata",
- MD);
+ // We may have functions that are synthesized by the compiler, e.g. in
+ // WPD, that we can't currently determine the entry count.
+ if (isExplicitlyUnknownProfileMetadata(*MD))
continue;
- }
+
Check(MD->getNumOperands() >= 2,
"!prof annotations should have no less than 2 operands", MD);
@@ -2830,6 +2824,7 @@ static Instruction *getSuccPad(Instruction *Terminator) {
}
void Verifier::verifySiblingFuncletUnwinds() {
+ llvm::TimeTraceScope timeScope("Verifier verify sibling funclet unwinds");
SmallPtrSet<Instruction *, 8> Visited;
SmallPtrSet<Instruction *, 8> Active;
for (const auto &Pair : SiblingFuncletInfo) {
@@ -3006,7 +3001,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);
@@ -3020,7 +3015,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);
@@ -3190,7 +3185,7 @@ void Verifier::visitFunction(const Function &F) {
// Scope and SP could be the same MDNode and we don't want to skip
// validation in that case
- if (SP && ((Scope != SP) && !Seen.insert(SP).second))
+ if ((Scope != SP) && !Seen.insert(SP).second)
return;
CheckDI(SP->describes(&F),
@@ -3634,7 +3629,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.
@@ -3839,14 +3834,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!");
@@ -5021,6 +5016,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;
@@ -5496,6 +5498,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);
@@ -6724,7 +6729,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);
@@ -6772,6 +6779,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);