[llvm] [FunctionAttrs] Add `errno` inference logic (PR #129067)
    Antonio Frighetto via llvm-commits 
    llvm-commits at lists.llvm.org
       
    Tue Oct 21 02:56:14 PDT 2025
    
    
  
https://github.com/antoniofrighetto updated https://github.com/llvm/llvm-project/pull/129067
>From 228a06cb692673cc5b85b53c42fb01745f562a44 Mon Sep 17 00:00:00 2001
From: Antonio Frighetto <me at antoniofrighetto.com>
Date: Tue, 18 Feb 2025 14:20:39 +0100
Subject: [PATCH] [FunctionAttrs] Infer `errnomem` location when accessing
 errno
Deduce `errnomem` for a given memory location: accesses to
`__errno_location` et alia do access `errnomem` memory.
---
 llvm/lib/Transforms/IPO/FunctionAttrs.cpp     | 11 ++++
 .../FunctionAttrs/read-write-errno.ll         | 56 +++++++++++++++++++
 2 files changed, 67 insertions(+)
 create mode 100644 llvm/test/Transforms/FunctionAttrs/read-write-errno.ll
diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
index 50130da01c7ba..70534a9332438 100644
--- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -136,6 +136,16 @@ static void addLocAccess(MemoryEffects &ME, const MemoryLocation &Loc,
     ME |= MemoryEffects::argMemOnly(MR);
     return;
   }
+  if (auto *CI = dyn_cast<CallInst>(UO)) {
+    if (auto *Callee = CI->getCalledFunction(); Callee && Callee->hasName()) {
+      static constexpr auto ErrnoFnNames = {"__errno_location", "_errno",
+                                            "__errno", "___errno"};
+      if (is_contained(ErrnoFnNames, Callee->getName())) {
+        ME |= MemoryEffects::errnoMemOnly(MR);
+        return;
+      }
+    }
+  }
 
   // If it's not an identified object, it might be an argument.
   if (!isIdentifiedObject(UO))
@@ -258,6 +268,7 @@ checkFunctionMemoryAccess(Function &F, bool ThisBody, AAResults &AAR,
     if (I.isVolatile())
       ME |= MemoryEffects::inaccessibleMemOnly(MR);
 
+    // Refine memory effects for the given location.
     addLocAccess(ME, *Loc, MR, AAR);
   }
 
diff --git a/llvm/test/Transforms/FunctionAttrs/read-write-errno.ll b/llvm/test/Transforms/FunctionAttrs/read-write-errno.ll
new file mode 100644
index 0000000000000..ee8abfe3dd06c
--- /dev/null
+++ b/llvm/test/Transforms/FunctionAttrs/read-write-errno.ll
@@ -0,0 +1,56 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -passes=function-attrs -S < %s | FileCheck --check-prefixes=FNATTRS %s
+; RUN: opt -passes=attributor-light -S < %s | FileCheck --check-prefixes=ATTRIBUTOR %s
+
+define i32 @test_read_errno() {
+; FNATTRS-LABEL: define i32 @test_read_errno() {
+; FNATTRS-NEXT:    [[CALL:%.*]] = call ptr @__errno_location()
+; FNATTRS-NEXT:    [[ERRNO:%.*]] = load i32, ptr [[CALL]], align 4
+; FNATTRS-NEXT:    ret i32 [[ERRNO]]
+;
+; ATTRIBUTOR-LABEL: define i32 @test_read_errno() {
+; ATTRIBUTOR-NEXT:    [[CALL:%.*]] = call ptr @__errno_location()
+; ATTRIBUTOR-NEXT:    [[ERRNO:%.*]] = load i32, ptr [[CALL]], align 4
+; ATTRIBUTOR-NEXT:    ret i32 [[ERRNO]]
+;
+  %call = call ptr @__errno_location()
+  %errno = load i32, ptr %call
+  ret i32 %errno
+}
+
+define ptr @test_write_errno() {
+; FNATTRS-LABEL: define noundef ptr @test_write_errno() {
+; FNATTRS-NEXT:    [[CALL:%.*]] = call ptr @__errno_location()
+; FNATTRS-NEXT:    store i32 0, ptr [[CALL]], align 4
+; FNATTRS-NEXT:    ret ptr [[CALL]]
+;
+; ATTRIBUTOR-LABEL: define ptr @test_write_errno() {
+; ATTRIBUTOR-NEXT:    [[CALL:%.*]] = call ptr @__errno_location()
+; ATTRIBUTOR-NEXT:    store i32 0, ptr [[CALL]], align 4
+; ATTRIBUTOR-NEXT:    ret ptr [[CALL]]
+;
+  %call = call ptr @__errno_location()
+  store i32 0, ptr %call
+  ret ptr %call
+}
+
+define i32 @test_readwrite_errno() {
+; FNATTRS-LABEL: define i32 @test_readwrite_errno() {
+; FNATTRS-NEXT:    [[CALL:%.*]] = call ptr @__errno_location()
+; FNATTRS-NEXT:    store i32 0, ptr [[CALL]], align 4
+; FNATTRS-NEXT:    [[ERRNO:%.*]] = load i32, ptr [[CALL]], align 4
+; FNATTRS-NEXT:    ret i32 [[ERRNO]]
+;
+; ATTRIBUTOR-LABEL: define i32 @test_readwrite_errno() {
+; ATTRIBUTOR-NEXT:    [[CALL:%.*]] = call ptr @__errno_location()
+; ATTRIBUTOR-NEXT:    store i32 0, ptr [[CALL]], align 4
+; ATTRIBUTOR-NEXT:    [[ERRNO:%.*]] = load i32, ptr [[CALL]], align 4
+; ATTRIBUTOR-NEXT:    ret i32 [[ERRNO]]
+;
+  %call = call ptr @__errno_location()
+  store i32 0, ptr %call
+  %errno = load i32, ptr %call
+  ret i32 %errno
+}
+
+declare ptr @__errno_location()
    
    
More information about the llvm-commits
mailing list