Skip to content

Commit 32c6e16

Browse files
[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.
1 parent 03742c5 commit 32c6e16

File tree

9 files changed

+100
-31
lines changed

9 files changed

+100
-31
lines changed

llvm/docs/LangRef.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8864,6 +8864,28 @@ For example, the following metadata section contains two library specifiers::
88648864
Each library specifier will be handled independently by the consuming linker.
88658865
The effect of the library specifiers are defined by the consuming linker.
88668866

8867+
'``llvm.errno.tbaa``' Named Metadata
8868+
====================================
8869+
8870+
The module-level ``!llvm.errno.tbaa`` metadata specifies the TBAA nodes used
8871+
for accessing ``errno``. These nodes are guaranteed to represent int-compatible
8872+
accesses according to C/C++ strict aliasing rules. This should let LLVM alias
8873+
analyses to reason about aliasing with ``errno`` when calling library functions
8874+
that may set ``errno``, allowing optimizations such as store-to-load forwarding
8875+
across such routines.
8876+
8877+
For example, the following is a valid metadata specifying the TBAA information
8878+
for an integer access:
8879+
8880+
!llvm.errno.tbaa = !{!0}
8881+
!0 = !{!1, !1, i64 0}
8882+
!1 = !{!"int", !2, i64 0}
8883+
!2 = !{!"omnipotent char", !3, i64 0}
8884+
!3 = !{!"Simple C/C++ TBAA"}
8885+
8886+
Multiple TBAA operands are allowed to support merging of modules that may use
8887+
different TBAA hierarchies (e.g., when mixing C and C++).
8888+
88678889
.. _summary:
88688890

88698891
ThinLTO Summary

llvm/include/llvm/IR/Verifier.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ class TBAAVerifier {
7575
public:
7676
TBAAVerifier(VerifierSupport *Diagnostic = nullptr)
7777
: Diagnostic(Diagnostic) {}
78-
/// Visit an instruction and return true if it is valid, return false if an
79-
/// invalid TBAA is attached.
80-
LLVM_ABI bool visitTBAAMetadata(Instruction &I, const MDNode *MD);
78+
/// Visit an instruction, or a TBAA node itself as part of a metadata, and
79+
/// return true if it is valid, return false if an invalid TBAA is attached.
80+
LLVM_ABI bool visitTBAAMetadata(Instruction *I, const MDNode *MD);
8181
};
8282

8383
/// Check a function for errors, useful for use when debugging a

llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7024,7 +7024,7 @@ Error BitcodeReader::materialize(GlobalValue *GV) {
70247024
if (!MDLoader->isStrippingTBAA()) {
70257025
for (auto &I : instructions(F)) {
70267026
MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa);
7027-
if (!TBAA || TBAAVerifyHelper.visitTBAAMetadata(I, TBAA))
7027+
if (!TBAA || TBAAVerifyHelper.visitTBAAMetadata(&I, TBAA))
70287028
continue;
70297029
MDLoader->setStripTBAA(true);
70307030
stripTBAA(F->getParent());

llvm/lib/IR/Verifier.cpp

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,7 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
480480
visitModuleFlags();
481481
visitModuleIdents();
482482
visitModuleCommandLines();
483+
visitModuleErrnoTBAA();
483484

484485
verifyCompileUnits();
485486

@@ -516,6 +517,7 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
516517
void visitComdat(const Comdat &C);
517518
void visitModuleIdents();
518519
void visitModuleCommandLines();
520+
void visitModuleErrnoTBAA();
519521
void visitModuleFlags();
520522
void visitModuleFlag(const MDNode *Op,
521523
DenseMap<const MDString *, const MDNode *> &SeenIDs,
@@ -1815,6 +1817,18 @@ void Verifier::visitModuleCommandLines() {
18151817
}
18161818
}
18171819

1820+
void Verifier::visitModuleErrnoTBAA() {
1821+
const NamedMDNode *ErrnoTBAA = M.getNamedMetadata("llvm.errno.tbaa");
1822+
if (!ErrnoTBAA)
1823+
return;
1824+
1825+
Check(ErrnoTBAA->getNumOperands() >= 1,
1826+
"llvm.errno.tbaa must have at least one operand", ErrnoTBAA);
1827+
1828+
for (const MDNode *N : ErrnoTBAA->operands())
1829+
TBAAVerifyHelper.visitTBAAMetadata(nullptr, N);
1830+
}
1831+
18181832
void Verifier::visitModuleFlags() {
18191833
const NamedMDNode *Flags = M.getModuleFlagsMetadata();
18201834
if (!Flags) return;
@@ -5537,7 +5551,7 @@ void Verifier::visitInstruction(Instruction &I) {
55375551
visitNofreeMetadata(I, MD);
55385552

55395553
if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa))
5540-
TBAAVerifyHelper.visitTBAAMetadata(I, TBAA);
5554+
TBAAVerifyHelper.visitTBAAMetadata(&I, TBAA);
55415555

55425556
if (MDNode *MD = I.getMetadata(LLVMContext::MD_noalias))
55435557
visitAliasScopeListMetadata(MD);
@@ -7879,21 +7893,22 @@ static bool isNewFormatTBAATypeNode(llvm::MDNode *Type) {
78797893
return isa_and_nonnull<MDNode>(Type->getOperand(0));
78807894
}
78817895

7882-
bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {
7883-
CheckTBAA(MD->getNumOperands() > 0, "TBAA metadata cannot have 0 operands",
7884-
&I, MD);
7896+
bool TBAAVerifier::visitTBAAMetadata(Instruction *I, const MDNode *MD) {
7897+
CheckTBAA(MD->getNumOperands() > 0, "TBAA metadata cannot have 0 operands", I,
7898+
MD);
78857899

7886-
CheckTBAA(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) ||
7887-
isa<VAArgInst>(I) || isa<AtomicRMWInst>(I) ||
7888-
isa<AtomicCmpXchgInst>(I),
7889-
"This instruction shall not have a TBAA access tag!", &I);
7900+
if (I)
7901+
CheckTBAA(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) ||
7902+
isa<VAArgInst>(I) || isa<AtomicRMWInst>(I) ||
7903+
isa<AtomicCmpXchgInst>(I),
7904+
"This instruction shall not have a TBAA access tag!", I);
78907905

78917906
bool IsStructPathTBAA =
78927907
isa<MDNode>(MD->getOperand(0)) && MD->getNumOperands() >= 3;
78937908

78947909
CheckTBAA(IsStructPathTBAA,
78957910
"Old-style TBAA is no longer allowed, use struct-path TBAA instead",
7896-
&I);
7911+
I);
78977912

78987913
MDNode *BaseNode = dyn_cast_or_null<MDNode>(MD->getOperand(0));
78997914
MDNode *AccessType = dyn_cast_or_null<MDNode>(MD->getOperand(1));
@@ -7902,17 +7917,17 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {
79027917

79037918
if (IsNewFormat) {
79047919
CheckTBAA(MD->getNumOperands() == 4 || MD->getNumOperands() == 5,
7905-
"Access tag metadata must have either 4 or 5 operands", &I, MD);
7920+
"Access tag metadata must have either 4 or 5 operands", I, MD);
79067921
} else {
79077922
CheckTBAA(MD->getNumOperands() < 5,
7908-
"Struct tag metadata must have either 3 or 4 operands", &I, MD);
7923+
"Struct tag metadata must have either 3 or 4 operands", I, MD);
79097924
}
79107925

79117926
// Check the access size field.
79127927
if (IsNewFormat) {
79137928
auto *AccessSizeNode = mdconst::dyn_extract_or_null<ConstantInt>(
79147929
MD->getOperand(3));
7915-
CheckTBAA(AccessSizeNode, "Access size field must be a constant", &I, MD);
7930+
CheckTBAA(AccessSizeNode, "Access size field must be a constant", I, MD);
79167931
}
79177932

79187933
// Check the immutability flag.
@@ -7921,45 +7936,45 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {
79217936
auto *IsImmutableCI = mdconst::dyn_extract_or_null<ConstantInt>(
79227937
MD->getOperand(ImmutabilityFlagOpNo));
79237938
CheckTBAA(IsImmutableCI,
7924-
"Immutability tag on struct tag metadata must be a constant", &I,
7939+
"Immutability tag on struct tag metadata must be a constant", I,
79257940
MD);
79267941
CheckTBAA(
79277942
IsImmutableCI->isZero() || IsImmutableCI->isOne(),
7928-
"Immutability part of the struct tag metadata must be either 0 or 1",
7929-
&I, MD);
7943+
"Immutability part of the struct tag metadata must be either 0 or 1", I,
7944+
MD);
79307945
}
79317946

