cmd/internal/gc: Use shifts for powers-of-two indexing
Fixes #10638
Change-Id: I7bbaad7e5a599aa94d1d158e903596231c7e9897
Reviewed-on: https://go-review.googlesource.com/9535
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
diff --git a/src/cmd/internal/gc/cgen.go b/src/cmd/internal/gc/cgen.go
index 15dca37..501cdcb 100644
--- a/src/cmd/internal/gc/cgen.go
+++ b/src/cmd/internal/gc/cgen.go
@@ -1132,12 +1132,18 @@
} else if w == 1 {
Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &n2, &n3)
} else {
- Regalloc(&n4, Types[TUINT32], nil)
- Nodconst(&n1, Types[TUINT32], int64(w))
- Thearch.Gmove(&n1, &n4)
- Thearch.Gins(Thearch.Optoas(OMUL, Types[TUINT32]), &n4, &n2)
+ if w&(w-1) == 0 {
+ // Power of 2. Use shift.
+ Thearch.Ginscon(Thearch.Optoas(OLSH, Types[TUINT32]), int64(log2(uint64(w))), &n2)
+ } else {
+ // Not a power of 2. Use multiply.
+ Regalloc(&n4, Types[TUINT32], nil)
+ Nodconst(&n1, Types[TUINT32], int64(w))
+ Thearch.Gmove(&n1, &n4)
+ Thearch.Gins(Thearch.Optoas(OMUL, Types[TUINT32]), &n4, &n2)
+ Regfree(&n4)
+ }
Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &n2, &n3)
- Regfree(&n4)
}
*a = n3
Regfree(&n2)
@@ -1292,8 +1298,13 @@
} else if w == 1 {
Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &n2, &n3)
} else {
- Nodconst(&tmp, Types[TUINT32], int64(w))
- Thearch.Gins(Thearch.Optoas(OMUL, Types[TUINT32]), &tmp, &n2)
+ if w&(w-1) == 0 {
+ // Power of 2. Use shift.
+ Thearch.Ginscon(Thearch.Optoas(OLSH, Types[TUINT32]), int64(log2(uint64(w))), &n2)
+ } else {
+ // Not a power of 2. Use multiply.
+ Thearch.Ginscon(Thearch.Optoas(OMUL, Types[TUINT32]), int64(w), &n2)
+ }
Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &n2, &n3)
}
@@ -1485,7 +1496,13 @@
} else if w == 1 {
Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &n2, &n3)
} else {
- Thearch.Ginscon(Thearch.Optoas(OMUL, t), int64(w), &n2)
+ if w&(w-1) == 0 {
+ // Power of 2. Use shift.
+ Thearch.Ginscon(Thearch.Optoas(OLSH, t), int64(log2(w)), &n2)
+ } else {
+ // Not a power of 2. Use multiply.
+ Thearch.Ginscon(Thearch.Optoas(OMUL, t), int64(w), &n2)
+ }
Thearch.Gins(Thearch.Optoas(OADD, Types[Tptr]), &n2, &n3)
}
@@ -1502,6 +1519,15 @@
}
}
+// log2 returns the logarithm base 2 of n. n must be a power of 2.
+func log2(n uint64) int {
+ x := 0
+ for n>>uint(x) != 1 {
+ x++
+ }
+ return x
+}
+
/*
* generate:
* res = &n;