Skip to content

Commit d8e0a6d

Browse files
author
serge-sans-paille
committed
[LowerConstantIntrinsics] Support phi operand in __builtin_object_size folder
The implementation is just a generalization of the Select handler. We're no trying to be smart and compute any kind of fixed point. Differential Revision: https://reviews.llvm.org/D121897
1 parent 0ebac76 commit d8e0a6d

File tree

3 files changed

+91
-28
lines changed

3 files changed

+91
-28
lines changed

llvm/include/llvm/Analysis/MemoryBuiltins.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ class ObjectSizeOffsetVisitor
229229
SizeOffsetType visitInstruction(Instruction &I);
230230

231231
private:
232+
SizeOffsetType combineSizeOffset(SizeOffsetType LHS, SizeOffsetType RHS);
232233
SizeOffsetType computeImpl(Value *V);
233234
bool CheckedZextOrTrunc(APInt &I);
234235
};

llvm/lib/Analysis/MemoryBuiltins.cpp

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <cassert>
4343
#include <cstdint>
4444
#include <iterator>
45+
#include <numeric>
4546
#include <type_traits>
4647
#include <utility>
4748

@@ -812,37 +813,35 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitLoadInst(LoadInst&) {
812813
return unknown();
813814
}
814815

815-
SizeOffsetType ObjectSizeOffsetVisitor::visitPHINode(PHINode&) {
816-
// too complex to analyze statically.
817-
return unknown();
818-
}
816+
SizeOffsetType ObjectSizeOffsetVisitor::combineSizeOffset(SizeOffsetType LHS,
817+
SizeOffsetType RHS) {
818+
if (!bothKnown(LHS) || !bothKnown(RHS))
819+
return unknown();
819820

820-
SizeOffsetType ObjectSizeOffsetVisitor::visitSelectInst(SelectInst &I) {
821-
SizeOffsetType TrueSide = compute(I.getTrueValue());
822-
SizeOffsetType FalseSide = compute(I.getFalseValue());
823-
if (bothKnown(TrueSide) && bothKnown(FalseSide)) {
824-
if (TrueSide == FalseSide) {
825-
return TrueSide;
826-
}
821+
switch (Options.EvalMode) {
822+
case ObjectSizeOpts::Mode::Min:
823+
return (getSizeWithOverflow(LHS).slt(getSizeWithOverflow(RHS))) ? LHS : RHS;
824+
case ObjectSizeOpts::Mode::Max:
825+
return (getSizeWithOverflow(LHS).sgt(getSizeWithOverflow(RHS))) ? LHS : RHS;
826+
case ObjectSizeOpts::Mode::Exact:
827+
return (getSizeWithOverflow(LHS).eq(getSizeWithOverflow(RHS))) ? LHS
828+
: unknown();
829+
}
830+
llvm_unreachable("missing an eval mode");
831+
}
827832

828-
APInt TrueResult = getSizeWithOverflow(TrueSide);
829-
APInt FalseResult = getSizeWithOverflow(FalseSide);
833+
SizeOffsetType ObjectSizeOffsetVisitor::visitPHINode(PHINode &PN) {
834+
auto IncomingValues = PN.incoming_values();
835+
return std::accumulate(IncomingValues.begin() + 1, IncomingValues.end(),
836+
compute(*IncomingValues.begin()),
837+
[this](SizeOffsetType LHS, Value *VRHS) {
838+
return combineSizeOffset(LHS, compute(VRHS));
839+
});
840+
}
830841

831-
if (TrueResult == FalseResult) {
832-
return TrueSide;
833-
}
834-
if (Options.EvalMode == ObjectSizeOpts::Mode::Min) {
835-
if (TrueResult.slt(FalseResult))
836-
return TrueSide;
837-
return FalseSide;
838-
}
839-
if (Options.EvalMode == ObjectSizeOpts::Mode::Max) {
840-
if (TrueResult.sgt(FalseResult))
841-
return TrueSide;
842-
return FalseSide;
843-
}
844-
}
845-
return unknown();
842+
SizeOffsetType ObjectSizeOffsetVisitor::visitSelectInst(SelectInst &I) {
843+
return combineSizeOffset(compute(I.getTrueValue()),
844+
compute(I.getFalseValue()));
846845
}
847846

848847
SizeOffsetType ObjectSizeOffsetVisitor::visitUndefValue(UndefValue&) {
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 -lower-constant-intrinsics -S < %s | FileCheck %s
3+
4+
5+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
6+
target triple = "x86_64-unknown-linux-gnu"
7+
8+
declare dso_local noalias noundef i8* @malloc(i64 noundef) local_unnamed_addr
9+
declare i64 @llvm.objectsize.i64.p0i8(i8*, i1 immarg, i1 immarg, i1 immarg)
10+
11+
@buffer = dso_local global [4 x i8] zeroinitializer, align 1
12+
13+
define dso_local i64 @pick_max(i32 noundef %n) local_unnamed_addr {
14+
; CHECK-LABEL: @pick_max(
15+
; CHECK-NEXT: entry:
16+
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0
17+
; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
18+
; CHECK: if.else:
19+
; CHECK-NEXT: [[MALLOCED:%.*]] = call noalias dereferenceable_or_null(8) i8* @malloc(i64 noundef 8)
20+
; CHECK-NEXT: br label [[IF_END]]
21+
; CHECK: if.end:
22+
; CHECK-NEXT: [[P:%.*]] = phi i8* [ [[MALLOCED]], [[IF_ELSE]] ], [ getelementptr inbounds ([4 x i8], [4 x i8]* @buffer, i64 0, i64 0), [[ENTRY:%.*]] ]
23+
; CHECK-NEXT: ret i64 8
24+
;
25+
entry:
26+
%cond = icmp eq i32 %n, 0
27+
br i1 %cond, label %if.else, label %if.end
28+
29+
if.else:
30+
%malloced = call noalias dereferenceable_or_null(8) i8* @malloc(i64 noundef 8)
31+
br label %if.end
32+
33+
if.end:
34+
%p = phi i8* [ %malloced, %if.else ], [ getelementptr inbounds ([4 x i8], [4 x i8]* @buffer, i64 0, i64 0), %entry ]
35+
%size = call i64 @llvm.objectsize.i64.p0i8(i8* %p, i1 false, i1 true, i1 false)
36+
ret i64 %size
37+
}
38+
39+
define dso_local i64 @pick_min(i32 noundef %n) local_unnamed_addr {
40+
; CHECK-LABEL: @pick_min(
41+
; CHECK-NEXT: entry:
42+
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0
43+
; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
44+
; CHECK: if.else:
45+
; CHECK-NEXT: [[MALLOCED:%.*]] = call noalias dereferenceable_or_null(8) i8* @malloc(i64 noundef 8)
46+
; CHECK-NEXT: br label [[IF_END]]
47+
; CHECK: if.end:
48+
; CHECK-NEXT: [[P:%.*]] = phi i8* [ [[MALLOCED]], [[IF_ELSE]] ], [ getelementptr inbounds ([4 x i8], [4 x i8]* @buffer, i64 0, i64 0), [[ENTRY:%.*]] ]
49+
; CHECK-NEXT: ret i64 4
50+
;
51+
entry:
52+
%cond = icmp eq i32 %n, 0
53+
br i1 %cond, label %if.else, label %if.end
54+
55+
if.else:
56+
%malloced = call noalias dereferenceable_or_null(8) i8* @malloc(i64 noundef 8)
57+
br label %if.end
58+
59+
if.end:
60+
%p = phi i8* [ %malloced, %if.else ], [ getelementptr inbounds ([4 x i8], [4 x i8]* @buffer, i64 0, i64 0), %entry ]
61+
%size = call i64 @llvm.objectsize.i64.p0i8(i8* %p, i1 true, i1 true, i1 false)
62+
ret i64 %size
63+
}

0 commit comments

Comments
 (0)