Skip to content

Commit 5e7e499

Browse files
committed
[JumpThreading] Clone noalias.scope.decl when threading blocks
When cloning instructions during jump threading, also clone and adapt any declared scopes. This is primarily important when threading loop exits, because we'll end up with two dominating scope declarations in that case (at least after additional loop rotation). This addresses a loose thread from https://reviews.llvm.org/rG2556b413a7b8#975012. Differential Revision: https://reviews.llvm.org/D97154
1 parent bccdf6b commit 5e7e499

File tree

4 files changed

+88
-0
lines changed

4 files changed

+88
-0
lines changed

llvm/include/llvm/Transforms/Utils/Cloning.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,13 @@ void updateProfileCallee(
295295
void identifyNoAliasScopesToClone(
296296
ArrayRef<BasicBlock *> BBs, SmallVectorImpl<MDNode *> &NoAliasDeclScopes);
297297

298+
/// Find the 'llvm.experimental.noalias.scope.decl' intrinsics in the specified
299+
/// instruction range and extract their scope. These are candidates for
300+
/// duplication when cloning.
301+
void identifyNoAliasScopesToClone(
302+
BasicBlock::iterator Start, BasicBlock::iterator End,
303+
SmallVectorImpl<MDNode *> &NoAliasDeclScopes);
304+
298305
/// Duplicate the specified list of noalias decl scopes.
299306
/// The 'Ext' string is added as an extension to the name.
300307
/// Afterwards, the ClonedScopes contains the mapping of the original scope

llvm/lib/Transforms/Scalar/JumpThreading.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2076,6 +2076,15 @@ JumpThreadingPass::cloneInstructions(BasicBlock::iterator BI,
20762076
ValueMapping[PN] = NewPN;
20772077
}
20782078

2079+
// Clone noalias scope declarations in the threaded block. When threading a
2080+
// loop exit, we would otherwise end up with two idential scope declarations
2081+
// visible at the same time.
2082+
SmallVector<MDNode *> NoAliasScopes;
2083+
DenseMap<MDNode *, MDNode *> ClonedScopes;
2084+
LLVMContext &Context = PredBB->getContext();
2085+
identifyNoAliasScopesToClone(BI, BE, NoAliasScopes);
2086+
cloneNoAliasScopes(NoAliasScopes, ClonedScopes, "thread", Context);
2087+
20792088
// Clone the non-phi instructions of the source basic block into NewBB,
20802089
// keeping track of the mapping and using it to remap operands in the cloned
20812090
// instructions.
@@ -2084,6 +2093,7 @@ JumpThreadingPass::cloneInstructions(BasicBlock::iterator BI,
20842093
New->setName(BI->getName());
20852094
NewBB->getInstList().push_back(New);
20862095
ValueMapping[&*BI] = New;
2096+
adaptNoAliasScopes(New, ClonedScopes, Context);
20872097

20882098
// Remap operands to patch up intra-block references.
20892099
for (unsigned i = 0, e = New->getNumOperands(); i != e; ++i)

llvm/lib/Transforms/Utils/CloneFunction.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,3 +1036,11 @@ void llvm::identifyNoAliasScopesToClone(
10361036
if (auto *Decl = dyn_cast<NoAliasScopeDeclInst>(&I))
10371037
NoAliasDeclScopes.push_back(Decl->getScopeList());
10381038
}
1039+
1040+
void llvm::identifyNoAliasScopesToClone(
1041+
BasicBlock::iterator Start, BasicBlock::iterator End,
1042+
SmallVectorImpl<MDNode *> &NoAliasDeclScopes) {
1043+
for (Instruction &I : make_range(Start, End))
1044+
if (auto *Decl = dyn_cast<NoAliasScopeDeclInst>(&I))
1045+
NoAliasDeclScopes.push_back(Decl->getScopeList());
1046+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt -S -jump-threading < %s | FileCheck %s
3+
4+
define void @test(i8* %ptr) {
5+
; CHECK-LABEL: @test(
6+
; CHECK-NEXT: entry:
7+
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata !0)
8+
; CHECK-NEXT: br label [[LOOP:%.*]]
9+
; CHECK: loop:
10+
; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[LATCH:%.*]] ]
11+
; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[I]], 100
12+
; CHECK-NEXT: br i1 [[C]], label [[EXIT:%.*]], label [[LATCH]]
13+
; CHECK: latch:
14+
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata !3)
15+
; CHECK-NEXT: store i8 0, i8* [[PTR:%.*]], align 1, !noalias !0
16+
; CHECK-NEXT: store i8 1, i8* [[PTR]], align 1, !noalias !3
17+
; CHECK-NEXT: [[I_INC]] = add i32 [[I]], 1
18+
; CHECK-NEXT: br label [[LOOP]]
19+
; CHECK: exit:
20+
; CHECK-NEXT: call void @llvm.experimental.noalias.scope.decl(metadata !5)
21+
; CHECK-NEXT: store i8 0, i8* [[PTR]], align 1, !noalias !0
22+
; CHECK-NEXT: store i8 1, i8* [[PTR]], align 1, !noalias !5
23+
; CHECK-NEXT: ret void
24+
;
25+
entry:
26+
call void @llvm.experimental.noalias.scope.decl(metadata !0)
27+
br label %loop
28+
29+
loop:
30+
%i = phi i32 [ 0, %entry ], [ %i.inc, %latch ]
31+
%c = icmp eq i32 %i, 100
32+
br i1 %c, label %if, label %latch
33+
34+
if:
35+
br label %latch
36+
37+
latch:
38+
%p = phi i1 [ true, %if ], [ false, %loop ]
39+
call void @llvm.experimental.noalias.scope.decl(metadata !3)
40+
store i8 0, i8* %ptr, !noalias !0
41+
store i8 1, i8* %ptr, !noalias !3
42+
%i.inc = add i32 %i, 1
43+
br i1 %p, label %exit, label %loop
44+
45+
exit:
46+
ret void
47+
}
48+
49+
declare void @llvm.experimental.noalias.scope.decl(metadata)
50+
51+
!0 = !{!1}
52+
!1 = distinct !{!1, !2, !"scope1"}
53+
!2 = distinct !{!2, !"domain"}
54+
!3 = !{!4}
55+
!4 = distinct !{!4, !2, !"scope2"}
56+
57+
; CHECK: !0 = !{!1}
58+
; CHECK: !1 = distinct !{!1, !2, !"scope1"}
59+
; CHECK: !2 = distinct !{!2, !"domain"}
60+
; CHECK: !3 = !{!4}
61+
; CHECK: !4 = distinct !{!4, !2, !"scope2"}
62+
; CHECK: !5 = !{!6}
63+
; CHECK: !6 = distinct !{!6, !2, !"scope2:thread"}

0 commit comments

Comments
 (0)