Skip to content

Conversation

@JonPsson1
Copy link
Contributor

Use hasAddressTaken() in SystemZ instead of doing this computation in isFullyInternal(), and make sure to only do this once per Function.

I started out by adding this cache in Function, but then with a test failure I realized that an optimization pass can of course change if a function has its address taken or not. Therefore it seems like the cache for this must be local to SystemZISelLowering.

…s() (NFC).

Use hasAddressTaken() in SystemZ instead of doing this computation
in isFullyInternal(), and make sure to only do this once per Function.
@llvmbot
Copy link
Member

llvmbot commented Mar 12, 2025

@llvm/pr-subscribers-backend-systemz

Author: Jonas Paulsson (JonPsson1)

Changes

Use hasAddressTaken() in SystemZ instead of doing this computation in isFullyInternal(), and make sure to only do this once per Function.

I started out by adding this cache in Function, but then with a test failure I realized that an optimization pass can of course change if a function has its address taken or not. Therefore it seems like the cache for this must be local to SystemZISelLowering.


Full diff: https://github.com/llvm/llvm-project/pull/131039.diff

2 Files Affected:

  • (modified) llvm/lib/Target/SystemZ/SystemZISelLowering.cpp (+16-23)
  • (modified) llvm/lib/Target/SystemZ/SystemZISelLowering.h (+7-3)
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index 1e0c303a2e4da..8e61e6bcda57e 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -10200,22 +10200,6 @@ SDValue SystemZTargetLowering::lowerVECREDUCE_ADD(SDValue Op,
       DAG.getConstant(OpVT.getVectorNumElements() - 1, DL, MVT::i32));
 }
 
-// Only consider a function fully internal as long as it has local linkage
-// and is not used in any other way than acting as the called function at
-// call sites.
-bool SystemZTargetLowering::isFullyInternal(const Function *Fn) const {
-  if (!Fn->hasLocalLinkage())
-    return false;
-  for (const User *U : Fn->users()) {
-    if (auto *CB = dyn_cast<CallBase>(U)) {
-      if (CB->getCalledFunction() != Fn)
-        return false;
-    } else
-      return false;
-  }
-  return true;
-}
-
 static void printFunctionArgExts(const Function *F, raw_fd_ostream &OS) {
   FunctionType *FT = F->getFunctionType();
   const AttributeList &Attrs = F->getAttributes();
@@ -10234,6 +10218,16 @@ static void printFunctionArgExts(const Function *F, raw_fd_ostream &OS) {
   OS << ")\n";
 }
 
+bool SystemZTargetLowering::isInternal(const Function *Fn) const {
+  std::map<const Function *, bool>::iterator Itr = IsInternalCache.find(Fn);
+  if (Itr == IsInternalCache.end())
+    Itr = IsInternalCache
+              .insert(std::pair<const Function *, bool>(
+                  Fn, (Fn->hasLocalLinkage() && !Fn->hasAddressTaken())))
+              .first;
+  return Itr->second;
+}
+
 void SystemZTargetLowering::
 verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
                              const Function *F, SDValue Callee) const {
@@ -10246,8 +10240,8 @@ verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
   const Function *CalleeFn = nullptr;
   if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee))
     if ((CalleeFn = dyn_cast<Function>(G->getGlobal())))
