"@string = constant i8 0" is a value i8* string of length zero. Analyze that
authorNick Lewycky <nicholas@mxc.ca>
Thu, 20 Oct 2011 00:34:35 +0000 (00:34 +0000)
committerNick Lewycky <nicholas@mxc.ca>
Thu, 20 Oct 2011 00:34:35 +0000 (00:34 +0000)
correctly in GetStringLength, fixing PR11181!

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

lib/Analysis/ValueTracking.cpp
test/Transforms/SimplifyLibCalls/StrLen.ll

index 4d94f619fda15457c8b398abab5b25f0d83fe56c..e80ee65abde89c7e980d62a9262f66b43dfb4c69 100644 (file)
@@ -1525,8 +1525,7 @@ Value *llvm::GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset,
 /// null-terminated C string pointed to by V.  If successful, it returns true
 /// and returns the string in Str.  If unsuccessful, it returns false.
 bool llvm::GetConstantStringInfo(const Value *V, std::string &Str,
-                                 uint64_t Offset,
-                                 bool StopAtNul) {
+                                 uint64_t Offset, bool StopAtNul) {
   // If V is NULL then return false;
   if (V == NULL) return false;
 
@@ -1536,7 +1535,7 @@ bool llvm::GetConstantStringInfo(const Value *V, std::string &Str,
   
   // If the value is not a GEP instruction nor a constant expression with a
   // GEP instruction, then return false because ConstantArray can't occur
-  // any other way
+  // any other way.
   const User *GEP = 0;
   if (const GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(V)) {
     GEP = GEPI;
@@ -1576,7 +1575,7 @@ bool llvm::GetConstantStringInfo(const Value *V, std::string &Str,
     return GetConstantStringInfo(GEP->getOperand(0), Str, StartIdx+Offset,
                                  StopAtNul);
   }
-  
+
   // The GEP instruction, constant or instruction, must reference a global
   // variable that is a constant and is initialized. The referenced constant
   // initializer is the array that we'll use for optimization.
@@ -1585,8 +1584,8 @@ bool llvm::GetConstantStringInfo(const Value *V, std::string &Str,
     return false;
   const Constant *GlobalInit = GV->getInitializer();
   
-  // Handle the ConstantAggregateZero case
-  if (isa<ConstantAggregateZero>(GlobalInit)) {
+  // Handle the all-zeros case
+  if (GlobalInit->isNullValue()) {
     // This is a degenerate case. The initializer is constant zero so the
     // length of the string must be zero.
     Str.clear();
@@ -1667,6 +1666,14 @@ static uint64_t GetStringLengthH(Value *V, SmallPtrSet<PHINode*, 32> &PHIs) {
     return Len1;
   }
 
+  // As a special-case, "@string = constant i8 0" is also a string with zero
+  // length, not wrapped in a bitcast or GEP.
+  if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
+    if (GV->isConstant() && GV->hasDefinitiveInitializer())
+      if (GV->getInitializer()->isNullValue()) return 1;
+    return 0;
+  }
+
   // If the value is not a GEP instruction nor a constant expression with a
   // GEP instruction, then return unknown.
   User *GEP = 0;
index 45b349d6840db72331b3d0e0565c3536992c0867..acd8aaf6e543ded760d6c7e8385322c3523fbe87 100644 (file)
@@ -6,6 +6,7 @@ target datalayout = "e-p:32:32"
 @hello = constant [6 x i8] c"hello\00"         ; <[6 x i8]*> [#uses=3]
 @null = constant [1 x i8] zeroinitializer              ; <[1 x i8]*> [#uses=3]
 @null_hello = constant [7 x i8] c"\00hello\00"         ; <[7 x i8]*> [#uses=1]
+@nullstring = constant i8 0
 
 declare i32 @strlen(i8*)
 
@@ -54,3 +55,8 @@ define i1 @test7() {
        %ne_null = icmp ne i32 %null_l, 0               ; <i1> [#uses=1]
        ret i1 %ne_null
 }
+
+define i32 @test8() {
+       %len = tail call i32 @strlen(i8* @nullstring) nounwind
+       ret i32 %len
+}