Skip to content

Commit

Permalink
cmd/internal/gc: Use shifts for powers-of-two indexing
Browse files Browse the repository at this point in the history
Fixes golang#10638

Change-Id: I7bbaad7e5a599aa94d1d158e903596231c7e9897
Reviewed-on: https://go-review.googlesource.com/9535
Reviewed-by: Josh Bleecher Snyder <[email protected]>
  • Loading branch information
randall77 committed May 5, 2015
1 parent 71274e4 commit 135389d
Showing 1 changed file with 34 additions and 8 deletions.
42 changes: 34 additions & 8 deletions src/cmd/internal/gc/cgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -1132,12 +1132,18 @@ func Agenr(n *Node, a *Node, res *Node) {
} 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)
Expand Down Expand Up @@ -1292,8 +1298,13 @@ func Agenr(n *Node, a *Node, res *Node) {
} 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)
}

Expand Down Expand Up @@ -1485,7 +1496,13 @@ func Agenr(n *Node, a *Node, res *Node) {
} 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)
}

Expand All @@ -1502,6 +1519,15 @@ func Agenr(n *Node, a *Node, res *Node) {
}
}

// 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;
Expand Down

0 comments on commit 135389d

Please sign in to comment.