-      IsInternal = isFullyInternal(CalleeFn);
-  if (!verifyNarrowIntegerArgs(Outs, IsInternal)) {
+      IsInternal = isInternal(CalleeFn);
+  if (!IsInternal && !verifyNarrowIntegerArgs(Outs)) {
     errs() << "ERROR: Missing extension attribute of passed "
            << "value in call to function:\n" << "Callee:  ";
     if (CalleeFn != nullptr)
@@ -10268,7 +10262,7 @@ verifyNarrowIntegerArgs_Ret(const SmallVectorImpl<ISD::OutputArg> &Outs,
   if (!EnableIntArgExtCheck)
     return;
 
-  if (!verifyNarrowIntegerArgs(Outs, isFullyInternal(F))) {
+  if (!isInternal(F) && !verifyNarrowIntegerArgs(Outs)) {
     errs() << "ERROR: Missing extension attribute of returned "
            << "value from function:\n";
     printFunctionArgExts(F, errs());
@@ -10278,10 +10272,9 @@ verifyNarrowIntegerArgs_Ret(const SmallVectorImpl<ISD::OutputArg> &Outs,
 
 // Verify that narrow integer arguments are extended as required by the ABI.
 // Return false if an error is found.
-bool SystemZTargetLowering::
-verifyNarrowIntegerArgs(const SmallVectorImpl<ISD::OutputArg> &Outs,
-                        bool IsInternal) const {
-  if (IsInternal || !Subtarget.isTargetELF())
+bool SystemZTargetLowering::verifyNarrowIntegerArgs(
+    const SmallVectorImpl<ISD::OutputArg> &Outs) const {
+  if (!Subtarget.isTargetELF())
     return true;
 
   if (EnableIntArgExtCheck.getNumOccurrences()) {
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
index 839a550012444..971a948c3c857 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h
@@ -815,13 +815,17 @@ class SystemZTargetLowering : public TargetLowering {
   getTargetMMOFlags(const Instruction &I) const override;
   const TargetRegisterClass *getRepRegClassFor(MVT VT) const override;
 
-  bool isFullyInternal(const Function *Fn) const;
+private:
+  bool isInternal(const Function *Fn) const;
+  mutable std::map<const Function *, bool> IsInternalCache;
   void verifyNarrowIntegerArgs_Call(const SmallVectorImpl<ISD::OutputArg> &Outs,
                                     const Function *F, SDValue Callee) const;
   void verifyNarrowIntegerArgs_Ret(const SmallVectorImpl<ISD::OutputArg> &Outs,
                                    const Function *F) const;
-  bool verifyNarrowIntegerArgs(const SmallVectorImpl<ISD::OutputArg> &Outs,
-                               bool IsInternal) const;
+  bool
+  verifyNarrowIntegerArgs(const SmallVectorImpl<ISD::OutputArg> &Outs) const;
+
+public:
 };
 
 struct SystemZVectorConstantInfo {

@uweigand
Copy link
Member

Instead of adding the new map, can't this bit of information be cached in SystemZMachineFunctionInfo?

@JonPsson1
Copy link
Contributor Author

Instead of adding the new map, can't this bit of information be cached in SystemZMachineFunctionInfo?

I think SystemZTargetLowering is created once per module, while SystemZMachineFunctionInfo is created for each Function.

@uweigand
Copy link
Member

Instead of adding the new map, can't this bit of information be cached in SystemZMachineFunctionInfo?

I think SystemZTargetLowering is created once per module, while SystemZMachineFunctionInfo is created for each Function.

Well yes, that's why it should be the better place to store per-Function data, right?

@JonPsson1
Copy link
Contributor Author

Instead of adding the new map, can't this bit of information be cached in SystemZMachineFunctionInfo?

I think SystemZTargetLowering is created once per module, while SystemZMachineFunctionInfo is created for each Function.

Well yes, that's why it should be the better place to store per-Function data, right?

Oh, I wasn't aware that the MachineFunctionInfo survives the compilation of the MF. In that case I agree it would make sense.

@JonPsson1
Copy link
Contributor Author

Hmm, I am kind of stuck at the point of getting a MachineFunction from the given Function. It's common to do MF->getFunction() and get the Function, but there doesn't seem to be a way to do it the other way around.

There is a MachineFunctionAnalysis that runs, but I am not sure if it creates an MF (and MFI) ahead of time for all Functions in the module, or if it does this when compilation of it begins. Of course, an MF with an MFI would have to be created ahead of time for this to work.

I guess it might not be so bad to add a Function flag directly and set it at the point of instruction selection, when the Function/Module will not be modified anymore. But that is a bit more intrusive into common-code on the other hand.

Copy link
Member

@uweigand uweigand left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the discussion above, I think just keeping this cache is probably the best solution after all, so let's go with it as is. LGTM!

@JonPsson1 JonPsson1 merged commit b13373d into llvm:main Mar 21, 2025
10 of 13 checks passed
@JonPsson1 JonPsson1 deleted the VerIntArgs branch March 21, 2025 18:07
@llvm-ci
Copy link
Collaborator

llvm-ci commented Mar 21, 2025

LLVM Buildbot has detected a new failure on builder openmp-offload-amdgpu-runtime running on omp-vega20-0 while building llvm at step 7 "Add check check-offload".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/30/builds/18142

Here is the relevant piece of the build log for the reference
Step 7 (Add check check-offload) failure: test (failure)
******************** TEST 'libomptarget :: amdgcn-amd-amdhsa :: offloading/gpupgo/pgo2.c' FAILED ********************
Exit Code: 1

Command Output (stdout):
--
# RUN: at line 1
/home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/./bin/clang -fopenmp    -I /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.src/offload/test -I /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -L /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload -L /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/./lib -L /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src  -nogpulib -Wl,-rpath,/home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload -Wl,-rpath,/home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -Wl,-rpath,/home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/./lib  -fopenmp-targets=amdgcn-amd-amdhsa /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.src/offload/test/offloading/gpupgo/pgo2.c -o /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload/test/amdgcn-amd-amdhsa/offloading/gpupgo/Output/pgo2.c.tmp /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/./lib/libomptarget.devicertl.a -fprofile-generate
# executed command: /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/./bin/clang -fopenmp -I /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.src/offload/test -I /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -L /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload -L /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/./lib -L /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -nogpulib -Wl,-rpath,/home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload -Wl,-rpath,/home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -Wl,-rpath,/home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/./lib -fopenmp-targets=amdgcn-amd-amdhsa /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.src/offload/test/offloading/gpupgo/pgo2.c -o /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload/test/amdgcn-amd-amdhsa/offloading/gpupgo/Output/pgo2.c.tmp /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/./lib/libomptarget.devicertl.a -fprofile-generate
# note: command had no output on stdout or stderr
# RUN: at line 2
env LLVM_PROFILE_FILE=pgo2.c.llvm.profraw      /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload/test/amdgcn-amd-amdhsa/offloading/gpupgo/Output/pgo2.c.tmp 2>&1
# executed command: env LLVM_PROFILE_FILE=pgo2.c.llvm.profraw /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/runtimes/runtimes-bins/offload/test/amdgcn-amd-amdhsa/offloading/gpupgo/Output/pgo2.c.tmp
# note: command had no output on stdout or stderr
# RUN: at line 4
llvm-profdata show --all-functions --counts      pgo2.c.llvm.profraw | /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/./bin/FileCheck /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.src/offload/test/offloading/gpupgo/pgo2.c      --check-prefix="LLVM-HOST"
# executed command: llvm-profdata show --all-functions --counts pgo2.c.llvm.profraw
# note: command had no output on stdout or stderr
# executed command: /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/./bin/FileCheck /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.src/offload/test/offloading/gpupgo/pgo2.c --check-prefix=LLVM-HOST
# note: command had no output on stdout or stderr
# RUN: at line 7
llvm-profdata show --all-functions --counts      amdgcn-amd-amdhsa.pgo2.c.llvm.profraw      | /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/./bin/FileCheck /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.src/offload/test/offloading/gpupgo/pgo2.c --check-prefix="LLVM-DEVICE"
# executed command: llvm-profdata show --all-functions --counts amdgcn-amd-amdhsa.pgo2.c.llvm.profraw
# note: command had no output on stdout or stderr
# executed command: /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.build/./bin/FileCheck /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.src/offload/test/offloading/gpupgo/pgo2.c --check-prefix=LLVM-DEVICE
# .---command stderr------------
# | /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.src/offload/test/offloading/gpupgo/pgo2.c:81:17: error: LLVM-DEVICE: expected string not found in input
# | // LLVM-DEVICE: Block counts: [10, 2, 1]
# |                 ^
# | <stdin>:4:13: note: scanning from here
# |  Counters: 3
# |             ^
# | <stdin>:5:2: note: possible intended match here
# |  Block counts: [10, 3, 1]
# |  ^
# | 
# | Input file: <stdin>
# | Check file: /home/ompworker/bbot/openmp-offload-amdgpu-runtime/llvm.src/offload/test/offloading/gpupgo/pgo2.c
# | 
# | -dump-input=help explains the following input dump.
# | 
# | Input was:
# | <<<<<<
# |             1: Counters: 
# |             2:  __omp_offloading_802_b3a8121_main_l61: 
# |             3:  Hash: 0x07735b6a1ad4d6e5 
# |             4:  Counters: 3 
# | check:81'0                 X error: no match found
# |             5:  Block counts: [10, 3, 1] 
# | check:81'0     ~~~~~~~~~~~~~~~~~~~~~~~~~~
# | check:81'1      ?                         possible intended match
...

@llvm-ci
Copy link
Collaborator

llvm-ci commented Mar 21, 2025

LLVM Buildbot has detected a new failure on builder lldb-aarch64-ubuntu running on linaro-lldb-aarch64-ubuntu while building llvm at step 6 "test".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/59/builds/14709

Here is the relevant piece of the build log for the reference
Step 6 (test) failure: build (failure)
...
UNSUPPORTED: lldb-api :: functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCNSURL.py (349 of 2109)
UNSUPPORTED: lldb-api :: functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjNSException.py (350 of 2109)
UNSUPPORTED: lldb-api :: functionalities/data-formatter/data-formatter-objc/TestDataFormatterObjCPlain.py (351 of 2109)
UNSUPPORTED: lldb-api :: functionalities/data-formatter/data-formatter-objc/cmtime/TestDataFormatterCMTime.py (352 of 2109)
UNSUPPORTED: lldb-api :: functionalities/data-formatter/data-formatter-objc/nsindexpath/TestDataFormatterNSIndexPath.py (353 of 2109)
UNSUPPORTED: lldb-api :: functionalities/data-formatter/data-formatter-objc/nsstring/TestDataFormatterNSString.py (354 of 2109)
UNSUPPORTED: lldb-api :: functionalities/data-formatter/data-formatter-proper-plurals/TestFormattersOneIsSingular.py (355 of 2109)
PASS: lldb-api :: functionalities/data-formatter/data-formatter-ptr-to-array/TestPtrToArrayFormatting.py (356 of 2109)
PASS: lldb-api :: functionalities/data-formatter/data-formatter-script/TestDataFormatterScript.py (357 of 2109)
PASS: lldb-api :: functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py (358 of 2109)
FAIL: lldb-api :: functionalities/data-formatter/data-formatter-skip-summary/TestDataFormatterSkipSummary.py (359 of 2109)
******************** TEST 'lldb-api :: functionalities/data-formatter/data-formatter-skip-summary/TestDataFormatterSkipSummary.py' FAILED ********************
Script:
--
/usr/bin/python3.10 /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib --env LLVM_INCLUDE_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/include --env LLVM_TOOLS_DIR=/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --arch aarch64 --build-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex --lldb-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/lldb --compiler /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/clang --dsymutil /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./bin --lldb-obj-root /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/tools/lldb --lldb-libs-dir /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/./lib /home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/llvm-project/lldb/test/API/functionalities/data-formatter/data-formatter-skip-summary -p TestDataFormatterSkipSummary.py
--
Exit Code: -11

Command Output (stdout):
--
lldb version 21.0.0git (https://github.com/llvm/llvm-project.git revision b13373db251f4ee0e6471783ce8d86e74c3f1928)
  clang revision b13373db251f4ee0e6471783ce8d86e74c3f1928
  llvm revision b13373db251f4ee0e6471783ce8d86e74c3f1928
Skipping the following test categories: ['libc++', 'dsym', 'gmodules', 'debugserver', 'objc']

--
Command Output (stderr):
--
UNSUPPORTED: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_with_run_command_dsym (TestDataFormatterSkipSummary.SkipSummaryDataFormatterTestCase) (test case does not fall in any category of interest for this run) 
PASS: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_with_run_command_dwarf (TestDataFormatterSkipSummary.SkipSummaryDataFormatterTestCase)
PASS: LLDB (/home/tcwg-buildbot/worker/lldb-aarch64-ubuntu/build/bin/clang-aarch64) :: test_with_run_command_dwo (TestDataFormatterSkipSummary.SkipSummaryDataFormatterTestCase)
----------------------------------------------------------------------
Ran 3 tests in 0.960s

OK (skipped=1)

--

********************
PASS: lldb-api :: functionalities/data-formatter/data-formatter-python-synth/TestDataFormatterPythonSynth.py (360 of 2109)
PASS: lldb-api :: functionalities/data-formatter/data-formatter-stl/generic/coroutine_handle/TestCoroutineHandle.py (361 of 2109)
PASS: lldb-api :: functionalities/data-formatter/data-formatter-stl/generic/list/loop/TestDataFormatterGenericListLoop.py (362 of 2109)
PASS: lldb-api :: functionalities/data-formatter/data-formatter-stl/generic/bitset/TestDataFormatterGenericBitset.py (363 of 2109)
PASS: lldb-api :: functionalities/data-formatter/data-formatter-stl/generic/deque/TestDataFormatterGenericDeque.py (364 of 2109)
PASS: lldb-api :: functionalities/data-formatter/data-formatter-stl/generic/list/TestDataFormatterGenericList.py (365 of 2109)
PASS: lldb-api :: functionalities/data-formatter/data-formatter-stl/generic/multimap/TestDataFormatterGenericMultiMap.py (366 of 2109)
PASS: lldb-api :: functionalities/data-formatter/data-formatter-stl/generic/optional/TestDataFormatterGenericOptional.py (367 of 2109)
PASS: lldb-api :: functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py (368 of 2109)
PASS: lldb-api :: functionalities/data-formatter/data-formatter-stl/libcxx-simulators/optional/TestDataFormatterLibcxxOptionalSimulator.py (369 of 2109)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants