Skip to content

Commit 1bb9298

Browse files
[Inline][Cloning] Drop incompatible attributes from NewFunc
Performing `instSimplify` while cloning is unsafe due to incomplete remapping (as reported in #87534). Ideally, `instSimplify` ought to reason on the updated newly-cloned function, after returns have been rewritten and callee entry basic block / call-site have been fixed up. This is in contrast to `CloneAndPruneIntoFromInst` behaviour, which is inherently expected to clone basic blocks, with pruning on top of – if any –, and not actually fixing up returns / CFG, which should be up to the Inliner. We may solve this by letting `instSimplify` work on the newly-cloned function, while maintaining old function attributes, so as to avoid inconsistencies between the yet-to-be-solved return type, and new function ret type attributes.
1 parent 42c7cb6 commit 1bb9298

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

llvm/lib/Transforms/Utils/CloneFunction.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "llvm/Analysis/DomTreeUpdater.h"
1919
#include "llvm/Analysis/InstructionSimplify.h"
2020
#include "llvm/Analysis/LoopInfo.h"
21+
#include "llvm/IR/AttributeMask.h"
2122
#include "llvm/IR/CFG.h"
2223
#include "llvm/IR/Constants.h"
2324
#include "llvm/IR/DebugInfo.h"
@@ -819,6 +820,14 @@ void llvm::CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc,
819820
}
820821
}
821822

823+
// Drop all incompatible return attributes that cannot be applied to NewFunc
824+
// during cloning, so as to allow instruction simplification to reason on the
825+
// old state of the function. The original attributes are restored later.
826+
AttributeMask IncompatibleAttrs =
827+
AttributeFuncs::typeIncompatible(OldFunc->getReturnType());
828+
AttributeList Attrs = NewFunc->getAttributes();
829+
NewFunc->removeRetAttrs(IncompatibleAttrs);
830+
822831
// As phi-nodes have been now remapped, allow incremental simplification of
823832
// newly-cloned instructions.
824833
const DataLayout &DL = NewFunc->getParent()->getDataLayout();
@@ -849,6 +858,9 @@ void llvm::CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc,
849858
}
850859
}
851860

861+
// Restore attributes.
862+
NewFunc->setAttributes(Attrs);
863+
852864
// Remap debug intrinsic operands now that all values have been mapped.
853865
// Doing this now (late) preserves use-before-defs in debug intrinsics. If
854866
// we didn't do this, ValueAsMetadata(use-before-def) operands would be
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2+
; RUN: opt < %s -passes=inline -S | FileCheck %s
3+
; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
4+
5+
define void @callee() {
6+
; CHECK-LABEL: define void @callee() {
7+
; CHECK-NEXT: entry:
8+
; CHECK-NEXT: [[VAL_PTR:%.*]] = load ptr, ptr null, align 8
9+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[VAL_PTR]], null
10+
; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr null, align 8
11+
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i64 undef, i64 [[VAL]]
12+
; CHECK-NEXT: ret void
13+
;
14+
entry:
15+
%val_ptr = load ptr, ptr null, align 8
16+
%cmp = icmp eq ptr %val_ptr, null
17+
%val = load i64, ptr null, align 8
18+
%sel = select i1 %cmp, i64 undef, i64 %val
19+
ret void
20+
}
21+
22+
define noundef i1 @caller() {
23+
; CHECK-LABEL: define noundef i1 @caller() {
24+
; CHECK-NEXT: [[VAL_PTR_I:%.*]] = load ptr, ptr null, align 8
25+
; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq ptr [[VAL_PTR_I]], null
26+
; CHECK-NEXT: [[VAL_I:%.*]] = load i64, ptr null, align 8
27+
; CHECK-NEXT: [[SEL_I:%.*]] = select i1 [[CMP_I]], i64 undef, i64 [[VAL_I]]
28+
; CHECK-NEXT: ret i1 false
29+
;
30+
call void @callee()
31+
ret i1 false
32+
}

0 commit comments

Comments
 (0)