Skip to content

Commit e412697

Browse files
[MemoryBuiltins] Cache the result of ObjectOffsetSizeVisitor::visit. #64796 (#65326)
visit will skip visiting instructions it already has visited to avoid issues with cycles in the data graph. However, the result of this skipping behavior is that if we encounter the same instruction twice, and that instruction has a well defined result and isn't part of a cycle, we will introduce unknowns into the analysis even though we knew the size and offset of the instruction's result. Instead of skipping such instructions, keep a cache of the result of visiting them. This result is initialized to unknown() before visiting, so if we happen to visit it again recursively (perhaps as the result of a cycle or a phi), we will get unknown as the cached result and exit out.
1 parent 0a692b6 commit e412697

File tree

3 files changed

+65
-5
lines changed

3 files changed

+65
-5
lines changed

llvm/include/llvm/Analysis/MemoryBuiltins.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ class ObjectSizeOffsetVisitor
198198
ObjectSizeOpts Options;
199199
unsigned IntTyBits;
200200
APInt Zero;
201-
SmallPtrSet<Instruction *, 8> SeenInsts;
201+
DenseMap<Instruction *, SizeOffsetType> SeenInsts;
202202

203203
APInt align(APInt Size, MaybeAlign Align);
204204

llvm/lib/Analysis/MemoryBuiltins.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -733,10 +733,14 @@ SizeOffsetType ObjectSizeOffsetVisitor::computeImpl(Value *V) {
733733
if (Instruction *I = dyn_cast<Instruction>(V)) {
734734
// If we have already seen this instruction, bail out. Cycles can happen in
735735
// unreachable code after constant propagation.
736-
if (!SeenInsts.insert(I).second)
737-
return unknown();
738-
739-
return visit(*I);
736+
auto P = SeenInsts.try_emplace(I, unknown());
737+
if (!P.second)
738+
return P.first->second;
739+
SizeOffsetType Res = visit(*I);
740+
// Cache the result for later visits. If we happened to visit this during
741+
// the above recursion, we would consider it unknown until now.
742+
SeenInsts[I] = Res;
743+
return Res;
740744
}
741745
if (Argument *A = dyn_cast<Argument>(V))
742746
return visitArgument(*A);

llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,59 @@ if.end:
6161
%size = call i64 @llvm.objectsize.i64.p0(ptr %p, i1 true, i1 true, i1 false)
6262
ret i64 %size
6363
}
64+
65+
define i64 @pick_max_same(i32 %n) {
66+
; CHECK-LABEL: @pick_max_same(
67+
; CHECK-NEXT: entry:
68+
; CHECK-NEXT: [[BUFFER:%.*]] = alloca i8, i64 20, align 1
69+
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0
70+
; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
71+
; CHECK: if.else:
72+
; CHECK-NEXT: [[OFFSETED:%.*]] = getelementptr i8, ptr [[BUFFER]], i64 10
73+
; CHECK-NEXT: br label [[IF_END]]
74+
; CHECK: if.end:
75+
; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[OFFSETED]], [[IF_ELSE]] ], [ [[BUFFER]], [[ENTRY:%.*]] ]
76+
; CHECK-NEXT: ret i64 20
77+
;
78+
entry:
79+
%buffer = alloca i8, i64 20
80+
%cond = icmp eq i32 %n, 0
81+
br i1 %cond, label %if.else, label %if.end
82+
83+
if.else:
84+
%offseted = getelementptr i8, ptr %buffer, i64 10
85+
br label %if.end
86+
87+
if.end:
88+
%p = phi ptr [ %offseted, %if.else ], [ %buffer, %entry ]
89+
%size = call i64 @llvm.objectsize.i64.p0(ptr %p, i1 false, i1 true, i1 false)
90+
ret i64 %size
91+
}
92+
93+
define i64 @pick_min_same(i32 %n) {
94+
; CHECK-LABEL: @pick_min_same(
95+
; CHECK-NEXT: entry:
96+
; CHECK-NEXT: [[BUFFER:%.*]] = alloca i8, i64 20, align 1
97+
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0
98+
; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
99+
; CHECK: if.else:
100+
; CHECK-NEXT: [[OFFSETED:%.*]] = getelementptr i8, ptr [[BUFFER]], i64 10
101+
; CHECK-NEXT: br label [[IF_END]]
102+
; CHECK: if.end:
103+
; CHECK-NEXT: [[P:%.*]] = phi ptr [ [[OFFSETED]], [[IF_ELSE]] ], [ [[BUFFER]], [[ENTRY:%.*]] ]
104+
; CHECK-NEXT: ret i64 10
105+
;
106+
entry:
107+
%buffer = alloca i8, i64 20
108+
%cond = icmp eq i32 %n, 0
109+
br i1 %cond, label %if.else, label %if.end
110+
111+
if.else:
112+
%offseted = getelementptr i8, ptr %buffer, i64 10
113+
br label %if.end
114+
115+
if.end:
116+
%p = phi ptr [ %offseted, %if.else ], [ %buffer, %entry ]
117+
%size = call i64 @llvm.objectsize.i64.p0(ptr %p, i1 true, i1 true, i1 false)
118+
ret i64 %size
119+
}

0 commit comments

Comments
 (0)