regexp: don't allocate when All methods find no matches

name                old time/op    new time/op    delta
FindAllNoMatches-8     216ns ± 3%     122ns ± 2%   -43.52%  (p=0.000 n=10+10)

name                old alloc/op   new alloc/op   delta
FindAllNoMatches-8      240B ± 0%        0B       -100.00%  (p=0.000 n=10+10)

name                old allocs/op  new allocs/op  delta
FindAllNoMatches-8      1.00 ± 0%      0.00       -100.00%  (p=0.000 n=10+10)

This work was supported by Sourcegraph.

Change-Id: I30aac201370ccfb40a6ff637402020ac20f61f70
Reviewed-on: https://go-review.googlesource.com/87418
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/regexp/all_test.go b/src/regexp/all_test.go
index 28fe20c..0fabeae 100644
--- a/src/regexp/all_test.go
+++ b/src/regexp/all_test.go
@@ -581,6 +581,19 @@
 	}
 }
 
+func BenchmarkFindAllNoMatches(b *testing.B) {
+	re := MustCompile("a+b+")
+	s := []byte("acddee")
+	b.ReportAllocs()
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		all := re.FindAll(s, -1)
+		if all != nil {
+			b.Fatalf("FindAll(%q) = %q; want nil", s, all)
+		}
+	}
+}
+
 func BenchmarkFindString(b *testing.B) {
 	b.StopTimer()
 	re := MustCompile("a+b+")
diff --git a/src/regexp/regexp.go b/src/regexp/regexp.go
index b1af23e..023920c 100644
--- a/src/regexp/regexp.go
+++ b/src/regexp/regexp.go
@@ -984,13 +984,13 @@
 	if n < 0 {
 		n = len(b) + 1
 	}
-	result := make([][]byte, 0, startSize)
+	var result [][]byte
 	re.allMatches("", b, n, func(match []int) {
+		if result == nil {
+			result = make([][]byte, 0, startSize)
+		}
 		result = append(result, b[match[0]:match[1]])
 	})
-	if len(result) == 0 {
-		return nil
-	}
 	return result
 }
 
@@ -1002,13 +1002,13 @@
 	if n < 0 {
 		n = len(b) + 1
 	}
-	result := make([][]int, 0, startSize)
+	var result [][]int
 	re.allMatches("", b, n, func(match []int) {
+		if result == nil {
+			result = make([][]int, 0, startSize)
+		}
 		result = append(result, match[0:2])
 	})
-	if len(result) == 0 {
-		return nil
-	}
 	return result
 }
 
@@ -1020,13 +1020,13 @@
 	if n < 0 {
 		n = len(s) + 1
 	}
-	result := make([]string, 0, startSize)
+	var result []string
 	re.allMatches(s, nil, n, func(match []int) {
+		if result == nil {
+			result = make([]string, 0, startSize)
+		}
 		result = append(result, s[match[0]:match[1]])
 	})
-	if len(result) == 0 {
-		return nil
-	}
 	return result
 }
 
@@ -1038,13 +1038,13 @@
 	if n < 0 {
 		n = len(s) + 1
 	}
-	result := make([][]int, 0, startSize)
+	var result [][]int
 	re.allMatches(s, nil, n, func(match []int) {
+		if result == nil {
+			result = make([][]int, 0, startSize)
+		}
 		result = append(result, match[0:2])
 	})
-	if len(result) == 0 {
-		return nil
-	}
 	return result
 }
 
@@ -1056,8 +1056,11 @@
 	if n < 0 {
 		n = len(b) + 1
 	}
-	result := make([][][]byte, 0, startSize)
+	var result [][][]byte
 	re.allMatches("", b, n, func(match []int) {
+		if result == nil {
+			result = make([][][]byte, 0, startSize)
+		}
 		slice := make([][]byte, len(match)/2)
 		for j := range slice {
 			if match[2*j] >= 0 {
@@ -1066,9 +1069,6 @@
 		}
 		result = append(result, slice)
 	})
-	if len(result) == 0 {
-		return nil
-	}
 	return result
 }
 
@@ -1080,13 +1080,13 @@
 	if n < 0 {
 		n = len(b) + 1
 	}
-	result := make([][]int, 0, startSize)
+	var result [][]int
 	re.allMatches("", b, n, func(match []int) {
+		if result == nil {
+			result = make([][]int, 0, startSize)
+		}
 		result = append(result, match)
 	})
-	if len(result) == 0 {
-		return nil
-	}
 	return result
 }
 
@@ -1098,8 +1098,11 @@
 	if n < 0 {
 		n = len(s) + 1
 	}
-	result := make([][]string, 0, startSize)
+	var result [][]string
 	re.allMatches(s, nil, n, func(match []int) {
+		if result == nil {
+			result = make([][]string, 0, startSize)
+		}
 		slice := make([]string, len(match)/2)
 		for j := range slice {
 			if match[2*j] >= 0 {
@@ -1108,9 +1111,6 @@
 		}
 		result = append(result, slice)
 	})
-	if len(result) == 0 {
-		return nil
-	}
 	return result
 }
 
@@ -1123,13 +1123,13 @@
 	if n < 0 {
 		n = len(s) + 1
 	}
-	result := make([][]int, 0, startSize)
+	var result [][]int
 	re.allMatches(s, nil, n, func(match []int) {
+		if result == nil {
+			result = make([][]int, 0, startSize)
+		}
 		result = append(result, match)
 	})
-	if len(result) == 0 {
-		return nil
-	}
 	return result
 }