Skip to content

Commit 81c1e35

Browse files
[IR][ModRef] Introduce errno memory location
Model C/C++ `errno` macro by adding a corresponding `errno` memory location kind to the IR. Preliminary work to separate `errno` writes from other memory accesses, to the benefit of alias analyses and optimization correctness. Previous discussion: https://discourse.llvm.org/t/rfc-modelling-errno-memory-effects/82972.
1 parent 0575815 commit 81c1e35

File tree

21 files changed

+113
-46
lines changed

21 files changed

+113
-46
lines changed

llvm/include/llvm/AsmParser/LLToken.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,11 +201,13 @@ enum Kind {
201201
kw_readwrite,
202202
kw_argmem,
203203
kw_inaccessiblemem,
204+
kw_errnomem,
204205

205206
// Legacy memory attributes:
206207
kw_argmemonly,
207208
kw_inaccessiblememonly,
208209
kw_inaccessiblemem_or_argmemonly,
210+
kw_errnomemonly,
209211

210212
// nofpclass attribute:
211213
kw_all,

llvm/include/llvm/IR/Function.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,10 @@ class LLVM_ABI Function : public GlobalObject, public ilist_node<Function> {
575575
bool onlyAccessesInaccessibleMemory() const;
576576
void setOnlyAccessesInaccessibleMemory();
577577

578+
/// Determine if the function may only access errno memory.
579+
bool onlyAccessesErrnoMemory() const;
580+
void setOnlyAccessesErrnoMemory();
581+
578582
/// Determine if the function may only access memory that is
579583
/// either inaccessible from the IR or pointed to by its arguments.
580584
bool onlyAccessesInaccessibleMemOrArgMem() const;

llvm/include/llvm/IR/InstrTypes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1907,6 +1907,10 @@ class CallBase : public Instruction {
19071907
bool onlyAccessesInaccessibleMemory() const;
19081908
void setOnlyAccessesInaccessibleMemory();
19091909

1910+
/// Determine if the function may only access errno memory.
1911+
bool onlyAccessesErrnoMemory() const;
1912+
void setOnlyAccessesErrnoMemory();
1913+
19101914
/// Determine if the function may only access memory that is
19111915
/// either inaccessible from the IR or pointed to by its arguments.
19121916
bool onlyAccessesInaccessibleMemOrArgMem() const;

llvm/include/llvm/Support/ModRef.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,10 @@ enum class IRMemLocation {
6161
ArgMem = 0,
6262
/// Memory that is inaccessible via LLVM IR.
6363
InaccessibleMem = 1,
64+
/// Errno memory.
65+
ErrnoMem = 2,
6466
/// Any other memory.
65-
Other = 2,
67+
Other = 3,
6668

6769
/// Helpers to iterate all locations in the MemoryEffectsBase class.
6870
First = ArgMem,
@@ -139,6 +141,11 @@ template <typename LocationEnum> class MemoryEffectsBase {
139141
return MemoryEffectsBase(Location::InaccessibleMem, MR);
140142
}
141143

144+
/// Create MemoryEffectsBase that can only access errno memory.
145+
static MemoryEffectsBase errnoMemOnly(ModRefInfo MR = ModRefInfo::ModRef) {
146+
return MemoryEffectsBase(Location::ErrnoMem, MR);
147+
}
148+
142149
/// Create MemoryEffectsBase that can only access inaccessible or argument
143150
/// memory.
144151
static MemoryEffectsBase
@@ -207,11 +214,21 @@ template <typename LocationEnum> class MemoryEffectsBase {
207214
return isModOrRefSet(getModRef(Location::ArgMem));
208215
}
209216

217+
/// Whether this function may access errno memory.
218+
bool doesAccessErrnoMem() const {
219+
return isModOrRefSet(getModRef(Location::ErrnoMem));
220+
}
221+
210222
/// Whether this function only (at most) accesses inaccessible memory.
211223
bool onlyAccessesInaccessibleMem() const {
212224
return getWithoutLoc(Location::InaccessibleMem).doesNotAccessMemory();
213225
}
214226

227+
/// Whether this function only (at most) accesses errno memory.
228+
bool onlyAccessesErrnoMem() const {
229+
return getWithoutLoc(Location::ErrnoMem).doesNotAccessMemory();
230+
}
231+
215232
/// Whether this function only (at most) accesses argument and inaccessible
216233
/// memory.
217234
bool onlyAccessesInaccessibleOrArgMem() const {

llvm/lib/AsmParser/LLLexer.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,7 @@ lltok::Kind LLLexer::LexIdentifier() {
701701
KEYWORD(readwrite);
702702
KEYWORD(argmem);
703703
KEYWORD(inaccessiblemem);
704+
KEYWORD(errnomem);
704705
KEYWORD(argmemonly);
705706
KEYWORD(inaccessiblememonly);
706707
KEYWORD(inaccessiblemem_or_argmemonly);

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1668,6 +1668,9 @@ static bool upgradeMemoryAttr(MemoryEffects &ME, lltok::Kind Kind) {
16681668
case lltok::kw_inaccessiblememonly:
16691669
ME &= MemoryEffects::inaccessibleMemOnly();
16701670
return true;
1671+
case lltok::kw_errnomemonly:
1672+
ME &= MemoryEffects::errnoMemOnly();
1673+
return true;
16711674
case lltok::kw_inaccessiblemem_or_argmemonly:
16721675
ME &= MemoryEffects::inaccessibleOrArgMemOnly();
16731676
return true;
@@ -2488,6 +2491,8 @@ static std::optional<MemoryEffects::Location> keywordToLoc(lltok::Kind Tok) {
24882491
return IRMemLocation::ArgMem;
24892492
case lltok::kw_inaccessiblemem:
24902493
return IRMemLocation::InaccessibleMem;
2494+
case lltok::kw_errnomem:
2495+
return IRMemLocation::ErrnoMem;
24912496
default:
24922497
return std::nullopt;
24932498
}
@@ -2536,7 +2541,7 @@ std::optional<MemoryEffects> LLParser::parseMemoryAttr() {
25362541
std::optional<ModRefInfo> MR = keywordToModRef(Lex.getKind());
25372542
if (!MR) {
25382543
if (!Loc)
2539-
tokError("expected memory location (argmem, inaccessiblemem) "
2544+
tokError("expected memory location (argmem, inaccessiblemem, errnomem) "
25402545
"or access kind (none, read, write, readwrite)");
25412546
else
25422547
tokError("expected access kind (none, read, write, readwrite)");

llvm/lib/IR/Attributes.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,9 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
637637
case IRMemLocation::InaccessibleMem:
638638
OS << "inaccessiblemem: ";
639639
break;
640+
case IRMemLocation::ErrnoMem:
641+
OS << "errnomem: ";
642+
break;
640643
case IRMemLocation::Other:
641644
llvm_unreachable("This is represented as the default access kind");
642645
}

llvm/lib/IR/Function.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,14 @@ void Function::setOnlyAccessesInaccessibleMemory() {
922922
setMemoryEffects(getMemoryEffects() & MemoryEffects::inaccessibleMemOnly());
923923
}
924924

925+
/// Determine if the function may only access errno memory.
926+
bool Function::onlyAccessesErrnoMemory() const {
927+
return getMemoryEffects().onlyAccessesErrnoMem();
928+
}
929+
void Function::setOnlyAccessesErrnoMemory() {
930+
setMemoryEffects(getMemoryEffects() & MemoryEffects::errnoMemOnly());
931+
}
932+
925933
/// Determine if the function may only access memory that is
926934
/// either inaccessible from the IR or pointed to by its arguments.
927935
bool Function::onlyAccessesInaccessibleMemOrArgMem() const {

llvm/lib/IR/Instructions.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,14 @@ void CallBase::setOnlyAccessesInaccessibleMemory() {
665665
setMemoryEffects(getMemoryEffects() & MemoryEffects::inaccessibleMemOnly());
666666
}
667667

668+
/// Determine if the function may only access errno memory.
669+
bool CallBase::onlyAccessesErrnoMemory() const {
670+
return getMemoryEffects().onlyAccessesErrnoMem();
671+
}
672+
void CallBase::setOnlyAccessesErrnoMemory() {
673+
setMemoryEffects(getMemoryEffects() & MemoryEffects::errnoMemOnly());
674+
}
675+
668676
/// Determine if the function may only access memory that is
669677
/// either inaccessible from the IR or pointed to by its arguments.
670678
bool CallBase::onlyAccessesInaccessibleMemOrArgMem() const {

llvm/lib/Support/ModRef.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, MemoryEffects ME) {
4242
case IRMemLocation::InaccessibleMem:
4343
OS << "InaccessibleMem: ";
4444
break;
45+
case IRMemLocation::ErrnoMem:
46+
OS << "ErrnoMem: ";
47+
break;
4548
case IRMemLocation::Other:
4649
OS << "Other: ";
4750
break;

0 commit comments

Comments
 (0)