79327947
CheckTBAA(BaseNode && AccessType,
79337948
"Malformed struct tag metadata: base and access-type "
79347949
"should be non-null and point to Metadata nodes",
7935-
&I, MD, BaseNode, AccessType);
7950+
I, MD, BaseNode, AccessType);
79367951

79377952
if (!IsNewFormat) {
79387953
CheckTBAA(isValidScalarTBAANode(AccessType),
7939-
"Access type node must be a valid scalar type", &I, MD,
7954+
"Access type node must be a valid scalar type", I, MD,
79407955
AccessType);
79417956
}
79427957

79437958
auto *OffsetCI = mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(2));
7944-
CheckTBAA(OffsetCI, "Offset must be constant integer", &I, MD);
7959+
CheckTBAA(OffsetCI, "Offset must be constant integer", I, MD);
79457960

79467961
APInt Offset = OffsetCI->getValue();
79477962
bool SeenAccessTypeInPath = false;
79487963

79497964
SmallPtrSet<MDNode *, 4> StructPath;
79507965

79517966
for (/* empty */; BaseNode && !IsRootTBAANode(BaseNode);
7952-
BaseNode = getFieldNodeFromTBAABaseNode(I, BaseNode, Offset,
7953-
IsNewFormat)) {
7967+
BaseNode =
7968+
getFieldNodeFromTBAABaseNode(*I, BaseNode, Offset, IsNewFormat)) {
79547969
if (!StructPath.insert(BaseNode).second) {
7955-
CheckFailed("Cycle detected in struct path", &I, MD);
7970+
CheckFailed("Cycle detected in struct path", I, MD);
79567971
return false;
79577972
}
79587973

79597974
bool Invalid;
79607975
unsigned BaseNodeBitWidth;
7961-
std::tie(Invalid, BaseNodeBitWidth) = verifyTBAABaseNode(I, BaseNode,
7962-
IsNewFormat);
7976+
std::tie(Invalid, BaseNodeBitWidth) =
7977+
verifyTBAABaseNode(*I, BaseNode, IsNewFormat);
79637978

79647979
// If the base node is invalid in itself, then we've already printed all the
79657980
// errors we wanted to print.
@@ -7969,20 +7984,20 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {
79697984
SeenAccessTypeInPath |= BaseNode == AccessType;
79707985

79717986
if (isValidScalarTBAANode(BaseNode) || BaseNode == AccessType)
7972-
CheckTBAA(Offset == 0, "Offset not zero at the point of scalar access",
7973-
&I, MD, &Offset);
7987+
CheckTBAA(Offset == 0, "Offset not zero at the point of scalar access", I,
7988+
MD, &Offset);
79747989

79757990
CheckTBAA(BaseNodeBitWidth == Offset.getBitWidth() ||
79767991
(BaseNodeBitWidth == 0 && Offset == 0) ||
79777992
(IsNewFormat && BaseNodeBitWidth == ~0u),
7978-
"Access bit-width not the same as description bit-width", &I, MD,
7993+
"Access bit-width not the same as description bit-width", I, MD,
79797994
BaseNodeBitWidth, Offset.getBitWidth());
79807995

79817996
if (IsNewFormat && SeenAccessTypeInPath)
79827997
break;
79837998
}
79847999

7985-
CheckTBAA(SeenAccessTypeInPath, "Did not see access type in access path!", &I,
8000+
CheckTBAA(SeenAccessTypeInPath, "Did not see access type in access path!", I,
79868001
MD);
79878002
return true;
79888003
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
!llvm.errno.tbaa = !{!0}
2+
!0 = !{!1, !1, i64 0}
3+
!1 = !{!"int", !2, i64 0}
4+
!2 = !{!"omnipotent char", !3, i64 0}
5+
!3 = !{!"Simple C++ TBAA"}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
!llvm.errno.tbaa = !{!0}
2+
!0 = !{!1, !1, i64 0}
3+
!1 = !{!"int", !2, i64 0}
4+
!2 = !{!"omnipotent char", !3, i64 0}
5+
!3 = !{!"Simple C/C++ TBAA"}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
; RUN: llvm-link %S/Inputs/errno-tbaa-metadata.ll %S/Inputs/errno-tbaa-cxx-metadata.ll -S -o - | FileCheck %s --check-prefix=CHECK-MERGE
2+
; RUN: llvm-link %S/Inputs/errno-tbaa-metadata.ll %S/Inputs/errno-tbaa-metadata.ll -S -o - | FileCheck %s --check-prefix=CHECK-DEDUP
3+
4+
; Ensure merging when linking modules w/ different errno TBAA hierarchies.
5+
; CHECK-MERGE: !llvm.errno.tbaa = !{![[NODE0:[0-9]+]], ![[NODE1:[0-9]+]]}
6+
7+
; Ensure deduplication when linking modules w/ identical errno TBAA nodes.
8+
; CHECK-DEDUP: !llvm.errno.tbaa = !{![[NODE:[0-9]+]]}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
2+
3+
; CHECK: assembly parsed, but does not verify as correct!
4+
; CHECK-NEXT: llvm.errno.tbaa must have at least one operand
5+
!llvm.errno.tbaa = !{}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
2+
3+
; CHECK: assembly parsed, but does not verify as correct!
4+
; CHECK-NEXT: Malformed struct tag metadata: base and access-type should be non-null and point to Metadata nodes
5+
!llvm.errno.tbaa = !{!0}
6+
!0 = !{!1, i64 0, !1}
7+
!1 = !{!"int", !2, i64 0}
8+
!2 = !{!"omnipotent char", !3, i64 0}
9+
!3 = !{!"Simple C/C++ TBAA"}

0 commit comments

Comments
 (0)