[BasicAA] Remove special casing of memset_pattern16 in favor of generic attribute...
authorPhilip Reames <listmail@philipreames.com>
Wed, 6 Jan 2016 04:53:16 +0000 (04:53 +0000)
committerPhilip Reames <listmail@philipreames.com>
Wed, 6 Jan 2016 04:53:16 +0000 (04:53 +0000)
Most of the properties of memset_pattern16 can be now covered by the generic attributes and inferred by InferFunctionAttrs.  The only exceptions are:
- We don't yet have a writeonly attribute for the first argument.
- We don't have an attribute for modeling the access size facts encoded in MemoryLocation.cpp.

Differential Revision: http://reviews.llvm.org/D15879

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@256911 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/BasicAliasAnalysis.cpp
lib/Transforms/IPO/InferFunctionAttrs.cpp
test/Analysis/BasicAA/memset_pattern.ll
test/Transforms/InferFunctionAttrs/annotate.ll

index ace596dc5f6268b3f784b9a2780f62497612b501..85404d87a611eb7ed4581053a6d595335ea9b235 100644 (file)
@@ -543,7 +543,6 @@ static bool isMemsetPattern16(const Function *MS,
         isa<IntegerType>(MemsetType->getParamType(2)))
       return true;
   }
         isa<IntegerType>(MemsetType->getParamType(2)))
       return true;
   }
-
   return false;
 }
 
   return false;
 }
 
@@ -583,9 +582,6 @@ FunctionModRefBehavior BasicAAResult::getModRefBehavior(const Function *F) {
   if (F->onlyAccessesArgMemory())
     Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesArgumentPointees);
 
   if (F->onlyAccessesArgMemory())
     Min = FunctionModRefBehavior(Min & FMRB_OnlyAccessesArgumentPointees);
 
-  if (isMemsetPattern16(F, TLI))
-    Min = FMRB_OnlyAccessesArgumentPointees;
-
   // Otherwise be conservative.
   return FunctionModRefBehavior(AAResultBase::getModRefBehavior(F) & Min);
 }
   // Otherwise be conservative.
   return FunctionModRefBehavior(AAResultBase::getModRefBehavior(F) & Min);
 }
@@ -609,14 +605,11 @@ ModRefInfo BasicAAResult::getArgModRefInfo(ImmutableCallSite CS,
   // We can bound the aliasing properties of memset_pattern16 just as we can
   // for memcpy/memset.  This is particularly important because the
   // LoopIdiomRecognizer likes to turn loops into calls to memset_pattern16
   // We can bound the aliasing properties of memset_pattern16 just as we can
   // for memcpy/memset.  This is particularly important because the
   // LoopIdiomRecognizer likes to turn loops into calls to memset_pattern16
-  // whenever possible.
-  if (CS.getCalledFunction() &&
-      isMemsetPattern16(CS.getCalledFunction(), TLI)) {
-    assert((ArgIdx == 0 || ArgIdx == 1) &&
-           "Invalid argument index for memset_pattern16");
-    return ArgIdx ? MRI_Ref : MRI_Mod;
-  }
-  // FIXME: Handle memset_pattern4 and memset_pattern8 also.
+  // whenever possible.  Note that all but the missing writeonly attribute are
+  // handled via InferFunctionAttr.
+  if (CS.getCalledFunction() && isMemsetPattern16(CS.getCalledFunction(), TLI))
+    if (ArgIdx == 0)
+      return MRI_Mod;
 
   if (CS.paramHasAttr(ArgIdx + 1, Attribute::ReadOnly))
     return MRI_Ref;
 
   if (CS.paramHasAttr(ArgIdx + 1, Attribute::ReadOnly))
     return MRI_Ref;
index 0f0182ef92be9e6270776554cd1c3325366bd837..4295a7595c29f3952c6caaa1917d30b96cf1e0e1 100644 (file)
@@ -22,6 +22,7 @@ using namespace llvm;
 
 STATISTIC(NumReadNone, "Number of functions inferred as readnone");
 STATISTIC(NumReadOnly, "Number of functions inferred as readonly");
 
 STATISTIC(NumReadNone, "Number of functions inferred as readnone");
 STATISTIC(NumReadOnly, "Number of functions inferred as readonly");
+STATISTIC(NumArgMemOnly, "Number of functions inferred as argmemonly");
 STATISTIC(NumNoUnwind, "Number of functions inferred as nounwind");
 STATISTIC(NumNoCapture, "Number of arguments inferred as nocapture");
 STATISTIC(NumReadOnlyArg, "Number of arguments inferred as readonly");
 STATISTIC(NumNoUnwind, "Number of functions inferred as nounwind");
 STATISTIC(NumNoCapture, "Number of arguments inferred as nocapture");
 STATISTIC(NumReadOnlyArg, "Number of arguments inferred as readonly");
@@ -44,6 +45,15 @@ static bool setOnlyReadsMemory(Function &F) {
   return true;
 }
 
   return true;
 }
 
+static bool setOnlyAccessesArgMemory(Function &F) {
+  if (F.onlyAccessesArgMemory())
+    return false;
+  F.setOnlyAccessesArgMemory ();
+  ++NumArgMemOnly;
+  return true;
+}
+
+
 static bool setDoesNotThrow(Function &F) {
   if (F.doesNotThrow())
     return false;
 static bool setDoesNotThrow(Function &F) {
   if (F.doesNotThrow())
     return false;
@@ -900,6 +910,20 @@ static bool inferPrototypeAttributes(Function &F,
     Changed |= setDoesNotAlias(F, AttributeSet::ReturnIndex);
     return Changed;
 
     Changed |= setDoesNotAlias(F, AttributeSet::ReturnIndex);
     return Changed;
 
+  //TODO: add LibFunc entries for:
+  //case LibFunc::memset_pattern4:
+  //case LibFunc::memset_pattern8:
+  case LibFunc::memset_pattern16:
+    if (FTy->isVarArg() || FTy->getNumParams() != 3 ||
+        !isa<PointerType>(FTy->getParamType(0)) ||
+        !isa<PointerType>(FTy->getParamType(1)) ||
+        !isa<IntegerType>(FTy->getParamType(2)))
+      return false;
+
+    Changed |= setOnlyAccessesArgMemory(F);
+    Changed |= setOnlyReadsMemory(F, 2);
+    return Changed;
+
   default:
     // FIXME: It'd be really nice to cover all the library functions we're
     // aware of here.
   default:
     // FIXME: It'd be really nice to cover all the library functions we're
     // aware of here.
index 25bdb2e202fb7f217e5da32c8263b99585443be1..821cbdf4bb06402fe0e09966b11586871b60b084 100644 (file)
@@ -18,4 +18,4 @@ entry:
   ret i32 %l
 }
 
   ret i32 %l
 }
 
-declare void @memset_pattern16(i8*, i8*, i64)
+declare void @memset_pattern16(i8*, i8* readonly, i64) argmemonly
index 709feb486c2013c6c548542a155a5e6b94bcbf10..1cb7ab137c02195ac6b7d84ffe3fedc5d05b0ddc 100644 (file)
@@ -22,9 +22,14 @@ declare i8* @_Znwj(i64)
 declare i8* @_Znwm(i64)
 ; CHECK: declare noalias nonnull i8* @_Znwm(i64)
 
 declare i8* @_Znwm(i64)
 ; CHECK: declare noalias nonnull i8* @_Znwm(i64)
 
+declare void @memset_pattern16(i8*, i8*, i64)
+; CHECK: declare void @memset_pattern16(i8*, i8*, i64)
+; CHECK-POSIX: declare void @memset_pattern16(i8*, i8* readonly, i64) [[G2:#[0-9]+]]
+
 declare i32 @gettimeofday(i8*, i8*)
 ; CHECK-POSIX: declare i32 @gettimeofday(i8* nocapture, i8* nocapture) [[G0:#[0-9]+]]
 
 ; CHECK: attributes [[G0]] = { nounwind }
 ; CHECK: attributes [[G1]] = { nounwind readonly }
 ; CHECK-POSIX: attributes [[G0]] = { nounwind }
 declare i32 @gettimeofday(i8*, i8*)
 ; CHECK-POSIX: declare i32 @gettimeofday(i8* nocapture, i8* nocapture) [[G0:#[0-9]+]]
 
 ; CHECK: attributes [[G0]] = { nounwind }
 ; CHECK: attributes [[G1]] = { nounwind readonly }
 ; CHECK-POSIX: attributes [[G0]] = { nounwind }
+; CHECK-POSIX: attributes [[G2]] = { argmemonly }