[lld] [llvm] [ThinLTO] Don't mark calloc function dead (PR #72673)

via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 30 09:08:44 PST 2023


https://github.com/eleviant updated https://github.com/llvm/llvm-project/pull/72673

>From b5badb959f286289fd299a1c3b3605e278dcfe94 Mon Sep 17 00:00:00 2001
From: Evgeny Leviant <eleviant at accesssoftek.com>
Date: Fri, 17 Nov 2023 15:32:24 +0300
Subject: [PATCH] [ThinLTO] Don't mark calloc function dead

Dead store elimination pass may fold malloc + memset calls into a
single call to calloc. If calloc is not preserved and is not being
called directly it can be marked dead during thin link and result
in link error.
---
 lld/test/ELF/lto/libcall-archive-calloc.ll |  4 ++--
 llvm/include/llvm/IR/RuntimeLibcalls.def   |  2 ++
 llvm/test/ThinLTO/X86/builtin-nostrip.ll   | 13 +++++++++++--
 3 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/lld/test/ELF/lto/libcall-archive-calloc.ll b/lld/test/ELF/lto/libcall-archive-calloc.ll
index 12d5d4ae572d99b..f082a6ce68abcc7 100644
--- a/lld/test/ELF/lto/libcall-archive-calloc.ll
+++ b/lld/test/ELF/lto/libcall-archive-calloc.ll
@@ -11,12 +11,12 @@
 ; RUN: llvm-dis < t.0.4.opt.bc | FileCheck %s
 ; RUN: llvm-nm t | FileCheck %s --check-prefix=NM
 
-; CHECK: declare noalias noundef ptr @calloc(i64 noundef, i64 noundef)
+; CHECK: define dso_local void @calloc
 
 ; NM-NOT:  {{.}}
 ; NM:      {{.*}} T _start
 ;; TODO: Currently the symbol is lazy, which lowers to a SHN_ABS symbol at address 0.
-; NM-NEXT: {{.*}} A calloc
+; NM-NEXT: {{.*}} T calloc
 ; NM-NEXT: {{.*}} T foo
 ; NM-NEXT: {{.*}} T malloc
 ; NM-NEXT: {{.*}} T memset
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.def b/llvm/include/llvm/IR/RuntimeLibcalls.def
index 6ec98e278988428..19dea60bebf9be5 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.def
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.def
@@ -438,6 +438,8 @@ HANDLE_LIBCALL(UO_PPCF128, "__gcc_qunord")
 HANDLE_LIBCALL(MEMCPY, "memcpy")
 HANDLE_LIBCALL(MEMMOVE, "memmove")
 HANDLE_LIBCALL(MEMSET, "memset")
+// DSEPass can emit calloc if it finds a pair of malloc/memset
+HANDLE_LIBCALL(CALLOC, "calloc")
 HANDLE_LIBCALL(BZERO, nullptr)
 
 // Element-wise unordered-atomic memory of different sizes
diff --git a/llvm/test/ThinLTO/X86/builtin-nostrip.ll b/llvm/test/ThinLTO/X86/builtin-nostrip.ll
index 1b6a4ef879254e4..9ac58cf824d2f74 100644
--- a/llvm/test/ThinLTO/X86/builtin-nostrip.ll
+++ b/llvm/test/ThinLTO/X86/builtin-nostrip.ll
@@ -10,7 +10,8 @@
 ; RUN: llvm-lto2 run %t1.bc -o %t.out -save-temps \
 ; RUN:   -r %t1.bc,bar,pl \
 ; RUN:   -r %t1.bc,__stack_chk_guard,pl \
-; RUN:   -r %t1.bc,__stack_chk_fail,pl
+; RUN:   -r %t1.bc,__stack_chk_fail,pl \
+; RUN:   -r %t1.bc,calloc,pl
 ; RUN: llvm-nm %t.out.1 | FileCheck %s --check-prefix=CHECK-NM
 
 ; Re-compile, this time without the thinlto indices.
@@ -20,7 +21,8 @@
 ; RUN: llvm-lto2 run %t4.bc -o %t5.out -save-temps \
 ; RUN:   -r %t4.bc,bar,pl \
 ; RUN:   -r %t4.bc,__stack_chk_guard,pl \
-; RUN:   -r %t4.bc,__stack_chk_fail,pl
+; RUN:   -r %t4.bc,__stack_chk_fail,pl \
+; RUN:   -r %t4.bc,calloc,pl
 ; RUN: llvm-nm %t5.out.0 | FileCheck %s --check-prefix=CHECK-NM
 
 ; Test the old lto interface without thinlto.
@@ -30,6 +32,9 @@
 ; CHECK-NM-NOT: bar
 ; CHECK-NM: T __stack_chk_fail
 ; CHECK-NM: D __stack_chk_guard
+; Allow calloc to be internalized so --gc-sections can
+; still eliminate it if it's not really used anywhere.
+; CHECK-NM: {{[Tt]}} calloc
 ; CHECK-NM-NOT: bar
 
 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
@@ -44,3 +49,7 @@ define void @bar() {
 define void @__stack_chk_fail() {
     ret void
 }
+
+define ptr @calloc(i64, i64) {
+    ret ptr null
+}



More information about the llvm-commits mailing list