Skip to content

Commit

Permalink
[AutoUpgrade] Don't upgrade intrinsics returning overloaded struct type
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nikic committed Mar 30, 2022
1 parent f29002a commit d688725
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 3 deletions.
12 changes: 9 additions & 3 deletions llvm/lib/IR/AutoUpgrade.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
18 changes: 18 additions & 0 deletions llvm/test/Assembler/struct-ret-without-upgrade.ll
Original file line number Diff line number Diff line change
@@ -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)

0 comments on commit d688725

Please sign in to comment.