[llvm] d688725 - [AutoUpgrade] Don't upgrade intrinsics returning overloaded struct type

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 30 08:27:33 PDT 2022


Author: Nikita Popov
Date: 2022-03-30T17:27:26+02:00
New Revision: d6887256c2cae1b1b721bd47459be6d86003db6f

URL: https://github.com/llvm/llvm-project/commit/d6887256c2cae1b1b721bd47459be6d86003db6f
DIFF: https://github.com/llvm/llvm-project/commit/d6887256c2cae1b1b721bd47459be6d86003db6f.diff

LOG: [AutoUpgrade] Don't upgrade intrinsics returning overloaded struct type

We only want to do the upgrade from named to anonymous struct
return if the intrinsic is declared to return a struct, but not
if it has an overloaded return type that just happens to be a
struct. In that case the struct type will be mangled into the
intrinsic name and there is no problem.

This should address the problem reported in
https://reviews.llvm.org/D122471#3416598.

Added: 
    llvm/test/Assembler/struct-ret-without-upgrade.ll

Modified: 
    llvm/lib/IR/AutoUpgrade.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index bf52b098d8d88..8aaf5e67256eb 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -1005,9 +1005,15 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
       return true;
   }
 
-  if (auto *ST = dyn_cast<StructType>(F->getReturnType())) {
-    if (!ST->isLiteral() || ST->isPacked()) {
-      // Replace return type with literal non-packed struct.
+  auto *ST = dyn_cast<StructType>(F->getReturnType());
+  if (ST && (!ST->isLiteral() || ST->isPacked())) {
+    // Replace return type with literal non-packed struct. Only do this for
+    // intrinsics declared to return a struct, not for intrinsics with
+    // overloaded return type, in which case the exact struct type will be
+    // mangled into the name.
+    SmallVector<Intrinsic::IITDescriptor> Desc;
+    Intrinsic::getIntrinsicInfoTableEntries(F->getIntrinsicID(), Desc);
+    if (Desc.front().Kind == Intrinsic::IITDescriptor::Struct) {
       auto *FT = F->getFunctionType();
       auto *NewST = StructType::get(ST->getContext(), ST->elements());
       auto *NewFT = FunctionType::get(NewST, FT->params(), FT->isVarArg());

diff  --git a/llvm/test/Assembler/struct-ret-without-upgrade.ll b/llvm/test/Assembler/struct-ret-without-upgrade.ll
new file mode 100644
index 0000000000000..992b2f9f767fa
--- /dev/null
+++ b/llvm/test/Assembler/struct-ret-without-upgrade.ll
@@ -0,0 +1,18 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -S < %s | FileCheck %s
+
+; This is an overloaded struct return, we should not try to update it to an
+; anonymous struct return.
+
+%ty = type { i32 }
+
+define %ty @test(%ty %arg) {
+; CHECK-LABEL: @test(
+; CHECK-NEXT:    [[COPY:%.*]] = call [[TY:%.*]] @llvm.ssa.copy.s_tys([[TY]] [[ARG:%.*]])
+; CHECK-NEXT:    ret [[TY]] [[COPY]]
+;
+  %copy = call %ty @llvm.ssa.copy.s_tys(%ty %arg)
+  ret %ty %copy
+}
+
+declare %ty @llvm.ssa.copy.s_tys(%ty)


        


More information about the llvm-commits mailing list