[llvm] d8e0a6d - [LowerConstantIntrinsics] Support phi operand in __builtin_object_size folder

via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 21 03:31:17 PDT 2022


Author: serge-sans-paille
Date: 2022-03-21T11:30:50+01:00
New Revision: d8e0a6d5e9dd2311641f9a8a5d2bf90829951ddc

URL: https://github.com/llvm/llvm-project/commit/d8e0a6d5e9dd2311641f9a8a5d2bf90829951ddc
DIFF: https://github.com/llvm/llvm-project/commit/d8e0a6d5e9dd2311641f9a8a5d2bf90829951ddc.diff

LOG: [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

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

Modified: 
    llvm/include/llvm/Analysis/MemoryBuiltins.h
    llvm/lib/Analysis/MemoryBuiltins.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/MemoryBuiltins.h b/llvm/include/llvm/Analysis/MemoryBuiltins.h
index 0c62731a7797c..f8fba19620537 100644
--- a/llvm/include/llvm/Analysis/MemoryBuiltins.h
+++ b/llvm/include/llvm/Analysis/MemoryBuiltins.h
@@ -229,6 +229,7 @@ class ObjectSizeOffsetVisitor
   SizeOffsetType visitInstruction(Instruction &I);
 
 private:
+  SizeOffsetType combineSizeOffset(SizeOffsetType LHS, SizeOffsetType RHS);
   SizeOffsetType computeImpl(Value *V);
   bool CheckedZextOrTrunc(APInt &I);
 };

diff  --git a/llvm/lib/Analysis/MemoryBuiltins.cpp b/llvm/lib/Analysis/MemoryBuiltins.cpp
index 4b7582b6e05ed..34f7fc78619c5 100644
--- a/llvm/lib/Analysis/MemoryBuiltins.cpp
+++ b/llvm/lib/Analysis/MemoryBuiltins.cpp
@@ -42,6 +42,7 @@
 #include <cassert>
 #include <cstdint>
 #include <iterator>
+#include <numeric>
 #include <type_traits>
 #include <utility>
 
@@ -812,37 +813,35 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitLoadInst(LoadInst&) {
   return unknown();
 }
 
