Skip to content

Commit 7d0cb2a

Browse files
committed
cmd/compile: constant fold 128-bit multiplies
The full 64x64->128 multiply comes up when using bits.Mul64. The 64x64->64+overflow multiply comes up in unsafe.Slice when using a constant length. Change-Id: I298515162ca07d804b2d699d03bc957ca30a4ebc Reviewed-on: https://go-review.googlesource.com/c/go/+/667175 Reviewed-by: Junyang Shao <[email protected]> Reviewed-by: Keith Randall <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 7a17711 commit 7d0cb2a

File tree

4 files changed

+138
-1
lines changed

4 files changed

+138
-1
lines changed

src/cmd/compile/internal/ssa/_gen/generic.rules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@
139139
(Mul64 (Const64 [c]) (Const64 [d])) => (Const64 [c*d])
140140
(Mul32F (Const32F [c]) (Const32F [d])) && c*d == c*d => (Const32F [c*d])
141141
(Mul64F (Const64F [c]) (Const64F [d])) && c*d == c*d => (Const64F [c*d])
142+
(Mul32uhilo (Const32 [c]) (Const32 [d])) => (MakeTuple (Const32 <typ.UInt32> [bitsMulU32(c, d).hi]) (Const32 <typ.UInt32> [bitsMulU32(c,d).lo]))
143+
(Mul64uhilo (Const64 [c]) (Const64 [d])) => (MakeTuple (Const64 <typ.UInt64> [bitsMulU64(c, d).hi]) (Const64 <typ.UInt64> [bitsMulU64(c,d).lo]))
144+
(Mul32uover (Const32 [c]) (Const32 [d])) => (MakeTuple (Const32 <typ.UInt32> [bitsMulU32(c, d).lo]) (ConstBool <typ.Bool> [bitsMulU32(c,d).hi != 0]))
145+
(Mul64uover (Const64 [c]) (Const64 [d])) => (MakeTuple (Const64 <typ.UInt64> [bitsMulU64(c, d).lo]) (ConstBool <typ.Bool> [bitsMulU64(c,d).hi != 0]))
142146

143147
(And8 (Const8 [c]) (Const8 [d])) => (Const8 [c&d])
144148
(And16 (Const16 [c]) (Const16 [d])) => (Const16 [c&d])

src/cmd/compile/internal/ssa/rewrite.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2584,3 +2584,14 @@ func bitsAdd64(x, y, carry int64) (r struct{ sum, carry int64 }) {
25842584
r.sum, r.carry = int64(s), int64(c)
25852585
return
25862586
}
2587+
2588+
func bitsMulU64(x, y int64) (r struct{ hi, lo int64 }) {
2589+
hi, lo := bits.Mul64(uint64(x), uint64(y))
2590+
r.hi, r.lo = int64(hi), int64(lo)
2591+
return
2592+
}
2593+
func bitsMulU32(x, y int32) (r struct{ hi, lo int32 }) {
2594+
hi, lo := bits.Mul32(uint32(x), uint32(y))
2595+
r.hi, r.lo = int32(hi), int32(lo)
2596+
return
2597+
}

src/cmd/compile/internal/ssa/rewritegeneric.go

Lines changed: 108 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/codegen/mathbits.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66

77
package codegen
88

9-
import "math/bits"
9+
import (
10+
"math/bits"
11+
"unsafe"
12+
)
1013

1114
// ----------------------- //
1215
// bits.LeadingZeros //
@@ -957,6 +960,17 @@ func Mul64LoOnly(x, y uint64) uint64 {
957960
return lo
958961
}
959962

963+
func Mul64Const() (uint64, uint64) {
964+
// 7133701809754865664 == 99<<56
965+
// arm64:"MOVD\t[$]7133701809754865664, R1", "MOVD\t[$]88, R0"
966+
return bits.Mul64(99+88<<8, 1<<56)
967+
}
968+
969+
func MulUintOverflow(p *uint64) []uint64 {
970+
// arm64:"CMP\t[$]72"
971+
return unsafe.Slice(p, 9)
972+
}
973+
960974
// --------------- //
961975
// bits.Div* //
962976
// --------------- //

0 commit comments

Comments
 (0)