aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/Verifier.cpp
diff options
context:
space:
mode:
authorAntonio Frighetto <me@antoniofrighetto.com>2025-09-24 15:59:32 +0200
committerAntonio Frighetto <me@antoniofrighetto.com>2025-09-24 15:59:32 +0200
commit32c6e162462bbca3beb2259b90cc922a7419ba2c (patch)
tree9f0267bbb5519da8472272dfd6ea6b8249100d8c /llvm/lib/IR/Verifier.cpp
parent03742c5dacef177a990f0fa3a3d11ba720fc0ac5 (diff)
downloadllvm-32c6e162462bbca3beb2259b90cc922a7419ba2c.zip
llvm-32c6e162462bbca3beb2259b90cc922a7419ba2c.tar.gz
llvm-32c6e162462bbca3beb2259b90cc922a7419ba2c.tar.bz2
[IR] Introduce `llvm.errno.tbaa` metadata for errno alias disambiguation
Add a new named module-level frontend-annotated metadata that specifies the TBAA node for an integer access, for which, C/C++ `errno` accesses are guaranteed to use (under strict aliasing). This should allow LLVM to prove the involved memory location/ accesses may not alias `errno`; thus, to perform optimizations around errno-writing libcalls (store-to-load forwarding amongst others). Previous discussion: https://discourse.llvm.org/t/rfc-modelling-errno-memory-effects/82972.
Diffstat (limited to 'llvm/lib/IR/Verifier.cpp')
-rw-r--r--llvm/lib/IR/Verifier.cpp69
1 files changed, 42 insertions, 27 deletions
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 0c6175b1..6ff9693 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -480,6 +480,7 @@ public:
visitModuleFlags();
visitModuleIdents();
visitModuleCommandLines();
+ visitModuleErrnoTBAA();
verifyCompileUnits();
@@ -516,6 +517,7 @@ private:
void visitComdat(const Comdat &C);
void visitModuleIdents();
void visitModuleCommandLines();
+ void visitModuleErrnoTBAA();
void visitModuleFlags();
void visitModuleFlag(const MDNode *Op,
DenseMap<const MDString *, const MDNode *> &SeenIDs,
@@ -1815,6 +1817,18 @@ void Verifier::visitModuleCommandLines() {
}
}
+void Verifier::visitModuleErrnoTBAA() {
+ const NamedMDNode *ErrnoTBAA = M.getNamedMetadata("llvm.errno.tbaa");
+ if (!ErrnoTBAA)
+ return;
+
+ Check(ErrnoTBAA->getNumOperands() >= 1,
+ "llvm.errno.tbaa must have at least one operand", ErrnoTBAA);
+
+ for (const MDNode *N : ErrnoTBAA->operands())
+ TBAAVerifyHelper.visitTBAAMetadata(nullptr, N);
+}
+
void Verifier::visitModuleFlags() {
const NamedMDNode *Flags = M.getModuleFlagsMetadata();
if (!Flags) return;
@@ -5537,7 +5551,7 @@ void Verifier::visitInstruction(Instruction &I) {
visitNofreeMetadata(I, MD);
if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa))
- TBAAVerifyHelper.visitTBAAMetadata(I, TBAA);
+ TBAAVerifyHelper.visitTBAAMetadata(&I, TBAA);
if (MDNode *MD = I.getMetadata(LLVMContext::MD_noalias))
visitAliasScopeListMetadata(MD);
@@ -7879,21 +7893,22 @@ static bool isNewFormatTBAATypeNode(llvm::MDNode *Type) {
return isa_and_nonnull<MDNode>(Type->getOperand(0));
}
-bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {
- CheckTBAA(MD->getNumOperands() > 0, "TBAA metadata cannot have 0 operands",
- &I, MD);
+bool TBAAVerifier::visitTBAAMetadata(Instruction *I, const MDNode *MD) {
+ CheckTBAA(MD->getNumOperands() > 0, "TBAA metadata cannot have 0 operands", I,
+ MD);
- CheckTBAA(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) ||
- isa<VAArgInst>(I) || isa<AtomicRMWInst>(I) ||
- isa<AtomicCmpXchgInst>(I),
- "This instruction shall not have a TBAA access tag!", &I);
+ if (I)
+ CheckTBAA(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) ||
+ isa<VAArgInst>(I) || isa<AtomicRMWInst>(I) ||
+ isa<AtomicCmpXchgInst>(I),
+ "This instruction shall not have a TBAA access tag!", I);
bool IsStructPathTBAA =
isa<MDNode>(MD->getOperand(0)) && MD->getNumOperands() >= 3;
CheckTBAA(IsStructPathTBAA,
"Old-style TBAA is no longer allowed, use struct-path TBAA instead",
- &I);
+ I);
MDNode *BaseNode = dyn_cast_or_null<MDNode>(MD->getOperand(0));
MDNode *AccessType = dyn_cast_or_null<MDNode>(MD->getOperand(1));
@@ -7902,17 +7917,17 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {
if (IsNewFormat) {
CheckTBAA(MD->getNumOperands() == 4 || MD->getNumOperands() == 5,
- "Access tag metadata must have either 4 or 5 operands", &I, MD);
+ "Access tag metadata must have either 4 or 5 operands", I, MD);
} else {
CheckTBAA(MD->getNumOperands() < 5,
- "Struct tag metadata must have either 3 or 4 operands", &I, MD);
+ "Struct tag metadata must have either 3 or 4 operands", I, MD);
}
// Check the access size field.
if (IsNewFormat) {
auto *AccessSizeNode = mdconst::dyn_extract_or_null<ConstantInt>(
MD->getOperand(3));
- CheckTBAA(AccessSizeNode, "Access size field must be a constant", &I, MD);
+ CheckTBAA(AccessSizeNode, "Access size field must be a constant", I, MD);
}
// Check the immutability flag.
@@ -7921,27 +7936,27 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {
auto *IsImmutableCI = mdconst::dyn_extract_or_null<ConstantInt>(
MD->getOperand(ImmutabilityFlagOpNo));
CheckTBAA(IsImmutableCI,
- "Immutability tag on struct tag metadata must be a constant", &I,
+ "Immutability tag on struct tag metadata must be a constant", I,
MD);
CheckTBAA(
IsImmutableCI->isZero() || IsImmutableCI->isOne(),
- "Immutability part of the struct tag metadata must be either 0 or 1",
- &I, MD);
+ "Immutability part of the struct tag metadata must be either 0 or 1", I,
+ MD);
}
CheckTBAA(BaseNode && AccessType,
"Malformed struct tag metadata: base and access-type "
"should be non-null and point to Metadata nodes",
- &I, MD, BaseNode, AccessType);
+ I, MD, BaseNode, AccessType);
if (!IsNewFormat) {
CheckTBAA(isValidScalarTBAANode(AccessType),
- "Access type node must be a valid scalar type", &I, MD,
+ "Access type node must be a valid scalar type", I, MD,
AccessType);
}
auto *OffsetCI = mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(2));
- CheckTBAA(OffsetCI, "Offset must be constant integer", &I, MD);
+ CheckTBAA(OffsetCI, "Offset must be constant integer", I, MD);
APInt Offset = OffsetCI->getValue();
bool SeenAccessTypeInPath = false;
@@ -7949,17 +7964,17 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {
SmallPtrSet<MDNode *, 4> StructPath;
for (/* empty */; BaseNode && !IsRootTBAANode(BaseNode);
- BaseNode = getFieldNodeFromTBAABaseNode(I, BaseNode, Offset,
- IsNewFormat)) {
+ BaseNode =
+ getFieldNodeFromTBAABaseNode(*I, BaseNode, Offset, IsNewFormat)) {
if (!StructPath.insert(BaseNode).second) {
- CheckFailed("Cycle detected in struct path", &I, MD);
+ CheckFailed("Cycle detected in struct path", I, MD);
return false;
}
bool Invalid;
unsigned BaseNodeBitWidth;
- std::tie(Invalid, BaseNodeBitWidth) = verifyTBAABaseNode(I, BaseNode,
- IsNewFormat);
+ std::tie(Invalid, BaseNodeBitWidth) =
+ verifyTBAABaseNode(*I, BaseNode, IsNewFormat);
// If the base node is invalid in itself, then we've already printed all the
// errors we wanted to print.
@@ -7969,20 +7984,20 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {
SeenAccessTypeInPath |= BaseNode == AccessType;
if (isValidScalarTBAANode(BaseNode) || BaseNode == AccessType)
- CheckTBAA(Offset == 0, "Offset not zero at the point of scalar access",
- &I, MD, &Offset);
+ CheckTBAA(Offset == 0, "Offset not zero at the point of scalar access", I,
+ MD, &Offset);
CheckTBAA(BaseNodeBitWidth == Offset.getBitWidth() ||
(BaseNodeBitWidth == 0 && Offset == 0) ||
(IsNewFormat && BaseNodeBitWidth == ~0u),
- "Access bit-width not the same as description bit-width", &I, MD,
+ "Access bit-width not the same as description bit-width", I, MD,
BaseNodeBitWidth, Offset.getBitWidth());
if (IsNewFormat && SeenAccessTypeInPath)
break;
}
- CheckTBAA(SeenAccessTypeInPath, "Did not see access type in access path!", &I,
+ CheckTBAA(SeenAccessTypeInPath, "Did not see access type in access path!", I,
MD);
return true;
}