-SizeOffsetType ObjectSizeOffsetVisitor::visitPHINode(PHINode&) {
-  // too complex to analyze statically.
-  return unknown();
-}
+SizeOffsetType ObjectSizeOffsetVisitor::combineSizeOffset(SizeOffsetType LHS,
+                                                          SizeOffsetType RHS) {
+  if (!bothKnown(LHS) || !bothKnown(RHS))
+    return unknown();
 
-SizeOffsetType ObjectSizeOffsetVisitor::visitSelectInst(SelectInst &I) {
-  SizeOffsetType TrueSide  = compute(I.getTrueValue());
-  SizeOffsetType FalseSide = compute(I.getFalseValue());
-  if (bothKnown(TrueSide) && bothKnown(FalseSide)) {
-    if (TrueSide == FalseSide) {
-        return TrueSide;
-    }
+  switch (Options.EvalMode) {
+  case ObjectSizeOpts::Mode::Min:
+    return (getSizeWithOverflow(LHS).slt(getSizeWithOverflow(RHS))) ? LHS : RHS;
+  case ObjectSizeOpts::Mode::Max:
+    return (getSizeWithOverflow(LHS).sgt(getSizeWithOverflow(RHS))) ? LHS : RHS;
+  case ObjectSizeOpts::Mode::Exact:
+    return (getSizeWithOverflow(LHS).eq(getSizeWithOverflow(RHS))) ? LHS
+                                                                   : unknown();
+  }
+  llvm_unreachable("missing an eval mode");
+}
 
-    APInt TrueResult = getSizeWithOverflow(TrueSide);
-    APInt FalseResult = getSizeWithOverflow(FalseSide);
+SizeOffsetType ObjectSizeOffsetVisitor::visitPHINode(PHINode &PN) {
+  auto IncomingValues = PN.incoming_values();
+  return std::accumulate(IncomingValues.begin() + 1, IncomingValues.end(),
+                         compute(*IncomingValues.begin()),
+                         [this](SizeOffsetType LHS, Value *VRHS) {
+                           return combineSizeOffset(LHS, compute(VRHS));
+                         });
+}
 
-    if (TrueResult == FalseResult) {
-      return TrueSide;
-    }
-    if (Options.EvalMode == ObjectSizeOpts::Mode::Min) {
-      if (TrueResult.slt(FalseResult))
-        return TrueSide;
-      return FalseSide;
-    }
-    if (Options.EvalMode == ObjectSizeOpts::Mode::Max) {
-      if (TrueResult.sgt(FalseResult))
-        return TrueSide;
-      return FalseSide;
-    }
-  }
-  return unknown();
+SizeOffsetType ObjectSizeOffsetVisitor::visitSelectInst(SelectInst &I) {
+  return combineSizeOffset(compute(I.getTrueValue()),
+                           compute(I.getFalseValue()));
 }
 
 SizeOffsetType ObjectSizeOffsetVisitor::visitUndefValue(UndefValue&) {

diff  --git a/llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll b/llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll
new file mode 100644
index 0000000000000..a31a1970ee2c5
--- /dev/null
+++ b/llvm/test/Transforms/LowerConstantIntrinsics/builtin-object-size-phi.ll
@@ -0,0 +1,63 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -lower-constant-intrinsics  -S < %s | FileCheck %s
+
+
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+declare dso_local noalias noundef i8* @malloc(i64 noundef) local_unnamed_addr
+declare i64 @llvm.objectsize.i64.p0i8(i8*, i1 immarg, i1 immarg, i1 immarg)
+
+ at buffer = dso_local global [4 x i8] zeroinitializer, align 1
+
+define dso_local i64 @pick_max(i32 noundef %n) local_unnamed_addr {
+; CHECK-LABEL: @pick_max(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0
+; CHECK-NEXT:    br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.else:
+; CHECK-NEXT:    [[MALLOCED:%.*]] = call noalias dereferenceable_or_null(8) i8* @malloc(i64 noundef 8)
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[P:%.*]] = phi i8* [ [[MALLOCED]], [[IF_ELSE]] ], [ getelementptr inbounds ([4 x i8], [4 x i8]* @buffer, i64 0, i64 0), [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret i64 8
+;
+entry:
+  %cond = icmp eq i32 %n, 0
+  br i1 %cond, label %if.else, label %if.end
+
+if.else:
+  %malloced = call noalias dereferenceable_or_null(8) i8* @malloc(i64 noundef 8)
+  br label %if.end
+
+if.end:
+  %p = phi i8* [ %malloced, %if.else ], [ getelementptr inbounds ([4 x i8], [4 x i8]* @buffer, i64 0, i64 0), %entry ]
+  %size = call i64 @llvm.objectsize.i64.p0i8(i8* %p, i1 false, i1 true, i1 false)
+  ret i64 %size
+}
+
+define dso_local i64 @pick_min(i32 noundef %n) local_unnamed_addr {
+; CHECK-LABEL: @pick_min(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[COND:%.*]] = icmp eq i32 [[N:%.*]], 0
+; CHECK-NEXT:    br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_END:%.*]]
+; CHECK:       if.else:
+; CHECK-NEXT:    [[MALLOCED:%.*]] = call noalias dereferenceable_or_null(8) i8* @malloc(i64 noundef 8)
+; CHECK-NEXT:    br label [[IF_END]]
+; CHECK:       if.end:
+; CHECK-NEXT:    [[P:%.*]] = phi i8* [ [[MALLOCED]], [[IF_ELSE]] ], [ getelementptr inbounds ([4 x i8], [4 x i8]* @buffer, i64 0, i64 0), [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret i64 4
+;
+entry:
+  %cond = icmp eq i32 %n, 0
+  br i1 %cond, label %if.else, label %if.end
+
+if.else:
+  %malloced = call noalias dereferenceable_or_null(8) i8* @malloc(i64 noundef 8)
+  br label %if.end
+
+if.end:
+  %p = phi i8* [ %malloced, %if.else ], [ getelementptr inbounds ([4 x i8], [4 x i8]* @buffer, i64 0, i64 0), %entry ]
+  %size = call i64 @llvm.objectsize.i64.p0i8(i8* %p, i1 true, i1 true, i1 false)
+  ret i64 %size
+}


        


More information about the llvm-commits mailing list