[StackSafety] Use SCEV to find mem operation length
authorVitaly Buka <vitalybuka@google.com>
Wed, 27 May 2020 06:20:12 +0000 (23:20 -0700)
committerVitaly Buka <vitalybuka@google.com>
Wed, 27 May 2020 06:22:37 +0000 (23:22 -0700)
llvm/lib/Analysis/StackSafetyAnalysis.cpp
llvm/test/Analysis/StackSafetyAnalysis/local.ll
llvm/test/Analysis/StackSafetyAnalysis/memintrin.ll

index f72197e..1581ca8 100644 (file)
@@ -247,9 +247,8 @@ StackSafetyLocalAnalysis::getAccessRange(Value *Addr, Value *Base,
 
 ConstantRange StackSafetyLocalAnalysis::getAccessRange(Value *Addr, Value *Base,
                                                        TypeSize Size) {
-  ConstantRange SizeRange = Size.isScalable()
-                                ? ConstantRange::getFull(PointerSize)
-                                : getRange(0, Size.getFixedSize());
+  ConstantRange SizeRange =
+      Size.isScalable() ? UnknownRange : getRange(0, Size.getFixedSize());
   return getAccessRange(Addr, Base, SizeRange);
 }
 
@@ -262,13 +261,21 @@ ConstantRange StackSafetyLocalAnalysis::getMemIntrinsicAccessRange(
     if (MI->getRawDest() != U)
       return getRange(0, 1);
   }
-  const auto *Len = dyn_cast<ConstantInt>(MI->getLength());
-  // Non-constant size => unsafe. FIXME: try SCEV getRange.
-  if (!Len)
+  auto *CalculationTy = IntegerType::getIntNTy(SE.getContext(), PointerSize);
+  if (!SE.isSCEVable(MI->getLength()->getType()))
     return UnknownRange;
-  ConstantRange AccessRange =
-      getAccessRange(U, Base, getRange(0, Len->getZExtValue()));
-  return AccessRange;
+
+  const SCEV *Expr =
+      SE.getTruncateOrZeroExtend(SE.getSCEV(MI->getLength()), CalculationTy);
+  ConstantRange LenRange = SE.getSignedRange(Expr);
+  assert(!LenRange.isEmptySet());
+  if (LenRange.isSignWrappedSet() || LenRange.isFullSet() ||
+      LenRange.getUpper().isNegative())
+    return UnknownRange;
+  LenRange = LenRange.sextOrTrunc(PointerSize);
+  ConstantRange SizeRange(APInt::getNullValue(PointerSize),
+                          LenRange.getUpper() - 1);
+  return getAccessRange(U, Base, SizeRange);
 }
 
 /// The function analyzes all local uses of Ptr (alloca or argument) and
index 445fb5c..f749dc0 100644 (file)
@@ -362,7 +362,7 @@ define dso_local void @SizeCheck(i32 %sz) {
 ; CHECK-NEXT: args uses:
 ; CHECK-NEXT: sz[]: [0,1){{$}}
 ; CHECK-NEXT: allocas uses:
-; CHECK-NEXT: x1[128]: full-set{{$}}
+; CHECK-NEXT: x1[128]: [0,4294967295){{$}}
 ; CHECK-NOT: ]:
 entry:
   %x1 = alloca [128 x i8], align 16
index 2eea9ea..87c92ac 100644 (file)
@@ -55,7 +55,7 @@ define void @MemsetNonConst(i32 %size) {
 ; CHECK-NEXT: args uses:
 ; CHECK-NEXT: size[]: [0,1){{$}}
 ; CHECK-NEXT: allocas uses:
-; CHECK-NEXT: x[4]: full-set{{$}}
+; CHECK-NEXT: x[4]: [0,4294967295){{$}}
 ; CHECK-NOT: ]:
 entry:
   %x = alloca i32, align 4
@@ -71,7 +71,7 @@ define void @MemsetNonConstInBounds(i1 zeroext %z) {
 ; CHECK-NEXT: args uses:
 ; CHECK-NEXT: z[]: [0,1){{$}}
 ; CHECK-NEXT: allocas uses:
-; CHECK-NEXT: x[4]: full-set{{$}}
+; CHECK-NEXT: x[4]: [0,4294967295){{$}}
 ; CHECK-NOT: ]:
 entry:
   %x = alloca i32, align 4