go/test/codegen/divmod.go
Russ Cox 6e165b4d17 cmd/compile: implement Avg64u, Hmul64, Hmul64u for wasm
This lets us remove useAvg and useHmul from the division rules.
The compiler is simpler and the generated code is faster.

goos: wasip1
goarch: wasm
pkg: internal/strconv
                               │   old.txt   │               new.txt               │
                               │   sec/op    │   sec/op     vs base                │
AppendFloat/Decimal              192.8n ± 1%   194.6n ± 0%   +0.91% (p=0.000 n=10)
AppendFloat/Float                328.6n ± 0%   279.6n ± 0%  -14.93% (p=0.000 n=10)
AppendFloat/Exp                  335.6n ± 1%   289.2n ± 1%  -13.80% (p=0.000 n=10)
AppendFloat/NegExp               336.0n ± 0%   289.1n ± 1%  -13.97% (p=0.000 n=10)
AppendFloat/LongExp              332.4n ± 0%   285.2n ± 1%  -14.20% (p=0.000 n=10)
AppendFloat/Big                  348.2n ± 0%   300.1n ± 0%  -13.83% (p=0.000 n=10)
AppendFloat/BinaryExp            137.4n ± 0%   138.2n ± 0%   +0.55% (p=0.001 n=10)
AppendFloat/32Integer            193.3n ± 1%   196.5n ± 0%   +1.66% (p=0.000 n=10)
AppendFloat/32ExactFraction      283.3n ± 0%   268.9n ± 1%   -5.08% (p=0.000 n=10)
AppendFloat/32Point              279.9n ± 0%   266.5n ± 0%   -4.80% (p=0.000 n=10)
AppendFloat/32Exp                300.1n ± 0%   288.3n ± 1%   -3.90% (p=0.000 n=10)
AppendFloat/32NegExp             288.2n ± 1%   277.9n ± 1%   -3.59% (p=0.000 n=10)
AppendFloat/32Shortest           261.7n ± 0%   250.2n ± 0%   -4.39% (p=0.000 n=10)
AppendFloat/32Fixed8Hard         173.3n ± 1%   158.9n ± 1%   -8.31% (p=0.000 n=10)
AppendFloat/32Fixed9Hard         180.0n ± 0%   167.9n ± 2%   -6.70% (p=0.000 n=10)
AppendFloat/64Fixed1             167.1n ± 0%   149.6n ± 1%  -10.50% (p=0.000 n=10)
AppendFloat/64Fixed2             162.4n ± 1%   146.5n ± 0%   -9.73% (p=0.000 n=10)
AppendFloat/64Fixed2.5           165.5n ± 0%   149.4n ± 1%   -9.70% (p=0.000 n=10)
AppendFloat/64Fixed3             166.4n ± 1%   150.2n ± 0%   -9.74% (p=0.000 n=10)
AppendFloat/64Fixed4             163.7n ± 0%   149.6n ± 1%   -8.62% (p=0.000 n=10)
AppendFloat/64Fixed5Hard         182.8n ± 1%   167.1n ± 1%   -8.61% (p=0.000 n=10)
AppendFloat/64Fixed12            222.2n ± 0%   208.8n ± 0%   -6.05% (p=0.000 n=10)
AppendFloat/64Fixed16            197.6n ± 1%   181.7n ± 0%   -8.02% (p=0.000 n=10)
AppendFloat/64Fixed12Hard        194.5n ± 0%   181.0n ± 0%   -6.99% (p=0.000 n=10)
AppendFloat/64Fixed17Hard        205.1n ± 1%   191.9n ± 0%   -6.44% (p=0.000 n=10)
AppendFloat/64Fixed18Hard        6.269µ ± 0%   6.643µ ± 0%   +5.97% (p=0.000 n=10)
AppendFloat/64FixedF1            211.7n ± 1%   197.0n ± 0%   -6.95% (p=0.000 n=10)
AppendFloat/64FixedF2            189.4n ± 0%   174.2n ± 0%   -8.08% (p=0.000 n=10)
AppendFloat/64FixedF3            169.0n ± 0%   154.9n ± 0%   -8.32% (p=0.000 n=10)
AppendFloat/Slowpath64           321.2n ± 0%   274.2n ± 1%  -14.63% (p=0.000 n=10)
AppendFloat/SlowpathDenormal64   307.4n ± 1%   261.2n ± 0%  -15.03% (p=0.000 n=10)
AppendInt                        3.367µ ± 1%   3.376µ ± 0%        ~ (p=0.517 n=10)
AppendUint                       675.5n ± 0%   676.9n ± 0%        ~ (p=0.196 n=10)
AppendIntSmall                   28.13n ± 1%   28.17n ± 0%   +0.14% (p=0.015 n=10)
AppendUintVarlen/digits=1        20.70n ± 0%   20.51n ± 1%   -0.89% (p=0.018 n=10)
AppendUintVarlen/digits=2        20.43n ± 0%   20.27n ± 0%   -0.81% (p=0.001 n=10)
AppendUintVarlen/digits=3        38.48n ± 0%   37.93n ± 0%   -1.43% (p=0.000 n=10)
AppendUintVarlen/digits=4        41.10n ± 0%   38.78n ± 1%   -5.62% (p=0.000 n=10)
AppendUintVarlen/digits=5        42.25n ± 1%   42.11n ± 0%   -0.32% (p=0.041 n=10)
AppendUintVarlen/digits=6        45.40n ± 1%   43.14n ± 0%   -4.98% (p=0.000 n=10)
AppendUintVarlen/digits=7        46.81n ± 1%   46.03n ± 0%   -1.66% (p=0.000 n=10)
AppendUintVarlen/digits=8        48.88n ± 1%   46.59n ± 1%   -4.68% (p=0.000 n=10)
AppendUintVarlen/digits=9        49.94n ± 2%   49.41n ± 1%   -1.06% (p=0.000 n=10)
AppendUintVarlen/digits=10       57.28n ± 1%   56.92n ± 1%   -0.62% (p=0.045 n=10)
AppendUintVarlen/digits=11       60.09n ± 1%   58.11n ± 2%   -3.30% (p=0.000 n=10)
AppendUintVarlen/digits=12       62.22n ± 0%   61.85n ± 0%   -0.59% (p=0.000 n=10)
AppendUintVarlen/digits=13       64.94n ± 0%   62.92n ± 0%   -3.10% (p=0.000 n=10)
AppendUintVarlen/digits=14       65.42n ± 1%   65.19n ± 1%   -0.34% (p=0.005 n=10)
AppendUintVarlen/digits=15       68.17n ± 0%   66.13n ± 0%   -2.99% (p=0.000 n=10)
AppendUintVarlen/digits=16       70.21n ± 1%   70.09n ± 1%        ~ (p=0.517 n=10)
AppendUintVarlen/digits=17       72.93n ± 0%   70.49n ± 0%   -3.34% (p=0.000 n=10)
AppendUintVarlen/digits=18       73.01n ± 0%   72.75n ± 0%   -0.35% (p=0.000 n=10)
AppendUintVarlen/digits=19       79.27n ± 1%   79.49n ± 1%        ~ (p=0.671 n=10)
AppendUintVarlen/digits=20       82.18n ± 0%   80.43n ± 1%   -2.14% (p=0.000 n=10)
geomean                          143.4n        136.0n        -5.20%


