[instsimplify] When compare allocas, consider their minimal size
authorPhilip Reames <listmail@philipreames.com>
Thu, 17 Feb 2022 17:50:32 +0000 (09:50 -0800)
committerPhilip Reames <listmail@philipreames.com>
Thu, 17 Feb 2022 17:53:24 +0000 (09:53 -0800)
The code was using exact sizing only, but since what we really need is just to make sure the offsets are in bounds, a minimum bound on the object size is sufficient.

To demonstrate the difference, support computing minimum sizes from obects of scalable vector type.

llvm/lib/Analysis/InstructionSimplify.cpp
llvm/lib/Analysis/MemoryBuiltins.cpp
llvm/test/Transforms/InstSimplify/compare.ll

index 7d5b62d..35e9314 100644 (file)
@@ -2631,6 +2631,7 @@ computePointerICmp(CmpInst::Predicate Pred, Value *LHS, Value *RHS,
         (isa<AllocaInst>(RHS) || isa<GlobalVariable>(RHS))) {
       uint64_t LHSSize, RHSSize;
       ObjectSizeOpts Opts;
+      Opts.EvalMode = ObjectSizeOpts::Mode::Min;
       Opts.NullIsUnknownSize =
           NullPointerIsDefined(cast<AllocaInst>(LHS)->getFunction());
       if (getObjectSize(LHS, LHSSize, DL, TLI, Opts) &&
index 5dc5665..a52b1a8 100644 (file)
@@ -659,10 +659,10 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitAllocaInst(AllocaInst &I) {
   if (!I.getAllocatedType()->isSized())
     return unknown();
 
-  if (isa<ScalableVectorType>(I.getAllocatedType()))
+  TypeSize ElemSize = DL.getTypeAllocSize(I.getAllocatedType());
+  if (ElemSize.isScalable() && Options.EvalMode != ObjectSizeOpts::Mode::Min)
     return unknown();
-
-  APInt Size(IntTyBits, DL.getTypeAllocSize(I.getAllocatedType()));
+  APInt Size(IntTyBits, ElemSize.getKnownMinSize());
   if (!I.isArrayAllocation())
     return std::make_pair(align(Size, I.getAlign()), Zero);
 
index 7daee2a..25a6c19 100644 (file)
@@ -2727,5 +2727,15 @@ define i1 @zero_sized_alloca2() {
   ret i1 %res
 }
 
+define i1 @scalar_vectors_are_non_empty() {
+; CHECK-LABEL: @scalar_vectors_are_non_empty(
+; CHECK-NEXT:    ret i1 true
+;
+  %a = alloca <vscale x 2 x i32>
+  %b = alloca <vscale x 2 x i32>
+  %res = icmp ne <vscale x 2 x i32>* %a, %b
+  ret i1 %res
+}
+
 
 attributes #0 = { null_pointer_is_valid }