Change-Id: I8245814a0259ad13cf9225f57db8e9fe3d2e4267
Reviewed-on: https://go-review.googlesource.com/c/go/+/717407
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
2025-11-04 11:38:18 -08:00

1200 lines
26 KiB
Go

// asmcheck
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package codegen
// Div and mod rewrites, testing cmd/compile/internal/ssa/_gen/divmod.rules.
// See comments there for "Case 1" etc.
// Convert multiplication by a power of two to a shift.
func mul32_uint8(i uint8) uint8 {
// 386: "SHLL [$]5,"
// arm64: "LSL [$]5,"
return i * 32
}
func mul32_uint16(i uint16) uint16 {
// 386: "SHLL [$]5,"
// arm64: "LSL [$]5,"
return i * 32
}
func mul32_uint32(i uint32) uint32 {
// 386: "SHLL [$]5,"
// arm64: "LSL [$]5,"
return i * 32
}
func mul32_uint64(i uint64) uint64 {
// 386: "SHLL [$]5,"
// 386: "SHRL [$]27,"
// arm64: "LSL [$]5,"
return i * 32
}
func mulNeg32_int8(i int8) int8 {
// 386: "SHLL [$]5,"
// 386: "NEGL"
// arm64: "NEG R[0-9]+<<5,"
return i * -32
}
func mulNeg32_int16(i int16) int16 {
// 386: "SHLL [$]5,"
// 386: "NEGL"
// arm64: "NEG R[0-9]+<<5,"
return i * -32
}
func mulNeg32_int32(i int32) int32 {
// 386: "SHLL [$]5,"
// 386: "NEGL"
// arm64: "NEG R[0-9]+<<5,"
return i * -32
}
func mulNeg32_int64(i int64) int64 {
// 386: "SHLL [$]5,"
// 386: "SHRL [$]27,"
// 386: "SBBL"
// arm64: "NEG R[0-9]+<<5,"
return i * -32
}
// Signed divide by power of 2.
func div32_int8(i int8) int8 {
// 386: "SARB [$]7,"
// 386: "SHRB [$]3,"
// 386: "ADDL"
// 386: "SARB [$]5,"
// arm64: "SBFX [$]7, R[0-9]+, [$]1,"
// arm64: "ADD R[0-9]+>>3,"
// arm64: "SBFX [$]5, R[0-9]+, [$]3,"
return i / 32
}
func div32_int16(i int16) int16 {
// 386: "SARW [$]15,"
// 386: "SHRW [$]11,"
// 386: "ADDL"
// 386: "SARW [$]5,"
// arm64: "SBFX [$]15, R[0-9]+, [$]1,"
// arm64: "ADD R[0-9]+>>11,"
// arm64: "SBFX [$]5, R[0-9]+, [$]11,"
return i / 32
}
func div32_int32(i int32) int32 {
// 386: "SARL [$]31,"
// 386: "SHRL [$]27,"
// 386: "ADDL"
// 386: "SARL [$]5,"
// arm64: "SBFX [$]31, R[0-9]+, [$]1,"
// arm64: "ADD R[0-9]+>>27,"
// arm64: "SBFX [$]5, R[0-9]+, [$]27,"
return i / 32
}
func div32_int64(i int64) int64 {
// 386: "SARL [$]31,"
// 386: "SHRL [$]27,"
// 386: "ADDL"
// 386: "SARL [$]5,"
// 386: "SHRL [$]5,"
// 386: "SHLL [$]27,"
// arm64: "ASR [$]63,"
// arm64: "ADD R[0-9]+>>59,"
// arm64: "ASR [$]5,"
return i / 32
}
// Case 1. Signed divides where 2N ≤ register size.
func div7_int8(i int8) int8 {
// 386: "SARL [$]31,"
// 386: "IMUL3L [$]147,"
// 386: "SARL [$]10,"
// 386: "SUBL"
// arm64: "MOVD [$]147,"
// arm64: "MULW"
// arm64: "SBFX [$]10, R[0-9]+, [$]22,"
// arm64: "SUB R[0-9]+->31,"
// wasm: "I64Const [$]147"
return i / 7
}
func div7_int16(i int16) int16 {
// 386: "SARL [$]31,"
// 386: "IMUL3L [$]37450,"
// 386: "SARL [$]18,"
// 386: "SUBL"
// arm64: "MOVD [$]37450,"
// arm64: "MULW"
// arm64: "SBFX [$]18, R[0-9]+, [$]14,"
// arm64: "SUB R[0-9]+->31,"
// wasm: "I64Const [$]37450"
return i / 7
}
func div7_int32(i int32) int32 {
// 64-bit only
// arm64: "MOVD [$]2454267027,"
// arm64: "MUL "
// arm64: "ASR [$]34,"
// arm64: "SUB R[0-9]+->63,"
// wasm: "I64Const [$]2454267027"
return i / 7
}
// Case 2. Signed divides where m is even.
func div9_int32(i int32) int32 {
// 386: "SARL [$]31,"
// 386: "MOVL [$]1908874354,"
// 386: "IMULL"
// 386: "SARL [$]2,"
// 386: "SUBL"
// arm64: "MOVD [$]3817748708,"
// arm64: "MUL "
// arm64: "ASR [$]35,"
// arm64: "SUB R[0-9]+->63,"
// wasm: "I64Const [$]3817748708"
return i / 9
}
func div7_int64(i int64) int64 {
// 64-bit only
// arm64 MOVD $5270498306774157605, SMULH, ASR $1, SUB ->63
// arm64: "MOVD [$]5270498306774157605,"
// arm64: "SMULH"
// arm64: "ASR [$]1,"
// arm64: "SUB R[0-9]+->63,"
// wasm: "I64Const [$]613566757"
// wasm: "I64Const [$]1227133513"
return i / 7
}
// Case 3. Signed divides where m is odd.
func div3_int32(i int32) int32 {
// 386: "SARL [$]31,"
// 386: "MOVL [$]-1431655765,"
// 386: "IMULL"
// 386: "SARL [$]1,"
// 386: "SUBL"
// arm64: "MOVD [$]2863311531,"
// arm64: "MUL"
// arm64: "ASR [$]33,"
// arm64: "SUB R[0-9]+->63,"
// wasm: "I64Const [$]2863311531"
return i / 3
}
func div3_int64(i int64) int64 {
// 64-bit only
// arm64: "MOVD [$]-6148914691236517205,"
// arm64: "SMULH"
// arm64: "ADD"
// arm64: "ASR [$]1,"
// arm64: "SUB R[0-9]+->63,"
// wasm: "I64Const [$]-1431655766"
// wasm: "I64Const [$]2863311531"
return i / 3
}
// Case 4. Unsigned divide where x < 1<<(N-1).
func div7_int16u(i int16) int16 {
if i < 0 {
return 0
}
// 386: "IMUL3L [$]37450,"
// 386: "SHRL [$]18,"
// 386: -"SUBL"
// arm64: "MOVD [$]37450,"
// arm64: "MULW"
// arm64: "UBFX [$]18, R[0-9]+, [$]14,"
// arm64: -"SUB"
// wasm: "I64Const [$]37450"
// wasm -"I64Sub"
return i / 7
}
func div7_int32u(i int32) int32 {
if i < 0 {
return 0
}
// 386: "MOVL [$]-1840700269,"
// 386: "MULL"
// 386: "SHRL [$]2"
// 386: -"SUBL"
// arm64: "MOVD [$]2454267027,"
// arm64: "MUL"
// arm64: "LSR [$]34,"
// arm64: -"SUB"
// wasm: "I64Const [$]2454267027"
// wasm -"I64Sub"
return i / 7
}
func div7_int64u(i int64) int64 {
// 64-bit only
if i < 0 {
return 0
}
// arm64: "MOVD [$]-7905747460161236406,"
// arm64: "UMULH"
// arm64: "LSR [$]2,"
// arm64: -"SUB"
// wasm: "I64Const [$]1227133514"
// wasm: "I64Const [$]2454267026"
// wasm -"I64Sub"
return i / 7
}
// Case 5. Unsigned divide where 2N+1 ≤ register size.
func div7_uint8(i uint8) uint8 {
// 386: "IMUL3L [$]293,"
// 386: "SHRL [$]11,"
// arm64: "MOVD [$]293,"
// arm64: "MULW"
// arm64: "UBFX [$]11, R[0-9]+, [$]21,"
// wasm: "I64Const [$]293"
return i / 7
}
func div7_uint16(i uint16) uint16 {
// only 64-bit
// arm64: "MOVD [$]74899,"
// arm64: "MUL"
// arm64: "LSR [$]19,"
// wasm: "I64Const [$]74899"
return i / 7
}
// Case 6. Unsigned divide where m is even.
func div3_uint16(i uint16) uint16 {
// 386: "IMUL3L [$]43691," "SHRL [$]17,"
// arm64: "MOVD [$]87382,"
// arm64: "MUL"
// arm64: "LSR [$]18,"
// wasm: "I64Const [$]87382"
return i / 3
}
func div3_uint32(i uint32) uint32 {
// 386: "MOVL [$]-1431655765," "MULL", "SHRL [$]1,"
// arm64: "MOVD [$]2863311531,"
// arm64: "MUL"
// arm64: "LSR [$]33,"
// wasm: "I64Const [$]2863311531"
return i / 3
}
func div3_uint64(i uint64) uint64 {
// 386: "MOVL [$]-1431655766"
// 386: "MULL"
// 386: "SHRL [$]1"
// 386 -".*CALL"
// arm64: "MOVD [$]-6148914691236517205,"
// arm64: "UMULH"
// arm64: "LSR [$]1,"
// wasm: "I64Const [$]2863311530"
// wasm: "I64Const [$]2863311531"
return i / 3
}
// Case 7. Unsigned divide where c is even.
func div14_uint16(i uint16) uint16 {
// 32-bit only
// 386: "SHRL [$]1,"
// 386: "IMUL3L [$]37450,"
// 386: "SHRL [$]18,"
return i / 14
}
func div14_uint32(i uint32) uint32 {
// 386: "SHRL [$]1,"
// 386: "MOVL [$]-1840700269,"
// 386: "SHRL [$]2,"
// arm64: "UBFX [$]1, R[0-9]+, [$]31,"
// arm64: "MOVD [$]2454267027,"
// arm64: "MUL"
// arm64: "LSR [$]34,"
// wasm: "I64Const [$]2454267027"
return i / 14
}
func div14_uint64(i uint64) uint64 {
// 386: "MOVL [$]-1840700270,"
// 386: "MULL"
// 386: "SHRL [$]2,"
// 386: -".*CALL"
// arm64: "MOVD [$]-7905747460161236406,"
// arm64: "UMULH"
// arm64: "LSR [$]2,"
// wasm: "I64Const [$]1227133514"
// wasm: "I64Const [$]2454267026"
return i / 14
}
// Case 8. Unsigned divide on systems with avg.
func div7_uint16a(i uint16) uint16 {
// only 32-bit
// 386: "SHLL [$]16,"
// 386: "IMUL3L [$]9363,"
// 386: "ADDL"
// 386: "RCRL [$]1,"
// 386: "SHRL [$]18,"
return i / 7
}
func div7_uint32(i uint32) uint32 {
// 386: "MOVL [$]613566757,"
// 386: "MULL"
// 386: "ADDL"
// 386: "RCRL [$]1,"
// 386: "SHRL [$]2,"
// arm64: "UBFIZ [$]32, R[0-9]+, [$]32,"
// arm64: "MOVD [$]613566757,"
// arm64: "MUL"
// arm64: "SUB"
// arm64: "ADD R[0-9]+>>1,"
// arm64: "LSR [$]34,"
// wasm: "I64Const [$]613566757"
return i / 7
}
func div7_uint64(i uint64) uint64 {
// 386: "MOVL [$]-1840700269,"
// 386: "MULL"
// 386: "SHRL [$]2,"
// 386: -".*CALL"
// arm64: "MOVD [$]2635249153387078803,"
// arm64: "UMULH"
// arm64: "SUB",
// arm64: "ADD R[0-9]+>>1,"
// arm64: "LSR [$]2,"
// wasm: "I64Const [$]613566756"
// wasm: "I64Const [$]2454267027"
return i / 7
}
func div12345_uint64(i uint64) uint64 {
// 386: "MOVL [$]-1444876402,"
// 386: "MOVL [$]835683390,"
// 386: "MULL"
// 386: "SHRL [$]13,"
// 386: "SHLL [$]19,"
// arm64: "MOVD [$]-6205696892516465602,"
// arm64: "UMULH"
// arm64: "LSR [$]13,"
// wasm: "I64Const [$]835683390"
// wasm: "I64Const [$]2850090894"
return i / 12345
}
// Divisibility and non-divisibility by power of two.
func divis32_uint8(i uint8) bool {
// 386: "TESTB [$]31,"
// arm64: "TSTW [$]31,"
return i%32 == 0
}
func ndivis32_uint8(i uint8) bool {
// 386: "TESTB [$]31,"
// arm64: "TSTW [$]31,"
return i%32 != 0
}
func divis32_uint16(i uint16) bool {
// 386: "TESTW [$]31,"
// arm64: "TSTW [$]31,"
return i%32 == 0
}
func ndivis32_uint16(i uint16) bool {
// 386: "TESTW [$]31,"
// arm64: "TSTW [$]31,"
return i%32 != 0
}
func divis32_uint32(i uint32) bool {
// 386: "TESTL [$]31,"
// arm64: "TSTW [$]31,"
return i%32 == 0
}
func ndivis32_uint32(i uint32) bool {
// 386: "TESTL [$]31,"
// arm64: "TSTW [$]31,"
return i%32 != 0
}
func divis32_uint64(i uint64) bool {
// 386: "TESTL [$]31,"
// arm64: "TST [$]31,"
return i%32 == 0
}
func ndivis32_uint64(i uint64) bool {
// 386: "TESTL [$]31,"
// arm64: "TST [$]31,"
return i%32 != 0
}
func divis32_int8(i int8) bool {
// 386: "TESTB [$]31,"
// arm64: "TSTW [$]31,"
return i%32 == 0
}
func ndivis32_int8(i int8) bool {
// 386: "TESTB [$]31,"
// arm64: "TSTW [$]31,"
return i%32 != 0
}
func divis32_int16(i int16) bool {
// 386: "TESTW [$]31,"
// arm64: "TSTW [$]31,"
return i%32 == 0
}
func ndivis32_int16(i int16) bool {
// 386: "TESTW [$]31,"
// arm64: "TSTW [$]31,"
return i%32 != 0
}
func divis32_int32(i int32) bool {
// 386: "TESTL [$]31,"
// arm64: "TSTW [$]31,"
return i%32 == 0
}
func ndivis32_int32(i int32) bool {
// 386: "TESTL [$]31,"
// arm64: "TSTW [$]31,"
return i%32 != 0
}
func divis32_int64(i int64) bool {
// 386: "TESTL [$]31,"
// arm64: "TST [$]31,"
return i%32 == 0
}
func ndivis32_int64(i int64) bool {
// 386: "TESTL [$]31,"
// arm64: "TST [$]31,"
return i%32 != 0
}
// Divide with divisibility check; reuse divide intermediate mod.
func div_divis32_uint8(i uint8) (uint8, bool) {
// 386: "SHRB [$]5,"
// 386: "TESTB [$]31,",
// 386: "SETEQ"
// arm64: "UBFX [$]5, R[0-9]+, [$]3"
// arm64: "TSTW [$]31,"
// arm64: "CSET EQ"
return i / 32, i%32 == 0
}
func div_ndivis32_uint8(i uint8) (uint8, bool) {
// 386: "SHRB [$]5,"
// 386: "TESTB [$]31,",
// 386: "SETNE"
// arm64: "UBFX [$]5, R[0-9]+, [$]3"
// arm64: "TSTW [$]31,"
// arm64: "CSET NE"
return i / 32, i%32 != 0
}
func div_divis32_uint16(i uint16) (uint16, bool) {
// 386: "SHRW [$]5,"
// 386: "TESTW [$]31,",
// 386: "SETEQ"
// arm64: "UBFX [$]5, R[0-9]+, [$]11"
// arm64: "TSTW [$]31,"
// arm64: "CSET EQ"
return i / 32, i%32 == 0
}
func div_ndivis32_uint16(i uint16) (uint16, bool) {
// 386: "SHRW [$]5,"
// 386: "TESTW [$]31,",
// 386: "SETNE"
// arm64: "UBFX [$]5, R[0-9]+, [$]11,"
// arm64: "TSTW [$]31,"
// arm64: "CSET NE"
return i / 32, i%32 != 0
}
func div_divis32_uint32(i uint32) (uint32, bool) {
// 386: "SHRL [$]5,"
// 386: "TESTL [$]31,",
// 386: "SETEQ"
// arm64: "UBFX [$]5, R[0-9]+, [$]27,"
// arm64: "TSTW [$]31,"
// arm64: "CSET EQ"
return i / 32, i%32 == 0
}
func div_ndivis32_uint32(i uint32) (uint32, bool) {
// 386: "SHRL [$]5,"
// 386: "TESTL [$]31,",
// 386: "SETNE"
// arm64: "UBFX [$]5, R[0-9]+, [$]27,"
// arm64: "TSTW [$]31,"
// arm64: "CSET NE"
return i / 32, i%32 != 0
}
func div_divis32_uint64(i uint64) (uint64, bool) {
// 386: "SHRL [$]5,"
// 386: "SHLL [$]27,"
// 386: "TESTL [$]31,",
// 386: "SETEQ"
// arm64: "LSR [$]5,"
// arm64: "TST [$]31,"
// arm64: "CSET EQ"
return i / 32, i%32 == 0
}
func div_ndivis32_uint64(i uint64) (uint64, bool) {
// 386: "SHRL [$]5,"
// 386: "SHLL [$]27,"
// 386: "TESTL [$]31,",
// 386: "SETNE"
// arm64: "LSR [$]5,"
// arm64: "TST [$]31,"
// arm64: "CSET NE"
return i / 32, i%32 != 0
}
func div_divis32_int8(i int8) (int8, bool) {
// 386: "SARB [$]7,"
// 386: "SHRB [$]3,"
// 386: "SARB [$]5,"
// 386: "TESTB [$]31,",
// 386: "SETEQ"
// arm64: "SBFX [$]7, R[0-9]+, [$]1,"
// arm64: "ADD R[0-9]+>>3,"
// arm64: "SBFX [$]5, R[0-9]+, [$]3,"
// arm64: "TSTW [$]31,"
// arm64: "CSET EQ"
return i / 32, i%32 == 0
}
func div_ndivis32_int8(i int8) (int8, bool) {
// 386: "SARB [$]7,"
// 386: "SHRB [$]3,"
// 386: "SARB [$]5,"
// 386: "TESTB [$]31,",
// 386: "SETNE"
// arm64: "SBFX [$]7, R[0-9]+, [$]1,"
// arm64: "ADD R[0-9]+>>3,"
// arm64: "SBFX [$]5, R[0-9]+, [$]3,"
// arm64: "TSTW [$]31,"
// arm64: "CSET NE"
return i / 32, i%32 != 0
}
func div_divis32_int16(i int16) (int16, bool) {
// 386: "SARW [$]15,"
// 386: "SHRW [$]11,"
// 386: "SARW [$]5,"
// 386: "TESTW [$]31,",
// 386: "SETEQ"
// arm64: "SBFX [$]15, R[0-9]+, [$]1,"
// arm64: "ADD R[0-9]+>>11,"
// arm64: "SBFX [$]5, R[0-9]+, [$]11,"
// arm64: "TSTW [$]31,"
// arm64: "CSET EQ"
return i / 32, i%32 == 0
}
func div_ndivis32_int16(i int16) (int16, bool) {
// 386: "SARW [$]15,"
// 386: "SHRW [$]11,"
// 386: "SARW [$]5,"
// 386: "TESTW [$]31,",
// 386: "SETNE"
// arm64: "SBFX [$]15, R[0-9]+, [$]1,"
// arm64: "ADD R[0-9]+>>11,"
// arm64: "SBFX [$]5, R[0-9]+, [$]11,"
// arm64: "TSTW [$]31,"
// arm64: "CSET NE"
return i / 32, i%32 != 0
}
func div_divis32_int32(i int32) (int32, bool) {
// 386: "SARL [$]31,"
// 386: "SHRL [$]27,"
// 386: "SARL [$]5,"
// 386: "TESTL [$]31,",
// 386: "SETEQ"
// arm64: "SBFX [$]31, R[0-9]+, [$]1,"
// arm64: "ADD R[0-9]+>>27,"
// arm64: "SBFX [$]5, R[0-9]+, [$]27,"
// arm64: "TSTW [$]31,"
// arm64: "CSET EQ"
return i / 32, i%32 == 0
}
func div_ndivis32_int32(i int32) (int32, bool) {
// 386: "SARL [$]31,"
// 386: "SHRL [$]27,"
// 386: "SARL [$]5,"
// 386: "TESTL [$]31,",
// 386: "SETNE"
// arm64: "SBFX [$]31, R[0-9]+, [$]1,"
// arm64: "ADD R[0-9]+>>27,"
// arm64: "SBFX [$]5, R[0-9]+, [$]27,"
// arm64: "TSTW [$]31,"
// arm64: "CSET NE"
return i / 32, i%32 != 0
}
func div_divis32_int64(i int64) (int64, bool) {
// 386: "SARL [$]31,"
// 386: "SHRL [$]27,"
// 386: "SARL [$]5,"
// 386: "SHLL [$]27,"
// 386: "TESTL [$]31,",
// 386: "SETEQ"
// arm64: "ASR [$]63,"
// arm64: "ADD R[0-9]+>>59,"
// arm64: "ASR [$]5,"
// arm64: "TST [$]31,"
// arm64: "CSET EQ"
return i / 32, i%32 == 0
}
func div_ndivis32_int64(i int64) (int64, bool) {
// 386: "SARL [$]31,"
// 386: "SHRL [$]27,"
// 386: "SARL [$]5,"
// 386: "SHLL [$]27,"
// 386: "TESTL [$]31,",
// 386: "SETNE"
// arm64: "ASR [$]63,"
// arm64: "ADD R[0-9]+>>59,"
// arm64: "ASR [$]5,"
// arm64: "TST [$]31,"
// arm64: "CSET NE"
return i / 32, i%32 != 0
}
// Divisibility and non-divisibility by non-power-of-two.
func divis6_uint8(i uint8) bool {
// 386: "IMUL3L [$]-85,"
// 386: "ROLB [$]7,"
// 386: "CMPB .*, [$]42"
// 386: "SETLS"
// arm64: "MOVD [$]-85,"
// arm64: "MULW"
// arm64: "UBFX [$]1, R[0-9]+, [$]7,"
// arm64: "ORR R[0-9]+<<7"
// arm64: "CMPW [$]42,"
// arm64: "CSET LS"
return i%6 == 0
}
func ndivis6_uint8(i uint8) bool {
// 386: "IMUL3L [$]-85,"
// 386: "ROLB [$]7,"
// 386: "CMPB .*, [$]42"
// 386: "SETHI"
// arm64: "MOVD [$]-85,"
// arm64: "MULW"
// arm64: "UBFX [$]1, R[0-9]+, [$]7,"
// arm64: "ORR R[0-9]+<<7"
// arm64: "CMPW [$]42,"
// arm64: "CSET HI"
return i%6 != 0
}
func divis6_uint16(i uint16) bool {
// 386: "IMUL3L [$]-21845,"
// 386: "ROLW [$]15,"
// 386: "CMPW .*, [$]10922"
// 386: "SETLS"
// arm64: "MOVD [$]-21845,"
// arm64: "MULW"
// arm64: "ORR R[0-9]+<<16"
// arm64: "RORW [$]17,"
// arm64: "MOVD [$]10922,"
// arm64: "CSET LS"
return i%6 == 0
}
func ndivis6_uint16(i uint16) bool {
// 386: "IMUL3L [$]-21845,"
// 386: "ROLW [$]15,"
// 386: "CMPW .*, [$]10922"
// 386: "SETHI"
// arm64: "MOVD [$]-21845,"
// arm64: "MULW"
// arm64: "ORR R[0-9]+<<16"
// arm64: "RORW [$]17,"
// arm64: "MOVD [$]10922,"
// arm64: "CSET HI"
return i%6 != 0
}
func divis6_uint32(i uint32) bool {
// 386: "IMUL3L [$]-1431655765,"
// 386: "ROLL [$]31,"
// 386: "CMPL .*, [$]715827882"
// 386: "SETLS"
// arm64: "MOVD [$]-1431655765,"
// arm64: "MULW"
// arm64: "RORW [$]1,"
// arm64: "MOVD [$]715827882,"
// arm64: "CSET LS"
return i%6 == 0
}
func ndivis6_uint32(i uint32) bool {
// 386: "IMUL3L [$]-1431655765,"
// 386: "ROLL [$]31,"
// 386: "CMPL .*, [$]715827882"
// 386: "SETHI"
// arm64: "MOVD [$]-1431655765,"
// arm64: "MULW"
// arm64: "RORW [$]1,"
// arm64: "MOVD [$]715827882,"
// arm64: "CSET HI"
return i%6 != 0
}
func divis6_uint64(i uint64) bool {
// 386: "IMUL3L [$]-1431655766,"
// 386: "IMUL3L [$]-1431655765,"
// 386: "MULL"
// 386: "SHRL [$]1,"
// 386: "SHLL [$]31,"
// 386: "CMPL .*, [$]715827882"
// 386: "SETLS"
// arm64: "MOVD [$]-6148914691236517205,"
// arm64: "MUL "
// arm64: "ROR [$]1,"
// arm64: "MOVD [$]3074457345618258602,"
// arm64: "CSET LS"
return i%6 == 0
}
func ndivis6_uint64(i uint64) bool {
// 386: "IMUL3L [$]-1431655766,"
// 386: "IMUL3L [$]-1431655765,"
// 386: "MULL"
// 386: "SHRL [$]1,"
// 386: "SHLL [$]31,"
// 386: "CMPL .*, [$]715827882"
// 386: "SETHI"
// arm64: "MOVD [$]-6148914691236517205,"
// arm64: "MUL "
// arm64: "ROR [$]1,"
// arm64: "MOVD [$]3074457345618258602,"
// arm64: "CSET HI"
return i%6 != 0
}
func divis6_int8(i int8) bool {
// 386: "IMUL3L [$]-85,"
// 386: "ADDL [$]42,"
// 386: "ROLB [$]7,"
// 386: "CMPB .*, [$]42"
// 386: "SETLS"
// arm64: "MOVD [$]-85,"
// arm64: "MULW"
// arm64: "ADD [$]42,"
// arm64: "UBFX [$]1, R[0-9]+, [$]7,"
// arm64: "ORR R[0-9]+<<7"
// arm64: "CMPW [$]42,"
// arm64: "CSET LS"
return i%6 == 0
}
func ndivis6_int8(i int8) bool {
// 386: "IMUL3L [$]-85,"
// 386: "ADDL [$]42,"
// 386: "ROLB [$]7,"
// 386: "CMPB .*, [$]42"
// 386: "SETHI"
// arm64: "MOVD [$]-85,"
// arm64: "MULW"
// arm64: "ADD [$]42,"
// arm64: "UBFX [$]1, R[0-9]+, [$]7,"
// arm64: "ORR R[0-9]+<<7"
// arm64: "CMPW [$]42,"
// arm64: "CSET HI"
return i%6 != 0
}
func divis6_int16(i int16) bool {
// 386: "IMUL3L [$]-21845,"
// 386: "ADDL [$]10922,"
// 386: "ROLW [$]15,"
// 386: "CMPW .*, [$]10922"
// 386: "SETLS"
// arm64: "MOVD [$]-21845,"
// arm64: "MULW"
// arm64: "MOVD [$]10922,"
// arm64: "ADD "
// arm64: "ORR R[0-9]+<<16"
// arm64: "RORW [$]17,"
// arm64: "MOVD [$]10922,"
// arm64: "CSET LS"
return i%6 == 0
}
func ndivis6_int16(i int16) bool {
// 386: "IMUL3L [$]-21845,"
// 386: "ADDL [$]10922,"
// 386: "ROLW [$]15,"
// 386: "CMPW .*, [$]10922"
// 386: "SETHI"
// arm64: "MOVD [$]-21845,"
// arm64: "MULW"
// arm64: "MOVD [$]10922,"
// arm64: "ADD "
// arm64: "ORR R[0-9]+<<16"
// arm64: "RORW [$]17,"
// arm64: "MOVD [$]10922,"
// arm64: "CSET HI"
return i%6 != 0
}
func divis6_int32(i int32) bool {
// 386: "IMUL3L [$]-1431655765,"
// 386: "ADDL [$]715827882,"
// 386: "ROLL [$]31,"
// 386: "CMPL .*, [$]715827882"
// 386: "SETLS"
// arm64: "MOVD [$]-1431655765,"
// arm64: "MULW"
// arm64: "MOVD [$]715827882,"
// arm64: "ADD "
// arm64: "RORW [$]1,"
// arm64: "CSET LS"
return i%6 == 0
}
func ndivis6_int32(i int32) bool {
// 386: "IMUL3L [$]-1431655765,"
// 386: "ADDL [$]715827882,"
// 386: "ROLL [$]31,"
// 386: "CMPL .*, [$]715827882"
// 386: "SETHI"
// arm64: "MOVD [$]-1431655765,"
// arm64: "MULW"
// arm64: "MOVD [$]715827882,"
// arm64: "ADD "
// arm64: "RORW [$]1,"
// arm64: "CSET HI"
return i%6 != 0
}
func divis6_int64(i int64) bool {
// 386: "IMUL3L [$]-1431655766,"
// 386: "IMUL3L [$]-1431655765,"
// 386: "ADCL [$]715827882,"
// 386: "CMPL .*, [$]715827882"
// 386: "CMPL .*, [$]-1431655766"
// 386: "SETLS"
// arm64: "MOVD [$]-6148914691236517205,"
// arm64: "MUL "
// arm64: "MOVD [$]3074457345618258602,"
// arm64: "ADD "
// arm64: "ROR [$]1,"
// arm64: "CSET LS"
return i%6 == 0
}
func ndivis6_int64(i int64) bool {
// 386: "IMUL3L [$]-1431655766,"
// 386: "IMUL3L [$]-1431655765,"
// 386: "ADCL [$]715827882,"
// 386: "CMPL .*, [$]715827882"
// 386: "CMPL .*, [$]-1431655766"
// 386: "SETHI"
// arm64: "MOVD [$]-6148914691236517205,"
// arm64: "MUL "
// arm64: "MOVD [$]3074457345618258602,"
// arm64: "ADD "
// arm64: "ROR [$]1,"
// arm64: "CSET HI"
return i%6 != 0
}
func div_divis6_uint8(i uint8) (uint8, bool) {
// 386: "IMUL3L [$]342,"
// 386: "SHRL [$]11,"
// 386: "SETEQ"
// 386: -"RO[RL]"
// arm64: "MOVD [$]342,"
// arm64: "MULW"
// arm64: "UBFX [$]11, R[0-9]+, [$]21,"
// arm64: "CSET EQ"
// arm64: -"RO[RL]"
return i / 6, i%6 == 0
}
func div_ndivis6_uint8(i uint8) (uint8, bool) {
// 386: "IMUL3L [$]342,"
// 386: "SHRL [$]11,"
// 386: "SETNE"
// 386: -"RO[RL]"
// arm64: "MOVD [$]342,"
// arm64: "MULW"
// arm64: "UBFX [$]11, R[0-9]+, [$]21,"
// arm64: "CSET NE"
// arm64: -"RO[RL]"
return i / 6, i%6 != 0
}
func div_divis6_uint16(i uint16) (uint16, bool) {
// 386: "IMUL3L [$]43691,"
// 386: "SHRL [$]18,"
// 386: "SHLL [$]1,"
// 386: "SETEQ"
// 386: -"RO[RL]"
// arm64: "MOVD [$]87382,"
// arm64: "MUL "
// arm64: "LSR [$]19,"
// arm64: "CSET EQ"
// arm64: -"RO[RL]"
return i / 6, i%6 == 0
}
func div_ndivis6_uint16(i uint16) (uint16, bool) {
// 386: "IMUL3L [$]43691,"
// 386: "SHRL [$]18,"
// 386: "SHLL [$]1,"
// 386: "SETNE"
// 386: -"RO[RL]"
// arm64: "MOVD [$]87382,"
// arm64: "MUL "
// arm64: "LSR [$]19,"
// arm64: "CSET NE"
// arm64: -"RO[RL]"
return i / 6, i%6 != 0
}
func div_divis6_uint32(i uint32) (uint32, bool) {
// 386: "MOVL [$]-1431655765,"
// 386: "SHRL [$]2,"
// 386: "SHLL [$]1,"
// 386: "SETEQ"
// 386: -"RO[RL]"
// arm64: "MOVD [$]2863311531,"
// arm64: "MUL "
// arm64: "LSR [$]34,"
// arm64: "CSET EQ"
// arm64: -"RO[RL]"
return i / 6, i%6 == 0
}
func div_ndivis6_uint32(i uint32) (uint32, bool) {
// 386: "MOVL [$]-1431655765,"
// 386: "SHRL [$]2,"
// 386: "SHLL [$]1,"
// 386: "SETNE"
// 386: -"RO[RL]"
// arm64: "MOVD [$]2863311531,"
// arm64: "MUL "
// arm64: "LSR [$]34,"
// arm64: "CSET NE"
// arm64: -"RO[RL]"
return i / 6, i%6 != 0
}
func div_divis6_uint64(i uint64) (uint64, bool) {
// 386: "MOVL [$]-1431655766,"
// 386: "MOVL [$]-1431655765,"
// 386: "MULL"
// 386: "SHRL [$]2,"
// 386: "SHLL [$]30,"
// 386: "SETEQ"
// 386: -".*CALL"
// 386: -"RO[RL]"
// arm64: "MOVD [$]-6148914691236517205,"
// arm64: "UMULH"
// arm64: "LSR [$]2,"
// arm64: "CSET EQ"
// arm64: -"RO[RL]"
return i / 6, i%6 == 0
}
func div_ndivis6_uint64(i uint64) (uint64, bool) {
// 386: "MOVL [$]-1431655766,"
// 386: "MOVL [$]-1431655765,"
// 386: "MULL"
// 386: "SHRL [$]2,"
// 386: "SHLL [$]30,"
// 386: "SETNE"
// 386: -".*CALL"
// 386: -"RO[RL]"
// arm64: "MOVD [$]-6148914691236517205,"
// arm64: "UMULH"
// arm64: "LSR [$]2,"
// arm64: "CSET NE"
// arm64: -"RO[RL]"
return i / 6, i%6 != 0
}
func div_divis6_int8(i int8) (int8, bool) {
// 386: "SARL [$]31,"
// 386: "IMUL3L [$]171,"
// 386: "SARL [$]10,"
// 386: "SHLL [$]1,"
// 386: "SETEQ"
// 386: -"RO[RL]"
// arm64: "MOVD [$]171,"
// arm64: "MULW"
// arm64: "SBFX [$]10, R[0-9]+, [$]22,"
// arm64: "SUB R[0-9]+->31,"
// arm64: "CSET EQ"
// arm64: -"RO[RL]"
return i / 6, i%6 == 0
}
func div_ndivis6_int8(i int8) (int8, bool) {
// 386: "SARL [$]31,"
// 386: "IMUL3L [$]171,"
// 386: "SARL [$]10,"
// 386: "SHLL [$]1,"
// 386: "SETNE"
// 386: -"RO[RL]"
// arm64: "MOVD [$]171,"
// arm64: "MULW"
// arm64: "SBFX [$]10, R[0-9]+, [$]22,"
// arm64: "SUB R[0-9]+->31,"
// arm64: "CSET NE"
// arm64: -"RO[RL]"
return i / 6, i%6 != 0
}
func div_divis6_int16(i int16) (int16, bool) {
// 386: "SARL [$]31,"
// 386: "IMUL3L [$]43691,"
// 386: "SARL [$]18,"
// 386: "SHLL [$]1,"
// 386: "SETEQ"
// 386: -"RO[RL]"
// arm64: "MOVD [$]43691,"
// arm64: "MULW"
// arm64: "SBFX [$]18, R[0-9]+, [$]14,"
// arm64: "SUB R[0-9]+->31,"
// arm64: "CSET EQ"
// arm64: -"RO[RL]"
return i / 6, i%6 == 0
}
func div_ndivis6_int16(i int16) (int16, bool) {
// 386: "SARL [$]31,"
// 386: "IMUL3L [$]43691,"
// 386: "SARL [$]18,"
// 386: "SHLL [$]1,"
// 386: "SETNE"
// 386: -"RO[RL]"
// arm64: "MOVD [$]43691,"
// arm64: "MULW"
// arm64: "SBFX [$]18, R[0-9]+, [$]14,"
// arm64: "SUB R[0-9]+->31,"
// arm64: "CSET NE"
// arm64: -"RO[RL]"
return i / 6, i%6 != 0
}
func div_divis6_int32(i int32) (int32, bool) {
// 386: "SARL [$]31,"
// 386: "MOVL [$]-1431655765,"
// 386: "IMULL"
// 386: "SARL [$]2,"
// 386: "SHLL [$]1,"
// 386: "SETEQ"
// 386: -"RO[RL]"
// arm64: "MOVD [$]2863311531,"
// arm64: "MUL "
// arm64: "ASR [$]34,"
// arm64: "SUB R[0-9]+->63,"
// arm64: "CSET EQ"
// arm64: -"RO[RL]"
return i / 6, i%6 == 0
}
func div_ndivis6_int32(i int32) (int32, bool) {
// 386: "SARL [$]31,"
// 386: "MOVL [$]-1431655765,"
// 386: "IMULL"
// 386: "SARL [$]2,"
// 386: "SHLL [$]1,"
// 386: "SETNE"
// 386: -"RO[RL]"
// arm64: "MOVD [$]2863311531,"
// arm64: "MUL "
// arm64: "ASR [$]34,"
// arm64: "SUB R[0-9]+->63,"
// arm64: "CSET NE"
// arm64: -"RO[RL]"
return i / 6, i%6 != 0
}
func div_divis6_int64(i int64) (int64, bool) {
// 386: "ANDL [$]-1431655766,"
// 386: "ANDL [$]-1431655765,"
// 386: "MOVL [$]-1431655766,"
// 386: "MOVL [$]-1431655765,"
// 386: "SUBL" "SBBL"
// 386: "MULL"
// 386: "SETEQ"
// 386: -"SET(LS|HI)"
// 386: -".*CALL"
// 386: -"RO[RL]"
// arm64: "MOVD [$]-6148914691236517205,"
// arm64: "SMULH"
// arm64: "ADD"
// arm64: "ASR [$]2,"
// arm64: "SUB R[0-9]+->63,"
// arm64: "CSET EQ"
// arm64: -"RO[RL]"
return i / 6, i%6 == 0
}
func div_ndivis6_int64(i int64) (int64, bool) {
// 386: "ANDL [$]-1431655766,"
// 386: "ANDL [$]-1431655765,"
// 386: "MOVL [$]-1431655766,"
// 386: "MOVL [$]-1431655765,"
// 386: "SUBL" "SBBL"
// 386: "MULL"
// 386: "SETNE"
// 386: -"SET(LS|HI)"
// 386: -".*CALL"
// 386: -"RO[RL]"
// arm64: "MOVD [$]-6148914691236517205,"
// arm64: "SMULH"
// arm64: "ADD"
// arm64: "ASR [$]2,"
// arm64: "SUB R[0-9]+->63,"
// arm64: "CSET NE"
// arm64: -"RO[RL]"
return i / 6, i%6 != 0
}