mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.simd] all: merge master (924fe98) into dev.simd
Conflicts: - src/cmd/compile/internal/amd64/ssa.go - src/cmd/compile/internal/ssa/expand_calls.go - src/cmd/compile/internal/ssagen/ssa.go - src/internal/buildcfg/exp.go - src/internal/cpu/cpu.go - src/internal/cpu/cpu_x86.go - src/runtime/mkpreempt.go - src/runtime/preempt_amd64.go - src/runtime/preempt_amd64.s Merge List: + 2025-08-14924fe98902cmd/internal/obj/riscv: add encoding for compressed riscv64 instructions + 2025-08-13320df537cccmd/compile: emit classify instructions for infinity tests on riscv64 + 2025-08-13ca66f907ddcmd/compile: use generated loops instead of DUFFCOPY on amd64 + 2025-08-134b1800e476encoding/json/v2: cleanup error constructors + 2025-08-13af8870708bencoding/json/v2: fix incorrect marshaling of NaN in float64 any + 2025-08-130a75e5a07bencoding/json/v2: fix wrong type with cyclic marshal error in map[string]any + 2025-08-13de9b6f9875cmd/pprof: update vendored github.com/google/pprof + 2025-08-13674c5f0eddos/exec: fix incorrect expansion of ".." in LookPath on plan9 + 2025-08-139bbea0f21acmd/compile: during regalloc, fixedreg values are always available + 2025-08-1308eef97500runtime/trace: fix documentation typo + 2025-08-132fe5d51d04internal/trace: fix wrong scope for Event.Range or EvGCSweepActive + 2025-08-139fcb87c352cmd/compile: teach prove about len's & cap's max based on the element size + 2025-08-139763ece873cmd/compile: absorb NEGV into branch on loong64 + 2025-08-13f10a82b76fall: update vendored dependencies [generated] + 2025-08-133bea95b277cmd/link/internal/ld: remove OpenBSD buildid workaround + 2025-08-1290b7d7aaa2cmd/compile/internal: optimize multiplication use new operation 'ADDshiftLLV' on loong64 + 2025-08-121b263fc604runtime/race: restore previous version of LLVM TSAN on macOS + 2025-08-12b266318cf7cmd/compile/internal/ssa: use BEQ/BNE to optimize the combination of XOR and EQ/NE on loong64 + 2025-08-12adbf59525cinternal/runtime/gc/scan: avoid -1 index when cache sizes unavailable + 2025-08-124e182db5fcRevert "cmd/compile: use generated loops instead of DUFFCOPY on amd64" + 2025-08-12d2b3c1a504internal/trace: clarify which StateTransition events have stacks + 2025-08-12f63e12d0e0internal/trace: fix Sync.ClockSnapshot comment + 2025-08-128e317da77dinternal/trace: remove unused StateTransition.id field + 2025-08-12f67d8ff34ainternal/trace/tracev2: adjust comment for consistency + 2025-08-12fe4d445c36internal/trace/tracev2: fix EvSTWBegin comment to include stack ID + 2025-08-12750789fab7internal/trace/internal/testgen: fix missing stacks nframes arg + 2025-08-12889ab74169internal/runtime/gc/scan: import scan kernel from gclab [green tea] + 2025-08-12182336bf05net/http: fix data race in client + 2025-08-12f04421ea9acmd/compile: soften test for 74788 + 2025-08-1228aa529c99cmd/compile: use generated loops instead of DUFFZERO on arm64 + 2025-08-12ec9e1176c3cmd/compile: use generated loops instead of DUFFCOPY on amd64 + 2025-08-12d0a64f7969Revert "cmd/compile/internal/ssa: Use transitive properties for len/cap" + 2025-08-1200a7bdcb55all: delete aliastypeparams GOEXPERIMENT + 2025-08-1174421a305bRevert "cmd/compile: allow multi-field structs to be stored directly in interfaces" + 2025-08-11c31359138cRevert "cmd/compile: allow StructSelect [x] of interface data fields for x>0" + 2025-08-117248995b60Revert "cmd/compile: allow more args in StructMake folding rule" + 2025-08-11caf9fc3ccdRevert "reflect: handle zero-sized fields of directly-stored structures correctly" + 2025-08-11ce3f3e2ae7cmd/link/internal/ld, internal/syscall/unix: use posix_fallocate on netbsd + 2025-08-113dbef65bf3database/sql: allow drivers to override Scan behavior + 2025-08-112b804abf07net: context aware Dialer.Dial functions + 2025-08-116abfe7b0decmd/dist: require Go 1.24.6 as minimum bootstrap toolchain + 2025-08-11691af6ca28encoding/json: fix Indent trailing whitespace regression in goexperiment.jsonv2 + 2025-08-11925149da20net/http: add example for CrossOriginProtection + 2025-08-11cf4af0b2f3encoding/json/v2: fix UnmarshalDecode regression with EOF + 2025-08-11b096ddb9eainternal/runtime/maps: loop invariant code motion with h2(hash) by hand + 2025-08-11a2431776ebnet, os, file/filepath, syscall: use slices.Equal in tests + 2025-08-11a7f05b38f7cmd/compile: convert branch with zero to more optimal branch zero on loong64 + 2025-08-111718828c81internal/sync: warn about incorrect unsafe usage in HashTrieMap + 2025-08-11084c0f8494cmd/compile: allow InlMark operations to be speculatively executed + 2025-08-10a62f72f7a7cmd/compile/internal/ssa: optimise more branches with SGTconst/SGTUconst on loong64 + 2025-08-08fbac94a799internal/sync: rename Store parameter from old to new + 2025-08-08317be4cfebcmd/compile/internal/staticinit: remove deadcode + 2025-08-08bce5601cbbcmd/go: fix fips doc link + 2025-08-08777d76c4f2text/template: use sync.OnceValue for builtinFuncs + 2025-08-080201524c52math: remove redundant infinity tests + 2025-08-08dcc77f9e3ccmd/go: fix get -tool when multiple packages are provided + 2025-08-08c7b85e9ddcall: update blog link + 2025-08-08a8dd771e13crypto/tls: check if quic conn can send session ticket + 2025-08-08bdb2d50fdfnet: fix WriteMsgUDPAddrPort addr handling on IPv4 sockets + 2025-08-08768c51e368internal/runtime/maps: remove unused var bitsetDeleted + 2025-08-08b3388569a1reflect: handle zero-sized fields of directly-stored structures correctly + 2025-08-08d83b16fcb8internal/bytealg: vector implementation of compare for riscv64 + 2025-08-07dd3abf6bc5internal/bytealg: optimize Index/IndexString on loong64 + 2025-08-0773ff6d1480cmd/internal/obj/loong64: change the immediate range of ALSL{W/WU/V} + 2025-08-07f3606b0825cmd/compile/internal/ssa: fix typo in LOONG64Ops.go comment + 2025-08-07ee7bb8969acmd/internal/obj/loong64: add support for FSEL instruction + 2025-08-071f7ffca171time: skip TestLongAdjustTimers on plan9 (too slow) + 2025-08-068282b72d62runtime/race: update darwin race syso + 2025-08-06dc54d7b607all: remove support for windows/arm + 2025-08-06e0a1ea431ccmd/compile: make panicBounds stack frame smaller on ppc64 + 2025-08-062747f925dddebug/macho: support reading imported symbols without LC_DYSYMTAB + 2025-08-06025d36917ccmd/internal/testdir: pass -buildid to link command + 2025-08-06f53dcb6280cmd/internal/testdir: unify link command + 2025-08-06a3895fe9f1database/sql: avoid closing Rows while scan is in progress + 2025-08-06608e9fac90go/types, types2: flip on position tracing + 2025-08-0672e8237cc1cmd/compile: allow more args in StructMake folding rule + 2025-08-063406a617d9internal/bytealg: vector implementation of indexbyte for riscv64 + 2025-08-0675ea2d05c0internal/bytealg: vector implementation of equal for riscv64 + 2025-08-0517a8be7117crypto/sha512: use const table for key loading on loong64 + 2025-08-05dda9d780e2crypto/sha256: use const table for key loading on loong64 + 2025-08-055defe8ebb3internal/chacha8rand: replace WORD with instruction VMOVQ + 2025-08-054c7362e41ccmd/internal/obj/loong64: add new instructions ALSL{W/WU/V} for loong64 + 2025-08-05a552737418cmd/compile: fold negation into multiplication on loong64 + 2025-08-05e1fd4faf91runtime: fix godoc comment for inVDSOPage + 2025-08-05bcd25c79aacmd/compile: allow StructSelect [x] of interface data fields for x>0 + 2025-08-05b0945a54b5cmd/dist, internal/platform: mark freebsd/riscv64 broken + 2025-08-0555d961b202runtime: save AVX2 and AVX-512 state on asynchronous preemption + 2025-08-05af0c4fe2caruntime: save scalar registers off stack in amd64 async preemption + 2025-08-05e73afaae69internal/cpu: add AVX-512-CD and DQ, and derived "basic AVX-512" + 2025-08-05cef381ba60runtime: eliminate global state in mkpreempt.go + 2025-08-05c0025d5e0bgo/parser: correct comment in expectedErrors + 2025-08-054ee0df8c46cmd: remove dead code + 2025-08-05a2c45f0eb1runtime: test VDSO symbol hash values + 2025-08-05cd55f86b8dcmd/compile: allow multi-field structs to be stored directly in interfaces + 2025-08-0521ab0128b6cmd/compile: remove support for old-style bounds check calls + 2025-08-05802d056c78cmd/compile: move ppc64 over to new bounds check strategy + 2025-08-05a3295df873cmd/compile/internal/ssa: Use transitive properties for len/cap + 2025-08-05bd082857a5doc: fix typo in go memory model doc + 2025-08-052b622b05a9cmd/compile: remove isUintXPowerOfTwo functions + 2025-08-0572147ffa75cmd/compile: simplify isUintXPowerOfTwo implementation + 2025-08-0526da1199ebcmd/compile: make isUint{32,64}PowerOfTwo implementations clearer + 2025-08-055ab9f23977cmd/compile, runtime: add checkptr instrumentation for unsafe.Add + 2025-08-05fcc036f03bcmd/compile: optimise float <-> int register moves on riscv64 Change-Id: Ie94f29d9b0cc14a52a536866f5abaef27b5c52d7
This commit is contained in:
commit
a4ad41708d
360 changed files with 10289 additions and 7265 deletions
4
api/next/49097.txt
Normal file
4
api/next/49097.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
pkg net, method (*Dialer) DialIP(context.Context, string, netip.Addr, netip.Addr) (*IPConn, error) #49097
|
||||||
|
pkg net, method (*Dialer) DialTCP(context.Context, string, netip.AddrPort, netip.AddrPort) (*TCPConn, error) #49097
|
||||||
|
pkg net, method (*Dialer) DialUDP(context.Context, string, netip.AddrPort, netip.AddrPort) (*UDPConn, error) #49097
|
||||||
|
pkg net, method (*Dialer) DialUnix(context.Context, string, *UnixAddr, *UnixAddr) (*UnixConn, error) #49097
|
||||||
5
api/next/67546.txt
Normal file
5
api/next/67546.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
pkg database/sql/driver, type RowsColumnScanner interface { Close, Columns, Next, ScanColumn } #67546
|
||||||
|
pkg database/sql/driver, type RowsColumnScanner interface, Close() error #67546
|
||||||
|
pkg database/sql/driver, type RowsColumnScanner interface, Columns() []string #67546
|
||||||
|
pkg database/sql/driver, type RowsColumnScanner interface, Next([]Value) error #67546
|
||||||
|
pkg database/sql/driver, type RowsColumnScanner interface, ScanColumn(interface{}, int) error #67546
|
||||||
|
|
@ -231,7 +231,7 @@ do exactly this.
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
A read of an array, struct, or complex number
|
A read of an array, struct, or complex number
|
||||||
may by implemented as a read of each individual sub-value
|
may be implemented as a read of each individual sub-value
|
||||||
(array element, struct field, or real/imaginary component),
|
(array element, struct field, or real/imaginary component),
|
||||||
in any order.
|
in any order.
|
||||||
Similarly, a write of an array, struct, or complex number
|
Similarly, a write of an array, struct, or complex number
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,9 @@
|
||||||
|
|
||||||
## Linker {#linker}
|
## Linker {#linker}
|
||||||
|
|
||||||
|
## Bootstrap {#bootstrap}
|
||||||
|
|
||||||
|
<!-- go.dev/issue/69315 -->
|
||||||
|
As mentioned in the [Go 1.24 release notes](/doc/go1.24#bootstrap), Go 1.26 now requires
|
||||||
|
Go 1.24.6 or later for bootstrap.
|
||||||
|
We expect that Go 1.28 will require a minor release of Go 1.26 or later for bootstrap.
|
||||||
|
|
|
||||||
1
doc/next/6-stdlib/99-minor/database/sql/driver/67546.md
Normal file
1
doc/next/6-stdlib/99-minor/database/sql/driver/67546.md
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
A database driver may implement [RowsColumnScanner] to entirely override `Scan` behavior.
|
||||||
1
doc/next/6-stdlib/99-minor/net/49097.md
Normal file
1
doc/next/6-stdlib/99-minor/net/49097.md
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Added context aware dial functions for TCP, UDP, IP and Unix networks.
|
||||||
|
|
@ -1,2 +1,6 @@
|
||||||
## Ports {#ports}
|
## Ports {#ports}
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
<!-- go.dev/issue/71671 -->
|
||||||
|
As [announced](/doc/go1.25#windows) in the Go 1.25 release notes, the [broken](/doc/go1.24#windows) 32-bit windows/arm port (`GOOS=windows` `GOARCH=arm`) is removed.
|
||||||
|
|
|
||||||
|
|
@ -23,18 +23,6 @@ func jumpLoong64(word string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsLoong64MUL reports whether the op (as defined by an loong64.A* constant) is
|
|
||||||
// one of the MUL/DIV/REM instructions that require special handling.
|
|
||||||
func IsLoong64MUL(op obj.As) bool {
|
|
||||||
switch op {
|
|
||||||
case loong64.AMUL, loong64.AMULU, loong64.AMULV, loong64.AMULVU,
|
|
||||||
loong64.ADIV, loong64.ADIVU, loong64.ADIVV, loong64.ADIVVU,
|
|
||||||
loong64.AREM, loong64.AREMU, loong64.AREMV, loong64.AREMVU:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsLoong64RDTIME reports whether the op (as defined by an loong64.A*
|
// IsLoong64RDTIME reports whether the op (as defined by an loong64.A*
|
||||||
// constant) is one of the RDTIMELW/RDTIMEHW/RDTIMED instructions that
|
// constant) is one of the RDTIMELW/RDTIMEHW/RDTIMED instructions that
|
||||||
// require special handling.
|
// require special handling.
|
||||||
|
|
|
||||||
|
|
@ -974,14 +974,6 @@ func (p *Parser) getConstant(prog *obj.Prog, op obj.As, addr *obj.Addr) int64 {
|
||||||
return addr.Offset
|
return addr.Offset
|
||||||
}
|
}
|
||||||
|
|
||||||
// getImmediate checks that addr represents an immediate constant and returns its value.
|
|
||||||
func (p *Parser) getImmediate(prog *obj.Prog, op obj.As, addr *obj.Addr) int64 {
|
|
||||||
if addr.Type != obj.TYPE_CONST || addr.Name != 0 || addr.Reg != 0 || addr.Index != 0 {
|
|
||||||
p.errorf("%s: expected immediate constant; found %s", op, obj.Dconv(prog, addr))
|
|
||||||
}
|
|
||||||
return addr.Offset
|
|
||||||
}
|
|
||||||
|
|
||||||
// getRegister checks that addr represents a register and returns its value.
|
// getRegister checks that addr represents a register and returns its value.
|
||||||
func (p *Parser) getRegister(prog *obj.Prog, op obj.As, addr *obj.Addr) int16 {
|
func (p *Parser) getRegister(prog *obj.Prog, op obj.As, addr *obj.Addr) int16 {
|
||||||
if addr.Type != obj.TYPE_REG || addr.Offset != 0 || addr.Name != 0 || addr.Index != 0 {
|
if addr.Type != obj.TYPE_REG || addr.Offset != 0 || addr.Name != 0 || addr.Index != 0 {
|
||||||
|
|
|
||||||
|
|
@ -376,6 +376,10 @@ lable2:
|
||||||
FTINTRNEVF F0, F2 // 02e41a01
|
FTINTRNEVF F0, F2 // 02e41a01
|
||||||
FTINTRNEVD F0, F2 // 02e81a01
|
FTINTRNEVD F0, F2 // 02e81a01
|
||||||
|
|
||||||
|
// FSEL instruction
|
||||||
|
FSEL FCC0, F1, F2, F3 // 4304000d
|
||||||
|
FSEL FCC1, F1, F2 // 4284000d
|
||||||
|
|
||||||
// LDX.{B,BU,H,HU,W,WU,D} instructions
|
// LDX.{B,BU,H,HU,W,WU,D} instructions
|
||||||
MOVB (R14)(R13), R12 // cc350038
|
MOVB (R14)(R13), R12 // cc350038
|
||||||
MOVBU (R14)(R13), R12 // cc352038
|
MOVBU (R14)(R13), R12 // cc352038
|
||||||
|
|
@ -1095,3 +1099,8 @@ lable2:
|
||||||
XVBITREVH $15, X2, X1 // 417c1877
|
XVBITREVH $15, X2, X1 // 417c1877
|
||||||
XVBITREVW $31, X2, X1 // 41fc1877
|
XVBITREVW $31, X2, X1 // 41fc1877
|
||||||
XVBITREVV $63, X2, X1 // 41fc1977
|
XVBITREVV $63, X2, X1 // 41fc1977
|
||||||
|
|
||||||
|
// ALSL{W/WU/D}
|
||||||
|
ALSLW $4, R4, R5, R6 // 86940500
|
||||||
|
ALSLWU $4, R4, R5, R6 // 86940700
|
||||||
|
ALSLV $4, R4, R5, R6 // 86942d00
|
||||||
|
|
|
||||||
|
|
@ -182,45 +182,6 @@ func memIdx(a *obj.Addr, v *ssa.Value) {
|
||||||
a.Index = i
|
a.Index = i
|
||||||
}
|
}
|
||||||
|
|
||||||
// DUFFZERO consists of repeated blocks of 4 MOVUPSs + LEAQ,
|
|
||||||
// See runtime/mkduff.go.
|
|
||||||
const (
|
|
||||||
dzBlocks = 16 // number of MOV/ADD blocks
|
|
||||||
dzBlockLen = 4 // number of clears per block
|
|
||||||
dzBlockSize = 23 // size of instructions in a single block
|
|
||||||
dzMovSize = 5 // size of single MOV instruction w/ offset
|
|
||||||
dzLeaqSize = 4 // size of single LEAQ instruction
|
|
||||||
dzClearStep = 16 // number of bytes cleared by each MOV instruction
|
|
||||||
)
|
|
||||||
|
|
||||||
func duffStart(size int64) int64 {
|
|
||||||
x, _ := duff(size)
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
func duffAdj(size int64) int64 {
|
|
||||||
_, x := duff(size)
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
// duff returns the offset (from duffzero, in bytes) and pointer adjust (in bytes)
|
|
||||||
// required to use the duffzero mechanism for a block of the given size.
|
|
||||||
func duff(size int64) (int64, int64) {
|
|
||||||
if size < 32 || size > 1024 || size%dzClearStep != 0 {
|
|
||||||
panic("bad duffzero size")
|
|
||||||
}
|
|
||||||
steps := size / dzClearStep
|
|
||||||
blocks := steps / dzBlockLen
|
|
||||||
steps %= dzBlockLen
|
|
||||||
off := dzBlockSize * (dzBlocks - blocks)
|
|
||||||
var adj int64
|
|
||||||
if steps != 0 {
|
|
||||||
off -= dzLeaqSize
|
|
||||||
off -= dzMovSize * steps
|
|
||||||
adj -= dzClearStep * (dzBlockLen - steps)
|
|
||||||
}
|
|
||||||
return off, adj
|
|
||||||
}
|
|
||||||
|
|
||||||
func getgFromTLS(s *ssagen.State, r int16) {
|
func getgFromTLS(s *ssagen.State, r int16) {
|
||||||
// See the comments in cmd/internal/obj/x86/obj6.go
|
// See the comments in cmd/internal/obj/x86/obj6.go
|
||||||
// near CanUse1InsnTLS for a detailed explanation of these instructions.
|
// near CanUse1InsnTLS for a detailed explanation of these instructions.
|
||||||
|
|
@ -1168,20 +1129,110 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
||||||
zero16(off + n - 16)
|
zero16(off + n - 16)
|
||||||
}
|
}
|
||||||
|
|
||||||
case ssa.OpAMD64DUFFCOPY:
|
case ssa.OpAMD64LoweredMove:
|
||||||
p := s.Prog(obj.ADUFFCOPY)
|
dstReg := v.Args[0].Reg()
|
||||||
p.To.Type = obj.TYPE_ADDR
|
srcReg := v.Args[1].Reg()
|
||||||
p.To.Sym = ir.Syms.Duffcopy
|
if dstReg == srcReg {
|
||||||
if v.AuxInt%16 != 0 {
|
break
|
||||||
v.Fatalf("bad DUFFCOPY AuxInt %v", v.AuxInt)
|
}
|
||||||
|
tmpReg := int16(x86.REG_X14)
|
||||||
|
n := v.AuxInt
|
||||||
|
if n < 16 {
|
||||||
|
v.Fatalf("Move too small %d", n)
|
||||||
|
}
|
||||||
|
// move 16 bytes from srcReg+off to dstReg+off.
|
||||||
|
move16 := func(off int64) {
|
||||||
|
move16(s, srcReg, dstReg, tmpReg, off)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate copying instructions.
|
||||||
|
var off int64
|
||||||
|
for n >= 16 {
|
||||||
|
move16(off)
|
||||||
|
off += 16
|
||||||
|
n -= 16
|
||||||
|
}
|
||||||
|
if n != 0 {
|
||||||
|
// use partially overlapped read/write.
|
||||||
|
// TODO: use smaller operations when we can?
|
||||||
|
move16(off + n - 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
case ssa.OpAMD64LoweredMoveLoop:
|
||||||
|
dstReg := v.Args[0].Reg()
|
||||||
|
srcReg := v.Args[1].Reg()
|
||||||
|
if dstReg == srcReg {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
countReg := v.RegTmp()
|
||||||
|
tmpReg := int16(x86.REG_X14)
|
||||||
|
n := v.AuxInt
|
||||||
|
loopSize := int64(64)
|
||||||
|
if n < 3*loopSize {
|
||||||
|
// - a loop count of 0 won't work.
|
||||||
|
// - a loop count of 1 is useless.
|
||||||
|
// - a loop count of 2 is a code size ~tie
|
||||||
|
// 4 instructions to implement the loop
|
||||||
|
// 4 instructions in the loop body
|
||||||
|
// vs
|
||||||
|
// 8 instructions in the straightline code
|
||||||
|
// Might as well use straightline code.
|
||||||
|
v.Fatalf("ZeroLoop size too small %d", n)
|
||||||
|
}
|
||||||
|
// move 16 bytes from srcReg+off to dstReg+off.
|
||||||
|
move16 := func(off int64) {
|
||||||
|
move16(s, srcReg, dstReg, tmpReg, off)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put iteration count in a register.
|
||||||
|
// MOVL $n, countReg
|
||||||
|
p := s.Prog(x86.AMOVL)
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.From.Offset = n / loopSize
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = countReg
|
||||||
|
cntInit := p
|
||||||
|
|
||||||
|
// Copy loopSize bytes starting at srcReg to dstReg.
|
||||||
|
for i := range loopSize / 16 {
|
||||||
|
move16(i * 16)
|
||||||
|
}
|
||||||
|
// ADDQ $loopSize, srcReg
|
||||||
|
p = s.Prog(x86.AADDQ)
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.From.Offset = loopSize
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = srcReg
|
||||||
|
// ADDQ $loopSize, dstReg
|
||||||
|
p = s.Prog(x86.AADDQ)
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.From.Offset = loopSize
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = dstReg
|
||||||
|
// DECL countReg
|
||||||
|
p = s.Prog(x86.ADECL)
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = countReg
|
||||||
|
// Jump to loop header if we're not done yet.
|
||||||
|
// JNE head
|
||||||
|
p = s.Prog(x86.AJNE)
|
||||||
|
p.To.Type = obj.TYPE_BRANCH
|
||||||
|
p.To.SetTarget(cntInit.Link)
|
||||||
|
|
||||||
|
// Multiples of the loop size are now done.
|
||||||
|
n %= loopSize
|
||||||
|
|
||||||
|
// Copy any fractional portion.
|
||||||
|
var off int64
|
||||||
|
for n >= 16 {
|
||||||
|
move16(off)
|
||||||
|
off += 16
|
||||||
|
n -= 16
|
||||||
|
}
|
||||||
|
if n != 0 {
|
||||||
|
// Use partially-overlapping copy.
|
||||||
|
move16(off + n - 16)
|
||||||
}
|
}
|
||||||
p.To.Offset = 14 * (64 - v.AuxInt/16)
|
|
||||||
// 14 and 64 are magic constants. 14 is the number of bytes to encode:
|
|
||||||
// MOVUPS (SI), X0
|
|
||||||
// ADDQ $16, SI
|
|
||||||
// MOVUPS X0, (DI)
|
|
||||||
// ADDQ $16, DI
|
|
||||||
// and 64 is the number of such blocks. See src/runtime/duff_amd64.s:duffcopy.
|
|
||||||
|
|
||||||
case ssa.OpCopy: // TODO: use MOVQreg for reg->reg copies instead of OpCopy?
|
case ssa.OpCopy: // TODO: use MOVQreg for reg->reg copies instead of OpCopy?
|
||||||
if v.Type.IsMemory() {
|
if v.Type.IsMemory() {
|
||||||
|
|
@ -2149,6 +2200,24 @@ func zero16(s *ssagen.State, reg int16, off int64) {
|
||||||
p.To.Offset = off
|
p.To.Offset = off
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// move 16 bytes from src+off to dst+off using temporary register tmp.
|
||||||
|
func move16(s *ssagen.State, src, dst, tmp int16, off int64) {
|
||||||
|
// MOVUPS off(srcReg), tmpReg
|
||||||
|
// MOVUPS tmpReg, off(dstReg)
|
||||||
|
p := s.Prog(x86.AMOVUPS)
|
||||||
|
p.From.Type = obj.TYPE_MEM
|
||||||
|
p.From.Reg = src
|
||||||
|
p.From.Offset = off
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = tmp
|
||||||
|
p = s.Prog(x86.AMOVUPS)
|
||||||
|
p.From.Type = obj.TYPE_REG
|
||||||
|
p.From.Reg = tmp
|
||||||
|
p.To.Type = obj.TYPE_MEM
|
||||||
|
p.To.Reg = dst
|
||||||
|
p.To.Offset = off
|
||||||
|
}
|
||||||
|
|
||||||
// XXX maybe make this part of v.Reg?
|
// XXX maybe make this part of v.Reg?
|
||||||
// On the other hand, it is architecture-specific.
|
// On the other hand, it is architecture-specific.
|
||||||
func simdReg(v *ssa.Value) int16 {
|
func simdReg(v *ssa.Value) int16 {
|
||||||
|
|
|
||||||
|
|
@ -1050,33 +1050,118 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
||||||
p.From.Offset = int64(condCode)
|
p.From.Offset = int64(condCode)
|
||||||
p.To.Type = obj.TYPE_REG
|
p.To.Type = obj.TYPE_REG
|
||||||
p.To.Reg = v.Reg()
|
p.To.Reg = v.Reg()
|
||||||
case ssa.OpARM64DUFFZERO:
|
|
||||||
// runtime.duffzero expects start address in R20
|
|
||||||
p := s.Prog(obj.ADUFFZERO)
|
|
||||||
p.To.Type = obj.TYPE_MEM
|
|
||||||
p.To.Name = obj.NAME_EXTERN
|
|
||||||
p.To.Sym = ir.Syms.Duffzero
|
|
||||||
p.To.Offset = v.AuxInt
|
|
||||||
case ssa.OpARM64LoweredZero:
|
case ssa.OpARM64LoweredZero:
|
||||||
// STP.P (ZR,ZR), 16(R16)
|
ptrReg := v.Args[0].Reg()
|
||||||
// CMP Rarg1, R16
|
n := v.AuxInt
|
||||||
// BLE -2(PC)
|
if n < 16 {
|
||||||
// arg1 is the address of the last 16-byte unit to zero
|
v.Fatalf("Zero too small %d", n)
|
||||||
p := s.Prog(arm64.ASTP)
|
}
|
||||||
p.Scond = arm64.C_XPOST
|
|
||||||
p.From.Type = obj.TYPE_REGREG
|
// Generate zeroing instructions.
|
||||||
p.From.Reg = arm64.REGZERO
|
var off int64
|
||||||
p.From.Offset = int64(arm64.REGZERO)
|
for n >= 16 {
|
||||||
p.To.Type = obj.TYPE_MEM
|
// STP (ZR, ZR), off(ptrReg)
|
||||||
p.To.Reg = arm64.REG_R16
|
zero16(s, ptrReg, off, false)
|
||||||
p.To.Offset = 16
|
off += 16
|
||||||
p2 := s.Prog(arm64.ACMP)
|
n -= 16
|
||||||
p2.From.Type = obj.TYPE_REG
|
}
|
||||||
p2.From.Reg = v.Args[1].Reg()
|
// Write any fractional portion.
|
||||||
p2.Reg = arm64.REG_R16
|
// An overlapping 16-byte write can't be used here
|
||||||
p3 := s.Prog(arm64.ABLE)
|
// because STP's offsets must be a multiple of 8.
|
||||||
p3.To.Type = obj.TYPE_BRANCH
|
if n > 8 {
|
||||||
p3.To.SetTarget(p)
|
// MOVD ZR, off(ptrReg)
|
||||||
|
zero8(s, ptrReg, off)
|
||||||
|
off += 8
|
||||||
|
n -= 8
|
||||||
|
}
|
||||||
|
if n != 0 {
|
||||||
|
// MOVD ZR, off+n-8(ptrReg)
|
||||||
|
// TODO: for n<=4 we could use a smaller write.
|
||||||
|
zero8(s, ptrReg, off+n-8)
|
||||||
|
}
|
||||||
|
case ssa.OpARM64LoweredZeroLoop:
|
||||||
|
ptrReg := v.Args[0].Reg()
|
||||||
|
countReg := v.RegTmp()
|
||||||
|
n := v.AuxInt
|
||||||
|
loopSize := int64(64)
|
||||||
|
if n < 3*loopSize {
|
||||||
|
// - a loop count of 0 won't work.
|
||||||
|
// - a loop count of 1 is useless.
|
||||||
|
// - a loop count of 2 is a code size ~tie
|
||||||
|
// 3 instructions to implement the loop
|
||||||
|
// 4 instructions in the loop body
|
||||||
|
// vs
|
||||||
|
// 8 instructions in the straightline code
|
||||||
|
// Might as well use straightline code.
|
||||||
|
v.Fatalf("ZeroLoop size too small %d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put iteration count in a register.
|
||||||
|
// MOVD $n, countReg
|
||||||
|
p := s.Prog(arm64.AMOVD)
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.From.Offset = n / loopSize
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = countReg
|
||||||
|
cntInit := p
|
||||||
|
|
||||||
|
// Zero loopSize bytes starting at ptrReg.
|
||||||
|
// Increment ptrReg by loopSize as a side effect.
|
||||||
|
for range loopSize / 16 {
|
||||||
|
// STP.P (ZR, ZR), 16(ptrReg)
|
||||||
|
zero16(s, ptrReg, 0, true)
|
||||||
|
// TODO: should we use the postincrement form,
|
||||||
|
// or use a separate += 64 instruction?
|
||||||
|
// postincrement saves an instruction, but maybe
|
||||||
|
// it requires more integer units to do the +=16s.
|
||||||
|
}
|
||||||
|
// Decrement loop count.
|
||||||
|
// SUB $1, countReg
|
||||||
|
p = s.Prog(arm64.ASUB)
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.From.Offset = 1
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = countReg
|
||||||
|
// Jump to loop header if we're not done yet.
|
||||||
|
// CBNZ head
|
||||||
|
p = s.Prog(arm64.ACBNZ)
|
||||||
|
p.From.Type = obj.TYPE_REG
|
||||||
|
p.From.Reg = countReg
|
||||||
|
p.To.Type = obj.TYPE_BRANCH
|
||||||
|
p.To.SetTarget(cntInit.Link)
|
||||||
|
|
||||||
|
// Multiples of the loop size are now done.
|
||||||
|
n %= loopSize
|
||||||
|
|
||||||
|
// Write any fractional portion.
|
||||||
|
var off int64
|
||||||
|
for n >= 16 {
|
||||||
|
// STP (ZR, ZR), off(ptrReg)
|
||||||
|
zero16(s, ptrReg, off, false)
|
||||||
|
off += 16
|
||||||
|
n -= 16
|
||||||
|
}
|
||||||
|
if n > 8 {
|
||||||
|
// Note: an overlapping 16-byte write can't be used
|
||||||
|
// here because STP's offsets must be a multiple of 8.
|
||||||
|
// MOVD ZR, off(ptrReg)
|
||||||
|
zero8(s, ptrReg, off)
|
||||||
|
off += 8
|
||||||
|
n -= 8
|
||||||
|
}
|
||||||
|
if n != 0 {
|
||||||
|
// MOVD ZR, off+n-8(ptrReg)
|
||||||
|
// TODO: for n<=4 we could use a smaller write.
|
||||||
|
zero8(s, ptrReg, off+n-8)
|
||||||
|
}
|
||||||
|
// TODO: maybe we should use the count register to instead
|
||||||
|
// hold an end pointer and compare against that?
|
||||||
|
// ADD $n, ptrReg, endReg
|
||||||
|
// then
|
||||||
|
// CMP ptrReg, endReg
|
||||||
|
// BNE loop
|
||||||
|
// There's a past-the-end pointer here, any problem with that?
|
||||||
|
|
||||||
case ssa.OpARM64DUFFCOPY:
|
case ssa.OpARM64DUFFCOPY:
|
||||||
p := s.Prog(obj.ADUFFCOPY)
|
p := s.Prog(obj.ADUFFCOPY)
|
||||||
p.To.Type = obj.TYPE_MEM
|
p.To.Type = obj.TYPE_MEM
|
||||||
|
|
@ -1482,3 +1567,35 @@ func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg in
|
||||||
p.Pos = p.Pos.WithNotStmt()
|
p.Pos = p.Pos.WithNotStmt()
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// zero16 zeroes 16 bytes at reg+off.
|
||||||
|
// If postInc is true, increment reg by 16.
|
||||||
|
func zero16(s *ssagen.State, reg int16, off int64, postInc bool) {
|
||||||
|
// STP (ZR, ZR), off(reg)
|
||||||
|
p := s.Prog(arm64.ASTP)
|
||||||
|
p.From.Type = obj.TYPE_REGREG
|
||||||
|
p.From.Reg = arm64.REGZERO
|
||||||
|
p.From.Offset = int64(arm64.REGZERO)
|
||||||
|
p.To.Type = obj.TYPE_MEM
|
||||||
|
p.To.Reg = reg
|
||||||
|
p.To.Offset = off
|
||||||
|
if postInc {
|
||||||
|
if off != 0 {
|
||||||
|
panic("can't postinc with non-zero offset")
|
||||||
|
}
|
||||||
|
// STP.P (ZR, ZR), 16(reg)
|
||||||
|
p.Scond = arm64.C_XPOST
|
||||||
|
p.To.Offset = 16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// zero8 zeroes 8 bytes at reg+off.
|
||||||
|
func zero8(s *ssagen.State, reg int16, off int64) {
|
||||||
|
// MOVD ZR, off(reg)
|
||||||
|
p := s.Prog(arm64.AMOVD)
|
||||||
|
p.From.Type = obj.TYPE_REG
|
||||||
|
p.From.Reg = arm64.REGZERO
|
||||||
|
p.To.Type = obj.TYPE_MEM
|
||||||
|
p.To.Reg = reg
|
||||||
|
p.To.Offset = off
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,20 +9,14 @@ package importer
|
||||||
import (
|
import (
|
||||||
"cmd/compile/internal/base"
|
"cmd/compile/internal/base"
|
||||||
"cmd/compile/internal/types2"
|
"cmd/compile/internal/types2"
|
||||||
"fmt"
|
|
||||||
"go/token"
|
"go/token"
|
||||||
"internal/pkgbits"
|
"internal/pkgbits"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func assert(p bool) {
|
func assert(p bool) {
|
||||||
base.Assert(p)
|
base.Assert(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func errorf(format string, args ...interface{}) {
|
|
||||||
panic(fmt.Sprintf(format, args...))
|
|
||||||
}
|
|
||||||
|
|
||||||
const deltaNewFile = -64 // see cmd/compile/internal/gc/bexport.go
|
const deltaNewFile = -64 // see cmd/compile/internal/gc/bexport.go
|
||||||
|
|
||||||
// Synthesize a token.Pos
|
// Synthesize a token.Pos
|
||||||
|
|
@ -31,108 +25,6 @@ type fakeFileSet struct {
|
||||||
files map[string]*token.File
|
files map[string]*token.File
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *fakeFileSet) pos(file string, line, column int) token.Pos {
|
|
||||||
// TODO(mdempsky): Make use of column.
|
|
||||||
|
|
||||||
// Since we don't know the set of needed file positions, we
|
|
||||||
// reserve maxlines positions per file.
|
|
||||||
const maxlines = 64 * 1024
|
|
||||||
f := s.files[file]
|
|
||||||
if f == nil {
|
|
||||||
f = s.fset.AddFile(file, -1, maxlines)
|
|
||||||
s.files[file] = f
|
|
||||||
// Allocate the fake linebreak indices on first use.
|
|
||||||
// TODO(adonovan): opt: save ~512KB using a more complex scheme?
|
|
||||||
fakeLinesOnce.Do(func() {
|
|
||||||
fakeLines = make([]int, maxlines)
|
|
||||||
for i := range fakeLines {
|
|
||||||
fakeLines[i] = i
|
|
||||||
}
|
|
||||||
})
|
|
||||||
f.SetLines(fakeLines)
|
|
||||||
}
|
|
||||||
|
|
||||||
if line > maxlines {
|
|
||||||
line = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Treat the file as if it contained only newlines
|
|
||||||
// and column=1: use the line number as the offset.
|
|
||||||
return f.Pos(line - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
fakeLines []int
|
|
||||||
fakeLinesOnce sync.Once
|
|
||||||
)
|
|
||||||
|
|
||||||
func chanDir(d int) types2.ChanDir {
|
|
||||||
// tag values must match the constants in cmd/compile/internal/gc/go.go
|
|
||||||
switch d {
|
|
||||||
case 1 /* Crecv */ :
|
|
||||||
return types2.RecvOnly
|
|
||||||
case 2 /* Csend */ :
|
|
||||||
return types2.SendOnly
|
|
||||||
case 3 /* Cboth */ :
|
|
||||||
return types2.SendRecv
|
|
||||||
default:
|
|
||||||
errorf("unexpected channel dir %d", d)
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var predeclared = []types2.Type{
|
|
||||||
// basic types
|
|
||||||
types2.Typ[types2.Bool],
|
|
||||||
types2.Typ[types2.Int],
|
|
||||||
types2.Typ[types2.Int8],
|
|
||||||
types2.Typ[types2.Int16],
|
|
||||||
types2.Typ[types2.Int32],
|
|
||||||
types2.Typ[types2.Int64],
|
|
||||||
types2.Typ[types2.Uint],
|
|
||||||
types2.Typ[types2.Uint8],
|
|
||||||
types2.Typ[types2.Uint16],
|
|
||||||
types2.Typ[types2.Uint32],
|
|
||||||
types2.Typ[types2.Uint64],
|
|
||||||
types2.Typ[types2.Uintptr],
|
|
||||||
types2.Typ[types2.Float32],
|
|
||||||
types2.Typ[types2.Float64],
|
|
||||||
types2.Typ[types2.Complex64],
|
|
||||||
types2.Typ[types2.Complex128],
|
|
||||||
types2.Typ[types2.String],
|
|
||||||
|
|
||||||
// basic type aliases
|
|
||||||
types2.Universe.Lookup("byte").Type(),
|
|
||||||
types2.Universe.Lookup("rune").Type(),
|
|
||||||
|
|
||||||
// error
|
|
||||||
types2.Universe.Lookup("error").Type(),
|
|
||||||
|
|
||||||
// untyped types
|
|
||||||
types2.Typ[types2.UntypedBool],
|
|
||||||
types2.Typ[types2.UntypedInt],
|
|
||||||
types2.Typ[types2.UntypedRune],
|
|
||||||
types2.Typ[types2.UntypedFloat],
|
|
||||||
types2.Typ[types2.UntypedComplex],
|
|
||||||
types2.Typ[types2.UntypedString],
|
|
||||||
types2.Typ[types2.UntypedNil],
|
|
||||||
|
|
||||||
// package unsafe
|
|
||||||
types2.Typ[types2.UnsafePointer],
|
|
||||||
|
|
||||||
// invalid type
|
|
||||||
types2.Typ[types2.Invalid], // only appears in packages with errors
|
|
||||||
|
|
||||||
// used internally by gc; never used by this package or in .a files
|
|
||||||
// not to be confused with the universe any
|
|
||||||
anyType{},
|
|
||||||
|
|
||||||
// comparable
|
|
||||||
types2.Universe.Lookup("comparable").Type(),
|
|
||||||
|
|
||||||
// "any" has special handling: see usage of predeclared.
|
|
||||||
}
|
|
||||||
|
|
||||||
type anyType struct{}
|
type anyType struct{}
|
||||||
|
|
||||||
func (t anyType) Underlying() types2.Type { return t }
|
func (t anyType) Underlying() types2.Type { return t }
|
||||||
|
|
|
||||||
|
|
@ -1241,17 +1241,6 @@ func pruneUnusedAutos(ll []*ir.Name, vis *hairyVisitor) []*ir.Name {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// numNonClosures returns the number of functions in list which are not closures.
|
|
||||||
func numNonClosures(list []*ir.Func) int {
|
|
||||||
count := 0
|
|
||||||
for _, fn := range list {
|
|
||||||
if fn.OClosure == nil {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
func doList(list []ir.Node, do func(ir.Node) bool) bool {
|
func doList(list []ir.Node, do func(ir.Node) bool) bool {
|
||||||
for _, x := range list {
|
for _, x := range list {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
|
|
|
||||||
|
|
@ -399,14 +399,6 @@ func LargestNegativeScoreAdjustment(fn *ir.Func, props *FuncProps) int {
|
||||||
return score
|
return score
|
||||||
}
|
}
|
||||||
|
|
||||||
// LargestPositiveScoreAdjustment tries to estimate the largest possible
|
|
||||||
// positive score adjustment that could be applied to a given callsite.
|
|
||||||
// At the moment we don't have very many positive score adjustments, so
|
|
||||||
// this is just hard-coded, not table-driven.
|
|
||||||
func LargestPositiveScoreAdjustment(fn *ir.Func) int {
|
|
||||||
return adjValues[panicPathAdj] + adjValues[initFuncAdj]
|
|
||||||
}
|
|
||||||
|
|
||||||
// callSiteTab contains entries for each call in the function
|
// callSiteTab contains entries for each call in the function
|
||||||
// currently being processed by InlineCalls; this variable will either
|
// currently being processed by InlineCalls; this variable will either
|
||||||
// be set to 'cstabCache' below (for non-inlinable routines) or to the
|
// be set to 'cstabCache' below (for non-inlinable routines) or to the
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,3 @@ func DeepCopy(pos src.XPos, n Node) Node {
|
||||||
}
|
}
|
||||||
return edit(n)
|
return edit(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyList returns a list of deep copies (using DeepCopy) of the nodes in list.
|
|
||||||
func DeepCopyList(pos src.XPos, list []Node) []Node {
|
|
||||||
var out []Node
|
|
||||||
for _, n := range list {
|
|
||||||
out = append(out, DeepCopy(pos, n))
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -34,15 +34,6 @@ type miniNode struct {
|
||||||
esc uint16
|
esc uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
// posOr returns pos if known, or else n.pos.
|
|
||||||
// For use in DeepCopy.
|
|
||||||
func (n *miniNode) posOr(pos src.XPos) src.XPos {
|
|
||||||
if pos.IsKnown() {
|
|
||||||
return pos
|
|
||||||
}
|
|
||||||
return n.pos
|
|
||||||
}
|
|
||||||
|
|
||||||
// op can be read, but not written.
|
// op can be read, but not written.
|
||||||
// An embedding implementation can provide a SetOp if desired.
|
// An embedding implementation can provide a SetOp if desired.
|
||||||
// (The panicking SetOp is with the other panics below.)
|
// (The panicking SetOp is with the other panics below.)
|
||||||
|
|
|
||||||
|
|
@ -155,19 +155,6 @@ func Any(n Node, cond func(Node) bool) bool {
|
||||||
return do(n)
|
return do(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AnyList calls Any(x, cond) for each node x in the list, in order.
|
|
||||||
// If any call returns true, AnyList stops and returns true.
|
|
||||||
// Otherwise, AnyList returns false after calling Any(x, cond)
|
|
||||||
// for every x in the list.
|
|
||||||
func AnyList(list Nodes, cond func(Node) bool) bool {
|
|
||||||
for _, x := range list {
|
|
||||||
if Any(x, cond) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// EditChildren edits the child nodes of n, replacing each child x with edit(x).
|
// EditChildren edits the child nodes of n, replacing each child x with edit(x).
|
||||||
//
|
//
|
||||||
// Note that EditChildren(n, edit) only calls edit(x) for n's immediate children.
|
// Note that EditChildren(n, edit) only calls edit(x) for n's immediate children.
|
||||||
|
|
|
||||||
|
|
@ -1065,6 +1065,17 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
||||||
{Type: obj.TYPE_CONST, Offset: int64((v.AuxInt >> 0) & 0x1f)},
|
{Type: obj.TYPE_CONST, Offset: int64((v.AuxInt >> 0) & 0x1f)},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
case ssa.OpLOONG64ADDshiftLLV:
|
||||||
|
// ADDshiftLLV Rarg0, Rarg1, $shift
|
||||||
|
// ALSLV $shift, Rarg1, Rarg0, Rtmp
|
||||||
|
p := s.Prog(v.Op.Asm())
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.From.Offset = v.AuxInt
|
||||||
|
p.Reg = v.Args[1].Reg()
|
||||||
|
p.AddRestSourceReg(v.Args[0].Reg())
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = v.Reg()
|
||||||
|
|
||||||
case ssa.OpClobber, ssa.OpClobberReg:
|
case ssa.OpClobber, ssa.OpClobberReg:
|
||||||
// TODO: implement for clobberdead experiment. Nop is ok for now.
|
// TODO: implement for clobberdead experiment. Nop is ok for now.
|
||||||
default:
|
default:
|
||||||
|
|
@ -1075,8 +1086,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
||||||
var blockJump = map[ssa.BlockKind]struct {
|
var blockJump = map[ssa.BlockKind]struct {
|
||||||
asm, invasm obj.As
|
asm, invasm obj.As
|
||||||
}{
|
}{
|
||||||
ssa.BlockLOONG64EQ: {loong64.ABEQ, loong64.ABNE},
|
ssa.BlockLOONG64EQZ: {loong64.ABEQ, loong64.ABNE},
|
||||||
ssa.BlockLOONG64NE: {loong64.ABNE, loong64.ABEQ},
|
ssa.BlockLOONG64NEZ: {loong64.ABNE, loong64.ABEQ},
|
||||||
ssa.BlockLOONG64LTZ: {loong64.ABLTZ, loong64.ABGEZ},
|
ssa.BlockLOONG64LTZ: {loong64.ABLTZ, loong64.ABGEZ},
|
||||||
ssa.BlockLOONG64GEZ: {loong64.ABGEZ, loong64.ABLTZ},
|
ssa.BlockLOONG64GEZ: {loong64.ABGEZ, loong64.ABLTZ},
|
||||||
ssa.BlockLOONG64LEZ: {loong64.ABLEZ, loong64.ABGTZ},
|
ssa.BlockLOONG64LEZ: {loong64.ABLEZ, loong64.ABGTZ},
|
||||||
|
|
@ -1102,7 +1113,7 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
|
||||||
case ssa.BlockExit, ssa.BlockRetJmp:
|
case ssa.BlockExit, ssa.BlockRetJmp:
|
||||||
case ssa.BlockRet:
|
case ssa.BlockRet:
|
||||||
s.Prog(obj.ARET)
|
s.Prog(obj.ARET)
|
||||||
case ssa.BlockLOONG64EQ, ssa.BlockLOONG64NE,
|
case ssa.BlockLOONG64EQZ, ssa.BlockLOONG64NEZ,
|
||||||
ssa.BlockLOONG64LTZ, ssa.BlockLOONG64GEZ,
|
ssa.BlockLOONG64LTZ, ssa.BlockLOONG64GEZ,
|
||||||
ssa.BlockLOONG64LEZ, ssa.BlockLOONG64GTZ,
|
ssa.BlockLOONG64LEZ, ssa.BlockLOONG64GTZ,
|
||||||
ssa.BlockLOONG64BEQ, ssa.BlockLOONG64BNE,
|
ssa.BlockLOONG64BEQ, ssa.BlockLOONG64BNE,
|
||||||
|
|
@ -1132,7 +1143,7 @@ func ssaGenBlock(s *ssagen.State, b, next *ssa.Block) {
|
||||||
p.From.Type = obj.TYPE_REG
|
p.From.Type = obj.TYPE_REG
|
||||||
p.From.Reg = b.Controls[0].Reg()
|
p.From.Reg = b.Controls[0].Reg()
|
||||||
p.Reg = b.Controls[1].Reg()
|
p.Reg = b.Controls[1].Reg()
|
||||||
case ssa.BlockLOONG64EQ, ssa.BlockLOONG64NE,
|
case ssa.BlockLOONG64EQZ, ssa.BlockLOONG64NEZ,
|
||||||
ssa.BlockLOONG64LTZ, ssa.BlockLOONG64GEZ,
|
ssa.BlockLOONG64LTZ, ssa.BlockLOONG64GEZ,
|
||||||
ssa.BlockLOONG64LEZ, ssa.BlockLOONG64GTZ,
|
ssa.BlockLOONG64LEZ, ssa.BlockLOONG64GTZ,
|
||||||
ssa.BlockLOONG64FPT, ssa.BlockLOONG64FPF:
|
ssa.BlockLOONG64FPT, ssa.BlockLOONG64FPF:
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ type poser interface{ Pos() syntax.Pos }
|
||||||
type ender interface{ End() syntax.Pos }
|
type ender interface{ End() syntax.Pos }
|
||||||
|
|
||||||
func (m *posMap) pos(p poser) src.XPos { return m.makeXPos(p.Pos()) }
|
func (m *posMap) pos(p poser) src.XPos { return m.makeXPos(p.Pos()) }
|
||||||
func (m *posMap) end(p ender) src.XPos { return m.makeXPos(p.End()) }
|
|
||||||
|
|
||||||
func (m *posMap) makeXPos(pos syntax.Pos) src.XPos {
|
func (m *posMap) makeXPos(pos syntax.Pos) src.XPos {
|
||||||
// Predeclared objects (e.g., the result parameter for error.Error)
|
// Predeclared objects (e.g., the result parameter for error.Error)
|
||||||
|
|
|
||||||
|
|
@ -3681,17 +3681,6 @@ func expandInline(fn *ir.Func, pri pkgReaderIndex) {
|
||||||
typecheck.Target.Funcs = typecheck.Target.Funcs[:topdcls]
|
typecheck.Target.Funcs = typecheck.Target.Funcs[:topdcls]
|
||||||
}
|
}
|
||||||
|
|
||||||
// usedLocals returns a set of local variables that are used within body.
|
|
||||||
func usedLocals(body []ir.Node) ir.NameSet {
|
|
||||||
var used ir.NameSet
|
|
||||||
ir.VisitList(body, func(n ir.Node) {
|
|
||||||
if n, ok := n.(*ir.Name); ok && n.Op() == ir.ONAME && n.Class == ir.PAUTO {
|
|
||||||
used.Add(n)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return used
|
|
||||||
}
|
|
||||||
|
|
||||||
// @@@ Method wrappers
|
// @@@ Method wrappers
|
||||||
//
|
//
|
||||||
// Here we handle constructing "method wrappers," alternative entry
|
// Here we handle constructing "method wrappers," alternative entry
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ package noder
|
||||||
import (
|
import (
|
||||||
"cmp"
|
"cmp"
|
||||||
"fmt"
|
"fmt"
|
||||||
"internal/buildcfg"
|
|
||||||
"internal/pkgbits"
|
"internal/pkgbits"
|
||||||
"internal/types/errors"
|
"internal/types/errors"
|
||||||
"io"
|
"io"
|
||||||
|
|
@ -464,11 +463,8 @@ func readPackage(pr *pkgReader, importpkg *types.Pkg, localStub bool) {
|
||||||
// writeUnifiedExport writes to `out` the finalized, self-contained
|
// writeUnifiedExport writes to `out` the finalized, self-contained
|
||||||
// Unified IR export data file for the current compilation unit.
|
// Unified IR export data file for the current compilation unit.
|
||||||
func writeUnifiedExport(out io.Writer) {
|
func writeUnifiedExport(out io.Writer) {
|
||||||
// Use V2 as the encoded version aliastypeparams GOEXPERIMENT is enabled.
|
// Use V2 as the encoded version for aliastypeparams.
|
||||||
version := pkgbits.V1
|
version := pkgbits.V2
|
||||||
if buildcfg.Experiment.AliasTypeParams {
|
|
||||||
version = pkgbits.V2
|
|
||||||
}
|
|
||||||
l := linker{
|
l := linker{
|
||||||
pw: pkgbits.NewPkgEncoder(version, base.Debug.SyncFrames),
|
pw: pkgbits.NewPkgEncoder(version, base.Debug.SyncFrames),
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,11 +96,8 @@ type pkgWriter struct {
|
||||||
// newPkgWriter returns an initialized pkgWriter for the specified
|
// newPkgWriter returns an initialized pkgWriter for the specified
|
||||||
// package.
|
// package.
|
||||||
func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info, otherInfo map[*syntax.FuncLit]bool) *pkgWriter {
|
func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info, otherInfo map[*syntax.FuncLit]bool) *pkgWriter {
|
||||||
// Use V2 as the encoded version aliastypeparams GOEXPERIMENT is enabled.
|
// Use V2 as the encoded version for aliastypeparams.
|
||||||
version := pkgbits.V1
|
version := pkgbits.V2
|
||||||
if buildcfg.Experiment.AliasTypeParams {
|
|
||||||
version = pkgbits.V2
|
|
||||||
}
|
|
||||||
return &pkgWriter{
|
return &pkgWriter{
|
||||||
PkgEncoder: pkgbits.NewPkgEncoder(version, base.Debug.SyncFrames),
|
PkgEncoder: pkgbits.NewPkgEncoder(version, base.Debug.SyncFrames),
|
||||||
|
|
||||||
|
|
@ -2413,11 +2410,6 @@ func (p posVar) String() string {
|
||||||
return p.pos.String() + ":" + p.var_.String()
|
return p.pos.String() + ":" + p.var_.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *writer) exprList(expr syntax.Expr) {
|
|
||||||
w.Sync(pkgbits.SyncExprList)
|
|
||||||
w.exprs(syntax.UnpackListExpr(expr))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *writer) exprs(exprs []syntax.Expr) {
|
func (w *writer) exprs(exprs []syntax.Expr) {
|
||||||
w.Sync(pkgbits.SyncExprs)
|
w.Sync(pkgbits.SyncExprs)
|
||||||
w.Len(len(exprs))
|
w.Len(len(exprs))
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"cmd/compile/internal/types"
|
"cmd/compile/internal/types"
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"cmd/internal/obj/ppc64"
|
"cmd/internal/obj/ppc64"
|
||||||
|
"internal/abi"
|
||||||
"internal/buildcfg"
|
"internal/buildcfg"
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -1913,12 +1914,90 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
||||||
// AuxInt encodes how many buffer entries we need.
|
// AuxInt encodes how many buffer entries we need.
|
||||||
p.To.Sym = ir.Syms.GCWriteBarrier[v.AuxInt-1]
|
p.To.Sym = ir.Syms.GCWriteBarrier[v.AuxInt-1]
|
||||||
|
|
||||||
case ssa.OpPPC64LoweredPanicBoundsA, ssa.OpPPC64LoweredPanicBoundsB, ssa.OpPPC64LoweredPanicBoundsC:
|
case ssa.OpPPC64LoweredPanicBoundsRR, ssa.OpPPC64LoweredPanicBoundsRC, ssa.OpPPC64LoweredPanicBoundsCR, ssa.OpPPC64LoweredPanicBoundsCC:
|
||||||
p := s.Prog(obj.ACALL)
|
// Compute the constant we put in the PCData entry for this call.
|
||||||
|
code, signed := ssa.BoundsKind(v.AuxInt).Code()
|
||||||
|
xIsReg := false
|
||||||
|
yIsReg := false
|
||||||
|
xVal := 0
|
||||||
|
yVal := 0
|
||||||
|
switch v.Op {
|
||||||
|
case ssa.OpPPC64LoweredPanicBoundsRR:
|
||||||
|
xIsReg = true
|
||||||
|
xVal = int(v.Args[0].Reg() - ppc64.REG_R3)
|
||||||
|
yIsReg = true
|
||||||
|
yVal = int(v.Args[1].Reg() - ppc64.REG_R3)
|
||||||
|
case ssa.OpPPC64LoweredPanicBoundsRC:
|
||||||
|
xIsReg = true
|
||||||
|
xVal = int(v.Args[0].Reg() - ppc64.REG_R3)
|
||||||
|
c := v.Aux.(ssa.PanicBoundsC).C
|
||||||
|
if c >= 0 && c <= abi.BoundsMaxConst {
|
||||||
|
yVal = int(c)
|
||||||
|
} else {
|
||||||
|
// Move constant to a register
|
||||||
|
yIsReg = true
|
||||||
|
if yVal == xVal {
|
||||||
|
yVal = 1
|
||||||
|
}
|
||||||
|
p := s.Prog(ppc64.AMOVD)
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.From.Offset = c
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = ppc64.REG_R3 + int16(yVal)
|
||||||
|
}
|
||||||
|
case ssa.OpPPC64LoweredPanicBoundsCR:
|
||||||
|
yIsReg = true
|
||||||
|
yVal := int(v.Args[0].Reg() - ppc64.REG_R3)
|
||||||
|
c := v.Aux.(ssa.PanicBoundsC).C
|
||||||
|
if c >= 0 && c <= abi.BoundsMaxConst {
|
||||||
|
xVal = int(c)
|
||||||
|
} else {
|
||||||
|
// Move constant to a register
|
||||||
|
if xVal == yVal {
|
||||||
|
xVal = 1
|
||||||
|
}
|
||||||
|
p := s.Prog(ppc64.AMOVD)
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.From.Offset = c
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = ppc64.REG_R3 + int16(xVal)
|
||||||
|
}
|
||||||
|
case ssa.OpPPC64LoweredPanicBoundsCC:
|
||||||
|
c := v.Aux.(ssa.PanicBoundsCC).Cx
|
||||||
|
if c >= 0 && c <= abi.BoundsMaxConst {
|
||||||
|
xVal = int(c)
|
||||||
|
} else {
|
||||||
|
// Move constant to a register
|
||||||
|
xIsReg = true
|
||||||
|
p := s.Prog(ppc64.AMOVD)
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.From.Offset = c
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = ppc64.REG_R3 + int16(xVal)
|
||||||
|
}
|
||||||
|
c = v.Aux.(ssa.PanicBoundsCC).Cy
|
||||||
|
if c >= 0 && c <= abi.BoundsMaxConst {
|
||||||
|
yVal = int(c)
|
||||||
|
} else {
|
||||||
|
// Move constant to a register
|
||||||
|
yIsReg = true
|
||||||
|
yVal = 1
|
||||||
|
p := s.Prog(ppc64.AMOVD)
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.From.Offset = c
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = ppc64.REG_R3 + int16(yVal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c := abi.BoundsEncode(code, signed, xIsReg, yIsReg, xVal, yVal)
|
||||||
|
|
||||||
|
p := s.Prog(obj.APCDATA)
|
||||||
|
p.From.SetConst(abi.PCDATA_PanicBounds)
|
||||||
|
p.To.SetConst(int64(c))
|
||||||
|
p = s.Prog(obj.ACALL)
|
||||||
p.To.Type = obj.TYPE_MEM
|
p.To.Type = obj.TYPE_MEM
|
||||||
p.To.Name = obj.NAME_EXTERN
|
p.To.Name = obj.NAME_EXTERN
|
||||||
p.To.Sym = ssagen.BoundsCheckFunc[v.AuxInt]
|
p.To.Sym = ir.Syms.PanicBounds
|
||||||
s.UseArgs(16) // space used in callee args area by assembly stubs
|
|
||||||
|
|
||||||
case ssa.OpPPC64LoweredNilCheck:
|
case ssa.OpPPC64LoweredNilCheck:
|
||||||
if buildcfg.GOOS == "aix" {
|
if buildcfg.GOOS == "aix" {
|
||||||
|
|
|
||||||
|
|
@ -1468,10 +1468,3 @@ func MarkUsedIfaceMethod(n *ir.CallExpr) {
|
||||||
Add: InterfaceMethodOffset(ityp, midx),
|
Add: InterfaceMethodOffset(ityp, midx),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func deref(t *types.Type) *types.Type {
|
|
||||||
if t.IsPtr() {
|
|
||||||
return t.Elem()
|
|
||||||
}
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -417,9 +417,10 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
||||||
p.To.Type = obj.TYPE_REG
|
p.To.Type = obj.TYPE_REG
|
||||||
p.To.Reg = r
|
p.To.Reg = r
|
||||||
case ssa.OpRISCV64FSQRTS, ssa.OpRISCV64FNEGS, ssa.OpRISCV64FABSD, ssa.OpRISCV64FSQRTD, ssa.OpRISCV64FNEGD,
|
case ssa.OpRISCV64FSQRTS, ssa.OpRISCV64FNEGS, ssa.OpRISCV64FABSD, ssa.OpRISCV64FSQRTD, ssa.OpRISCV64FNEGD,
|
||||||
ssa.OpRISCV64FMVSX, ssa.OpRISCV64FMVDX,
|
ssa.OpRISCV64FMVSX, ssa.OpRISCV64FMVXS, ssa.OpRISCV64FMVDX, ssa.OpRISCV64FMVXD,
|
||||||
ssa.OpRISCV64FCVTSW, ssa.OpRISCV64FCVTSL, ssa.OpRISCV64FCVTWS, ssa.OpRISCV64FCVTLS,
|
ssa.OpRISCV64FCVTSW, ssa.OpRISCV64FCVTSL, ssa.OpRISCV64FCVTWS, ssa.OpRISCV64FCVTLS,
|
||||||
ssa.OpRISCV64FCVTDW, ssa.OpRISCV64FCVTDL, ssa.OpRISCV64FCVTWD, ssa.OpRISCV64FCVTLD, ssa.OpRISCV64FCVTDS, ssa.OpRISCV64FCVTSD,
|
ssa.OpRISCV64FCVTDW, ssa.OpRISCV64FCVTDL, ssa.OpRISCV64FCVTWD, ssa.OpRISCV64FCVTLD, ssa.OpRISCV64FCVTDS, ssa.OpRISCV64FCVTSD,
|
||||||
|
ssa.OpRISCV64FCLASSS, ssa.OpRISCV64FCLASSD,
|
||||||
ssa.OpRISCV64NOT, ssa.OpRISCV64NEG, ssa.OpRISCV64NEGW, ssa.OpRISCV64CLZ, ssa.OpRISCV64CLZW, ssa.OpRISCV64CTZ, ssa.OpRISCV64CTZW,
|
ssa.OpRISCV64NOT, ssa.OpRISCV64NEG, ssa.OpRISCV64NEGW, ssa.OpRISCV64CLZ, ssa.OpRISCV64CLZW, ssa.OpRISCV64CTZ, ssa.OpRISCV64CTZW,
|
||||||
ssa.OpRISCV64REV8, ssa.OpRISCV64CPOP, ssa.OpRISCV64CPOPW:
|
ssa.OpRISCV64REV8, ssa.OpRISCV64CPOP, ssa.OpRISCV64CPOPW:
|
||||||
p := s.Prog(v.Op.Asm())
|
p := s.Prog(v.Op.Asm())
|
||||||
|
|
|
||||||
|
|
@ -264,24 +264,6 @@
|
||||||
(Move [8] dst src mem) => (MOVQstore dst (MOVQload src mem) mem)
|
(Move [8] dst src mem) => (MOVQstore dst (MOVQload src mem) mem)
|
||||||
(Move [16] dst src mem) => (MOVOstore dst (MOVOload src mem) mem)
|
(Move [16] dst src mem) => (MOVOstore dst (MOVOload src mem) mem)
|
||||||
|
|
||||||
(Move [32] dst src mem) =>
|
|
||||||
(Move [16]
|
|
||||||
(OffPtr <dst.Type> dst [16])
|
|
||||||
(OffPtr <src.Type> src [16])
|
|
||||||
(Move [16] dst src mem))
|
|
||||||
|
|
||||||
(Move [48] dst src mem) =>
|
|
||||||
(Move [32]
|
|
||||||
(OffPtr <dst.Type> dst [16])
|
|
||||||
(OffPtr <src.Type> src [16])
|
|
||||||
(Move [16] dst src mem))
|
|
||||||
|
|
||||||
(Move [64] dst src mem) =>
|
|
||||||
(Move [32]
|
|
||||||
(OffPtr <dst.Type> dst [32])
|
|
||||||
(OffPtr <src.Type> src [32])
|
|
||||||
(Move [32] dst src mem))
|
|
||||||
|
|
||||||
(Move [3] dst src mem) =>
|
(Move [3] dst src mem) =>
|
||||||
(MOVBstore [2] dst (MOVBload [2] src mem)
|
(MOVBstore [2] dst (MOVBload [2] src mem)
|
||||||
(MOVWstore dst (MOVWload src mem) mem))
|
(MOVWstore dst (MOVWload src mem) mem))
|
||||||
|
|
@ -310,28 +292,19 @@
|
||||||
(MOVQstore [int32(s-8)] dst (MOVQload [int32(s-8)] src mem)
|
(MOVQstore [int32(s-8)] dst (MOVQload [int32(s-8)] src mem)
|
||||||
(MOVQstore dst (MOVQload src mem) mem))
|
(MOVQstore dst (MOVQload src mem) mem))
|
||||||
|
|
||||||
// Adjust moves to be a multiple of 16 bytes.
|
// Copying up to 192 bytes uses straightline code.
|
||||||
(Move [s] dst src mem)
|
(Move [s] dst src mem) && s > 16 && s < 192 && logLargeCopy(v, s) => (LoweredMove [s] dst src mem)
|
||||||
&& s > 16 && s%16 != 0 && s%16 <= 8 =>
|
|
||||||
(Move [s-s%16]
|
|
||||||
(OffPtr <dst.Type> dst [s%16])
|
|
||||||
(OffPtr <src.Type> src [s%16])
|
|
||||||
(MOVQstore dst (MOVQload src mem) mem))
|
|
||||||
(Move [s] dst src mem)
|
|
||||||
&& s > 16 && s%16 != 0 && s%16 > 8 =>
|
|
||||||
(Move [s-s%16]
|
|
||||||
(OffPtr <dst.Type> dst [s%16])
|
|
||||||
(OffPtr <src.Type> src [s%16])
|
|
||||||
(MOVOstore dst (MOVOload src mem) mem))
|
|
||||||
|
|
||||||
// Medium copying uses a duff device.
|
// Copying up to ~1KB uses a small loop.
|
||||||
(Move [s] dst src mem)
|
(Move [s] dst src mem) && s >= 192 && s <= repMoveThreshold && logLargeCopy(v, s) => (LoweredMoveLoop [s] dst src mem)
|
||||||
&& s > 64 && s <= 16*64 && s%16 == 0
|
|
||||||
&& logLargeCopy(v, s) =>
|
|
||||||
(DUFFCOPY [s] dst src mem)
|
|
||||||
|
|
||||||
// Large copying uses REP MOVSQ.
|
// Large copying uses REP MOVSQ.
|
||||||
(Move [s] dst src mem) && s > 16*64 && s%8 == 0 && logLargeCopy(v, s) =>
|
(Move [s] dst src mem) && s > repMoveThreshold && s%8 != 0 =>
|
||||||
|
(Move [s-s%8]
|
||||||
|
(OffPtr <dst.Type> dst [s%8])
|
||||||
|
(OffPtr <src.Type> src [s%8])
|
||||||
|
(MOVQstore dst (MOVQload src mem) mem))
|
||||||
|
(Move [s] dst src mem) && s > repMoveThreshold && s%8 == 0 && logLargeCopy(v, s) =>
|
||||||
(REPMOVSQ dst src (MOVQconst [s/8]) mem)
|
(REPMOVSQ dst src (MOVQconst [s/8]) mem)
|
||||||
|
|
||||||
// Lowering Zero instructions
|
// Lowering Zero instructions
|
||||||
|
|
@ -606,31 +579,31 @@
|
||||||
// mutandis, for UGE and SETAE, and CC and SETCC.
|
// mutandis, for UGE and SETAE, and CC and SETCC.
|
||||||
((NE|EQ) (TESTL (SHLL (MOVLconst [1]) x) y)) => ((ULT|UGE) (BTL x y))
|
((NE|EQ) (TESTL (SHLL (MOVLconst [1]) x) y)) => ((ULT|UGE) (BTL x y))
|
||||||
((NE|EQ) (TESTQ (SHLQ (MOVQconst [1]) x) y)) => ((ULT|UGE) (BTQ x y))
|
((NE|EQ) (TESTQ (SHLQ (MOVQconst [1]) x) y)) => ((ULT|UGE) (BTQ x y))
|
||||||
((NE|EQ) (TESTLconst [c] x)) && isUint32PowerOfTwo(int64(c))
|
((NE|EQ) (TESTLconst [c] x)) && isUnsignedPowerOfTwo(uint32(c))
|
||||||
=> ((ULT|UGE) (BTLconst [int8(log32(c))] x))
|
=> ((ULT|UGE) (BTLconst [int8(log32u(uint32(c)))] x))
|
||||||
((NE|EQ) (TESTQconst [c] x)) && isUint64PowerOfTwo(int64(c))
|
((NE|EQ) (TESTQconst [c] x)) && isUnsignedPowerOfTwo(uint64(c))
|
||||||
=> ((ULT|UGE) (BTQconst [int8(log32(c))] x))
|
=> ((ULT|UGE) (BTQconst [int8(log32u(uint32(c)))] x))
|
||||||
((NE|EQ) (TESTQ (MOVQconst [c]) x)) && isUint64PowerOfTwo(c)
|
((NE|EQ) (TESTQ (MOVQconst [c]) x)) && isUnsignedPowerOfTwo(uint64(c))
|
||||||
=> ((ULT|UGE) (BTQconst [int8(log64(c))] x))
|
=> ((ULT|UGE) (BTQconst [int8(log64u(uint64(c)))] x))
|
||||||
(SET(NE|EQ) (TESTL (SHLL (MOVLconst [1]) x) y)) => (SET(B|AE) (BTL x y))
|
(SET(NE|EQ) (TESTL (SHLL (MOVLconst [1]) x) y)) => (SET(B|AE) (BTL x y))
|
||||||
(SET(NE|EQ) (TESTQ (SHLQ (MOVQconst [1]) x) y)) => (SET(B|AE) (BTQ x y))
|
(SET(NE|EQ) (TESTQ (SHLQ (MOVQconst [1]) x) y)) => (SET(B|AE) (BTQ x y))
|
||||||
(SET(NE|EQ) (TESTLconst [c] x)) && isUint32PowerOfTwo(int64(c))
|
(SET(NE|EQ) (TESTLconst [c] x)) && isUnsignedPowerOfTwo(uint32(c))
|
||||||
=> (SET(B|AE) (BTLconst [int8(log32(c))] x))
|
=> (SET(B|AE) (BTLconst [int8(log32u(uint32(c)))] x))
|
||||||
(SET(NE|EQ) (TESTQconst [c] x)) && isUint64PowerOfTwo(int64(c))
|
(SET(NE|EQ) (TESTQconst [c] x)) && isUnsignedPowerOfTwo(uint64(c))
|
||||||
=> (SET(B|AE) (BTQconst [int8(log32(c))] x))
|
=> (SET(B|AE) (BTQconst [int8(log32u(uint32(c)))] x))
|
||||||
(SET(NE|EQ) (TESTQ (MOVQconst [c]) x)) && isUint64PowerOfTwo(c)
|
(SET(NE|EQ) (TESTQ (MOVQconst [c]) x)) && isUnsignedPowerOfTwo(uint64(c))
|
||||||
=> (SET(B|AE) (BTQconst [int8(log64(c))] x))
|
=> (SET(B|AE) (BTQconst [int8(log64u(uint64(c)))] x))
|
||||||
// SET..store variant
|
// SET..store variant
|
||||||
(SET(NE|EQ)store [off] {sym} ptr (TESTL (SHLL (MOVLconst [1]) x) y) mem)
|
(SET(NE|EQ)store [off] {sym} ptr (TESTL (SHLL (MOVLconst [1]) x) y) mem)
|
||||||
=> (SET(B|AE)store [off] {sym} ptr (BTL x y) mem)
|
=> (SET(B|AE)store [off] {sym} ptr (BTL x y) mem)
|
||||||
(SET(NE|EQ)store [off] {sym} ptr (TESTQ (SHLQ (MOVQconst [1]) x) y) mem)
|
(SET(NE|EQ)store [off] {sym} ptr (TESTQ (SHLQ (MOVQconst [1]) x) y) mem)
|
||||||
=> (SET(B|AE)store [off] {sym} ptr (BTQ x y) mem)
|
=> (SET(B|AE)store [off] {sym} ptr (BTQ x y) mem)
|
||||||
(SET(NE|EQ)store [off] {sym} ptr (TESTLconst [c] x) mem) && isUint32PowerOfTwo(int64(c))
|
(SET(NE|EQ)store [off] {sym} ptr (TESTLconst [c] x) mem) && isUnsignedPowerOfTwo(uint32(c))
|
||||||
=> (SET(B|AE)store [off] {sym} ptr (BTLconst [int8(log32(c))] x) mem)
|
=> (SET(B|AE)store [off] {sym} ptr (BTLconst [int8(log32u(uint32(c)))] x) mem)
|
||||||
(SET(NE|EQ)store [off] {sym} ptr (TESTQconst [c] x) mem) && isUint64PowerOfTwo(int64(c))
|
(SET(NE|EQ)store [off] {sym} ptr (TESTQconst [c] x) mem) && isUnsignedPowerOfTwo(uint64(c))
|
||||||
=> (SET(B|AE)store [off] {sym} ptr (BTQconst [int8(log32(c))] x) mem)
|
=> (SET(B|AE)store [off] {sym} ptr (BTQconst [int8(log32u(uint32(c)))] x) mem)
|
||||||
(SET(NE|EQ)store [off] {sym} ptr (TESTQ (MOVQconst [c]) x) mem) && isUint64PowerOfTwo(c)
|
(SET(NE|EQ)store [off] {sym} ptr (TESTQ (MOVQconst [c]) x) mem) && isUnsignedPowerOfTwo(uint64(c))
|
||||||
=> (SET(B|AE)store [off] {sym} ptr (BTQconst [int8(log64(c))] x) mem)
|
=> (SET(B|AE)store [off] {sym} ptr (BTQconst [int8(log64u(uint64(c)))] x) mem)
|
||||||
|
|
||||||
// Handle bit-testing in the form (a>>b)&1 != 0 by building the above rules
|
// Handle bit-testing in the form (a>>b)&1 != 0 by building the above rules
|
||||||
// and further combining shifts.
|
// and further combining shifts.
|
||||||
|
|
@ -655,14 +628,14 @@
|
||||||
(XOR(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y) x) => (BTC(Q|L) x y)
|
(XOR(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y) x) => (BTC(Q|L) x y)
|
||||||
// Note: only convert OR/XOR to BTS/BTC if the constant wouldn't fit in
|
// Note: only convert OR/XOR to BTS/BTC if the constant wouldn't fit in
|
||||||
// the constant field of the OR/XOR instruction. See issue 61694.
|
// the constant field of the OR/XOR instruction. See issue 61694.
|
||||||
((OR|XOR)Q (MOVQconst [c]) x) && isUint64PowerOfTwo(c) && uint64(c) >= 1<<31 => (BT(S|C)Qconst [int8(log64(c))] x)
|
((OR|XOR)Q (MOVQconst [c]) x) && isUnsignedPowerOfTwo(uint64(c)) && uint64(c) >= 1<<31 => (BT(S|C)Qconst [int8(log64u(uint64(c)))] x)
|
||||||
|
|
||||||
// Recognize bit clearing: a &^= 1<<b
|
// Recognize bit clearing: a &^= 1<<b
|
||||||
(AND(Q|L) (NOT(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y)) x) => (BTR(Q|L) x y)
|
(AND(Q|L) (NOT(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y)) x) => (BTR(Q|L) x y)
|
||||||
(ANDN(Q|L) x (SHL(Q|L) (MOV(Q|L)const [1]) y)) => (BTR(Q|L) x y)
|
(ANDN(Q|L) x (SHL(Q|L) (MOV(Q|L)const [1]) y)) => (BTR(Q|L) x y)
|
||||||
// Note: only convert AND to BTR if the constant wouldn't fit in
|
// Note: only convert AND to BTR if the constant wouldn't fit in
|
||||||
// the constant field of the AND instruction. See issue 61694.
|
// the constant field of the AND instruction. See issue 61694.
|
||||||
(ANDQ (MOVQconst [c]) x) && isUint64PowerOfTwo(^c) && uint64(^c) >= 1<<31 => (BTRQconst [int8(log64(^c))] x)
|
(ANDQ (MOVQconst [c]) x) && isUnsignedPowerOfTwo(uint64(^c)) && uint64(^c) >= 1<<31 => (BTRQconst [int8(log64u(uint64(^c)))] x)
|
||||||
|
|
||||||
// Special-case bit patterns on first/last bit.
|
// Special-case bit patterns on first/last bit.
|
||||||
// generic.rules changes ANDs of high-part/low-part masks into a couple of shifts,
|
// generic.rules changes ANDs of high-part/low-part masks into a couple of shifts,
|
||||||
|
|
|
||||||
|
|
@ -1014,20 +1014,38 @@ func init() {
|
||||||
// arg0 = destination pointer
|
// arg0 = destination pointer
|
||||||
// arg1 = source pointer
|
// arg1 = source pointer
|
||||||
// arg2 = mem
|
// arg2 = mem
|
||||||
// auxint = # of bytes to copy, must be multiple of 16
|
// auxint = # of bytes to copy
|
||||||
// returns memory
|
// returns memory
|
||||||
{
|
{
|
||||||
name: "DUFFCOPY",
|
name: "LoweredMove",
|
||||||
aux: "Int64",
|
aux: "Int64",
|
||||||
argLength: 3,
|
argLength: 3,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []regMask{buildReg("DI"), buildReg("SI")},
|
inputs: []regMask{gp, gp},
|
||||||
clobbers: buildReg("DI SI X0"), // uses X0 as a temporary
|
clobbers: buildReg("X14"), // uses X14 as a temporary
|
||||||
},
|
},
|
||||||
clobberFlags: true,
|
faultOnNilArg0: true,
|
||||||
//faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point
|
faultOnNilArg1: true,
|
||||||
//faultOnNilArg1: true,
|
},
|
||||||
unsafePoint: true, // FP maintenance around DUFFCOPY can be clobbered by interrupts
|
// arg0 = destination pointer
|
||||||
|
// arg1 = source pointer
|
||||||
|
// arg2 = mem
|
||||||
|
// auxint = # of bytes to copy
|
||||||
|
// returns memory
|
||||||
|
{
|
||||||
|
name: "LoweredMoveLoop",
|
||||||
|
aux: "Int64",
|
||||||
|
argLength: 3,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []regMask{gp, gp},
|
||||||
|
clobbers: buildReg("X14"), // uses X14 as a temporary
|
||||||
|
clobbersArg0: true,
|
||||||
|
clobbersArg1: true,
|
||||||
|
},
|
||||||
|
clobberFlags: true,
|
||||||
|
faultOnNilArg0: true,
|
||||||
|
faultOnNilArg1: true,
|
||||||
|
needIntTemp: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// arg0 = destination pointer
|
// arg0 = destination pointer
|
||||||
|
|
|
||||||
|
|
@ -392,44 +392,8 @@
|
||||||
(Zero [16] ptr mem) =>
|
(Zero [16] ptr mem) =>
|
||||||
(STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem)
|
(STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem)
|
||||||
|
|
||||||
(Zero [32] ptr mem) =>
|
(Zero [s] ptr mem) && s > 16 && s < 192 => (LoweredZero [s] ptr mem)
|
||||||
(STP [16] ptr (MOVDconst [0]) (MOVDconst [0])
|
(Zero [s] ptr mem) && s >= 192 => (LoweredZeroLoop [s] ptr mem)
|
||||||
(STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem))
|
|
||||||
|
|
||||||
(Zero [48] ptr mem) =>
|
|
||||||
(STP [32] ptr (MOVDconst [0]) (MOVDconst [0])
|
|
||||||
(STP [16] ptr (MOVDconst [0]) (MOVDconst [0])
|
|
||||||
(STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem)))
|
|
||||||
|
|
||||||
(Zero [64] ptr mem) =>
|
|
||||||
(STP [48] ptr (MOVDconst [0]) (MOVDconst [0])
|
|
||||||
(STP [32] ptr (MOVDconst [0]) (MOVDconst [0])
|
|
||||||
(STP [16] ptr (MOVDconst [0]) (MOVDconst [0])
|
|
||||||
(STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem))))
|
|
||||||
|
|
||||||
// strip off fractional word zeroing
|
|
||||||
(Zero [s] ptr mem) && s%16 != 0 && s%16 <= 8 && s > 16 =>
|
|
||||||
(Zero [8]
|
|
||||||
(OffPtr <ptr.Type> ptr [s-8])
|
|
||||||
(Zero [s-s%16] ptr mem))
|
|
||||||
(Zero [s] ptr mem) && s%16 != 0 && s%16 > 8 && s > 16 =>
|
|
||||||
(Zero [16]
|
|
||||||
(OffPtr <ptr.Type> ptr [s-16])
|
|
||||||
(Zero [s-s%16] ptr mem))
|
|
||||||
|
|
||||||
// medium zeroing uses a duff device
|
|
||||||
// 4, 16, and 64 are magic constants, see runtime/mkduff.go
|
|
||||||
(Zero [s] ptr mem)
|
|
||||||
&& s%16 == 0 && s > 64 && s <= 16*64 =>
|
|
||||||
(DUFFZERO [4 * (64 - s/16)] ptr mem)
|
|
||||||
|
|
||||||
// large zeroing uses a loop
|
|
||||||
(Zero [s] ptr mem)
|
|
||||||
&& s%16 == 0 && s > 16*64 =>
|
|
||||||
(LoweredZero
|
|
||||||
ptr
|
|
||||||
(ADDconst <ptr.Type> [s-16] ptr)
|
|
||||||
mem)
|
|
||||||
|
|
||||||
// moves
|
// moves
|
||||||
(Move [0] _ _ mem) => mem
|
(Move [0] _ _ mem) => mem
|
||||||
|
|
|
||||||
|
|
@ -536,44 +536,36 @@ func init() {
|
||||||
{name: "LessThanNoov", argLength: 1, reg: readflags}, // bool, true flags encode signed x<y but without honoring overflow, false otherwise.
|
{name: "LessThanNoov", argLength: 1, reg: readflags}, // bool, true flags encode signed x<y but without honoring overflow, false otherwise.
|
||||||
{name: "GreaterEqualNoov", argLength: 1, reg: readflags}, // bool, true flags encode signed x>=y but without honoring overflow, false otherwise.
|
{name: "GreaterEqualNoov", argLength: 1, reg: readflags}, // bool, true flags encode signed x>=y but without honoring overflow, false otherwise.
|
||||||
|
|
||||||
// duffzero
|
// medium zeroing
|
||||||
// arg0 = address of memory to zero
|
// arg0 = address of memory to zero
|
||||||
// arg1 = mem
|
// arg1 = mem
|
||||||
// auxint = offset into duffzero code to start executing
|
// auxint = # of bytes to zero
|
||||||
// returns mem
|
// returns mem
|
||||||
// R20 changed as side effect
|
|
||||||
// R16 and R17 may be clobbered by linker trampoline.
|
|
||||||
{
|
{
|
||||||
name: "DUFFZERO",
|
name: "LoweredZero",
|
||||||
aux: "Int64",
|
aux: "Int64",
|
||||||
argLength: 2,
|
argLength: 2,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []regMask{buildReg("R20")},
|
inputs: []regMask{gp},
|
||||||
clobbers: buildReg("R16 R17 R20 R30"),
|
|
||||||
},
|
},
|
||||||
//faultOnNilArg0: true, // Note: removed for 73748. TODO: reenable at some point
|
faultOnNilArg0: true,
|
||||||
unsafePoint: true, // FP maintenance around DUFFZERO can be clobbered by interrupts
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// large zeroing
|
// large zeroing
|
||||||
// arg0 = address of memory to zero (in R16 aka arm64.REGRT1, changed as side effect)
|
// arg0 = address of memory to zero
|
||||||
// arg1 = address of the last 16-byte unit to zero
|
// arg1 = mem
|
||||||
// arg2 = mem
|
// auxint = # of bytes to zero
|
||||||
// returns mem
|
// returns mem
|
||||||
// STP.P (ZR,ZR), 16(R16)
|
|
||||||
// CMP Rarg1, R16
|
|
||||||
// BLE -2(PC)
|
|
||||||
// Note: the-end-of-the-memory may be not a valid pointer. it's a problem if it is spilled.
|
|
||||||
// the-end-of-the-memory - 16 is with the area to zero, ok to spill.
|
|
||||||
{
|
{
|
||||||
name: "LoweredZero",
|
name: "LoweredZeroLoop",
|
||||||
argLength: 3,
|
aux: "Int64",
|
||||||
|
argLength: 2,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []regMask{buildReg("R16"), gp},
|
inputs: []regMask{gp},
|
||||||
clobbers: buildReg("R16"),
|
clobbersArg0: true,
|
||||||
},
|
},
|
||||||
clobberFlags: true,
|
|
||||||
faultOnNilArg0: true,
|
faultOnNilArg0: true,
|
||||||
|
needIntTemp: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// duffcopy
|
// duffcopy
|
||||||
|
|
|
||||||
|
|
@ -517,7 +517,7 @@
|
||||||
(GetCallerSP ...) => (LoweredGetCallerSP ...)
|
(GetCallerSP ...) => (LoweredGetCallerSP ...)
|
||||||
(GetCallerPC ...) => (LoweredGetCallerPC ...)
|
(GetCallerPC ...) => (LoweredGetCallerPC ...)
|
||||||
|
|
||||||
(If cond yes no) => (NE (MOVBUreg <typ.UInt64> cond) yes no)
|
(If cond yes no) => (NEZ (MOVBUreg <typ.UInt64> cond) yes no)
|
||||||
(MOVBUreg x:((SGT|SGTU) _ _)) => x
|
(MOVBUreg x:((SGT|SGTU) _ _)) => x
|
||||||
(MOVBUreg x:(XOR (MOVVconst [1]) ((SGT|SGTU) _ _))) => x
|
(MOVBUreg x:(XOR (MOVVconst [1]) ((SGT|SGTU) _ _))) => x
|
||||||
|
|
||||||
|
|
@ -755,6 +755,9 @@
|
||||||
|
|
||||||
(MULV x (MOVVconst [c])) && canMulStrengthReduce(config, c) => {mulStrengthReduce(v, x, c)}
|
(MULV x (MOVVconst [c])) && canMulStrengthReduce(config, c) => {mulStrengthReduce(v, x, c)}
|
||||||
|
|
||||||
|
(MULV (NEGV x) (MOVVconst [c])) => (MULV x (MOVVconst [-c]))
|
||||||
|
(MULV (NEGV x) (NEGV y)) => (MULV x y)
|
||||||
|
|
||||||
// div by constant
|
// div by constant
|
||||||
(DIVVU x (MOVVconst [1])) => x
|
(DIVVU x (MOVVconst [1])) => x
|
||||||
(DIVVU x (MOVVconst [c])) && isPowerOfTwo(c) => (SRLVconst [log64(c)] x)
|
(DIVVU x (MOVVconst [c])) && isPowerOfTwo(c) => (SRLVconst [log64(c)] x)
|
||||||
|
|
@ -899,41 +902,46 @@
|
||||||
// Optimizations
|
// Optimizations
|
||||||
|
|
||||||
// Absorb boolean tests into block
|
// Absorb boolean tests into block
|
||||||
(NE (FPFlagTrue cmp) yes no) => (FPT cmp yes no)
|
(NEZ (FPFlagTrue cmp) yes no) => (FPT cmp yes no)
|
||||||
(NE (FPFlagFalse cmp) yes no) => (FPF cmp yes no)
|
(NEZ (FPFlagFalse cmp) yes no) => (FPF cmp yes no)
|
||||||
(EQ (FPFlagTrue cmp) yes no) => (FPF cmp yes no)
|
(EQZ (FPFlagTrue cmp) yes no) => (FPF cmp yes no)
|
||||||
(EQ (FPFlagFalse cmp) yes no) => (FPT cmp yes no)
|
(EQZ (FPFlagFalse cmp) yes no) => (FPT cmp yes no)
|
||||||
(NE (XORconst [1] cmp:(SGT _ _)) yes no) => (EQ cmp yes no)
|
(NEZ (XORconst [1] cmp:(SGT _ _)) yes no) => (EQZ cmp yes no)
|
||||||
(NE (XORconst [1] cmp:(SGTU _ _)) yes no) => (EQ cmp yes no)
|
(NEZ (XORconst [1] cmp:(SGTU _ _)) yes no) => (EQZ cmp yes no)
|
||||||
(NE (XORconst [1] cmp:(SGTconst _)) yes no) => (EQ cmp yes no)
|
(NEZ (XORconst [1] cmp:(SGTconst _)) yes no) => (EQZ cmp yes no)
|
||||||
(NE (XORconst [1] cmp:(SGTUconst _)) yes no) => (EQ cmp yes no)
|
(NEZ (XORconst [1] cmp:(SGTUconst _)) yes no) => (EQZ cmp yes no)
|
||||||
(EQ (XORconst [1] cmp:(SGT _ _)) yes no) => (NE cmp yes no)
|
(EQZ (XORconst [1] cmp:(SGT _ _)) yes no) => (NEZ cmp yes no)
|
||||||
(EQ (XORconst [1] cmp:(SGTU _ _)) yes no) => (NE cmp yes no)
|
(EQZ (XORconst [1] cmp:(SGTU _ _)) yes no) => (NEZ cmp yes no)
|
||||||
(EQ (XORconst [1] cmp:(SGTconst _)) yes no) => (NE cmp yes no)
|
(EQZ (XORconst [1] cmp:(SGTconst _)) yes no) => (NEZ cmp yes no)
|
||||||
(EQ (XORconst [1] cmp:(SGTUconst _)) yes no) => (NE cmp yes no)
|
(EQZ (XORconst [1] cmp:(SGTUconst _)) yes no) => (NEZ cmp yes no)
|
||||||
(NE (SGTUconst [1] x) yes no) => (EQ x yes no)
|
(NEZ (SGTUconst [1] x) yes no) => (EQZ x yes no)
|
||||||
(EQ (SGTUconst [1] x) yes no) => (NE x yes no)
|
(EQZ (SGTUconst [1] x) yes no) => (NEZ x yes no)
|
||||||
(NE (SGTU x (MOVVconst [0])) yes no) => (NE x yes no)
|
(NEZ (SGTU x (MOVVconst [0])) yes no) => (NEZ x yes no)
|
||||||
(EQ (SGTU x (MOVVconst [0])) yes no) => (EQ x yes no)
|
(EQZ (SGTU x (MOVVconst [0])) yes no) => (EQZ x yes no)
|
||||||
(NE (SGTconst [0] x) yes no) => (LTZ x yes no)
|
(NEZ (SGTconst [0] x) yes no) => (LTZ x yes no)
|
||||||
(EQ (SGTconst [0] x) yes no) => (GEZ x yes no)
|
(EQZ (SGTconst [0] x) yes no) => (GEZ x yes no)
|
||||||
(NE (SGT x (MOVVconst [0])) yes no) => (GTZ x yes no)
|
(NEZ (SGT x (MOVVconst [0])) yes no) => (GTZ x yes no)
|
||||||
(EQ (SGT x (MOVVconst [0])) yes no) => (LEZ x yes no)
|
(EQZ (SGT x (MOVVconst [0])) yes no) => (LEZ x yes no)
|
||||||
|
|
||||||
(EQ (SGTU (MOVVconst [c]) y) yes no) && c >= -2048 && c <= 2047 => (EQ (SGTUconst [c] y) yes no)
|
// Convert EQZ/NEZ into more optimal branch conditions.
|
||||||
(NE (SGTU (MOVVconst [c]) y) yes no) && c >= -2048 && c <= 2047 => (NE (SGTUconst [c] y) yes no)
|
(EQZ (SGTU (MOVVconst [c]) y) yes no) && c >= -2048 && c <= 2047 => (EQZ (SGTUconst [c] y) yes no)
|
||||||
(EQ (SUBV x y) yes no) => (BEQ x y yes no)
|
(NEZ (SGTU (MOVVconst [c]) y) yes no) && c >= -2048 && c <= 2047 => (NEZ (SGTUconst [c] y) yes no)
|
||||||
(NE (SUBV x y) yes no) => (BNE x y yes no)
|
(EQZ (SUBV x y) yes no) => (BEQ x y yes no)
|
||||||
(EQ (SGT x y) yes no) => (BGE y x yes no)
|
(NEZ (SUBV x y) yes no) => (BNE x y yes no)
|
||||||
(NE (SGT x y) yes no) => (BLT y x yes no)
|
(EQZ (SGT x y) yes no) => (BGE y x yes no)
|
||||||
(EQ (SGTU x y) yes no) => (BGEU y x yes no)
|
(NEZ (SGT x y) yes no) => (BLT y x yes no)
|
||||||
(NE (SGTU x y) yes no) => (BLTU y x yes no)
|
(EQZ (SGTU x y) yes no) => (BGEU y x yes no)
|
||||||
|
(NEZ (SGTU x y) yes no) => (BLTU y x yes no)
|
||||||
|
(EQZ (SGTconst [c] y) yes no) => (BGE y (MOVVconst [c]) yes no)
|
||||||
|
(NEZ (SGTconst [c] y) yes no) => (BLT y (MOVVconst [c]) yes no)
|
||||||
|
(EQZ (SGTUconst [c] y) yes no) => (BGEU y (MOVVconst [c]) yes no)
|
||||||
|
(NEZ (SGTUconst [c] y) yes no) => (BLTU y (MOVVconst [c]) yes no)
|
||||||
|
|
||||||
// absorb constants into branches
|
// absorb constants into branches
|
||||||
(EQ (MOVVconst [0]) yes no) => (First yes no)
|
(EQZ (MOVVconst [0]) yes no) => (First yes no)
|
||||||
(EQ (MOVVconst [c]) yes no) && c != 0 => (First no yes)
|
(EQZ (MOVVconst [c]) yes no) && c != 0 => (First no yes)
|
||||||
(NE (MOVVconst [0]) yes no) => (First no yes)
|
(NEZ (MOVVconst [0]) yes no) => (First no yes)
|
||||||
(NE (MOVVconst [c]) yes no) && c != 0 => (First yes no)
|
(NEZ (MOVVconst [c]) yes no) && c != 0 => (First yes no)
|
||||||
(LTZ (MOVVconst [c]) yes no) && c < 0 => (First yes no)
|
(LTZ (MOVVconst [c]) yes no) && c < 0 => (First yes no)
|
||||||
(LTZ (MOVVconst [c]) yes no) && c >= 0 => (First no yes)
|
(LTZ (MOVVconst [c]) yes no) && c >= 0 => (First no yes)
|
||||||
(LEZ (MOVVconst [c]) yes no) && c <= 0 => (First yes no)
|
(LEZ (MOVVconst [c]) yes no) && c <= 0 => (First yes no)
|
||||||
|
|
@ -943,6 +951,22 @@
|
||||||
(GEZ (MOVVconst [c]) yes no) && c >= 0 => (First yes no)
|
(GEZ (MOVVconst [c]) yes no) && c >= 0 => (First yes no)
|
||||||
(GEZ (MOVVconst [c]) yes no) && c < 0 => (First no yes)
|
(GEZ (MOVVconst [c]) yes no) && c < 0 => (First no yes)
|
||||||
|
|
||||||
|
// absorb NEGV into branches
|
||||||
|
(EQZ (NEGV x) yes no) => (EQZ x yes no)
|
||||||
|
(NEZ (NEGV x) yes no) => (NEZ x yes no)
|
||||||
|
|
||||||
|
// Convert branch with zero to more optimal branch zero.
|
||||||
|
(BEQ (MOVVconst [0]) cond yes no) => (EQZ cond yes no)
|
||||||
|
(BEQ cond (MOVVconst [0]) yes no) => (EQZ cond yes no)
|
||||||
|
(BNE (MOVVconst [0]) cond yes no) => (NEZ cond yes no)
|
||||||
|
(BNE cond (MOVVconst [0]) yes no) => (NEZ cond yes no)
|
||||||
|
(BLT (MOVVconst [0]) cond yes no) => (GTZ cond yes no)
|
||||||
|
(BLT cond (MOVVconst [0]) yes no) => (LTZ cond yes no)
|
||||||
|
(BLTU (MOVVconst [0]) cond yes no) => (NEZ cond yes no)
|
||||||
|
(BGE (MOVVconst [0]) cond yes no) => (LEZ cond yes no)
|
||||||
|
(BGE cond (MOVVconst [0]) yes no) => (GEZ cond yes no)
|
||||||
|
(BGEU (MOVVconst [0]) cond yes no) => (EQZ cond yes no)
|
||||||
|
|
||||||
// Arch-specific inlining for small or disjoint runtime.memmove
|
// Arch-specific inlining for small or disjoint runtime.memmove
|
||||||
// Match post-lowering calls, register version.
|
// Match post-lowering calls, register version.
|
||||||
(SelectN [0] call:(CALLstatic {sym} dst src (MOVVconst [sz]) mem))
|
(SelectN [0] call:(CALLstatic {sym} dst src (MOVVconst [sz]) mem))
|
||||||
|
|
|
||||||
|
|
@ -577,11 +577,13 @@ func init() {
|
||||||
// is $hint and bit[41:5] is $n.
|
// is $hint and bit[41:5] is $n.
|
||||||
{name: "PRELD", argLength: 2, aux: "Int64", reg: preldreg, asm: "PRELD", hasSideEffects: true},
|
{name: "PRELD", argLength: 2, aux: "Int64", reg: preldreg, asm: "PRELD", hasSideEffects: true},
|
||||||
{name: "PRELDX", argLength: 2, aux: "Int64", reg: preldreg, asm: "PRELDX", hasSideEffects: true},
|
{name: "PRELDX", argLength: 2, aux: "Int64", reg: preldreg, asm: "PRELDX", hasSideEffects: true},
|
||||||
|
|
||||||
|
{name: "ADDshiftLLV", argLength: 2, aux: "Int64", reg: gp21, asm: "ALSLV"}, // arg0 + arg1<<auxInt, the value of auxInt should be in the range [1, 4].
|
||||||
}
|
}
|
||||||
|
|
||||||
blocks := []blockData{
|
blocks := []blockData{
|
||||||
{name: "EQ", controls: 1},
|
{name: "EQZ", controls: 1}, // = 0
|
||||||
{name: "NE", controls: 1},
|
{name: "NEZ", controls: 1}, // != 0
|
||||||
{name: "LTZ", controls: 1}, // < 0
|
{name: "LTZ", controls: 1}, // < 0
|
||||||
{name: "LEZ", controls: 1}, // <= 0
|
{name: "LEZ", controls: 1}, // <= 0
|
||||||
{name: "GTZ", controls: 1}, // > 0
|
{name: "GTZ", controls: 1}, // > 0
|
||||||
|
|
@ -589,7 +591,7 @@ func init() {
|
||||||
{name: "FPT", controls: 1}, // FP flag is true
|
{name: "FPT", controls: 1}, // FP flag is true
|
||||||
{name: "FPF", controls: 1}, // FP flag is false
|
{name: "FPF", controls: 1}, // FP flag is false
|
||||||
{name: "BEQ", controls: 2}, // controls[0] == controls[1]
|
{name: "BEQ", controls: 2}, // controls[0] == controls[1]
|
||||||
{name: "BNE", controls: 2}, // controls[0] == controls[1]
|
{name: "BNE", controls: 2}, // controls[0] != controls[1]
|
||||||
{name: "BGE", controls: 2}, // controls[0] >= controls[1]
|
{name: "BGE", controls: 2}, // controls[0] >= controls[1]
|
||||||
{name: "BLT", controls: 2}, // controls[0] < controls[1]
|
{name: "BLT", controls: 2}, // controls[0] < controls[1]
|
||||||
{name: "BGEU", controls: 2}, // controls[0] >= controls[1], unsigned
|
{name: "BGEU", controls: 2}, // controls[0] >= controls[1], unsigned
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,6 @@
|
||||||
|
|
||||||
// Prefer addition when shifting left by one.
|
// Prefer addition when shifting left by one.
|
||||||
(SLLVconst [1] x) => (ADDV x x)
|
(SLLVconst [1] x) => (ADDV x x)
|
||||||
|
|
||||||
|
(EQZ (XOR x y) yes no) => (BEQ x y yes no)
|
||||||
|
(NEZ (XOR x y) yes no) => (BNE x y yes no)
|
||||||
|
|
|
||||||
|
|
@ -553,9 +553,11 @@
|
||||||
// Publication barrier as intrinsic
|
// Publication barrier as intrinsic
|
||||||
(PubBarrier ...) => (LoweredPubBarrier ...)
|
(PubBarrier ...) => (LoweredPubBarrier ...)
|
||||||
|
|
||||||
(PanicBounds [kind] x y mem) && boundsABI(kind) == 0 => (LoweredPanicBoundsA [kind] x y mem)
|
(PanicBounds ...) => (LoweredPanicBoundsRR ...)
|
||||||
(PanicBounds [kind] x y mem) && boundsABI(kind) == 1 => (LoweredPanicBoundsB [kind] x y mem)
|
(LoweredPanicBoundsRR [kind] x (MOVDconst [c]) mem) => (LoweredPanicBoundsRC [kind] x {PanicBoundsC{C:c}} mem)
|
||||||
(PanicBounds [kind] x y mem) && boundsABI(kind) == 2 => (LoweredPanicBoundsC [kind] x y mem)
|
(LoweredPanicBoundsRR [kind] (MOVDconst [c]) y mem) => (LoweredPanicBoundsCR [kind] {PanicBoundsC{C:c}} y mem)
|
||||||
|
(LoweredPanicBoundsRC [kind] {p} (MOVDconst [c]) mem) => (LoweredPanicBoundsCC [kind] {PanicBoundsCC{Cx:c, Cy:p.C}} mem)
|
||||||
|
(LoweredPanicBoundsCR [kind] {p} (MOVDconst [c]) mem) => (LoweredPanicBoundsCC [kind] {PanicBoundsCC{Cx:p.C, Cy:c}} mem)
|
||||||
|
|
||||||
// Optimizations
|
// Optimizations
|
||||||
// Note that PPC "logical" immediates come in 0:15 and 16:31 unsigned immediate forms,
|
// Note that PPC "logical" immediates come in 0:15 and 16:31 unsigned immediate forms,
|
||||||
|
|
|
||||||
|
|
@ -171,10 +171,7 @@ func init() {
|
||||||
fpstore = regInfo{inputs: []regMask{gp | sp | sb, fp}}
|
fpstore = regInfo{inputs: []regMask{gp | sp | sb, fp}}
|
||||||
fpstoreidx = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb, fp}}
|
fpstoreidx = regInfo{inputs: []regMask{gp | sp | sb, gp | sp | sb, fp}}
|
||||||
callerSave = regMask(gp | fp | gr | xer)
|
callerSave = regMask(gp | fp | gr | xer)
|
||||||
r3 = buildReg("R3")
|
first7 = buildReg("R3 R4 R5 R6 R7 R8 R9")
|
||||||
r4 = buildReg("R4")
|
|
||||||
r5 = buildReg("R5")
|
|
||||||
r6 = buildReg("R6")
|
|
||||||
)
|
)
|
||||||
ops := []opData{
|
ops := []opData{
|
||||||
{name: "ADD", argLength: 2, reg: gp21, asm: "ADD", commutative: true}, // arg0 + arg1
|
{name: "ADD", argLength: 2, reg: gp21, asm: "ADD", commutative: true}, // arg0 + arg1
|
||||||
|
|
@ -706,12 +703,16 @@ func init() {
|
||||||
{name: "LoweredWB", argLength: 1, reg: regInfo{clobbers: (callerSave &^ buildReg("R0 R3 R4 R5 R6 R7 R8 R9 R10 R14 R15 R16 R17 R20 R21 g")) | buildReg("R31"), outputs: []regMask{buildReg("R29")}}, clobberFlags: true, aux: "Int64"},
|
{name: "LoweredWB", argLength: 1, reg: regInfo{clobbers: (callerSave &^ buildReg("R0 R3 R4 R5 R6 R7 R8 R9 R10 R14 R15 R16 R17 R20 R21 g")) | buildReg("R31"), outputs: []regMask{buildReg("R29")}}, clobberFlags: true, aux: "Int64"},
|
||||||
|
|
||||||
{name: "LoweredPubBarrier", argLength: 1, asm: "LWSYNC", hasSideEffects: true}, // Do data barrier. arg0=memory
|
{name: "LoweredPubBarrier", argLength: 1, asm: "LWSYNC", hasSideEffects: true}, // Do data barrier. arg0=memory
|
||||||
// There are three of these functions so that they can have three different register inputs.
|
|
||||||
// When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the
|
// LoweredPanicBoundsRR takes x and y, two values that caused a bounds check to fail.
|
||||||
// default registers to match so we don't need to copy registers around unnecessarily.
|
// the RC and CR versions are used when one of the arguments is a constant. CC is used
|
||||||
{name: "LoweredPanicBoundsA", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r5, r6}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
|
// when both are constant (normally both 0, as prove derives the fact that a [0] bounds
|
||||||
{name: "LoweredPanicBoundsB", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r4, r5}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
|
// failure means the length must have also been 0).
|
||||||
{name: "LoweredPanicBoundsC", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{r3, r4}}, typ: "Mem", call: true}, // arg0=idx, arg1=len, arg2=mem, returns memory. AuxInt contains report code (see PanicBounds in genericOps.go).
|
// AuxInt contains a report code (see PanicBounds in genericOps.go).
|
||||||
|
{name: "LoweredPanicBoundsRR", argLength: 3, aux: "Int64", reg: regInfo{inputs: []regMask{first7, first7}}, typ: "Mem", call: true}, // arg0=x, arg1=y, arg2=mem, returns memory.
|
||||||
|
{name: "LoweredPanicBoundsRC", argLength: 2, aux: "PanicBoundsC", reg: regInfo{inputs: []regMask{first7}}, typ: "Mem", call: true}, // arg0=x, arg1=mem, returns memory.
|
||||||
|
{name: "LoweredPanicBoundsCR", argLength: 2, aux: "PanicBoundsC", reg: regInfo{inputs: []regMask{first7}}, typ: "Mem", call: true}, // arg0=y, arg1=mem, returns memory.
|
||||||
|
{name: "LoweredPanicBoundsCC", argLength: 1, aux: "PanicBoundsCC", reg: regInfo{}, typ: "Mem", call: true}, // arg0=mem, returns memory.
|
||||||
|
|
||||||
// (InvertFlags (CMP a b)) == (CMP b a)
|
// (InvertFlags (CMP a b)) == (CMP b a)
|
||||||
// So if we want (LessThan (CMP a b)) but we can't do that because a is a constant,
|
// So if we want (LessThan (CMP a b)) but we can't do that because a is a constant,
|
||||||
|
|
|
||||||
|
|
@ -299,6 +299,11 @@
|
||||||
(base.Op != OpSB || !config.ctxt.Flag_dynlink) =>
|
(base.Op != OpSB || !config.ctxt.Flag_dynlink) =>
|
||||||
(MOV(B|BU|H|HU|W|WU|D)load [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
(MOV(B|BU|H|HU|W|WU|D)load [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||||
|
|
||||||
|
(FMOV(W|D)load [off1] {sym1} (MOVaddr [off2] {sym2} base) mem) &&
|
||||||
|
is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) &&
|
||||||
|
(base.Op != OpSB || !config.ctxt.Flag_dynlink) =>
|
||||||
|
(FMOV(W|D)load [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||||
|
|
||||||
(MOV(B|H|W|D)store [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) &&
|
(MOV(B|H|W|D)store [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) &&
|
||||||
is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) &&
|
is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) &&
|
||||||
(base.Op != OpSB || !config.ctxt.Flag_dynlink) =>
|
(base.Op != OpSB || !config.ctxt.Flag_dynlink) =>
|
||||||
|
|
@ -309,15 +314,26 @@
|
||||||
(base.Op != OpSB || !config.ctxt.Flag_dynlink) =>
|
(base.Op != OpSB || !config.ctxt.Flag_dynlink) =>
|
||||||
(MOV(B|H|W|D)storezero [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
(MOV(B|H|W|D)storezero [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||||
|
|
||||||
|
(FMOV(W|D)store [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem) &&
|
||||||
|
is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) &&
|
||||||
|
(base.Op != OpSB || !config.ctxt.Flag_dynlink) =>
|
||||||
|
(FMOV(W|D)store [off1+off2] {mergeSym(sym1,sym2)} base val mem)
|
||||||
|
|
||||||
(MOV(B|BU|H|HU|W|WU|D)load [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) =>
|
(MOV(B|BU|H|HU|W|WU|D)load [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) =>
|
||||||
(MOV(B|BU|H|HU|W|WU|D)load [off1+int32(off2)] {sym} base mem)
|
(MOV(B|BU|H|HU|W|WU|D)load [off1+int32(off2)] {sym} base mem)
|
||||||
|
|
||||||
|
(FMOV(W|D)load [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) =>
|
||||||
|
(FMOV(W|D)load [off1+int32(off2)] {sym} base mem)
|
||||||
|
|
||||||
(MOV(B|H|W|D)store [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(int64(off1)+off2) =>
|
(MOV(B|H|W|D)store [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(int64(off1)+off2) =>
|
||||||
(MOV(B|H|W|D)store [off1+int32(off2)] {sym} base val mem)
|
(MOV(B|H|W|D)store [off1+int32(off2)] {sym} base val mem)
|
||||||
|
|
||||||
(MOV(B|H|W|D)storezero [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) =>
|
(MOV(B|H|W|D)storezero [off1] {sym} (ADDI [off2] base) mem) && is32Bit(int64(off1)+off2) =>
|
||||||
(MOV(B|H|W|D)storezero [off1+int32(off2)] {sym} base mem)
|
(MOV(B|H|W|D)storezero [off1+int32(off2)] {sym} base mem)
|
||||||
|
|
||||||
|
(FMOV(W|D)store [off1] {sym} (ADDI [off2] base) val mem) && is32Bit(int64(off1)+off2) =>
|
||||||
|
(FMOV(W|D)store [off1+int32(off2)] {sym} base val mem)
|
||||||
|
|
||||||
// Similarly, fold ADDI into MOVaddr to avoid confusing live variable analysis
|
// Similarly, fold ADDI into MOVaddr to avoid confusing live variable analysis
|
||||||
// with OffPtr -> ADDI.
|
// with OffPtr -> ADDI.
|
||||||
(ADDI [c] (MOVaddr [d] {s} x)) && is32Bit(c+int64(d)) => (MOVaddr [int32(c)+d] {s} x)
|
(ADDI [c] (MOVaddr [d] {s} x)) && is32Bit(c+int64(d)) => (MOVaddr [int32(c)+d] {s} x)
|
||||||
|
|
@ -701,6 +717,13 @@
|
||||||
(MOVHUreg <t> x:(MOVHload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVHUload <t> [off] {sym} ptr mem)
|
(MOVHUreg <t> x:(MOVHload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVHUload <t> [off] {sym} ptr mem)
|
||||||
(MOVWUreg <t> x:(MOVWload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVWUload <t> [off] {sym} ptr mem)
|
(MOVWUreg <t> x:(MOVWload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) => @x.Block (MOVWUload <t> [off] {sym} ptr mem)
|
||||||
|
|
||||||
|
// Replace load from same location as preceding store with copy.
|
||||||
|
(MOVDload [off] {sym} ptr1 (FMOVDstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) => (FMVXD x)
|
||||||
|
(FMOVDload [off] {sym} ptr1 (MOVDstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) => (FMVDX x)
|
||||||
|
(MOVWload [off] {sym} ptr1 (FMOVWstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) => (FMVXS x)
|
||||||
|
(MOVWUload [off] {sym} ptr1 (FMOVWstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) => (MOVWUreg (FMVXS x))
|
||||||
|
(FMOVWload [off] {sym} ptr1 (MOVWstore [off] {sym} ptr2 x _)) && isSamePtr(ptr1, ptr2) => (FMVSX x)
|
||||||
|
|
||||||
// If a register move has only 1 use, just use the same register without emitting instruction
|
// If a register move has only 1 use, just use the same register without emitting instruction
|
||||||
// MOVnop does not emit an instruction, only for ensuring the type.
|
// MOVnop does not emit an instruction, only for ensuring the type.
|
||||||
(MOVDreg x) && x.Uses == 1 => (MOVDnop x)
|
(MOVDreg x) && x.Uses == 1 => (MOVDnop x)
|
||||||
|
|
@ -839,6 +862,18 @@
|
||||||
(F(MADD|NMADD|MSUB|NMSUB)D neg:(FNEGD x) y z) && neg.Uses == 1 => (F(NMSUB|MSUB|NMADD|MADD)D x y z)
|
(F(MADD|NMADD|MSUB|NMSUB)D neg:(FNEGD x) y z) && neg.Uses == 1 => (F(NMSUB|MSUB|NMADD|MADD)D x y z)
|
||||||
(F(MADD|NMADD|MSUB|NMSUB)D x y neg:(FNEGD z)) && neg.Uses == 1 => (F(MSUB|NMSUB|MADD|NMADD)D x y z)
|
(F(MADD|NMADD|MSUB|NMSUB)D x y neg:(FNEGD z)) && neg.Uses == 1 => (F(MSUB|NMSUB|MADD|NMADD)D x y z)
|
||||||
|
|
||||||
|
// Test for -∞ (bit 0) using 64 bit classify instruction.
|
||||||
|
(FLTD x (FMVDX (MOVDconst [int64(math.Float64bits(-math.MaxFloat64))]))) => (ANDI [1] (FCLASSD x))
|
||||||
|
(FLED (FMVDX (MOVDconst [int64(math.Float64bits(-math.MaxFloat64))])) x) => (SNEZ (ANDI <typ.Int64> [0xff &^ 1] (FCLASSD x)))
|
||||||
|
(FEQD x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(-1)))]))) => (ANDI [1] (FCLASSD x))
|
||||||
|
(FNED x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(-1)))]))) => (SEQZ (ANDI <typ.Int64> [1] (FCLASSD x)))
|
||||||
|
|
||||||
|
// Test for +∞ (bit 7) using 64 bit classify instruction.
|
||||||
|
(FLTD (FMVDX (MOVDconst [int64(math.Float64bits(math.MaxFloat64))])) x) => (SNEZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
|
||||||
|
(FLED x (FMVDX (MOVDconst [int64(math.Float64bits(math.MaxFloat64))]))) => (SNEZ (ANDI <typ.Int64> [0xff &^ (1<<7)] (FCLASSD x)))
|
||||||
|
(FEQD x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(1)))]))) => (SNEZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
|
||||||
|
(FNED x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(1)))]))) => (SEQZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
|
||||||
|
|
||||||
//
|
//
|
||||||
// Optimisations for rva22u64 and above.
|
// Optimisations for rva22u64 and above.
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -453,7 +453,8 @@ func init() {
|
||||||
{name: "FNMSUBS", argLength: 3, reg: fp31, asm: "FNMSUBS", commutative: true, typ: "Float32"}, // -(arg0 * arg1) - arg2
|
{name: "FNMSUBS", argLength: 3, reg: fp31, asm: "FNMSUBS", commutative: true, typ: "Float32"}, // -(arg0 * arg1) - arg2
|
||||||
{name: "FSQRTS", argLength: 1, reg: fp11, asm: "FSQRTS", typ: "Float32"}, // sqrt(arg0)
|
{name: "FSQRTS", argLength: 1, reg: fp11, asm: "FSQRTS", typ: "Float32"}, // sqrt(arg0)
|
||||||
{name: "FNEGS", argLength: 1, reg: fp11, asm: "FNEGS", typ: "Float32"}, // -arg0
|
{name: "FNEGS", argLength: 1, reg: fp11, asm: "FNEGS", typ: "Float32"}, // -arg0
|
||||||
{name: "FMVSX", argLength: 1, reg: gpfp, asm: "FMVSX", typ: "Float32"}, // reinterpret arg0 as float
|
{name: "FMVSX", argLength: 1, reg: gpfp, asm: "FMVSX", typ: "Float32"}, // reinterpret arg0 as float32
|
||||||
|
{name: "FMVXS", argLength: 1, reg: fpgp, asm: "FMVXS", typ: "Int32"}, // reinterpret arg0 as int32, sign extended to 64 bits
|
||||||
{name: "FCVTSW", argLength: 1, reg: gpfp, asm: "FCVTSW", typ: "Float32"}, // float32(low 32 bits of arg0)
|
{name: "FCVTSW", argLength: 1, reg: gpfp, asm: "FCVTSW", typ: "Float32"}, // float32(low 32 bits of arg0)
|
||||||
{name: "FCVTSL", argLength: 1, reg: gpfp, asm: "FCVTSL", typ: "Float32"}, // float32(arg0)
|
{name: "FCVTSL", argLength: 1, reg: gpfp, asm: "FCVTSL", typ: "Float32"}, // float32(arg0)
|
||||||
{name: "FCVTWS", argLength: 1, reg: fpgp, asm: "FCVTWS", typ: "Int32"}, // int32(arg0)
|
{name: "FCVTWS", argLength: 1, reg: fpgp, asm: "FCVTWS", typ: "Int32"}, // int32(arg0)
|
||||||
|
|
@ -480,7 +481,8 @@ func init() {
|
||||||
{name: "FNEGD", argLength: 1, reg: fp11, asm: "FNEGD", typ: "Float64"}, // -arg0
|
{name: "FNEGD", argLength: 1, reg: fp11, asm: "FNEGD", typ: "Float64"}, // -arg0
|
||||||
{name: "FABSD", argLength: 1, reg: fp11, asm: "FABSD", typ: "Float64"}, // abs(arg0)
|
{name: "FABSD", argLength: 1, reg: fp11, asm: "FABSD", typ: "Float64"}, // abs(arg0)
|
||||||
{name: "FSGNJD", argLength: 2, reg: fp21, asm: "FSGNJD", typ: "Float64"}, // copy sign of arg1 to arg0
|
{name: "FSGNJD", argLength: 2, reg: fp21, asm: "FSGNJD", typ: "Float64"}, // copy sign of arg1 to arg0
|
||||||
{name: "FMVDX", argLength: 1, reg: gpfp, asm: "FMVDX", typ: "Float64"}, // reinterpret arg0 as float
|
{name: "FMVDX", argLength: 1, reg: gpfp, asm: "FMVDX", typ: "Float64"}, // reinterpret arg0 as float64
|
||||||
|
{name: "FMVXD", argLength: 1, reg: fpgp, asm: "FMVXD", typ: "Int64"}, // reinterpret arg0 as int64
|
||||||
{name: "FCVTDW", argLength: 1, reg: gpfp, asm: "FCVTDW", typ: "Float64"}, // float64(low 32 bits of arg0)
|
{name: "FCVTDW", argLength: 1, reg: gpfp, asm: "FCVTDW", typ: "Float64"}, // float64(low 32 bits of arg0)
|
||||||
{name: "FCVTDL", argLength: 1, reg: gpfp, asm: "FCVTDL", typ: "Float64"}, // float64(arg0)
|
{name: "FCVTDL", argLength: 1, reg: gpfp, asm: "FCVTDL", typ: "Float64"}, // float64(arg0)
|
||||||
{name: "FCVTWD", argLength: 1, reg: fpgp, asm: "FCVTWD", typ: "Int32"}, // int32(arg0)
|
{name: "FCVTWD", argLength: 1, reg: fpgp, asm: "FCVTWD", typ: "Int32"}, // int32(arg0)
|
||||||
|
|
@ -495,6 +497,27 @@ func init() {
|
||||||
{name: "FLED", argLength: 2, reg: fp2gp, asm: "FLED"}, // arg0 <= arg1
|
{name: "FLED", argLength: 2, reg: fp2gp, asm: "FLED"}, // arg0 <= arg1
|
||||||
{name: "LoweredFMIND", argLength: 2, reg: fp21, resultNotInArgs: true, asm: "FMIND", commutative: true, typ: "Float64"}, // min(arg0, arg1)
|
{name: "LoweredFMIND", argLength: 2, reg: fp21, resultNotInArgs: true, asm: "FMIND", commutative: true, typ: "Float64"}, // min(arg0, arg1)
|
||||||
{name: "LoweredFMAXD", argLength: 2, reg: fp21, resultNotInArgs: true, asm: "FMAXD", commutative: true, typ: "Float64"}, // max(arg0, arg1)
|
{name: "LoweredFMAXD", argLength: 2, reg: fp21, resultNotInArgs: true, asm: "FMAXD", commutative: true, typ: "Float64"}, // max(arg0, arg1)
|
||||||
|
|
||||||
|
// Floating point classify (in the F and D extensions).
|
||||||
|
//
|
||||||
|
// The FCLASS instructions will always set exactly one bit in the output
|
||||||
|
// register, all other bits will be cleared.
|
||||||
|
//
|
||||||
|
// Bit | Class
|
||||||
|
// ====+=============================
|
||||||
|
// 0 | -∞
|
||||||
|
// 1 | a negative normal number
|
||||||
|
// 2 | a negative subnormal number
|
||||||
|
// 3 | -0
|
||||||
|
// 4 | +0
|
||||||
|
// 5 | a positive subnormal number
|
||||||
|
// 6 | a positive normal number
|
||||||
|
// 7 | +∞
|
||||||
|
// 8 | qNaN
|
||||||
|
// 9 | sNaN
|
||||||
|
// ====+=============================
|
||||||
|
{name: "FCLASSS", argLength: 1, reg: fpgp, asm: "FCLASSS", typ: "Int64"}, // classify float32
|
||||||
|
{name: "FCLASSD", argLength: 1, reg: fpgp, asm: "FCLASSD", typ: "Int64"}, // classify float64
|
||||||
}
|
}
|
||||||
|
|
||||||
RISCV64blocks := []blockData{
|
RISCV64blocks := []blockData{
|
||||||
|
|
|
||||||
|
|
@ -84,14 +84,6 @@ func (s *biasedSparseMap) getEntry(i int) (x uint, v int32) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// add inserts x->0 into s, provided that x is in the range of keys stored in s.
|
|
||||||
func (s *biasedSparseMap) add(x uint) {
|
|
||||||
if int(x) < s.first || int(x) >= s.cap() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.s.set(ID(int(x)-s.first), 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// add inserts x->v into s, provided that x is in the range of keys stored in s.
|
// add inserts x->v into s, provided that x is in the range of keys stored in s.
|
||||||
func (s *biasedSparseMap) set(x uint, v int32) {
|
func (s *biasedSparseMap) set(x uint, v int32) {
|
||||||
if int(x) < s.first || int(x) >= s.cap() {
|
if int(x) < s.first || int(x) >= s.cap() {
|
||||||
|
|
|
||||||
|
|
@ -436,8 +436,15 @@ func canSpeculativelyExecute(b *Block) bool {
|
||||||
// don't fuse memory ops, Phi ops, divides (can panic),
|
// don't fuse memory ops, Phi ops, divides (can panic),
|
||||||
// or anything else with side-effects
|
// or anything else with side-effects
|
||||||
for _, v := range b.Values {
|
for _, v := range b.Values {
|
||||||
if v.Op == OpPhi || isDivMod(v.Op) || isPtrArithmetic(v.Op) || v.Type.IsMemory() ||
|
if v.Op == OpPhi || isDivMod(v.Op) || isPtrArithmetic(v.Op) ||
|
||||||
v.MemoryArg() != nil || opcodeTable[v.Op].hasSideEffects {
|
v.Type.IsMemory() || opcodeTable[v.Op].hasSideEffects {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow inlining markers to be speculatively executed
|
||||||
|
// even though they have a memory argument.
|
||||||
|
// See issue #74915.
|
||||||
|
if v.Op != OpInlMark && v.MemoryArg() != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -574,7 +574,7 @@ func (c *Config) buildRecipes(arch string) {
|
||||||
}
|
}
|
||||||
case "loong64":
|
case "loong64":
|
||||||
// - multiply is 4 cycles.
|
// - multiply is 4 cycles.
|
||||||
// - add/sub/shift are 1 cycle.
|
// - add/sub/shift/alsl are 1 cycle.
|
||||||
// On loong64, using a multiply also needs to load the constant into a register.
|
// On loong64, using a multiply also needs to load the constant into a register.
|
||||||
// TODO: figure out a happy medium.
|
// TODO: figure out a happy medium.
|
||||||
mulCost = 45
|
mulCost = 45
|
||||||
|
|
@ -609,6 +609,15 @@ func (c *Config) buildRecipes(arch string) {
|
||||||
return m.Block.NewValue1I(m.Pos, OpLOONG64SLLVconst, m.Type, int64(i), x)
|
return m.Block.NewValue1I(m.Pos, OpLOONG64SLLVconst, m.Type, int64(i), x)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ADDshiftLLV
|
||||||
|
for i := 1; i < 5; i++ {
|
||||||
|
c := 10
|
||||||
|
r(1, 1<<i, c,
|
||||||
|
func(m, x, y *Value) *Value {
|
||||||
|
return m.Block.NewValue2I(m.Pos, OpLOONG64ADDshiftLLV, m.Type, int64(i), x, y)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.mulRecipes = map[int64]mulRecipe{}
|
c.mulRecipes = map[int64]mulRecipe{}
|
||||||
|
|
@ -726,7 +735,7 @@ func (c *Config) buildRecipes(arch string) {
|
||||||
// Currently:
|
// Currently:
|
||||||
// len(c.mulRecipes) == 5984 on arm64
|
// len(c.mulRecipes) == 5984 on arm64
|
||||||
// 680 on amd64
|
// 680 on amd64
|
||||||
// 5984 on loong64
|
// 9738 on loong64
|
||||||
// This function takes ~2.5ms on arm64.
|
// This function takes ~2.5ms on arm64.
|
||||||
//println(len(c.mulRecipes))
|
//println(len(c.mulRecipes))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,10 +77,6 @@ func (ls *liveSlot) String() string {
|
||||||
return fmt.Sprintf("0x%x.%d.%d", ls.Registers, ls.stackOffsetValue(), int32(ls.StackOffset)&1)
|
return fmt.Sprintf("0x%x.%d.%d", ls.Registers, ls.stackOffsetValue(), int32(ls.StackOffset)&1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ls liveSlot) absent() bool {
|
|
||||||
return ls.Registers == 0 && !ls.onStack()
|
|
||||||
}
|
|
||||||
|
|
||||||
// StackOffset encodes whether a value is on the stack and if so, where.
|
// StackOffset encodes whether a value is on the stack and if so, where.
|
||||||
// It is a 31-bit integer followed by a presence flag at the low-order
|
// It is a 31-bit integer followed by a presence flag at the low-order
|
||||||
// bit.
|
// bit.
|
||||||
|
|
|
||||||
|
|
@ -853,27 +853,6 @@ func (c *registerCursor) plus(regWidth Abi1RO) registerCursor {
|
||||||
return rc
|
return rc
|
||||||
}
|
}
|
||||||
|
|
||||||
// at returns the register cursor for component i of t, where the first
|
|
||||||
// component is numbered 0.
|
|
||||||
func (c *registerCursor) at(t *types.Type, i int) registerCursor {
|
|
||||||
rc := *c
|
|
||||||
if i == 0 || len(c.regs) == 0 {
|
|
||||||
return rc
|
|
||||||
}
|
|
||||||
if t.IsArray() {
|
|
||||||
w := c.config.NumParamRegs(t.Elem())
|
|
||||||
rc.nextSlice += Abi1RO(i * w)
|
|
||||||
return rc
|
|
||||||
}
|
|
||||||
if isStructNotSIMD(t) {
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
rc.next(t.FieldType(j))
|
|
||||||
}
|
|
||||||
return rc
|
|
||||||
}
|
|
||||||
panic("Haven't implemented this case yet, do I need to?")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *registerCursor) init(regs []abi.RegIndex, info *abi.ABIParamResultInfo, result *[]*Value, storeDest *Value, storeOffset int64) {
|
func (c *registerCursor) init(regs []abi.RegIndex, info *abi.ABIParamResultInfo, result *[]*Value, storeDest *Value, storeOffset int64) {
|
||||||
c.regs = regs
|
c.regs = regs
|
||||||
c.nextSlice = 0
|
c.nextSlice = 0
|
||||||
|
|
@ -932,17 +911,6 @@ type expandState struct {
|
||||||
indentLevel int // Indentation for debugging recursion
|
indentLevel int // Indentation for debugging recursion
|
||||||
}
|
}
|
||||||
|
|
||||||
// intPairTypes returns the pair of 32-bit int types needed to encode a 64-bit integer type on a target
|
|
||||||
// that has no 64-bit integer registers.
|
|
||||||
func (x *expandState) intPairTypes(et types.Kind) (tHi, tLo *types.Type) {
|
|
||||||
tHi = x.typs.UInt32
|
|
||||||
if et == types.TINT64 {
|
|
||||||
tHi = x.typs.Int32
|
|
||||||
}
|
|
||||||
tLo = x.typs.UInt32
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// offsetFrom creates an offset from a pointer, simplifying chained offsets and offsets from SP
|
// offsetFrom creates an offset from a pointer, simplifying chained offsets and offsets from SP
|
||||||
func (x *expandState) offsetFrom(b *Block, from *Value, offset int64, pt *types.Type) *Value {
|
func (x *expandState) offsetFrom(b *Block, from *Value, offset int64, pt *types.Type) *Value {
|
||||||
ft := from.Type
|
ft := from.Type
|
||||||
|
|
@ -966,29 +934,6 @@ func (x *expandState) offsetFrom(b *Block, from *Value, offset int64, pt *types.
|
||||||
return b.NewValue1I(from.Pos.WithNotStmt(), OpOffPtr, pt, offset, from)
|
return b.NewValue1I(from.Pos.WithNotStmt(), OpOffPtr, pt, offset, from)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *expandState) regWidth(t *types.Type) Abi1RO {
|
|
||||||
return Abi1RO(x.f.ABI1.NumParamRegs(t))
|
|
||||||
}
|
|
||||||
|
|
||||||
// regOffset returns the register offset of the i'th element of type t
|
|
||||||
func (x *expandState) regOffset(t *types.Type, i int) Abi1RO {
|
|
||||||
// TODO maybe cache this in a map if profiling recommends.
|
|
||||||
if i == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if t.IsArray() {
|
|
||||||
return Abi1RO(i) * x.regWidth(t.Elem())
|
|
||||||
}
|
|
||||||
if isStructNotSIMD(t) {
|
|
||||||
k := Abi1RO(0)
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
k += x.regWidth(t.FieldType(j))
|
|
||||||
}
|
|
||||||
return k
|
|
||||||
}
|
|
||||||
panic("Haven't implemented this case yet, do I need to?")
|
|
||||||
}
|
|
||||||
|
|
||||||
// prAssignForArg returns the ABIParamAssignment for v, assumed to be an OpArg.
|
// prAssignForArg returns the ABIParamAssignment for v, assumed to be an OpArg.
|
||||||
func (x *expandState) prAssignForArg(v *Value) *abi.ABIParamAssignment {
|
func (x *expandState) prAssignForArg(v *Value) *abi.ABIParamAssignment {
|
||||||
if v.Op != OpArg {
|
if v.Op != OpArg {
|
||||||
|
|
|
||||||
|
|
@ -485,53 +485,6 @@ const (
|
||||||
BoundsKindCount
|
BoundsKindCount
|
||||||
)
|
)
|
||||||
|
|
||||||
// boundsABI determines which register arguments a bounds check call should use. For an [a:b:c] slice, we do:
|
|
||||||
//
|
|
||||||
// CMPQ c, cap
|
|
||||||
// JA fail1
|
|
||||||
// CMPQ b, c
|
|
||||||
// JA fail2
|
|
||||||
// CMPQ a, b
|
|
||||||
// JA fail3
|
|
||||||
//
|
|
||||||
// fail1: CALL panicSlice3Acap (c, cap)
|
|
||||||
// fail2: CALL panicSlice3B (b, c)
|
|
||||||
// fail3: CALL panicSlice3C (a, b)
|
|
||||||
//
|
|
||||||
// When we register allocate that code, we want the same register to be used for
|
|
||||||
// the first arg of panicSlice3Acap and the second arg to panicSlice3B. That way,
|
|
||||||
// initializing that register once will satisfy both calls.
|
|
||||||
// That desire ends up dividing the set of bounds check calls into 3 sets. This function
|
|
||||||
// determines which set to use for a given panic call.
|
|
||||||
// The first arg for set 0 should be the second arg for set 1.
|
|
||||||
// The first arg for set 1 should be the second arg for set 2.
|
|
||||||
func boundsABI(b int64) int {
|
|
||||||
switch BoundsKind(b) {
|
|
||||||
case BoundsSlice3Alen,
|
|
||||||
BoundsSlice3AlenU,
|
|
||||||
BoundsSlice3Acap,
|
|
||||||
BoundsSlice3AcapU,
|
|
||||||
BoundsConvert:
|
|
||||||
return 0
|
|
||||||
case BoundsSliceAlen,
|
|
||||||
BoundsSliceAlenU,
|
|
||||||
BoundsSliceAcap,
|
|
||||||
BoundsSliceAcapU,
|
|
||||||
BoundsSlice3B,
|
|
||||||
BoundsSlice3BU:
|
|
||||||
return 1
|
|
||||||
case BoundsIndex,
|
|
||||||
BoundsIndexU,
|
|
||||||
BoundsSliceB,
|
|
||||||
BoundsSliceBU,
|
|
||||||
BoundsSlice3C,
|
|
||||||
BoundsSlice3CU:
|
|
||||||
return 2
|
|
||||||
default:
|
|
||||||
panic("bad BoundsKind")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the bounds error code needed by the runtime, and
|
// Returns the bounds error code needed by the runtime, and
|
||||||
// whether the x field is signed.
|
// whether the x field is signed.
|
||||||
func (b BoundsKind) Code() (rtabi.BoundsErrorCode, bool) {
|
func (b BoundsKind) Code() (rtabi.BoundsErrorCode, bool) {
|
||||||
|
|
|
||||||
|
|
@ -94,8 +94,8 @@ const (
|
||||||
BlockARM64GEnoov
|
BlockARM64GEnoov
|
||||||
BlockARM64JUMPTABLE
|
BlockARM64JUMPTABLE
|
||||||
|
|
||||||
BlockLOONG64EQ
|
BlockLOONG64EQZ
|
||||||
BlockLOONG64NE
|
BlockLOONG64NEZ
|
||||||
BlockLOONG64LTZ
|
BlockLOONG64LTZ
|
||||||
BlockLOONG64LEZ
|
BlockLOONG64LEZ
|
||||||
BlockLOONG64GTZ
|
BlockLOONG64GTZ
|
||||||
|
|
@ -250,8 +250,8 @@ var blockString = [...]string{
|
||||||
BlockARM64GEnoov: "GEnoov",
|
BlockARM64GEnoov: "GEnoov",
|
||||||
BlockARM64JUMPTABLE: "JUMPTABLE",
|
BlockARM64JUMPTABLE: "JUMPTABLE",
|
||||||
|
|
||||||
BlockLOONG64EQ: "EQ",
|
BlockLOONG64EQZ: "EQZ",
|
||||||
BlockLOONG64NE: "NE",
|
BlockLOONG64NEZ: "NEZ",
|
||||||
BlockLOONG64LTZ: "LTZ",
|
BlockLOONG64LTZ: "LTZ",
|
||||||
BlockLOONG64LEZ: "LEZ",
|
BlockLOONG64LEZ: "LEZ",
|
||||||
BlockLOONG64GTZ: "GTZ",
|
BlockLOONG64GTZ: "GTZ",
|
||||||
|
|
@ -1058,7 +1058,8 @@ const (
|
||||||
OpAMD64CALLtail
|
OpAMD64CALLtail
|
||||||
OpAMD64CALLclosure
|
OpAMD64CALLclosure
|
||||||
OpAMD64CALLinter
|
OpAMD64CALLinter
|
||||||
OpAMD64DUFFCOPY
|
OpAMD64LoweredMove
|
||||||
|
OpAMD64LoweredMoveLoop
|
||||||
OpAMD64REPMOVSQ
|
OpAMD64REPMOVSQ
|
||||||
OpAMD64InvertFlags
|
OpAMD64InvertFlags
|
||||||
OpAMD64LoweredGetG
|
OpAMD64LoweredGetG
|
||||||
|
|
@ -2891,8 +2892,8 @@ const (
|
||||||
OpARM64NotGreaterEqualF
|
OpARM64NotGreaterEqualF
|
||||||
OpARM64LessThanNoov
|
OpARM64LessThanNoov
|
||||||
OpARM64GreaterEqualNoov
|
OpARM64GreaterEqualNoov
|
||||||
OpARM64DUFFZERO
|
|
||||||
OpARM64LoweredZero
|
OpARM64LoweredZero
|
||||||
|
OpARM64LoweredZeroLoop
|
||||||
OpARM64DUFFCOPY
|
OpARM64DUFFCOPY
|
||||||
OpARM64LoweredMove
|
OpARM64LoweredMove
|
||||||
OpARM64LoweredGetClosurePtr
|
OpARM64LoweredGetClosurePtr
|
||||||
|
|
@ -3144,6 +3145,7 @@ const (
|
||||||
OpLOONG64LoweredPanicBoundsCC
|
OpLOONG64LoweredPanicBoundsCC
|
||||||
OpLOONG64PRELD
|
OpLOONG64PRELD
|
||||||
OpLOONG64PRELDX
|
OpLOONG64PRELDX
|
||||||
|
OpLOONG64ADDshiftLLV
|
||||||
|
|
||||||
OpMIPSADD
|
OpMIPSADD
|
||||||
OpMIPSADDconst
|
OpMIPSADDconst
|
||||||
|
|
@ -3627,9 +3629,10 @@ const (
|
||||||
OpPPC64LoweredAtomicOr32
|
OpPPC64LoweredAtomicOr32
|
||||||
OpPPC64LoweredWB
|
OpPPC64LoweredWB
|
||||||
OpPPC64LoweredPubBarrier
|
OpPPC64LoweredPubBarrier
|
||||||
OpPPC64LoweredPanicBoundsA
|
OpPPC64LoweredPanicBoundsRR
|
||||||
OpPPC64LoweredPanicBoundsB
|
OpPPC64LoweredPanicBoundsRC
|
||||||
OpPPC64LoweredPanicBoundsC
|
OpPPC64LoweredPanicBoundsCR
|
||||||
|
OpPPC64LoweredPanicBoundsCC
|
||||||
OpPPC64InvertFlags
|
OpPPC64InvertFlags
|
||||||
OpPPC64FlagEQ
|
OpPPC64FlagEQ
|
||||||
OpPPC64FlagLT
|
OpPPC64FlagLT
|
||||||
|
|
@ -3774,6 +3777,7 @@ const (
|
||||||
OpRISCV64FSQRTS
|
OpRISCV64FSQRTS
|
||||||
OpRISCV64FNEGS
|
OpRISCV64FNEGS
|
||||||
OpRISCV64FMVSX
|
OpRISCV64FMVSX
|
||||||
|
OpRISCV64FMVXS
|
||||||
OpRISCV64FCVTSW
|
OpRISCV64FCVTSW
|
||||||
OpRISCV64FCVTSL
|
OpRISCV64FCVTSL
|
||||||
OpRISCV64FCVTWS
|
OpRISCV64FCVTWS
|
||||||
|
|
@ -3799,6 +3803,7 @@ const (
|
||||||
OpRISCV64FABSD
|
OpRISCV64FABSD
|
||||||
OpRISCV64FSGNJD
|
OpRISCV64FSGNJD
|
||||||
OpRISCV64FMVDX
|
OpRISCV64FMVDX
|
||||||
|
OpRISCV64FMVXD
|
||||||
OpRISCV64FCVTDW
|
OpRISCV64FCVTDW
|
||||||
OpRISCV64FCVTDL
|
OpRISCV64FCVTDL
|
||||||
OpRISCV64FCVTWD
|
OpRISCV64FCVTWD
|
||||||
|
|
@ -3813,6 +3818,8 @@ const (
|
||||||
OpRISCV64FLED
|
OpRISCV64FLED
|
||||||
OpRISCV64LoweredFMIND
|
OpRISCV64LoweredFMIND
|
||||||
OpRISCV64LoweredFMAXD
|
OpRISCV64LoweredFMAXD
|
||||||
|
OpRISCV64FCLASSS
|
||||||
|
OpRISCV64FCLASSD
|
||||||
|
|
||||||
OpS390XFADDS
|
OpS390XFADDS
|
||||||
OpS390XFADD
|
OpS390XFADD
|
||||||
|
|
@ -17096,17 +17103,35 @@ var opcodeTable = [...]opInfo{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "DUFFCOPY",
|
name: "LoweredMove",
|
||||||
auxType: auxInt64,
|
auxType: auxInt64,
|
||||||
argLen: 3,
|
argLen: 3,
|
||||||
clobberFlags: true,
|
faultOnNilArg0: true,
|
||||||
unsafePoint: true,
|
faultOnNilArg1: true,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 128}, // DI
|
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
|
||||||
{1, 64}, // SI
|
{1, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
|
||||||
},
|
},
|
||||||
clobbers: 65728, // SI DI X0
|
clobbers: 1073741824, // X14
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "LoweredMoveLoop",
|
||||||
|
auxType: auxInt64,
|
||||||
|
argLen: 3,
|
||||||
|
clobberFlags: true,
|
||||||
|
needIntTemp: true,
|
||||||
|
faultOnNilArg0: true,
|
||||||
|
faultOnNilArg1: true,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
|
||||||
|
{1, 49135}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R15
|
||||||
|
},
|
||||||
|
clobbers: 1073741824, // X14
|
||||||
|
clobbersArg0: true,
|
||||||
|
clobbersArg1: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -43661,29 +43686,28 @@ var opcodeTable = [...]opInfo{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "DUFFZERO",
|
|
||||||
auxType: auxInt64,
|
|
||||||
argLen: 2,
|
|
||||||
unsafePoint: true,
|
|
||||||
reg: regInfo{
|
|
||||||
inputs: []inputInfo{
|
|
||||||
{0, 524288}, // R20
|
|
||||||
},
|
|
||||||
clobbers: 269156352, // R16 R17 R20 R30
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "LoweredZero",
|
name: "LoweredZero",
|
||||||
argLen: 3,
|
auxType: auxInt64,
|
||||||
clobberFlags: true,
|
argLen: 2,
|
||||||
faultOnNilArg0: true,
|
faultOnNilArg0: true,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 65536}, // R16
|
{0, 335544319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
|
||||||
{1, 335544319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
|
|
||||||
},
|
},
|
||||||
clobbers: 65536, // R16
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "LoweredZeroLoop",
|
||||||
|
auxType: auxInt64,
|
||||||
|
argLen: 2,
|
||||||
|
needIntTemp: true,
|
||||||
|
faultOnNilArg0: true,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 335544319}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 R30
|
||||||
|
},
|
||||||
|
clobbersArg0: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -47140,6 +47164,21 @@ var opcodeTable = [...]opInfo{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ADDshiftLLV",
|
||||||
|
auxType: auxInt64,
|
||||||
|
argLen: 2,
|
||||||
|
asm: loong64.AALSLV,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
},
|
||||||
|
outputs: []outputInfo{
|
||||||
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "ADD",
|
name: "ADD",
|
||||||
|
|
@ -53635,41 +53674,46 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{},
|
reg: regInfo{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "LoweredPanicBoundsA",
|
name: "LoweredPanicBoundsRR",
|
||||||
auxType: auxInt64,
|
auxType: auxInt64,
|
||||||
argLen: 3,
|
argLen: 3,
|
||||||
call: true,
|
call: true,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 32}, // R5
|
{0, 1016}, // R3 R4 R5 R6 R7 R8 R9
|
||||||
{1, 64}, // R6
|
{1, 1016}, // R3 R4 R5 R6 R7 R8 R9
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "LoweredPanicBoundsB",
|
name: "LoweredPanicBoundsRC",
|
||||||
auxType: auxInt64,
|
auxType: auxPanicBoundsC,
|
||||||
argLen: 3,
|
argLen: 2,
|
||||||
call: true,
|
call: true,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 16}, // R4
|
{0, 1016}, // R3 R4 R5 R6 R7 R8 R9
|
||||||
{1, 32}, // R5
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "LoweredPanicBoundsC",
|
name: "LoweredPanicBoundsCR",
|
||||||
auxType: auxInt64,
|
auxType: auxPanicBoundsC,
|
||||||
argLen: 3,
|
argLen: 2,
|
||||||
call: true,
|
call: true,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 8}, // R3
|
{0, 1016}, // R3 R4 R5 R6 R7 R8 R9
|
||||||
{1, 16}, // R4
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "LoweredPanicBoundsCC",
|
||||||
|
auxType: auxPanicBoundsCC,
|
||||||
|
argLen: 1,
|
||||||
|
call: true,
|
||||||
|
reg: regInfo{},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "InvertFlags",
|
name: "InvertFlags",
|
||||||
argLen: 1,
|
argLen: 1,
|
||||||
|
|
@ -55600,6 +55644,19 @@ var opcodeTable = [...]opInfo{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "FMVXS",
|
||||||
|
argLen: 1,
|
||||||
|
asm: riscv.AFMVXS,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
|
||||||
|
},
|
||||||
|
outputs: []outputInfo{
|
||||||
|
{0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "FCVTSW",
|
name: "FCVTSW",
|
||||||
argLen: 1,
|
argLen: 1,
|
||||||
|
|
@ -55960,6 +56017,19 @@ var opcodeTable = [...]opInfo{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "FMVXD",
|
||||||
|
argLen: 1,
|
||||||
|
asm: riscv.AFMVXD,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
|
||||||
|
},
|
||||||
|
outputs: []outputInfo{
|
||||||
|
{0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "FCVTDW",
|
name: "FCVTDW",
|
||||||
argLen: 1,
|
argLen: 1,
|
||||||
|
|
@ -56158,6 +56228,32 @@ var opcodeTable = [...]opInfo{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "FCLASSS",
|
||||||
|
argLen: 1,
|
||||||
|
asm: riscv.AFCLASSS,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
|
||||||
|
},
|
||||||
|
outputs: []outputInfo{
|
||||||
|
{0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "FCLASSD",
|
||||||
|
argLen: 1,
|
||||||
|
asm: riscv.AFCLASSD,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
|
||||||
|
},
|
||||||
|
outputs: []outputInfo{
|
||||||
|
{0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "FADDS",
|
name: "FADDS",
|
||||||
|
|
|
||||||
|
|
@ -145,10 +145,7 @@ func (l limit) signedMin(m int64) limit {
|
||||||
l.min = max(l.min, m)
|
l.min = max(l.min, m)
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
func (l limit) signedMax(m int64) limit {
|
|
||||||
l.max = min(l.max, m)
|
|
||||||
return l
|
|
||||||
}
|
|
||||||
func (l limit) signedMinMax(minimum, maximum int64) limit {
|
func (l limit) signedMinMax(minimum, maximum int64) limit {
|
||||||
l.min = max(l.min, minimum)
|
l.min = max(l.min, minimum)
|
||||||
l.max = min(l.max, maximum)
|
l.max = min(l.max, maximum)
|
||||||
|
|
@ -1622,7 +1619,16 @@ func initLimit(v *Value) limit {
|
||||||
lim = lim.unsignedMax(1)
|
lim = lim.unsignedMax(1)
|
||||||
|
|
||||||
// length operations
|
// length operations
|
||||||
case OpStringLen, OpSliceLen, OpSliceCap:
|
case OpSliceLen, OpSliceCap:
|
||||||
|
f := v.Block.Func
|
||||||
|
elemSize := uint64(v.Args[0].Type.Elem().Size())
|
||||||
|
if elemSize > 0 {
|
||||||
|
heapSize := uint64(1)<<(uint64(f.Config.PtrSize)*8) - 1
|
||||||
|
maximumElementsFittingInHeap := heapSize / elemSize
|
||||||
|
lim = lim.unsignedMax(maximumElementsFittingInHeap)
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
case OpStringLen:
|
||||||
lim = lim.signedMin(0)
|
lim = lim.signedMin(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -561,7 +561,14 @@ func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool, pos
|
||||||
pos = pos.WithNotStmt()
|
pos = pos.WithNotStmt()
|
||||||
// Check if v is already in a requested register.
|
// Check if v is already in a requested register.
|
||||||
if mask&vi.regs != 0 {
|
if mask&vi.regs != 0 {
|
||||||
r := pickReg(mask & vi.regs)
|
mask &= vi.regs
|
||||||
|
r := pickReg(mask)
|
||||||
|
if mask.contains(s.SPReg) {
|
||||||
|
// Prefer the stack pointer if it is allowed.
|
||||||
|
// (Needed because the op might have an Aux symbol
|
||||||
|
// that needs SP as its base.)
|
||||||
|
r = s.SPReg
|
||||||
|
}
|
||||||
if !s.allocatable.contains(r) {
|
if !s.allocatable.contains(r) {
|
||||||
return v // v is in a fixed register
|
return v // v is in a fixed register
|
||||||
}
|
}
|
||||||
|
|
@ -2484,7 +2491,7 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value, pos src.XP
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we're allowed to clobber the destination location.
|
// Check if we're allowed to clobber the destination location.
|
||||||
if len(e.cache[occupant.vid]) == 1 && !e.s.values[occupant.vid].rematerializeable {
|
if len(e.cache[occupant.vid]) == 1 && !e.s.values[occupant.vid].rematerializeable && !opcodeTable[e.s.orig[occupant.vid].Op].fixedReg {
|
||||||
// We can't overwrite the last copy
|
// We can't overwrite the last copy
|
||||||
// of a value that needs to survive.
|
// of a value that needs to survive.
|
||||||
return false
|
return false
|
||||||
|
|
@ -2988,11 +2995,6 @@ type desiredStateEntry struct {
|
||||||
regs [4]register
|
regs [4]register
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *desiredState) clear() {
|
|
||||||
d.entries = d.entries[:0]
|
|
||||||
d.avoid = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// get returns a list of desired registers for value vid.
|
// get returns a list of desired registers for value vid.
|
||||||
func (d *desiredState) get(vid ID) [4]register {
|
func (d *desiredState) get(vid ID) [4]register {
|
||||||
for _, e := range d.entries {
|
for _, e := range d.entries {
|
||||||
|
|
|
||||||
|
|
@ -240,6 +240,30 @@ func TestClobbersArg0(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestClobbersArg1(t *testing.T) {
|
||||||
|
c := testConfig(t)
|
||||||
|
f := c.Fun("entry",
|
||||||
|
Bloc("entry",
|
||||||
|
Valu("mem", OpInitMem, types.TypeMem, 0, nil),
|
||||||
|
Valu("src", OpArg, c.config.Types.Int64.PtrTo(), 0, c.Temp(c.config.Types.Int64.PtrTo())),
|
||||||
|
Valu("dst", OpArg, c.config.Types.Int64.PtrTo(), 0, c.Temp(c.config.Types.Int64.PtrTo())),
|
||||||
|
Valu("use1", OpArg, c.config.Types.Int64.PtrTo().PtrTo(), 0, c.Temp(c.config.Types.Int64.PtrTo().PtrTo())),
|
||||||
|
Valu("use2", OpArg, c.config.Types.Int64.PtrTo().PtrTo(), 0, c.Temp(c.config.Types.Int64.PtrTo().PtrTo())),
|
||||||
|
Valu("move", OpAMD64LoweredMoveLoop, types.TypeMem, 256, nil, "dst", "src", "mem"),
|
||||||
|
Valu("store1", OpAMD64MOVQstore, types.TypeMem, 0, nil, "use1", "src", "move"),
|
||||||
|
Valu("store2", OpAMD64MOVQstore, types.TypeMem, 0, nil, "use2", "dst", "store1"),
|
||||||
|
Exit("store2")))
|
||||||
|
flagalloc(f.f)
|
||||||
|
regalloc(f.f)
|
||||||
|
checkFunc(f.f)
|
||||||
|
// LoweredMoveLoop clobbers its arguments, so there must be a copy of "src" and "dst" somewhere
|
||||||
|
// so we still have that value available at the stores.
|
||||||
|
if n := numCopies(f.blocks["entry"]); n != 2 {
|
||||||
|
fmt.Printf("%s\n", f.f.String())
|
||||||
|
t.Errorf("got %d copies, want 2", n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func numSpills(b *Block) int {
|
func numSpills(b *Block) int {
|
||||||
return numOps(b, OpStoreReg)
|
return numOps(b, OpStoreReg)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ const (
|
||||||
removeDeadValues = true
|
removeDeadValues = true
|
||||||
|
|
||||||
repZeroThreshold = 1408 // size beyond which we use REP STOS for zeroing
|
repZeroThreshold = 1408 // size beyond which we use REP STOS for zeroing
|
||||||
|
repMoveThreshold = 1408 // size beyond which we use REP MOVS for copying
|
||||||
)
|
)
|
||||||
|
|
||||||
// deadcode indicates whether rewrite should try to remove any values that become dead.
|
// deadcode indicates whether rewrite should try to remove any values that become dead.
|
||||||
|
|
@ -504,18 +505,6 @@ func isUnsignedPowerOfTwo[T uint8 | uint16 | uint32 | uint64](n T) bool {
|
||||||
return n != 0 && n&(n-1) == 0
|
return n != 0 && n&(n-1) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// isUint64PowerOfTwo reports whether uint64(n) is a power of 2.
|
|
||||||
func isUint64PowerOfTwo(in int64) bool {
|
|
||||||
n := uint64(in)
|
|
||||||
return n > 0 && n&(n-1) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// isUint32PowerOfTwo reports whether uint32(n) is a power of 2.
|
|
||||||
func isUint32PowerOfTwo(in int64) bool {
|
|
||||||
n := uint64(uint32(in))
|
|
||||||
return n > 0 && n&(n-1) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// is32Bit reports whether n can be represented as a signed 32 bit integer.
|
// is32Bit reports whether n can be represented as a signed 32 bit integer.
|
||||||
func is32Bit(n int64) bool {
|
func is32Bit(n int64) bool {
|
||||||
return n == int64(int32(n))
|
return n == int64(int32(n))
|
||||||
|
|
@ -637,51 +626,16 @@ func truncate64Fto32F(f float64) float32 {
|
||||||
return math.Float32frombits(r)
|
return math.Float32frombits(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// extend32Fto64F converts a float32 value to a float64 value preserving the bit
|
|
||||||
// pattern of the mantissa.
|
|
||||||
func extend32Fto64F(f float32) float64 {
|
|
||||||
if !math.IsNaN(float64(f)) {
|
|
||||||
return float64(f)
|
|
||||||
}
|
|
||||||
// NaN bit patterns aren't necessarily preserved across conversion
|
|
||||||
// instructions so we need to do the conversion manually.
|
|
||||||
b := uint64(math.Float32bits(f))
|
|
||||||
// | sign | exponent | mantissa |
|
|
||||||
r := ((b << 32) & (1 << 63)) | (0x7ff << 52) | ((b & 0x7fffff) << (52 - 23))
|
|
||||||
return math.Float64frombits(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DivisionNeedsFixUp reports whether the division needs fix-up code.
|
// DivisionNeedsFixUp reports whether the division needs fix-up code.
|
||||||
func DivisionNeedsFixUp(v *Value) bool {
|
func DivisionNeedsFixUp(v *Value) bool {
|
||||||
return v.AuxInt == 0
|
return v.AuxInt == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// auxFrom64F encodes a float64 value so it can be stored in an AuxInt.
|
|
||||||
func auxFrom64F(f float64) int64 {
|
|
||||||
if f != f {
|
|
||||||
panic("can't encode a NaN in AuxInt field")
|
|
||||||
}
|
|
||||||
return int64(math.Float64bits(f))
|
|
||||||
}
|
|
||||||
|
|
||||||
// auxFrom32F encodes a float32 value so it can be stored in an AuxInt.
|
|
||||||
func auxFrom32F(f float32) int64 {
|
|
||||||
if f != f {
|
|
||||||
panic("can't encode a NaN in AuxInt field")
|
|
||||||
}
|
|
||||||
return int64(math.Float64bits(extend32Fto64F(f)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// auxTo32F decodes a float32 from the AuxInt value provided.
|
// auxTo32F decodes a float32 from the AuxInt value provided.
|
||||||
func auxTo32F(i int64) float32 {
|
func auxTo32F(i int64) float32 {
|
||||||
return truncate64Fto32F(math.Float64frombits(uint64(i)))
|
return truncate64Fto32F(math.Float64frombits(uint64(i)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// auxTo64F decodes a float64 from the AuxInt value provided.
|
|
||||||
func auxTo64F(i int64) float64 {
|
|
||||||
return math.Float64frombits(uint64(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
func auxIntToBool(i int64) bool {
|
func auxIntToBool(i int64) bool {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
return false
|
return false
|
||||||
|
|
@ -715,12 +669,6 @@ func auxIntToValAndOff(i int64) ValAndOff {
|
||||||
func auxIntToArm64BitField(i int64) arm64BitField {
|
func auxIntToArm64BitField(i int64) arm64BitField {
|
||||||
return arm64BitField(i)
|
return arm64BitField(i)
|
||||||
}
|
}
|
||||||
func auxIntToInt128(x int64) int128 {
|
|
||||||
if x != 0 {
|
|
||||||
panic("nonzero int128 not allowed")
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
func auxIntToFlagConstant(x int64) flagConstant {
|
func auxIntToFlagConstant(x int64) flagConstant {
|
||||||
return flagConstant(x)
|
return flagConstant(x)
|
||||||
}
|
}
|
||||||
|
|
@ -762,12 +710,6 @@ func valAndOffToAuxInt(v ValAndOff) int64 {
|
||||||
func arm64BitFieldToAuxInt(v arm64BitField) int64 {
|
func arm64BitFieldToAuxInt(v arm64BitField) int64 {
|
||||||
return int64(v)
|
return int64(v)
|
||||||
}
|
}
|
||||||
func int128ToAuxInt(x int128) int64 {
|
|
||||||
if x != 0 {
|
|
||||||
panic("nonzero int128 not allowed")
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
func flagConstantToAuxInt(x flagConstant) int64 {
|
func flagConstantToAuxInt(x flagConstant) int64 {
|
||||||
return int64(x)
|
return int64(x)
|
||||||
}
|
}
|
||||||
|
|
@ -838,23 +780,6 @@ func uaddOvf(a, b int64) bool {
|
||||||
return uint64(a)+uint64(b) < uint64(a)
|
return uint64(a)+uint64(b) < uint64(a)
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadLSymOffset simulates reading a word at an offset into a
|
|
||||||
// read-only symbol's runtime memory. If it would read a pointer to
|
|
||||||
// another symbol, that symbol is returned. Otherwise, it returns nil.
|
|
||||||
func loadLSymOffset(lsym *obj.LSym, offset int64) *obj.LSym {
|
|
||||||
if lsym.Type != objabi.SRODATA {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, r := range lsym.R {
|
|
||||||
if int64(r.Off) == offset && r.Type&^objabi.R_WEAK == objabi.R_ADDR && r.Add == 0 {
|
|
||||||
return r.Sym
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func devirtLECall(v *Value, sym *obj.LSym) *Value {
|
func devirtLECall(v *Value, sym *obj.LSym) *Value {
|
||||||
v.Op = OpStaticLECall
|
v.Op = OpStaticLECall
|
||||||
auxcall := v.Aux.(*AuxCall)
|
auxcall := v.Aux.(*AuxCall)
|
||||||
|
|
@ -1576,10 +1501,6 @@ func GetPPC64Shiftmb(auxint int64) int64 {
|
||||||
return int64(int8(auxint >> 8))
|
return int64(int8(auxint >> 8))
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPPC64Shiftme(auxint int64) int64 {
|
|
||||||
return int64(int8(auxint))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test if this value can encoded as a mask for a rlwinm like
|
// Test if this value can encoded as a mask for a rlwinm like
|
||||||
// operation. Masks can also extend from the msb and wrap to
|
// operation. Masks can also extend from the msb and wrap to
|
||||||
// the lsb too. That is, the valid masks are 32 bit strings
|
// the lsb too. That is, the valid masks are 32 bit strings
|
||||||
|
|
|
||||||
|
|
@ -7874,8 +7874,8 @@ func rewriteValueAMD64_OpAMD64ANDQ(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// match: (ANDQ (MOVQconst [c]) x)
|
// match: (ANDQ (MOVQconst [c]) x)
|
||||||
// cond: isUint64PowerOfTwo(^c) && uint64(^c) >= 1<<31
|
// cond: isUnsignedPowerOfTwo(uint64(^c)) && uint64(^c) >= 1<<31
|
||||||
// result: (BTRQconst [int8(log64(^c))] x)
|
// result: (BTRQconst [int8(log64u(uint64(^c)))] x)
|
||||||
for {
|
for {
|
||||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||||
if v_0.Op != OpAMD64MOVQconst {
|
if v_0.Op != OpAMD64MOVQconst {
|
||||||
|
|
@ -7883,11 +7883,11 @@ func rewriteValueAMD64_OpAMD64ANDQ(v *Value) bool {
|
||||||
}
|
}
|
||||||
c := auxIntToInt64(v_0.AuxInt)
|
c := auxIntToInt64(v_0.AuxInt)
|
||||||
x := v_1
|
x := v_1
|
||||||
if !(isUint64PowerOfTwo(^c) && uint64(^c) >= 1<<31) {
|
if !(isUnsignedPowerOfTwo(uint64(^c)) && uint64(^c) >= 1<<31) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v.reset(OpAMD64BTRQconst)
|
v.reset(OpAMD64BTRQconst)
|
||||||
v.AuxInt = int8ToAuxInt(int8(log64(^c)))
|
v.AuxInt = int8ToAuxInt(int8(log64u(uint64(^c))))
|
||||||
v.AddArg(x)
|
v.AddArg(x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -19197,8 +19197,8 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// match: (ORQ (MOVQconst [c]) x)
|
// match: (ORQ (MOVQconst [c]) x)
|
||||||
// cond: isUint64PowerOfTwo(c) && uint64(c) >= 1<<31
|
// cond: isUnsignedPowerOfTwo(uint64(c)) && uint64(c) >= 1<<31
|
||||||
// result: (BTSQconst [int8(log64(c))] x)
|
// result: (BTSQconst [int8(log64u(uint64(c)))] x)
|
||||||
for {
|
for {
|
||||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||||
if v_0.Op != OpAMD64MOVQconst {
|
if v_0.Op != OpAMD64MOVQconst {
|
||||||
|
|
@ -19206,11 +19206,11 @@ func rewriteValueAMD64_OpAMD64ORQ(v *Value) bool {
|
||||||
}
|
}
|
||||||
c := auxIntToInt64(v_0.AuxInt)
|
c := auxIntToInt64(v_0.AuxInt)
|
||||||
x := v_1
|
x := v_1
|
||||||
if !(isUint64PowerOfTwo(c) && uint64(c) >= 1<<31) {
|
if !(isUnsignedPowerOfTwo(uint64(c)) && uint64(c) >= 1<<31) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v.reset(OpAMD64BTSQconst)
|
v.reset(OpAMD64BTSQconst)
|
||||||
v.AuxInt = int8ToAuxInt(int8(log64(c)))
|
v.AuxInt = int8ToAuxInt(int8(log64u(uint64(c))))
|
||||||
v.AddArg(x)
|
v.AddArg(x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -22164,46 +22164,46 @@ func rewriteValueAMD64_OpAMD64SETEQ(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// match: (SETEQ (TESTLconst [c] x))
|
// match: (SETEQ (TESTLconst [c] x))
|
||||||
// cond: isUint32PowerOfTwo(int64(c))
|
// cond: isUnsignedPowerOfTwo(uint32(c))
|
||||||
// result: (SETAE (BTLconst [int8(log32(c))] x))
|
// result: (SETAE (BTLconst [int8(log32u(uint32(c)))] x))
|
||||||
for {
|
for {
|
||||||
if v_0.Op != OpAMD64TESTLconst {
|
if v_0.Op != OpAMD64TESTLconst {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c := auxIntToInt32(v_0.AuxInt)
|
c := auxIntToInt32(v_0.AuxInt)
|
||||||
x := v_0.Args[0]
|
x := v_0.Args[0]
|
||||||
if !(isUint32PowerOfTwo(int64(c))) {
|
if !(isUnsignedPowerOfTwo(uint32(c))) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpAMD64SETAE)
|
v.reset(OpAMD64SETAE)
|
||||||
v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
|
v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log32(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log32u(uint32(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
v.AddArg(v0)
|
v.AddArg(v0)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (SETEQ (TESTQconst [c] x))
|
// match: (SETEQ (TESTQconst [c] x))
|
||||||
// cond: isUint64PowerOfTwo(int64(c))
|
// cond: isUnsignedPowerOfTwo(uint64(c))
|
||||||
// result: (SETAE (BTQconst [int8(log32(c))] x))
|
// result: (SETAE (BTQconst [int8(log32u(uint32(c)))] x))
|
||||||
for {
|
for {
|
||||||
if v_0.Op != OpAMD64TESTQconst {
|
if v_0.Op != OpAMD64TESTQconst {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c := auxIntToInt32(v_0.AuxInt)
|
c := auxIntToInt32(v_0.AuxInt)
|
||||||
x := v_0.Args[0]
|
x := v_0.Args[0]
|
||||||
if !(isUint64PowerOfTwo(int64(c))) {
|
if !(isUnsignedPowerOfTwo(uint64(c))) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpAMD64SETAE)
|
v.reset(OpAMD64SETAE)
|
||||||
v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
|
v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log32(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log32u(uint32(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
v.AddArg(v0)
|
v.AddArg(v0)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (SETEQ (TESTQ (MOVQconst [c]) x))
|
// match: (SETEQ (TESTQ (MOVQconst [c]) x))
|
||||||
// cond: isUint64PowerOfTwo(c)
|
// cond: isUnsignedPowerOfTwo(uint64(c))
|
||||||
// result: (SETAE (BTQconst [int8(log64(c))] x))
|
// result: (SETAE (BTQconst [int8(log64u(uint64(c)))] x))
|
||||||
for {
|
for {
|
||||||
if v_0.Op != OpAMD64TESTQ {
|
if v_0.Op != OpAMD64TESTQ {
|
||||||
break
|
break
|
||||||
|
|
@ -22217,12 +22217,12 @@ func rewriteValueAMD64_OpAMD64SETEQ(v *Value) bool {
|
||||||
}
|
}
|
||||||
c := auxIntToInt64(v_0_0.AuxInt)
|
c := auxIntToInt64(v_0_0.AuxInt)
|
||||||
x := v_0_1
|
x := v_0_1
|
||||||
if !(isUint64PowerOfTwo(c)) {
|
if !(isUnsignedPowerOfTwo(uint64(c))) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v.reset(OpAMD64SETAE)
|
v.reset(OpAMD64SETAE)
|
||||||
v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
|
v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log64(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log64u(uint64(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
v.AddArg(v0)
|
v.AddArg(v0)
|
||||||
return true
|
return true
|
||||||
|
|
@ -22641,8 +22641,8 @@ func rewriteValueAMD64_OpAMD64SETEQstore(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// match: (SETEQstore [off] {sym} ptr (TESTLconst [c] x) mem)
|
// match: (SETEQstore [off] {sym} ptr (TESTLconst [c] x) mem)
|
||||||
// cond: isUint32PowerOfTwo(int64(c))
|
// cond: isUnsignedPowerOfTwo(uint32(c))
|
||||||
// result: (SETAEstore [off] {sym} ptr (BTLconst [int8(log32(c))] x) mem)
|
// result: (SETAEstore [off] {sym} ptr (BTLconst [int8(log32u(uint32(c)))] x) mem)
|
||||||
for {
|
for {
|
||||||
off := auxIntToInt32(v.AuxInt)
|
off := auxIntToInt32(v.AuxInt)
|
||||||
sym := auxToSym(v.Aux)
|
sym := auxToSym(v.Aux)
|
||||||
|
|
@ -22653,21 +22653,21 @@ func rewriteValueAMD64_OpAMD64SETEQstore(v *Value) bool {
|
||||||
c := auxIntToInt32(v_1.AuxInt)
|
c := auxIntToInt32(v_1.AuxInt)
|
||||||
x := v_1.Args[0]
|
x := v_1.Args[0]
|
||||||
mem := v_2
|
mem := v_2
|
||||||
if !(isUint32PowerOfTwo(int64(c))) {
|
if !(isUnsignedPowerOfTwo(uint32(c))) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpAMD64SETAEstore)
|
v.reset(OpAMD64SETAEstore)
|
||||||
v.AuxInt = int32ToAuxInt(off)
|
v.AuxInt = int32ToAuxInt(off)
|
||||||
v.Aux = symToAux(sym)
|
v.Aux = symToAux(sym)
|
||||||
v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
|
v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log32(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log32u(uint32(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
v.AddArg3(ptr, v0, mem)
|
v.AddArg3(ptr, v0, mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (SETEQstore [off] {sym} ptr (TESTQconst [c] x) mem)
|
// match: (SETEQstore [off] {sym} ptr (TESTQconst [c] x) mem)
|
||||||
// cond: isUint64PowerOfTwo(int64(c))
|
// cond: isUnsignedPowerOfTwo(uint64(c))
|
||||||
// result: (SETAEstore [off] {sym} ptr (BTQconst [int8(log32(c))] x) mem)
|
// result: (SETAEstore [off] {sym} ptr (BTQconst [int8(log32u(uint32(c)))] x) mem)
|
||||||
for {
|
for {
|
||||||
off := auxIntToInt32(v.AuxInt)
|
off := auxIntToInt32(v.AuxInt)
|
||||||
sym := auxToSym(v.Aux)
|
sym := auxToSym(v.Aux)
|
||||||
|
|
@ -22678,21 +22678,21 @@ func rewriteValueAMD64_OpAMD64SETEQstore(v *Value) bool {
|
||||||
c := auxIntToInt32(v_1.AuxInt)
|
c := auxIntToInt32(v_1.AuxInt)
|
||||||
x := v_1.Args[0]
|
x := v_1.Args[0]
|
||||||
mem := v_2
|
mem := v_2
|
||||||
if !(isUint64PowerOfTwo(int64(c))) {
|
if !(isUnsignedPowerOfTwo(uint64(c))) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpAMD64SETAEstore)
|
v.reset(OpAMD64SETAEstore)
|
||||||
v.AuxInt = int32ToAuxInt(off)
|
v.AuxInt = int32ToAuxInt(off)
|
||||||
v.Aux = symToAux(sym)
|
v.Aux = symToAux(sym)
|
||||||
v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
|
v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log32(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log32u(uint32(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
v.AddArg3(ptr, v0, mem)
|
v.AddArg3(ptr, v0, mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (SETEQstore [off] {sym} ptr (TESTQ (MOVQconst [c]) x) mem)
|
// match: (SETEQstore [off] {sym} ptr (TESTQ (MOVQconst [c]) x) mem)
|
||||||
// cond: isUint64PowerOfTwo(c)
|
// cond: isUnsignedPowerOfTwo(uint64(c))
|
||||||
// result: (SETAEstore [off] {sym} ptr (BTQconst [int8(log64(c))] x) mem)
|
// result: (SETAEstore [off] {sym} ptr (BTQconst [int8(log64u(uint64(c)))] x) mem)
|
||||||
for {
|
for {
|
||||||
off := auxIntToInt32(v.AuxInt)
|
off := auxIntToInt32(v.AuxInt)
|
||||||
sym := auxToSym(v.Aux)
|
sym := auxToSym(v.Aux)
|
||||||
|
|
@ -22710,14 +22710,14 @@ func rewriteValueAMD64_OpAMD64SETEQstore(v *Value) bool {
|
||||||
c := auxIntToInt64(v_1_0.AuxInt)
|
c := auxIntToInt64(v_1_0.AuxInt)
|
||||||
x := v_1_1
|
x := v_1_1
|
||||||
mem := v_2
|
mem := v_2
|
||||||
if !(isUint64PowerOfTwo(c)) {
|
if !(isUnsignedPowerOfTwo(uint64(c))) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v.reset(OpAMD64SETAEstore)
|
v.reset(OpAMD64SETAEstore)
|
||||||
v.AuxInt = int32ToAuxInt(off)
|
v.AuxInt = int32ToAuxInt(off)
|
||||||
v.Aux = symToAux(sym)
|
v.Aux = symToAux(sym)
|
||||||
v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
|
v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log64(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log64u(uint64(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
v.AddArg3(ptr, v0, mem)
|
v.AddArg3(ptr, v0, mem)
|
||||||
return true
|
return true
|
||||||
|
|
@ -24210,46 +24210,46 @@ func rewriteValueAMD64_OpAMD64SETNE(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// match: (SETNE (TESTLconst [c] x))
|
// match: (SETNE (TESTLconst [c] x))
|
||||||
// cond: isUint32PowerOfTwo(int64(c))
|
// cond: isUnsignedPowerOfTwo(uint32(c))
|
||||||
// result: (SETB (BTLconst [int8(log32(c))] x))
|
// result: (SETB (BTLconst [int8(log32u(uint32(c)))] x))
|
||||||
for {
|
for {
|
||||||
if v_0.Op != OpAMD64TESTLconst {
|
if v_0.Op != OpAMD64TESTLconst {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c := auxIntToInt32(v_0.AuxInt)
|
c := auxIntToInt32(v_0.AuxInt)
|
||||||
x := v_0.Args[0]
|
x := v_0.Args[0]
|
||||||
if !(isUint32PowerOfTwo(int64(c))) {
|
if !(isUnsignedPowerOfTwo(uint32(c))) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpAMD64SETB)
|
v.reset(OpAMD64SETB)
|
||||||
v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
|
v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log32(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log32u(uint32(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
v.AddArg(v0)
|
v.AddArg(v0)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (SETNE (TESTQconst [c] x))
|
// match: (SETNE (TESTQconst [c] x))
|
||||||
// cond: isUint64PowerOfTwo(int64(c))
|
// cond: isUnsignedPowerOfTwo(uint64(c))
|
||||||
// result: (SETB (BTQconst [int8(log32(c))] x))
|
// result: (SETB (BTQconst [int8(log32u(uint32(c)))] x))
|
||||||
for {
|
for {
|
||||||
if v_0.Op != OpAMD64TESTQconst {
|
if v_0.Op != OpAMD64TESTQconst {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c := auxIntToInt32(v_0.AuxInt)
|
c := auxIntToInt32(v_0.AuxInt)
|
||||||
x := v_0.Args[0]
|
x := v_0.Args[0]
|
||||||
if !(isUint64PowerOfTwo(int64(c))) {
|
if !(isUnsignedPowerOfTwo(uint64(c))) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpAMD64SETB)
|
v.reset(OpAMD64SETB)
|
||||||
v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
|
v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log32(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log32u(uint32(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
v.AddArg(v0)
|
v.AddArg(v0)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (SETNE (TESTQ (MOVQconst [c]) x))
|
// match: (SETNE (TESTQ (MOVQconst [c]) x))
|
||||||
// cond: isUint64PowerOfTwo(c)
|
// cond: isUnsignedPowerOfTwo(uint64(c))
|
||||||
// result: (SETB (BTQconst [int8(log64(c))] x))
|
// result: (SETB (BTQconst [int8(log64u(uint64(c)))] x))
|
||||||
for {
|
for {
|
||||||
if v_0.Op != OpAMD64TESTQ {
|
if v_0.Op != OpAMD64TESTQ {
|
||||||
break
|
break
|
||||||
|
|
@ -24263,12 +24263,12 @@ func rewriteValueAMD64_OpAMD64SETNE(v *Value) bool {
|
||||||
}
|
}
|
||||||
c := auxIntToInt64(v_0_0.AuxInt)
|
c := auxIntToInt64(v_0_0.AuxInt)
|
||||||
x := v_0_1
|
x := v_0_1
|
||||||
if !(isUint64PowerOfTwo(c)) {
|
if !(isUnsignedPowerOfTwo(uint64(c))) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v.reset(OpAMD64SETB)
|
v.reset(OpAMD64SETB)
|
||||||
v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
|
v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log64(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log64u(uint64(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
v.AddArg(v0)
|
v.AddArg(v0)
|
||||||
return true
|
return true
|
||||||
|
|
@ -24687,8 +24687,8 @@ func rewriteValueAMD64_OpAMD64SETNEstore(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// match: (SETNEstore [off] {sym} ptr (TESTLconst [c] x) mem)
|
// match: (SETNEstore [off] {sym} ptr (TESTLconst [c] x) mem)
|
||||||
// cond: isUint32PowerOfTwo(int64(c))
|
// cond: isUnsignedPowerOfTwo(uint32(c))
|
||||||
// result: (SETBstore [off] {sym} ptr (BTLconst [int8(log32(c))] x) mem)
|
// result: (SETBstore [off] {sym} ptr (BTLconst [int8(log32u(uint32(c)))] x) mem)
|
||||||
for {
|
for {
|
||||||
off := auxIntToInt32(v.AuxInt)
|
off := auxIntToInt32(v.AuxInt)
|
||||||
sym := auxToSym(v.Aux)
|
sym := auxToSym(v.Aux)
|
||||||
|
|
@ -24699,21 +24699,21 @@ func rewriteValueAMD64_OpAMD64SETNEstore(v *Value) bool {
|
||||||
c := auxIntToInt32(v_1.AuxInt)
|
c := auxIntToInt32(v_1.AuxInt)
|
||||||
x := v_1.Args[0]
|
x := v_1.Args[0]
|
||||||
mem := v_2
|
mem := v_2
|
||||||
if !(isUint32PowerOfTwo(int64(c))) {
|
if !(isUnsignedPowerOfTwo(uint32(c))) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpAMD64SETBstore)
|
v.reset(OpAMD64SETBstore)
|
||||||
v.AuxInt = int32ToAuxInt(off)
|
v.AuxInt = int32ToAuxInt(off)
|
||||||
v.Aux = symToAux(sym)
|
v.Aux = symToAux(sym)
|
||||||
v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
|
v0 := b.NewValue0(v.Pos, OpAMD64BTLconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log32(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log32u(uint32(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
v.AddArg3(ptr, v0, mem)
|
v.AddArg3(ptr, v0, mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (SETNEstore [off] {sym} ptr (TESTQconst [c] x) mem)
|
// match: (SETNEstore [off] {sym} ptr (TESTQconst [c] x) mem)
|
||||||
// cond: isUint64PowerOfTwo(int64(c))
|
// cond: isUnsignedPowerOfTwo(uint64(c))
|
||||||
// result: (SETBstore [off] {sym} ptr (BTQconst [int8(log32(c))] x) mem)
|
// result: (SETBstore [off] {sym} ptr (BTQconst [int8(log32u(uint32(c)))] x) mem)
|
||||||
for {
|
for {
|
||||||
off := auxIntToInt32(v.AuxInt)
|
off := auxIntToInt32(v.AuxInt)
|
||||||
sym := auxToSym(v.Aux)
|
sym := auxToSym(v.Aux)
|
||||||
|
|
@ -24724,21 +24724,21 @@ func rewriteValueAMD64_OpAMD64SETNEstore(v *Value) bool {
|
||||||
c := auxIntToInt32(v_1.AuxInt)
|
c := auxIntToInt32(v_1.AuxInt)
|
||||||
x := v_1.Args[0]
|
x := v_1.Args[0]
|
||||||
mem := v_2
|
mem := v_2
|
||||||
if !(isUint64PowerOfTwo(int64(c))) {
|
if !(isUnsignedPowerOfTwo(uint64(c))) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpAMD64SETBstore)
|
v.reset(OpAMD64SETBstore)
|
||||||
v.AuxInt = int32ToAuxInt(off)
|
v.AuxInt = int32ToAuxInt(off)
|
||||||
v.Aux = symToAux(sym)
|
v.Aux = symToAux(sym)
|
||||||
v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
|
v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log32(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log32u(uint32(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
v.AddArg3(ptr, v0, mem)
|
v.AddArg3(ptr, v0, mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (SETNEstore [off] {sym} ptr (TESTQ (MOVQconst [c]) x) mem)
|
// match: (SETNEstore [off] {sym} ptr (TESTQ (MOVQconst [c]) x) mem)
|
||||||
// cond: isUint64PowerOfTwo(c)
|
// cond: isUnsignedPowerOfTwo(uint64(c))
|
||||||
// result: (SETBstore [off] {sym} ptr (BTQconst [int8(log64(c))] x) mem)
|
// result: (SETBstore [off] {sym} ptr (BTQconst [int8(log64u(uint64(c)))] x) mem)
|
||||||
for {
|
for {
|
||||||
off := auxIntToInt32(v.AuxInt)
|
off := auxIntToInt32(v.AuxInt)
|
||||||
sym := auxToSym(v.Aux)
|
sym := auxToSym(v.Aux)
|
||||||
|
|
@ -24756,14 +24756,14 @@ func rewriteValueAMD64_OpAMD64SETNEstore(v *Value) bool {
|
||||||
c := auxIntToInt64(v_1_0.AuxInt)
|
c := auxIntToInt64(v_1_0.AuxInt)
|
||||||
x := v_1_1
|
x := v_1_1
|
||||||
mem := v_2
|
mem := v_2
|
||||||
if !(isUint64PowerOfTwo(c)) {
|
if !(isUnsignedPowerOfTwo(uint64(c))) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v.reset(OpAMD64SETBstore)
|
v.reset(OpAMD64SETBstore)
|
||||||
v.AuxInt = int32ToAuxInt(off)
|
v.AuxInt = int32ToAuxInt(off)
|
||||||
v.Aux = symToAux(sym)
|
v.Aux = symToAux(sym)
|
||||||
v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
|
v0 := b.NewValue0(v.Pos, OpAMD64BTQconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log64(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log64u(uint64(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
v.AddArg3(ptr, v0, mem)
|
v.AddArg3(ptr, v0, mem)
|
||||||
return true
|
return true
|
||||||
|
|
@ -29113,8 +29113,8 @@ func rewriteValueAMD64_OpAMD64XORQ(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// match: (XORQ (MOVQconst [c]) x)
|
// match: (XORQ (MOVQconst [c]) x)
|
||||||
// cond: isUint64PowerOfTwo(c) && uint64(c) >= 1<<31
|
// cond: isUnsignedPowerOfTwo(uint64(c)) && uint64(c) >= 1<<31
|
||||||
// result: (BTCQconst [int8(log64(c))] x)
|
// result: (BTCQconst [int8(log64u(uint64(c)))] x)
|
||||||
for {
|
for {
|
||||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||||
if v_0.Op != OpAMD64MOVQconst {
|
if v_0.Op != OpAMD64MOVQconst {
|
||||||
|
|
@ -29122,11 +29122,11 @@ func rewriteValueAMD64_OpAMD64XORQ(v *Value) bool {
|
||||||
}
|
}
|
||||||
c := auxIntToInt64(v_0.AuxInt)
|
c := auxIntToInt64(v_0.AuxInt)
|
||||||
x := v_1
|
x := v_1
|
||||||
if !(isUint64PowerOfTwo(c) && uint64(c) >= 1<<31) {
|
if !(isUnsignedPowerOfTwo(uint64(c)) && uint64(c) >= 1<<31) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v.reset(OpAMD64BTCQconst)
|
v.reset(OpAMD64BTCQconst)
|
||||||
v.AuxInt = int8ToAuxInt(int8(log64(c)))
|
v.AuxInt = int8ToAuxInt(int8(log64u(uint64(c))))
|
||||||
v.AddArg(x)
|
v.AddArg(x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -44409,75 +44409,6 @@ func rewriteValueAMD64_OpMove(v *Value) bool {
|
||||||
v.AddArg3(dst, v0, mem)
|
v.AddArg3(dst, v0, mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (Move [32] dst src mem)
|
|
||||||
// result: (Move [16] (OffPtr <dst.Type> dst [16]) (OffPtr <src.Type> src [16]) (Move [16] dst src mem))
|
|
||||||
for {
|
|
||||||
if auxIntToInt64(v.AuxInt) != 32 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
dst := v_0
|
|
||||||
src := v_1
|
|
||||||
mem := v_2
|
|
||||||
v.reset(OpMove)
|
|
||||||
v.AuxInt = int64ToAuxInt(16)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpOffPtr, dst.Type)
|
|
||||||
v0.AuxInt = int64ToAuxInt(16)
|
|
||||||
v0.AddArg(dst)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpOffPtr, src.Type)
|
|
||||||
v1.AuxInt = int64ToAuxInt(16)
|
|
||||||
v1.AddArg(src)
|
|
||||||
v2 := b.NewValue0(v.Pos, OpMove, types.TypeMem)
|
|
||||||
v2.AuxInt = int64ToAuxInt(16)
|
|
||||||
v2.AddArg3(dst, src, mem)
|
|
||||||
v.AddArg3(v0, v1, v2)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Move [48] dst src mem)
|
|
||||||
// result: (Move [32] (OffPtr <dst.Type> dst [16]) (OffPtr <src.Type> src [16]) (Move [16] dst src mem))
|
|
||||||
for {
|
|
||||||
if auxIntToInt64(v.AuxInt) != 48 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
dst := v_0
|
|
||||||
src := v_1
|
|
||||||
mem := v_2
|
|
||||||
v.reset(OpMove)
|
|
||||||
v.AuxInt = int64ToAuxInt(32)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpOffPtr, dst.Type)
|
|
||||||
v0.AuxInt = int64ToAuxInt(16)
|
|
||||||
v0.AddArg(dst)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpOffPtr, src.Type)
|
|
||||||
v1.AuxInt = int64ToAuxInt(16)
|
|
||||||
v1.AddArg(src)
|
|
||||||
v2 := b.NewValue0(v.Pos, OpMove, types.TypeMem)
|
|
||||||
v2.AuxInt = int64ToAuxInt(16)
|
|
||||||
v2.AddArg3(dst, src, mem)
|
|
||||||
v.AddArg3(v0, v1, v2)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Move [64] dst src mem)
|
|
||||||
// result: (Move [32] (OffPtr <dst.Type> dst [32]) (OffPtr <src.Type> src [32]) (Move [32] dst src mem))
|
|
||||||
for {
|
|
||||||
if auxIntToInt64(v.AuxInt) != 64 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
dst := v_0
|
|
||||||
src := v_1
|
|
||||||
mem := v_2
|
|
||||||
v.reset(OpMove)
|
|
||||||
v.AuxInt = int64ToAuxInt(32)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpOffPtr, dst.Type)
|
|
||||||
v0.AuxInt = int64ToAuxInt(32)
|
|
||||||
v0.AddArg(dst)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpOffPtr, src.Type)
|
|
||||||
v1.AuxInt = int64ToAuxInt(32)
|
|
||||||
v1.AddArg(src)
|
|
||||||
v2 := b.NewValue0(v.Pos, OpMove, types.TypeMem)
|
|
||||||
v2.AuxInt = int64ToAuxInt(32)
|
|
||||||
v2.AddArg3(dst, src, mem)
|
|
||||||
v.AddArg3(v0, v1, v2)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Move [3] dst src mem)
|
// match: (Move [3] dst src mem)
|
||||||
// result: (MOVBstore [2] dst (MOVBload [2] src mem) (MOVWstore dst (MOVWload src mem) mem))
|
// result: (MOVBstore [2] dst (MOVBload [2] src mem) (MOVWstore dst (MOVWload src mem) mem))
|
||||||
for {
|
for {
|
||||||
|
|
@ -44670,23 +44601,55 @@ func rewriteValueAMD64_OpMove(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (Move [s] dst src mem)
|
// match: (Move [s] dst src mem)
|
||||||
// cond: s > 16 && s%16 != 0 && s%16 <= 8
|
// cond: s > 16 && s < 192 && logLargeCopy(v, s)
|
||||||
// result: (Move [s-s%16] (OffPtr <dst.Type> dst [s%16]) (OffPtr <src.Type> src [s%16]) (MOVQstore dst (MOVQload src mem) mem))
|
// result: (LoweredMove [s] dst src mem)
|
||||||
for {
|
for {
|
||||||
s := auxIntToInt64(v.AuxInt)
|
s := auxIntToInt64(v.AuxInt)
|
||||||
dst := v_0
|
dst := v_0
|
||||||
src := v_1
|
src := v_1
|
||||||
mem := v_2
|
mem := v_2
|
||||||
if !(s > 16 && s%16 != 0 && s%16 <= 8) {
|
if !(s > 16 && s < 192 && logLargeCopy(v, s)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpAMD64LoweredMove)
|
||||||
|
v.AuxInt = int64ToAuxInt(s)
|
||||||
|
v.AddArg3(dst, src, mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (Move [s] dst src mem)
|
||||||
|
// cond: s >= 192 && s <= repMoveThreshold && logLargeCopy(v, s)
|
||||||
|
// result: (LoweredMoveLoop [s] dst src mem)
|
||||||
|
for {
|
||||||
|
s := auxIntToInt64(v.AuxInt)
|
||||||
|
dst := v_0
|
||||||
|
src := v_1
|
||||||
|
mem := v_2
|
||||||
|
if !(s >= 192 && s <= repMoveThreshold && logLargeCopy(v, s)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpAMD64LoweredMoveLoop)
|
||||||
|
v.AuxInt = int64ToAuxInt(s)
|
||||||
|
v.AddArg3(dst, src, mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (Move [s] dst src mem)
|
||||||
|
// cond: s > repMoveThreshold && s%8 != 0
|
||||||
|
// result: (Move [s-s%8] (OffPtr <dst.Type> dst [s%8]) (OffPtr <src.Type> src [s%8]) (MOVQstore dst (MOVQload src mem) mem))
|
||||||
|
for {
|
||||||
|
s := auxIntToInt64(v.AuxInt)
|
||||||
|
dst := v_0
|
||||||
|
src := v_1
|
||||||
|
mem := v_2
|
||||||
|
if !(s > repMoveThreshold && s%8 != 0) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpMove)
|
v.reset(OpMove)
|
||||||
v.AuxInt = int64ToAuxInt(s - s%16)
|
v.AuxInt = int64ToAuxInt(s - s%8)
|
||||||
v0 := b.NewValue0(v.Pos, OpOffPtr, dst.Type)
|
v0 := b.NewValue0(v.Pos, OpOffPtr, dst.Type)
|
||||||
v0.AuxInt = int64ToAuxInt(s % 16)
|
v0.AuxInt = int64ToAuxInt(s % 8)
|
||||||
v0.AddArg(dst)
|
v0.AddArg(dst)
|
||||||
v1 := b.NewValue0(v.Pos, OpOffPtr, src.Type)
|
v1 := b.NewValue0(v.Pos, OpOffPtr, src.Type)
|
||||||
v1.AuxInt = int64ToAuxInt(s % 16)
|
v1.AuxInt = int64ToAuxInt(s % 8)
|
||||||
v1.AddArg(src)
|
v1.AddArg(src)
|
||||||
v2 := b.NewValue0(v.Pos, OpAMD64MOVQstore, types.TypeMem)
|
v2 := b.NewValue0(v.Pos, OpAMD64MOVQstore, types.TypeMem)
|
||||||
v3 := b.NewValue0(v.Pos, OpAMD64MOVQload, typ.UInt64)
|
v3 := b.NewValue0(v.Pos, OpAMD64MOVQload, typ.UInt64)
|
||||||
|
|
@ -44696,56 +44659,14 @@ func rewriteValueAMD64_OpMove(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (Move [s] dst src mem)
|
// match: (Move [s] dst src mem)
|
||||||
// cond: s > 16 && s%16 != 0 && s%16 > 8
|
// cond: s > repMoveThreshold && s%8 == 0 && logLargeCopy(v, s)
|
||||||
// result: (Move [s-s%16] (OffPtr <dst.Type> dst [s%16]) (OffPtr <src.Type> src [s%16]) (MOVOstore dst (MOVOload src mem) mem))
|
|
||||||
for {
|
|
||||||
s := auxIntToInt64(v.AuxInt)
|
|
||||||
dst := v_0
|
|
||||||
src := v_1
|
|
||||||
mem := v_2
|
|
||||||
if !(s > 16 && s%16 != 0 && s%16 > 8) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpMove)
|
|
||||||
v.AuxInt = int64ToAuxInt(s - s%16)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpOffPtr, dst.Type)
|
|
||||||
v0.AuxInt = int64ToAuxInt(s % 16)
|
|
||||||
v0.AddArg(dst)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpOffPtr, src.Type)
|
|
||||||
v1.AuxInt = int64ToAuxInt(s % 16)
|
|
||||||
v1.AddArg(src)
|
|
||||||
v2 := b.NewValue0(v.Pos, OpAMD64MOVOstore, types.TypeMem)
|
|
||||||
v3 := b.NewValue0(v.Pos, OpAMD64MOVOload, types.TypeInt128)
|
|
||||||
v3.AddArg2(src, mem)
|
|
||||||
v2.AddArg3(dst, v3, mem)
|
|
||||||
v.AddArg3(v0, v1, v2)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Move [s] dst src mem)
|
|
||||||
// cond: s > 64 && s <= 16*64 && s%16 == 0 && logLargeCopy(v, s)
|
|
||||||
// result: (DUFFCOPY [s] dst src mem)
|
|
||||||
for {
|
|
||||||
s := auxIntToInt64(v.AuxInt)
|
|
||||||
dst := v_0
|
|
||||||
src := v_1
|
|
||||||
mem := v_2
|
|
||||||
if !(s > 64 && s <= 16*64 && s%16 == 0 && logLargeCopy(v, s)) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpAMD64DUFFCOPY)
|
|
||||||
v.AuxInt = int64ToAuxInt(s)
|
|
||||||
v.AddArg3(dst, src, mem)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Move [s] dst src mem)
|
|
||||||
// cond: s > 16*64 && s%8 == 0 && logLargeCopy(v, s)
|
|
||||||
// result: (REPMOVSQ dst src (MOVQconst [s/8]) mem)
|
// result: (REPMOVSQ dst src (MOVQconst [s/8]) mem)
|
||||||
for {
|
for {
|
||||||
s := auxIntToInt64(v.AuxInt)
|
s := auxIntToInt64(v.AuxInt)
|
||||||
dst := v_0
|
dst := v_0
|
||||||
src := v_1
|
src := v_1
|
||||||
mem := v_2
|
mem := v_2
|
||||||
if !(s > 16*64 && s%8 == 0 && logLargeCopy(v, s)) {
|
if !(s > repMoveThreshold && s%8 == 0 && logLargeCopy(v, s)) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpAMD64REPMOVSQ)
|
v.reset(OpAMD64REPMOVSQ)
|
||||||
|
|
@ -57598,40 +57519,40 @@ func rewriteBlockAMD64(b *Block) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// match: (EQ (TESTLconst [c] x))
|
// match: (EQ (TESTLconst [c] x))
|
||||||
// cond: isUint32PowerOfTwo(int64(c))
|
// cond: isUnsignedPowerOfTwo(uint32(c))
|
||||||
// result: (UGE (BTLconst [int8(log32(c))] x))
|
// result: (UGE (BTLconst [int8(log32u(uint32(c)))] x))
|
||||||
for b.Controls[0].Op == OpAMD64TESTLconst {
|
for b.Controls[0].Op == OpAMD64TESTLconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
c := auxIntToInt32(v_0.AuxInt)
|
c := auxIntToInt32(v_0.AuxInt)
|
||||||
x := v_0.Args[0]
|
x := v_0.Args[0]
|
||||||
if !(isUint32PowerOfTwo(int64(c))) {
|
if !(isUnsignedPowerOfTwo(uint32(c))) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v0 := b.NewValue0(v_0.Pos, OpAMD64BTLconst, types.TypeFlags)
|
v0 := b.NewValue0(v_0.Pos, OpAMD64BTLconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log32(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log32u(uint32(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
b.resetWithControl(BlockAMD64UGE, v0)
|
b.resetWithControl(BlockAMD64UGE, v0)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (EQ (TESTQconst [c] x))
|
// match: (EQ (TESTQconst [c] x))
|
||||||
// cond: isUint64PowerOfTwo(int64(c))
|
// cond: isUnsignedPowerOfTwo(uint64(c))
|
||||||
// result: (UGE (BTQconst [int8(log32(c))] x))
|
// result: (UGE (BTQconst [int8(log32u(uint32(c)))] x))
|
||||||
for b.Controls[0].Op == OpAMD64TESTQconst {
|
for b.Controls[0].Op == OpAMD64TESTQconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
c := auxIntToInt32(v_0.AuxInt)
|
c := auxIntToInt32(v_0.AuxInt)
|
||||||
x := v_0.Args[0]
|
x := v_0.Args[0]
|
||||||
if !(isUint64PowerOfTwo(int64(c))) {
|
if !(isUnsignedPowerOfTwo(uint64(c))) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
|
v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log32(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log32u(uint32(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
b.resetWithControl(BlockAMD64UGE, v0)
|
b.resetWithControl(BlockAMD64UGE, v0)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (EQ (TESTQ (MOVQconst [c]) x))
|
// match: (EQ (TESTQ (MOVQconst [c]) x))
|
||||||
// cond: isUint64PowerOfTwo(c)
|
// cond: isUnsignedPowerOfTwo(uint64(c))
|
||||||
// result: (UGE (BTQconst [int8(log64(c))] x))
|
// result: (UGE (BTQconst [int8(log64u(uint64(c)))] x))
|
||||||
for b.Controls[0].Op == OpAMD64TESTQ {
|
for b.Controls[0].Op == OpAMD64TESTQ {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
_ = v_0.Args[1]
|
_ = v_0.Args[1]
|
||||||
|
|
@ -57643,11 +57564,11 @@ func rewriteBlockAMD64(b *Block) bool {
|
||||||
}
|
}
|
||||||
c := auxIntToInt64(v_0_0.AuxInt)
|
c := auxIntToInt64(v_0_0.AuxInt)
|
||||||
x := v_0_1
|
x := v_0_1
|
||||||
if !(isUint64PowerOfTwo(c)) {
|
if !(isUnsignedPowerOfTwo(uint64(c))) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
|
v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log64(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log64u(uint64(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
b.resetWithControl(BlockAMD64UGE, v0)
|
b.resetWithControl(BlockAMD64UGE, v0)
|
||||||
return true
|
return true
|
||||||
|
|
@ -58578,40 +58499,40 @@ func rewriteBlockAMD64(b *Block) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// match: (NE (TESTLconst [c] x))
|
// match: (NE (TESTLconst [c] x))
|
||||||
// cond: isUint32PowerOfTwo(int64(c))
|
// cond: isUnsignedPowerOfTwo(uint32(c))
|
||||||
// result: (ULT (BTLconst [int8(log32(c))] x))
|
// result: (ULT (BTLconst [int8(log32u(uint32(c)))] x))
|
||||||
for b.Controls[0].Op == OpAMD64TESTLconst {
|
for b.Controls[0].Op == OpAMD64TESTLconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
c := auxIntToInt32(v_0.AuxInt)
|
c := auxIntToInt32(v_0.AuxInt)
|
||||||
x := v_0.Args[0]
|
x := v_0.Args[0]
|
||||||
if !(isUint32PowerOfTwo(int64(c))) {
|
if !(isUnsignedPowerOfTwo(uint32(c))) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v0 := b.NewValue0(v_0.Pos, OpAMD64BTLconst, types.TypeFlags)
|
v0 := b.NewValue0(v_0.Pos, OpAMD64BTLconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log32(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log32u(uint32(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
b.resetWithControl(BlockAMD64ULT, v0)
|
b.resetWithControl(BlockAMD64ULT, v0)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (NE (TESTQconst [c] x))
|
// match: (NE (TESTQconst [c] x))
|
||||||
// cond: isUint64PowerOfTwo(int64(c))
|
// cond: isUnsignedPowerOfTwo(uint64(c))
|
||||||
// result: (ULT (BTQconst [int8(log32(c))] x))
|
// result: (ULT (BTQconst [int8(log32u(uint32(c)))] x))
|
||||||
for b.Controls[0].Op == OpAMD64TESTQconst {
|
for b.Controls[0].Op == OpAMD64TESTQconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
c := auxIntToInt32(v_0.AuxInt)
|
c := auxIntToInt32(v_0.AuxInt)
|
||||||
x := v_0.Args[0]
|
x := v_0.Args[0]
|
||||||
if !(isUint64PowerOfTwo(int64(c))) {
|
if !(isUnsignedPowerOfTwo(uint64(c))) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
|
v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log32(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log32u(uint32(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
b.resetWithControl(BlockAMD64ULT, v0)
|
b.resetWithControl(BlockAMD64ULT, v0)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (NE (TESTQ (MOVQconst [c]) x))
|
// match: (NE (TESTQ (MOVQconst [c]) x))
|
||||||
// cond: isUint64PowerOfTwo(c)
|
// cond: isUnsignedPowerOfTwo(uint64(c))
|
||||||
// result: (ULT (BTQconst [int8(log64(c))] x))
|
// result: (ULT (BTQconst [int8(log64u(uint64(c)))] x))
|
||||||
for b.Controls[0].Op == OpAMD64TESTQ {
|
for b.Controls[0].Op == OpAMD64TESTQ {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
_ = v_0.Args[1]
|
_ = v_0.Args[1]
|
||||||
|
|
@ -58623,11 +58544,11 @@ func rewriteBlockAMD64(b *Block) bool {
|
||||||
}
|
}
|
||||||
c := auxIntToInt64(v_0_0.AuxInt)
|
c := auxIntToInt64(v_0_0.AuxInt)
|
||||||
x := v_0_1
|
x := v_0_1
|
||||||
if !(isUint64PowerOfTwo(c)) {
|
if !(isUnsignedPowerOfTwo(uint64(c))) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
|
v0 := b.NewValue0(v_0.Pos, OpAMD64BTQconst, types.TypeFlags)
|
||||||
v0.AuxInt = int8ToAuxInt(int8(log64(c)))
|
v0.AuxInt = int8ToAuxInt(int8(log64u(uint64(c))))
|
||||||
v0.AddArg(x)
|
v0.AddArg(x)
|
||||||
b.resetWithControl(BlockAMD64ULT, v0)
|
b.resetWithControl(BlockAMD64ULT, v0)
|
||||||
return true
|
return true
|
||||||
|
|
|
||||||
|
|
@ -22321,141 +22321,34 @@ func rewriteValueARM64_OpZero(v *Value) bool {
|
||||||
v.AddArg4(ptr, v0, v0, mem)
|
v.AddArg4(ptr, v0, v0, mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (Zero [32] ptr mem)
|
|
||||||
// result: (STP [16] ptr (MOVDconst [0]) (MOVDconst [0]) (STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem))
|
|
||||||
for {
|
|
||||||
if auxIntToInt64(v.AuxInt) != 32 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
ptr := v_0
|
|
||||||
mem := v_1
|
|
||||||
v.reset(OpARM64STP)
|
|
||||||
v.AuxInt = int32ToAuxInt(16)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
|
|
||||||
v0.AuxInt = int64ToAuxInt(0)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem)
|
|
||||||
v1.AuxInt = int32ToAuxInt(0)
|
|
||||||
v1.AddArg4(ptr, v0, v0, mem)
|
|
||||||
v.AddArg4(ptr, v0, v0, v1)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Zero [48] ptr mem)
|
|
||||||
// result: (STP [32] ptr (MOVDconst [0]) (MOVDconst [0]) (STP [16] ptr (MOVDconst [0]) (MOVDconst [0]) (STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem)))
|
|
||||||
for {
|
|
||||||
if auxIntToInt64(v.AuxInt) != 48 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
ptr := v_0
|
|
||||||
mem := v_1
|
|
||||||
v.reset(OpARM64STP)
|
|
||||||
v.AuxInt = int32ToAuxInt(32)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
|
|
||||||
v0.AuxInt = int64ToAuxInt(0)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem)
|
|
||||||
v1.AuxInt = int32ToAuxInt(16)
|
|
||||||
v2 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem)
|
|
||||||
v2.AuxInt = int32ToAuxInt(0)
|
|
||||||
v2.AddArg4(ptr, v0, v0, mem)
|
|
||||||
v1.AddArg4(ptr, v0, v0, v2)
|
|
||||||
v.AddArg4(ptr, v0, v0, v1)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Zero [64] ptr mem)
|
|
||||||
// result: (STP [48] ptr (MOVDconst [0]) (MOVDconst [0]) (STP [32] ptr (MOVDconst [0]) (MOVDconst [0]) (STP [16] ptr (MOVDconst [0]) (MOVDconst [0]) (STP [0] ptr (MOVDconst [0]) (MOVDconst [0]) mem))))
|
|
||||||
for {
|
|
||||||
if auxIntToInt64(v.AuxInt) != 64 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
ptr := v_0
|
|
||||||
mem := v_1
|
|
||||||
v.reset(OpARM64STP)
|
|
||||||
v.AuxInt = int32ToAuxInt(48)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpARM64MOVDconst, typ.UInt64)
|
|
||||||
v0.AuxInt = int64ToAuxInt(0)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem)
|
|
||||||
v1.AuxInt = int32ToAuxInt(32)
|
|
||||||
v2 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem)
|
|
||||||
v2.AuxInt = int32ToAuxInt(16)
|
|
||||||
v3 := b.NewValue0(v.Pos, OpARM64STP, types.TypeMem)
|
|
||||||
v3.AuxInt = int32ToAuxInt(0)
|
|
||||||
v3.AddArg4(ptr, v0, v0, mem)
|
|
||||||
v2.AddArg4(ptr, v0, v0, v3)
|
|
||||||
v1.AddArg4(ptr, v0, v0, v2)
|
|
||||||
v.AddArg4(ptr, v0, v0, v1)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Zero [s] ptr mem)
|
// match: (Zero [s] ptr mem)
|
||||||
// cond: s%16 != 0 && s%16 <= 8 && s > 16
|
// cond: s > 16 && s < 192
|
||||||
// result: (Zero [8] (OffPtr <ptr.Type> ptr [s-8]) (Zero [s-s%16] ptr mem))
|
// result: (LoweredZero [s] ptr mem)
|
||||||
for {
|
for {
|
||||||
s := auxIntToInt64(v.AuxInt)
|
s := auxIntToInt64(v.AuxInt)
|
||||||
ptr := v_0
|
ptr := v_0
|
||||||
mem := v_1
|
mem := v_1
|
||||||
if !(s%16 != 0 && s%16 <= 8 && s > 16) {
|
if !(s > 16 && s < 192) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpZero)
|
v.reset(OpARM64LoweredZero)
|
||||||
v.AuxInt = int64ToAuxInt(8)
|
v.AuxInt = int64ToAuxInt(s)
|
||||||
v0 := b.NewValue0(v.Pos, OpOffPtr, ptr.Type)
|
|
||||||
v0.AuxInt = int64ToAuxInt(s - 8)
|
|
||||||
v0.AddArg(ptr)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpZero, types.TypeMem)
|
|
||||||
v1.AuxInt = int64ToAuxInt(s - s%16)
|
|
||||||
v1.AddArg2(ptr, mem)
|
|
||||||
v.AddArg2(v0, v1)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Zero [s] ptr mem)
|
|
||||||
// cond: s%16 != 0 && s%16 > 8 && s > 16
|
|
||||||
// result: (Zero [16] (OffPtr <ptr.Type> ptr [s-16]) (Zero [s-s%16] ptr mem))
|
|
||||||
for {
|
|
||||||
s := auxIntToInt64(v.AuxInt)
|
|
||||||
ptr := v_0
|
|
||||||
mem := v_1
|
|
||||||
if !(s%16 != 0 && s%16 > 8 && s > 16) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpZero)
|
|
||||||
v.AuxInt = int64ToAuxInt(16)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpOffPtr, ptr.Type)
|
|
||||||
v0.AuxInt = int64ToAuxInt(s - 16)
|
|
||||||
v0.AddArg(ptr)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpZero, types.TypeMem)
|
|
||||||
v1.AuxInt = int64ToAuxInt(s - s%16)
|
|
||||||
v1.AddArg2(ptr, mem)
|
|
||||||
v.AddArg2(v0, v1)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (Zero [s] ptr mem)
|
|
||||||
// cond: s%16 == 0 && s > 64 && s <= 16*64
|
|
||||||
// result: (DUFFZERO [4 * (64 - s/16)] ptr mem)
|
|
||||||
for {
|
|
||||||
s := auxIntToInt64(v.AuxInt)
|
|
||||||
ptr := v_0
|
|
||||||
mem := v_1
|
|
||||||
if !(s%16 == 0 && s > 64 && s <= 16*64) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpARM64DUFFZERO)
|
|
||||||
v.AuxInt = int64ToAuxInt(4 * (64 - s/16))
|
|
||||||
v.AddArg2(ptr, mem)
|
v.AddArg2(ptr, mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (Zero [s] ptr mem)
|
// match: (Zero [s] ptr mem)
|
||||||
// cond: s%16 == 0 && s > 16*64
|
// cond: s >= 192
|
||||||
// result: (LoweredZero ptr (ADDconst <ptr.Type> [s-16] ptr) mem)
|
// result: (LoweredZeroLoop [s] ptr mem)
|
||||||
for {
|
for {
|
||||||
s := auxIntToInt64(v.AuxInt)
|
s := auxIntToInt64(v.AuxInt)
|
||||||
ptr := v_0
|
ptr := v_0
|
||||||
mem := v_1
|
mem := v_1
|
||||||
if !(s%16 == 0 && s > 16*64) {
|
if !(s >= 192) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
v.reset(OpARM64LoweredZero)
|
v.reset(OpARM64LoweredZeroLoop)
|
||||||
v0 := b.NewValue0(v.Pos, OpARM64ADDconst, ptr.Type)
|
v.AuxInt = int64ToAuxInt(s)
|
||||||
v0.AuxInt = int64ToAuxInt(s - 16)
|
v.AddArg2(ptr, mem)
|
||||||
v0.AddArg(ptr)
|
|
||||||
v.AddArg3(ptr, v0, mem)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -5539,6 +5539,7 @@ func rewriteValueLOONG64_OpLOONG64MULV(v *Value) bool {
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
b := v.Block
|
b := v.Block
|
||||||
config := b.Func.Config
|
config := b.Func.Config
|
||||||
|
typ := &b.Func.Config.Types
|
||||||
// match: (MULV _ (MOVVconst [0]))
|
// match: (MULV _ (MOVVconst [0]))
|
||||||
// result: (MOVVconst [0])
|
// result: (MOVVconst [0])
|
||||||
for {
|
for {
|
||||||
|
|
@ -5583,6 +5584,44 @@ func rewriteValueLOONG64_OpLOONG64MULV(v *Value) bool {
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
// match: (MULV (NEGV x) (MOVVconst [c]))
|
||||||
|
// result: (MULV x (MOVVconst [-c]))
|
||||||
|
for {
|
||||||
|
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||||
|
if v_0.Op != OpLOONG64NEGV {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
x := v_0.Args[0]
|
||||||
|
if v_1.Op != OpLOONG64MOVVconst {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
c := auxIntToInt64(v_1.AuxInt)
|
||||||
|
v.reset(OpLOONG64MULV)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpLOONG64MOVVconst, typ.UInt64)
|
||||||
|
v0.AuxInt = int64ToAuxInt(-c)
|
||||||
|
v.AddArg2(x, v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// match: (MULV (NEGV x) (NEGV y))
|
||||||
|
// result: (MULV x y)
|
||||||
|
for {
|
||||||
|
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||||
|
if v_0.Op != OpLOONG64NEGV {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
x := v_0.Args[0]
|
||||||
|
if v_1.Op != OpLOONG64NEGV {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
y := v_1.Args[0]
|
||||||
|
v.reset(OpLOONG64MULV)
|
||||||
|
v.AddArg2(x, y)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
// match: (MULV (MOVVconst [c]) (MOVVconst [d]))
|
// match: (MULV (MOVVconst [c]) (MOVVconst [d]))
|
||||||
// result: (MOVVconst [c*d])
|
// result: (MOVVconst [c*d])
|
||||||
for {
|
for {
|
||||||
|
|
@ -11440,8 +11479,124 @@ func rewriteValueLOONG64_OpZero(v *Value) bool {
|
||||||
func rewriteBlockLOONG64(b *Block) bool {
|
func rewriteBlockLOONG64(b *Block) bool {
|
||||||
typ := &b.Func.Config.Types
|
typ := &b.Func.Config.Types
|
||||||
switch b.Kind {
|
switch b.Kind {
|
||||||
case BlockLOONG64EQ:
|
case BlockLOONG64BEQ:
|
||||||
// match: (EQ (FPFlagTrue cmp) yes no)
|
// match: (BEQ (MOVVconst [0]) cond yes no)
|
||||||
|
// result: (EQZ cond yes no)
|
||||||
|
for b.Controls[0].Op == OpLOONG64MOVVconst {
|
||||||
|
v_0 := b.Controls[0]
|
||||||
|
if auxIntToInt64(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
cond := b.Controls[1]
|
||||||
|
b.resetWithControl(BlockLOONG64EQZ, cond)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (BEQ cond (MOVVconst [0]) yes no)
|
||||||
|
// result: (EQZ cond yes no)
|
||||||
|
for b.Controls[1].Op == OpLOONG64MOVVconst {
|
||||||
|
cond := b.Controls[0]
|
||||||
|
v_1 := b.Controls[1]
|
||||||
|
if auxIntToInt64(v_1.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.resetWithControl(BlockLOONG64EQZ, cond)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case BlockLOONG64BGE:
|
||||||
|
// match: (BGE (MOVVconst [0]) cond yes no)
|
||||||
|
// result: (LEZ cond yes no)
|
||||||
|
for b.Controls[0].Op == OpLOONG64MOVVconst {
|
||||||
|
v_0 := b.Controls[0]
|
||||||
|
if auxIntToInt64(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
cond := b.Controls[1]
|
||||||
|
b.resetWithControl(BlockLOONG64LEZ, cond)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (BGE cond (MOVVconst [0]) yes no)
|
||||||
|
// result: (GEZ cond yes no)
|
||||||
|
for b.Controls[1].Op == OpLOONG64MOVVconst {
|
||||||
|
cond := b.Controls[0]
|
||||||
|
v_1 := b.Controls[1]
|
||||||
|
if auxIntToInt64(v_1.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.resetWithControl(BlockLOONG64GEZ, cond)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case BlockLOONG64BGEU:
|
||||||
|
// match: (BGEU (MOVVconst [0]) cond yes no)
|
||||||
|
// result: (EQZ cond yes no)
|
||||||
|
for b.Controls[0].Op == OpLOONG64MOVVconst {
|
||||||
|
v_0 := b.Controls[0]
|
||||||
|
if auxIntToInt64(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
cond := b.Controls[1]
|
||||||
|
b.resetWithControl(BlockLOONG64EQZ, cond)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case BlockLOONG64BLT:
|
||||||
|
// match: (BLT (MOVVconst [0]) cond yes no)
|
||||||
|
// result: (GTZ cond yes no)
|
||||||
|
for b.Controls[0].Op == OpLOONG64MOVVconst {
|
||||||
|
v_0 := b.Controls[0]
|
||||||
|
if auxIntToInt64(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
cond := b.Controls[1]
|
||||||
|
b.resetWithControl(BlockLOONG64GTZ, cond)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (BLT cond (MOVVconst [0]) yes no)
|
||||||
|
// result: (LTZ cond yes no)
|
||||||
|
for b.Controls[1].Op == OpLOONG64MOVVconst {
|
||||||
|
cond := b.Controls[0]
|
||||||
|
v_1 := b.Controls[1]
|
||||||
|
if auxIntToInt64(v_1.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.resetWithControl(BlockLOONG64LTZ, cond)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case BlockLOONG64BLTU:
|
||||||
|
// match: (BLTU (MOVVconst [0]) cond yes no)
|
||||||
|
// result: (NEZ cond yes no)
|
||||||
|
for b.Controls[0].Op == OpLOONG64MOVVconst {
|
||||||
|
v_0 := b.Controls[0]
|
||||||
|
if auxIntToInt64(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
cond := b.Controls[1]
|
||||||
|
b.resetWithControl(BlockLOONG64NEZ, cond)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case BlockLOONG64BNE:
|
||||||
|
// match: (BNE (MOVVconst [0]) cond yes no)
|
||||||
|
// result: (NEZ cond yes no)
|
||||||
|
for b.Controls[0].Op == OpLOONG64MOVVconst {
|
||||||
|
v_0 := b.Controls[0]
|
||||||
|
if auxIntToInt64(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
cond := b.Controls[1]
|
||||||
|
b.resetWithControl(BlockLOONG64NEZ, cond)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (BNE cond (MOVVconst [0]) yes no)
|
||||||
|
// result: (NEZ cond yes no)
|
||||||
|
for b.Controls[1].Op == OpLOONG64MOVVconst {
|
||||||
|
cond := b.Controls[0]
|
||||||
|
v_1 := b.Controls[1]
|
||||||
|
if auxIntToInt64(v_1.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
b.resetWithControl(BlockLOONG64NEZ, cond)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case BlockLOONG64EQZ:
|
||||||
|
// match: (EQZ (FPFlagTrue cmp) yes no)
|
||||||
// result: (FPF cmp yes no)
|
// result: (FPF cmp yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64FPFlagTrue {
|
for b.Controls[0].Op == OpLOONG64FPFlagTrue {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
|
|
@ -11449,7 +11604,7 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.resetWithControl(BlockLOONG64FPF, cmp)
|
b.resetWithControl(BlockLOONG64FPF, cmp)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (EQ (FPFlagFalse cmp) yes no)
|
// match: (EQZ (FPFlagFalse cmp) yes no)
|
||||||
// result: (FPT cmp yes no)
|
// result: (FPT cmp yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64FPFlagFalse {
|
for b.Controls[0].Op == OpLOONG64FPFlagFalse {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
|
|
@ -11457,8 +11612,8 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.resetWithControl(BlockLOONG64FPT, cmp)
|
b.resetWithControl(BlockLOONG64FPT, cmp)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (EQ (XORconst [1] cmp:(SGT _ _)) yes no)
|
// match: (EQZ (XORconst [1] cmp:(SGT _ _)) yes no)
|
||||||
// result: (NE cmp yes no)
|
// result: (NEZ cmp yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64XORconst {
|
for b.Controls[0].Op == OpLOONG64XORconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
if auxIntToInt64(v_0.AuxInt) != 1 {
|
if auxIntToInt64(v_0.AuxInt) != 1 {
|
||||||
|
|
@ -11468,11 +11623,11 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
if cmp.Op != OpLOONG64SGT {
|
if cmp.Op != OpLOONG64SGT {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b.resetWithControl(BlockLOONG64NE, cmp)
|
b.resetWithControl(BlockLOONG64NEZ, cmp)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (EQ (XORconst [1] cmp:(SGTU _ _)) yes no)
|
// match: (EQZ (XORconst [1] cmp:(SGTU _ _)) yes no)
|
||||||
// result: (NE cmp yes no)
|
// result: (NEZ cmp yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64XORconst {
|
for b.Controls[0].Op == OpLOONG64XORconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
if auxIntToInt64(v_0.AuxInt) != 1 {
|
if auxIntToInt64(v_0.AuxInt) != 1 {
|
||||||
|
|
@ -11482,11 +11637,11 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
if cmp.Op != OpLOONG64SGTU {
|
if cmp.Op != OpLOONG64SGTU {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b.resetWithControl(BlockLOONG64NE, cmp)
|
b.resetWithControl(BlockLOONG64NEZ, cmp)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (EQ (XORconst [1] cmp:(SGTconst _)) yes no)
|
// match: (EQZ (XORconst [1] cmp:(SGTconst _)) yes no)
|
||||||
// result: (NE cmp yes no)
|
// result: (NEZ cmp yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64XORconst {
|
for b.Controls[0].Op == OpLOONG64XORconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
if auxIntToInt64(v_0.AuxInt) != 1 {
|
if auxIntToInt64(v_0.AuxInt) != 1 {
|
||||||
|
|
@ -11496,11 +11651,11 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
if cmp.Op != OpLOONG64SGTconst {
|
if cmp.Op != OpLOONG64SGTconst {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b.resetWithControl(BlockLOONG64NE, cmp)
|
b.resetWithControl(BlockLOONG64NEZ, cmp)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (EQ (XORconst [1] cmp:(SGTUconst _)) yes no)
|
// match: (EQZ (XORconst [1] cmp:(SGTUconst _)) yes no)
|
||||||
// result: (NE cmp yes no)
|
// result: (NEZ cmp yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64XORconst {
|
for b.Controls[0].Op == OpLOONG64XORconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
if auxIntToInt64(v_0.AuxInt) != 1 {
|
if auxIntToInt64(v_0.AuxInt) != 1 {
|
||||||
|
|
@ -11510,22 +11665,22 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
if cmp.Op != OpLOONG64SGTUconst {
|
if cmp.Op != OpLOONG64SGTUconst {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b.resetWithControl(BlockLOONG64NE, cmp)
|
b.resetWithControl(BlockLOONG64NEZ, cmp)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (EQ (SGTUconst [1] x) yes no)
|
// match: (EQZ (SGTUconst [1] x) yes no)
|
||||||
// result: (NE x yes no)
|
// result: (NEZ x yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64SGTUconst {
|
for b.Controls[0].Op == OpLOONG64SGTUconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
if auxIntToInt64(v_0.AuxInt) != 1 {
|
if auxIntToInt64(v_0.AuxInt) != 1 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
x := v_0.Args[0]
|
x := v_0.Args[0]
|
||||||
b.resetWithControl(BlockLOONG64NE, x)
|
b.resetWithControl(BlockLOONG64NEZ, x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (EQ (SGTU x (MOVVconst [0])) yes no)
|
// match: (EQZ (SGTU x (MOVVconst [0])) yes no)
|
||||||
// result: (EQ x yes no)
|
// result: (EQZ x yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64SGTU {
|
for b.Controls[0].Op == OpLOONG64SGTU {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
_ = v_0.Args[1]
|
_ = v_0.Args[1]
|
||||||
|
|
@ -11534,10 +11689,10 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
if v_0_1.Op != OpLOONG64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != 0 {
|
if v_0_1.Op != OpLOONG64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b.resetWithControl(BlockLOONG64EQ, x)
|
b.resetWithControl(BlockLOONG64EQZ, x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (EQ (SGTconst [0] x) yes no)
|
// match: (EQZ (SGTconst [0] x) yes no)
|
||||||
// result: (GEZ x yes no)
|
// result: (GEZ x yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64SGTconst {
|
for b.Controls[0].Op == OpLOONG64SGTconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
|
|
@ -11548,7 +11703,7 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.resetWithControl(BlockLOONG64GEZ, x)
|
b.resetWithControl(BlockLOONG64GEZ, x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (EQ (SGT x (MOVVconst [0])) yes no)
|
// match: (EQZ (SGT x (MOVVconst [0])) yes no)
|
||||||
// result: (LEZ x yes no)
|
// result: (LEZ x yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64SGT {
|
for b.Controls[0].Op == OpLOONG64SGT {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
|
|
@ -11561,9 +11716,9 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.resetWithControl(BlockLOONG64LEZ, x)
|
b.resetWithControl(BlockLOONG64LEZ, x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (EQ (SGTU (MOVVconst [c]) y) yes no)
|
// match: (EQZ (SGTU (MOVVconst [c]) y) yes no)
|
||||||
// cond: c >= -2048 && c <= 2047
|
// cond: c >= -2048 && c <= 2047
|
||||||
// result: (EQ (SGTUconst [c] y) yes no)
|
// result: (EQZ (SGTUconst [c] y) yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64SGTU {
|
for b.Controls[0].Op == OpLOONG64SGTU {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
y := v_0.Args[1]
|
y := v_0.Args[1]
|
||||||
|
|
@ -11578,10 +11733,10 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
v0 := b.NewValue0(v_0.Pos, OpLOONG64SGTUconst, typ.Bool)
|
v0 := b.NewValue0(v_0.Pos, OpLOONG64SGTUconst, typ.Bool)
|
||||||
v0.AuxInt = int64ToAuxInt(c)
|
v0.AuxInt = int64ToAuxInt(c)
|
||||||
v0.AddArg(y)
|
v0.AddArg(y)
|
||||||
b.resetWithControl(BlockLOONG64EQ, v0)
|
b.resetWithControl(BlockLOONG64EQZ, v0)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (EQ (SUBV x y) yes no)
|
// match: (EQZ (SUBV x y) yes no)
|
||||||
// result: (BEQ x y yes no)
|
// result: (BEQ x y yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64SUBV {
|
for b.Controls[0].Op == OpLOONG64SUBV {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
|
|
@ -11590,7 +11745,7 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.resetWithControl2(BlockLOONG64BEQ, x, y)
|
b.resetWithControl2(BlockLOONG64BEQ, x, y)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (EQ (SGT x y) yes no)
|
// match: (EQZ (SGT x y) yes no)
|
||||||
// result: (BGE y x yes no)
|
// result: (BGE y x yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64SGT {
|
for b.Controls[0].Op == OpLOONG64SGT {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
|
|
@ -11599,7 +11754,7 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.resetWithControl2(BlockLOONG64BGE, y, x)
|
b.resetWithControl2(BlockLOONG64BGE, y, x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (EQ (SGTU x y) yes no)
|
// match: (EQZ (SGTU x y) yes no)
|
||||||
// result: (BGEU y x yes no)
|
// result: (BGEU y x yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64SGTU {
|
for b.Controls[0].Op == OpLOONG64SGTU {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
|
|
@ -11608,7 +11763,29 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.resetWithControl2(BlockLOONG64BGEU, y, x)
|
b.resetWithControl2(BlockLOONG64BGEU, y, x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (EQ (MOVVconst [0]) yes no)
|
// match: (EQZ (SGTconst [c] y) yes no)
|
||||||
|
// result: (BGE y (MOVVconst [c]) yes no)
|
||||||
|
for b.Controls[0].Op == OpLOONG64SGTconst {
|
||||||
|
v_0 := b.Controls[0]
|
||||||
|
c := auxIntToInt64(v_0.AuxInt)
|
||||||
|
y := v_0.Args[0]
|
||||||
|
v0 := b.NewValue0(b.Pos, OpLOONG64MOVVconst, typ.UInt64)
|
||||||
|
v0.AuxInt = int64ToAuxInt(c)
|
||||||
|
b.resetWithControl2(BlockLOONG64BGE, y, v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (EQZ (SGTUconst [c] y) yes no)
|
||||||
|
// result: (BGEU y (MOVVconst [c]) yes no)
|
||||||
|
for b.Controls[0].Op == OpLOONG64SGTUconst {
|
||||||
|
v_0 := b.Controls[0]
|
||||||
|
c := auxIntToInt64(v_0.AuxInt)
|
||||||
|
y := v_0.Args[0]
|
||||||
|
v0 := b.NewValue0(b.Pos, OpLOONG64MOVVconst, typ.UInt64)
|
||||||
|
v0.AuxInt = int64ToAuxInt(c)
|
||||||
|
b.resetWithControl2(BlockLOONG64BGEU, y, v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (EQZ (MOVVconst [0]) yes no)
|
||||||
// result: (First yes no)
|
// result: (First yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64MOVVconst {
|
for b.Controls[0].Op == OpLOONG64MOVVconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
|
|
@ -11618,7 +11795,7 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.Reset(BlockFirst)
|
b.Reset(BlockFirst)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (EQ (MOVVconst [c]) yes no)
|
// match: (EQZ (MOVVconst [c]) yes no)
|
||||||
// cond: c != 0
|
// cond: c != 0
|
||||||
// result: (First no yes)
|
// result: (First no yes)
|
||||||
for b.Controls[0].Op == OpLOONG64MOVVconst {
|
for b.Controls[0].Op == OpLOONG64MOVVconst {
|
||||||
|
|
@ -11631,6 +11808,14 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.swapSuccessors()
|
b.swapSuccessors()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (EQZ (NEGV x) yes no)
|
||||||
|
// result: (EQZ x yes no)
|
||||||
|
for b.Controls[0].Op == OpLOONG64NEGV {
|
||||||
|
v_0 := b.Controls[0]
|
||||||
|
x := v_0.Args[0]
|
||||||
|
b.resetWithControl(BlockLOONG64EQZ, x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
case BlockLOONG64GEZ:
|
case BlockLOONG64GEZ:
|
||||||
// match: (GEZ (MOVVconst [c]) yes no)
|
// match: (GEZ (MOVVconst [c]) yes no)
|
||||||
// cond: c >= 0
|
// cond: c >= 0
|
||||||
|
|
@ -11685,12 +11870,12 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
}
|
}
|
||||||
case BlockIf:
|
case BlockIf:
|
||||||
// match: (If cond yes no)
|
// match: (If cond yes no)
|
||||||
// result: (NE (MOVBUreg <typ.UInt64> cond) yes no)
|
// result: (NEZ (MOVBUreg <typ.UInt64> cond) yes no)
|
||||||
for {
|
for {
|
||||||
cond := b.Controls[0]
|
cond := b.Controls[0]
|
||||||
v0 := b.NewValue0(cond.Pos, OpLOONG64MOVBUreg, typ.UInt64)
|
v0 := b.NewValue0(cond.Pos, OpLOONG64MOVBUreg, typ.UInt64)
|
||||||
v0.AddArg(cond)
|
v0.AddArg(cond)
|
||||||
b.resetWithControl(BlockLOONG64NE, v0)
|
b.resetWithControl(BlockLOONG64NEZ, v0)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
case BlockLOONG64LEZ:
|
case BlockLOONG64LEZ:
|
||||||
|
|
@ -11745,8 +11930,8 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.swapSuccessors()
|
b.swapSuccessors()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
case BlockLOONG64NE:
|
case BlockLOONG64NEZ:
|
||||||
// match: (NE (FPFlagTrue cmp) yes no)
|
// match: (NEZ (FPFlagTrue cmp) yes no)
|
||||||
// result: (FPT cmp yes no)
|
// result: (FPT cmp yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64FPFlagTrue {
|
for b.Controls[0].Op == OpLOONG64FPFlagTrue {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
|
|
@ -11754,7 +11939,7 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.resetWithControl(BlockLOONG64FPT, cmp)
|
b.resetWithControl(BlockLOONG64FPT, cmp)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (NE (FPFlagFalse cmp) yes no)
|
// match: (NEZ (FPFlagFalse cmp) yes no)
|
||||||
// result: (FPF cmp yes no)
|
// result: (FPF cmp yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64FPFlagFalse {
|
for b.Controls[0].Op == OpLOONG64FPFlagFalse {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
|
|
@ -11762,8 +11947,8 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.resetWithControl(BlockLOONG64FPF, cmp)
|
b.resetWithControl(BlockLOONG64FPF, cmp)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (NE (XORconst [1] cmp:(SGT _ _)) yes no)
|
// match: (NEZ (XORconst [1] cmp:(SGT _ _)) yes no)
|
||||||
// result: (EQ cmp yes no)
|
// result: (EQZ cmp yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64XORconst {
|
for b.Controls[0].Op == OpLOONG64XORconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
if auxIntToInt64(v_0.AuxInt) != 1 {
|
if auxIntToInt64(v_0.AuxInt) != 1 {
|
||||||
|
|
@ -11773,11 +11958,11 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
if cmp.Op != OpLOONG64SGT {
|
if cmp.Op != OpLOONG64SGT {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b.resetWithControl(BlockLOONG64EQ, cmp)
|
b.resetWithControl(BlockLOONG64EQZ, cmp)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (NE (XORconst [1] cmp:(SGTU _ _)) yes no)
|
// match: (NEZ (XORconst [1] cmp:(SGTU _ _)) yes no)
|
||||||
// result: (EQ cmp yes no)
|
// result: (EQZ cmp yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64XORconst {
|
for b.Controls[0].Op == OpLOONG64XORconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
if auxIntToInt64(v_0.AuxInt) != 1 {
|
if auxIntToInt64(v_0.AuxInt) != 1 {
|
||||||
|
|
@ -11787,11 +11972,11 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
if cmp.Op != OpLOONG64SGTU {
|
if cmp.Op != OpLOONG64SGTU {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b.resetWithControl(BlockLOONG64EQ, cmp)
|
b.resetWithControl(BlockLOONG64EQZ, cmp)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (NE (XORconst [1] cmp:(SGTconst _)) yes no)
|
// match: (NEZ (XORconst [1] cmp:(SGTconst _)) yes no)
|
||||||
// result: (EQ cmp yes no)
|
// result: (EQZ cmp yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64XORconst {
|
for b.Controls[0].Op == OpLOONG64XORconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
if auxIntToInt64(v_0.AuxInt) != 1 {
|
if auxIntToInt64(v_0.AuxInt) != 1 {
|
||||||
|
|
@ -11801,11 +11986,11 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
if cmp.Op != OpLOONG64SGTconst {
|
if cmp.Op != OpLOONG64SGTconst {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b.resetWithControl(BlockLOONG64EQ, cmp)
|
b.resetWithControl(BlockLOONG64EQZ, cmp)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (NE (XORconst [1] cmp:(SGTUconst _)) yes no)
|
// match: (NEZ (XORconst [1] cmp:(SGTUconst _)) yes no)
|
||||||
// result: (EQ cmp yes no)
|
// result: (EQZ cmp yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64XORconst {
|
for b.Controls[0].Op == OpLOONG64XORconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
if auxIntToInt64(v_0.AuxInt) != 1 {
|
if auxIntToInt64(v_0.AuxInt) != 1 {
|
||||||
|
|
@ -11815,22 +12000,22 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
if cmp.Op != OpLOONG64SGTUconst {
|
if cmp.Op != OpLOONG64SGTUconst {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b.resetWithControl(BlockLOONG64EQ, cmp)
|
b.resetWithControl(BlockLOONG64EQZ, cmp)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (NE (SGTUconst [1] x) yes no)
|
// match: (NEZ (SGTUconst [1] x) yes no)
|
||||||
// result: (EQ x yes no)
|
// result: (EQZ x yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64SGTUconst {
|
for b.Controls[0].Op == OpLOONG64SGTUconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
if auxIntToInt64(v_0.AuxInt) != 1 {
|
if auxIntToInt64(v_0.AuxInt) != 1 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
x := v_0.Args[0]
|
x := v_0.Args[0]
|
||||||
b.resetWithControl(BlockLOONG64EQ, x)
|
b.resetWithControl(BlockLOONG64EQZ, x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (NE (SGTU x (MOVVconst [0])) yes no)
|
// match: (NEZ (SGTU x (MOVVconst [0])) yes no)
|
||||||
// result: (NE x yes no)
|
// result: (NEZ x yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64SGTU {
|
for b.Controls[0].Op == OpLOONG64SGTU {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
_ = v_0.Args[1]
|
_ = v_0.Args[1]
|
||||||
|
|
@ -11839,10 +12024,10 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
if v_0_1.Op != OpLOONG64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != 0 {
|
if v_0_1.Op != OpLOONG64MOVVconst || auxIntToInt64(v_0_1.AuxInt) != 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
b.resetWithControl(BlockLOONG64NE, x)
|
b.resetWithControl(BlockLOONG64NEZ, x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (NE (SGTconst [0] x) yes no)
|
// match: (NEZ (SGTconst [0] x) yes no)
|
||||||
// result: (LTZ x yes no)
|
// result: (LTZ x yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64SGTconst {
|
for b.Controls[0].Op == OpLOONG64SGTconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
|
|
@ -11853,7 +12038,7 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.resetWithControl(BlockLOONG64LTZ, x)
|
b.resetWithControl(BlockLOONG64LTZ, x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (NE (SGT x (MOVVconst [0])) yes no)
|
// match: (NEZ (SGT x (MOVVconst [0])) yes no)
|
||||||
// result: (GTZ x yes no)
|
// result: (GTZ x yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64SGT {
|
for b.Controls[0].Op == OpLOONG64SGT {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
|
|
@ -11866,9 +12051,9 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.resetWithControl(BlockLOONG64GTZ, x)
|
b.resetWithControl(BlockLOONG64GTZ, x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (NE (SGTU (MOVVconst [c]) y) yes no)
|
// match: (NEZ (SGTU (MOVVconst [c]) y) yes no)
|
||||||
// cond: c >= -2048 && c <= 2047
|
// cond: c >= -2048 && c <= 2047
|
||||||
// result: (NE (SGTUconst [c] y) yes no)
|
// result: (NEZ (SGTUconst [c] y) yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64SGTU {
|
for b.Controls[0].Op == OpLOONG64SGTU {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
y := v_0.Args[1]
|
y := v_0.Args[1]
|
||||||
|
|
@ -11883,10 +12068,10 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
v0 := b.NewValue0(v_0.Pos, OpLOONG64SGTUconst, typ.Bool)
|
v0 := b.NewValue0(v_0.Pos, OpLOONG64SGTUconst, typ.Bool)
|
||||||
v0.AuxInt = int64ToAuxInt(c)
|
v0.AuxInt = int64ToAuxInt(c)
|
||||||
v0.AddArg(y)
|
v0.AddArg(y)
|
||||||
b.resetWithControl(BlockLOONG64NE, v0)
|
b.resetWithControl(BlockLOONG64NEZ, v0)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (NE (SUBV x y) yes no)
|
// match: (NEZ (SUBV x y) yes no)
|
||||||
// result: (BNE x y yes no)
|
// result: (BNE x y yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64SUBV {
|
for b.Controls[0].Op == OpLOONG64SUBV {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
|
|
@ -11895,7 +12080,7 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.resetWithControl2(BlockLOONG64BNE, x, y)
|
b.resetWithControl2(BlockLOONG64BNE, x, y)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (NE (SGT x y) yes no)
|
// match: (NEZ (SGT x y) yes no)
|
||||||
// result: (BLT y x yes no)
|
// result: (BLT y x yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64SGT {
|
for b.Controls[0].Op == OpLOONG64SGT {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
|
|
@ -11904,7 +12089,7 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.resetWithControl2(BlockLOONG64BLT, y, x)
|
b.resetWithControl2(BlockLOONG64BLT, y, x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (NE (SGTU x y) yes no)
|
// match: (NEZ (SGTU x y) yes no)
|
||||||
// result: (BLTU y x yes no)
|
// result: (BLTU y x yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64SGTU {
|
for b.Controls[0].Op == OpLOONG64SGTU {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
|
|
@ -11913,7 +12098,29 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.resetWithControl2(BlockLOONG64BLTU, y, x)
|
b.resetWithControl2(BlockLOONG64BLTU, y, x)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (NE (MOVVconst [0]) yes no)
|
// match: (NEZ (SGTconst [c] y) yes no)
|
||||||
|
// result: (BLT y (MOVVconst [c]) yes no)
|
||||||
|
for b.Controls[0].Op == OpLOONG64SGTconst {
|
||||||
|
v_0 := b.Controls[0]
|
||||||
|
c := auxIntToInt64(v_0.AuxInt)
|
||||||
|
y := v_0.Args[0]
|
||||||
|
v0 := b.NewValue0(b.Pos, OpLOONG64MOVVconst, typ.UInt64)
|
||||||
|
v0.AuxInt = int64ToAuxInt(c)
|
||||||
|
b.resetWithControl2(BlockLOONG64BLT, y, v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (NEZ (SGTUconst [c] y) yes no)
|
||||||
|
// result: (BLTU y (MOVVconst [c]) yes no)
|
||||||
|
for b.Controls[0].Op == OpLOONG64SGTUconst {
|
||||||
|
v_0 := b.Controls[0]
|
||||||
|
c := auxIntToInt64(v_0.AuxInt)
|
||||||
|
y := v_0.Args[0]
|
||||||
|
v0 := b.NewValue0(b.Pos, OpLOONG64MOVVconst, typ.UInt64)
|
||||||
|
v0.AuxInt = int64ToAuxInt(c)
|
||||||
|
b.resetWithControl2(BlockLOONG64BLTU, y, v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (NEZ (MOVVconst [0]) yes no)
|
||||||
// result: (First no yes)
|
// result: (First no yes)
|
||||||
for b.Controls[0].Op == OpLOONG64MOVVconst {
|
for b.Controls[0].Op == OpLOONG64MOVVconst {
|
||||||
v_0 := b.Controls[0]
|
v_0 := b.Controls[0]
|
||||||
|
|
@ -11924,7 +12131,7 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.swapSuccessors()
|
b.swapSuccessors()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (NE (MOVVconst [c]) yes no)
|
// match: (NEZ (MOVVconst [c]) yes no)
|
||||||
// cond: c != 0
|
// cond: c != 0
|
||||||
// result: (First yes no)
|
// result: (First yes no)
|
||||||
for b.Controls[0].Op == OpLOONG64MOVVconst {
|
for b.Controls[0].Op == OpLOONG64MOVVconst {
|
||||||
|
|
@ -11936,6 +12143,14 @@ func rewriteBlockLOONG64(b *Block) bool {
|
||||||
b.Reset(BlockFirst)
|
b.Reset(BlockFirst)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (NEZ (NEGV x) yes no)
|
||||||
|
// result: (NEZ x yes no)
|
||||||
|
for b.Controls[0].Op == OpLOONG64NEGV {
|
||||||
|
v_0 := b.Controls[0]
|
||||||
|
x := v_0.Args[0]
|
||||||
|
b.resetWithControl(BlockLOONG64NEZ, x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,5 +25,37 @@ func rewriteValueLOONG64latelower_OpLOONG64SLLVconst(v *Value) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteBlockLOONG64latelower(b *Block) bool {
|
func rewriteBlockLOONG64latelower(b *Block) bool {
|
||||||
|
switch b.Kind {
|
||||||
|
case BlockLOONG64EQZ:
|
||||||
|
// match: (EQZ (XOR x y) yes no)
|
||||||
|
// result: (BEQ x y yes no)
|
||||||
|
for b.Controls[0].Op == OpLOONG64XOR {
|
||||||
|
v_0 := b.Controls[0]
|
||||||
|
_ = v_0.Args[1]
|
||||||
|
v_0_0 := v_0.Args[0]
|
||||||
|
v_0_1 := v_0.Args[1]
|
||||||
|
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
|
||||||
|
x := v_0_0
|
||||||
|
y := v_0_1
|
||||||
|
b.resetWithControl2(BlockLOONG64BEQ, x, y)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case BlockLOONG64NEZ:
|
||||||
|
// match: (NEZ (XOR x y) yes no)
|
||||||
|
// result: (BNE x y yes no)
|
||||||
|
for b.Controls[0].Op == OpLOONG64XOR {
|
||||||
|
v_0 := b.Controls[0]
|
||||||
|
_ = v_0.Args[1]
|
||||||
|
v_0_0 := v_0.Args[0]
|
||||||
|
v_0_1 := v_0.Args[1]
|
||||||
|
for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 {
|
||||||
|
x := v_0_0
|
||||||
|
y := v_0_1
|
||||||
|
b.resetWithControl2(BlockLOONG64BNE, x, y)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -540,6 +540,12 @@ func rewriteValuePPC64(v *Value) bool {
|
||||||
return rewriteValuePPC64_OpPPC64LessEqual(v)
|
return rewriteValuePPC64_OpPPC64LessEqual(v)
|
||||||
case OpPPC64LessThan:
|
case OpPPC64LessThan:
|
||||||
return rewriteValuePPC64_OpPPC64LessThan(v)
|
return rewriteValuePPC64_OpPPC64LessThan(v)
|
||||||
|
case OpPPC64LoweredPanicBoundsCR:
|
||||||
|
return rewriteValuePPC64_OpPPC64LoweredPanicBoundsCR(v)
|
||||||
|
case OpPPC64LoweredPanicBoundsRC:
|
||||||
|
return rewriteValuePPC64_OpPPC64LoweredPanicBoundsRC(v)
|
||||||
|
case OpPPC64LoweredPanicBoundsRR:
|
||||||
|
return rewriteValuePPC64_OpPPC64LoweredPanicBoundsRR(v)
|
||||||
case OpPPC64MFVSRD:
|
case OpPPC64MFVSRD:
|
||||||
return rewriteValuePPC64_OpPPC64MFVSRD(v)
|
return rewriteValuePPC64_OpPPC64MFVSRD(v)
|
||||||
case OpPPC64MOVBZload:
|
case OpPPC64MOVBZload:
|
||||||
|
|
@ -667,7 +673,8 @@ func rewriteValuePPC64(v *Value) bool {
|
||||||
case OpPPC64XORconst:
|
case OpPPC64XORconst:
|
||||||
return rewriteValuePPC64_OpPPC64XORconst(v)
|
return rewriteValuePPC64_OpPPC64XORconst(v)
|
||||||
case OpPanicBounds:
|
case OpPanicBounds:
|
||||||
return rewriteValuePPC64_OpPanicBounds(v)
|
v.Op = OpPPC64LoweredPanicBoundsRR
|
||||||
|
return true
|
||||||
case OpPopCount16:
|
case OpPopCount16:
|
||||||
return rewriteValuePPC64_OpPopCount16(v)
|
return rewriteValuePPC64_OpPopCount16(v)
|
||||||
case OpPopCount32:
|
case OpPopCount32:
|
||||||
|
|
@ -6826,6 +6833,86 @@ func rewriteValuePPC64_OpPPC64LessThan(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func rewriteValuePPC64_OpPPC64LoweredPanicBoundsCR(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
// match: (LoweredPanicBoundsCR [kind] {p} (MOVDconst [c]) mem)
|
||||||
|
// result: (LoweredPanicBoundsCC [kind] {PanicBoundsCC{Cx:p.C, Cy:c}} mem)
|
||||||
|
for {
|
||||||
|
kind := auxIntToInt64(v.AuxInt)
|
||||||
|
p := auxToPanicBoundsC(v.Aux)
|
||||||
|
if v_0.Op != OpPPC64MOVDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := auxIntToInt64(v_0.AuxInt)
|
||||||
|
mem := v_1
|
||||||
|
v.reset(OpPPC64LoweredPanicBoundsCC)
|
||||||
|
v.AuxInt = int64ToAuxInt(kind)
|
||||||
|
v.Aux = panicBoundsCCToAux(PanicBoundsCC{Cx: p.C, Cy: c})
|
||||||
|
v.AddArg(mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func rewriteValuePPC64_OpPPC64LoweredPanicBoundsRC(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
// match: (LoweredPanicBoundsRC [kind] {p} (MOVDconst [c]) mem)
|
||||||
|
// result: (LoweredPanicBoundsCC [kind] {PanicBoundsCC{Cx:c, Cy:p.C}} mem)
|
||||||
|
for {
|
||||||
|
kind := auxIntToInt64(v.AuxInt)
|
||||||
|
p := auxToPanicBoundsC(v.Aux)
|
||||||
|
if v_0.Op != OpPPC64MOVDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := auxIntToInt64(v_0.AuxInt)
|
||||||
|
mem := v_1
|
||||||
|
v.reset(OpPPC64LoweredPanicBoundsCC)
|
||||||
|
v.AuxInt = int64ToAuxInt(kind)
|
||||||
|
v.Aux = panicBoundsCCToAux(PanicBoundsCC{Cx: c, Cy: p.C})
|
||||||
|
v.AddArg(mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func rewriteValuePPC64_OpPPC64LoweredPanicBoundsRR(v *Value) bool {
|
||||||
|
v_2 := v.Args[2]
|
||||||
|
v_1 := v.Args[1]
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
// match: (LoweredPanicBoundsRR [kind] x (MOVDconst [c]) mem)
|
||||||
|
// result: (LoweredPanicBoundsRC [kind] x {PanicBoundsC{C:c}} mem)
|
||||||
|
for {
|
||||||
|
kind := auxIntToInt64(v.AuxInt)
|
||||||
|
x := v_0
|
||||||
|
if v_1.Op != OpPPC64MOVDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := auxIntToInt64(v_1.AuxInt)
|
||||||
|
mem := v_2
|
||||||
|
v.reset(OpPPC64LoweredPanicBoundsRC)
|
||||||
|
v.AuxInt = int64ToAuxInt(kind)
|
||||||
|
v.Aux = panicBoundsCToAux(PanicBoundsC{C: c})
|
||||||
|
v.AddArg2(x, mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (LoweredPanicBoundsRR [kind] (MOVDconst [c]) y mem)
|
||||||
|
// result: (LoweredPanicBoundsCR [kind] {PanicBoundsC{C:c}} y mem)
|
||||||
|
for {
|
||||||
|
kind := auxIntToInt64(v.AuxInt)
|
||||||
|
if v_0.Op != OpPPC64MOVDconst {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c := auxIntToInt64(v_0.AuxInt)
|
||||||
|
y := v_1
|
||||||
|
mem := v_2
|
||||||
|
v.reset(OpPPC64LoweredPanicBoundsCR)
|
||||||
|
v.AuxInt = int64ToAuxInt(kind)
|
||||||
|
v.Aux = panicBoundsCToAux(PanicBoundsC{C: c})
|
||||||
|
v.AddArg2(y, mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
func rewriteValuePPC64_OpPPC64MFVSRD(v *Value) bool {
|
func rewriteValuePPC64_OpPPC64MFVSRD(v *Value) bool {
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
b := v.Block
|
b := v.Block
|
||||||
|
|
@ -12981,60 +13068,6 @@ func rewriteValuePPC64_OpPPC64XORconst(v *Value) bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValuePPC64_OpPanicBounds(v *Value) bool {
|
|
||||||
v_2 := v.Args[2]
|
|
||||||
v_1 := v.Args[1]
|
|
||||||
v_0 := v.Args[0]
|
|
||||||
// match: (PanicBounds [kind] x y mem)
|
|
||||||
// cond: boundsABI(kind) == 0
|
|
||||||
// result: (LoweredPanicBoundsA [kind] x y mem)
|
|
||||||
for {
|
|
||||||
kind := auxIntToInt64(v.AuxInt)
|
|
||||||
x := v_0
|
|
||||||
y := v_1
|
|
||||||
mem := v_2
|
|
||||||
if !(boundsABI(kind) == 0) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpPPC64LoweredPanicBoundsA)
|
|
||||||
v.AuxInt = int64ToAuxInt(kind)
|
|
||||||
v.AddArg3(x, y, mem)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (PanicBounds [kind] x y mem)
|
|
||||||
// cond: boundsABI(kind) == 1
|
|
||||||
// result: (LoweredPanicBoundsB [kind] x y mem)
|
|
||||||
for {
|
|
||||||
kind := auxIntToInt64(v.AuxInt)
|
|
||||||
x := v_0
|
|
||||||
y := v_1
|
|
||||||
mem := v_2
|
|
||||||
if !(boundsABI(kind) == 1) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpPPC64LoweredPanicBoundsB)
|
|
||||||
v.AuxInt = int64ToAuxInt(kind)
|
|
||||||
v.AddArg3(x, y, mem)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (PanicBounds [kind] x y mem)
|
|
||||||
// cond: boundsABI(kind) == 2
|
|
||||||
// result: (LoweredPanicBoundsC [kind] x y mem)
|
|
||||||
for {
|
|
||||||
kind := auxIntToInt64(v.AuxInt)
|
|
||||||
x := v_0
|
|
||||||
y := v_1
|
|
||||||
mem := v_2
|
|
||||||
if !(boundsABI(kind) == 2) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpPPC64LoweredPanicBoundsC)
|
|
||||||
v.AuxInt = int64ToAuxInt(kind)
|
|
||||||
v.AddArg3(x, y, mem)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
func rewriteValuePPC64_OpPopCount16(v *Value) bool {
|
func rewriteValuePPC64_OpPopCount16(v *Value) bool {
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
b := v.Block
|
b := v.Block
|
||||||
|
|
|
||||||
|
|
@ -513,14 +513,30 @@ func rewriteValueRISCV64(v *Value) bool {
|
||||||
return rewriteValueRISCV64_OpRISCV64FADDD(v)
|
return rewriteValueRISCV64_OpRISCV64FADDD(v)
|
||||||
case OpRISCV64FADDS:
|
case OpRISCV64FADDS:
|
||||||
return rewriteValueRISCV64_OpRISCV64FADDS(v)
|
return rewriteValueRISCV64_OpRISCV64FADDS(v)
|
||||||
|
case OpRISCV64FEQD:
|
||||||
|
return rewriteValueRISCV64_OpRISCV64FEQD(v)
|
||||||
|
case OpRISCV64FLED:
|
||||||
|
return rewriteValueRISCV64_OpRISCV64FLED(v)
|
||||||
|
case OpRISCV64FLTD:
|
||||||
|
return rewriteValueRISCV64_OpRISCV64FLTD(v)
|
||||||
case OpRISCV64FMADDD:
|
case OpRISCV64FMADDD:
|
||||||
return rewriteValueRISCV64_OpRISCV64FMADDD(v)
|
return rewriteValueRISCV64_OpRISCV64FMADDD(v)
|
||||||
case OpRISCV64FMADDS:
|
case OpRISCV64FMADDS:
|
||||||
return rewriteValueRISCV64_OpRISCV64FMADDS(v)
|
return rewriteValueRISCV64_OpRISCV64FMADDS(v)
|
||||||
|
case OpRISCV64FMOVDload:
|
||||||
|
return rewriteValueRISCV64_OpRISCV64FMOVDload(v)
|
||||||
|
case OpRISCV64FMOVDstore:
|
||||||
|
return rewriteValueRISCV64_OpRISCV64FMOVDstore(v)
|
||||||
|
case OpRISCV64FMOVWload:
|
||||||
|
return rewriteValueRISCV64_OpRISCV64FMOVWload(v)
|
||||||
|
case OpRISCV64FMOVWstore:
|
||||||
|
return rewriteValueRISCV64_OpRISCV64FMOVWstore(v)
|
||||||
case OpRISCV64FMSUBD:
|
case OpRISCV64FMSUBD:
|
||||||
return rewriteValueRISCV64_OpRISCV64FMSUBD(v)
|
return rewriteValueRISCV64_OpRISCV64FMSUBD(v)
|
||||||
case OpRISCV64FMSUBS:
|
case OpRISCV64FMSUBS:
|
||||||
return rewriteValueRISCV64_OpRISCV64FMSUBS(v)
|
return rewriteValueRISCV64_OpRISCV64FMSUBS(v)
|
||||||
|
case OpRISCV64FNED:
|
||||||
|
return rewriteValueRISCV64_OpRISCV64FNED(v)
|
||||||
case OpRISCV64FNMADDD:
|
case OpRISCV64FNMADDD:
|
||||||
return rewriteValueRISCV64_OpRISCV64FNMADDD(v)
|
return rewriteValueRISCV64_OpRISCV64FNMADDD(v)
|
||||||
case OpRISCV64FNMADDS:
|
case OpRISCV64FNMADDS:
|
||||||
|
|
@ -3754,6 +3770,149 @@ func rewriteValueRISCV64_OpRISCV64FADDS(v *Value) bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
func rewriteValueRISCV64_OpRISCV64FEQD(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
b := v.Block
|
||||||
|
typ := &b.Func.Config.Types
|
||||||
|
// match: (FEQD x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(-1)))])))
|
||||||
|
// result: (ANDI [1] (FCLASSD x))
|
||||||
|
for {
|
||||||
|
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||||
|
x := v_0
|
||||||
|
if v_1.Op != OpRISCV64FMVDX {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
v_1_0 := v_1.Args[0]
|
||||||
|
if v_1_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != int64(math.Float64bits(math.Inf(-1))) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64ANDI)
|
||||||
|
v.AuxInt = int64ToAuxInt(1)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpRISCV64FCLASSD, typ.Int64)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// match: (FEQD x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(1)))])))
|
||||||
|
// result: (SNEZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
|
||||||
|
for {
|
||||||
|
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||||
|
x := v_0
|
||||||
|
if v_1.Op != OpRISCV64FMVDX {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
v_1_0 := v_1.Args[0]
|
||||||
|
if v_1_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != int64(math.Float64bits(math.Inf(1))) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64SNEZ)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpRISCV64ANDI, typ.Int64)
|
||||||
|
v0.AuxInt = int64ToAuxInt(1 << 7)
|
||||||
|
v1 := b.NewValue0(v.Pos, OpRISCV64FCLASSD, typ.Int64)
|
||||||
|
v1.AddArg(x)
|
||||||
|
v0.AddArg(v1)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func rewriteValueRISCV64_OpRISCV64FLED(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
b := v.Block
|
||||||
|
typ := &b.Func.Config.Types
|
||||||
|
// match: (FLED (FMVDX (MOVDconst [int64(math.Float64bits(-math.MaxFloat64))])) x)
|
||||||
|
// result: (SNEZ (ANDI <typ.Int64> [0xff &^ 1] (FCLASSD x)))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpRISCV64FMVDX {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0_0 := v_0.Args[0]
|
||||||
|
if v_0_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_0_0.AuxInt) != int64(math.Float64bits(-math.MaxFloat64)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
x := v_1
|
||||||
|
v.reset(OpRISCV64SNEZ)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpRISCV64ANDI, typ.Int64)
|
||||||
|
v0.AuxInt = int64ToAuxInt(0xff &^ 1)
|
||||||
|
v1 := b.NewValue0(v.Pos, OpRISCV64FCLASSD, typ.Int64)
|
||||||
|
v1.AddArg(x)
|
||||||
|
v0.AddArg(v1)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (FLED x (FMVDX (MOVDconst [int64(math.Float64bits(math.MaxFloat64))])))
|
||||||
|
// result: (SNEZ (ANDI <typ.Int64> [0xff &^ (1<<7)] (FCLASSD x)))
|
||||||
|
for {
|
||||||
|
x := v_0
|
||||||
|
if v_1.Op != OpRISCV64FMVDX {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_1_0 := v_1.Args[0]
|
||||||
|
if v_1_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != int64(math.Float64bits(math.MaxFloat64)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64SNEZ)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpRISCV64ANDI, typ.Int64)
|
||||||
|
v0.AuxInt = int64ToAuxInt(0xff &^ (1 << 7))
|
||||||
|
v1 := b.NewValue0(v.Pos, OpRISCV64FCLASSD, typ.Int64)
|
||||||
|
v1.AddArg(x)
|
||||||
|
v0.AddArg(v1)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func rewriteValueRISCV64_OpRISCV64FLTD(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
b := v.Block
|
||||||
|
typ := &b.Func.Config.Types
|
||||||
|
// match: (FLTD x (FMVDX (MOVDconst [int64(math.Float64bits(-math.MaxFloat64))])))
|
||||||
|
// result: (ANDI [1] (FCLASSD x))
|
||||||
|
for {
|
||||||
|
x := v_0
|
||||||
|
if v_1.Op != OpRISCV64FMVDX {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_1_0 := v_1.Args[0]
|
||||||
|
if v_1_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != int64(math.Float64bits(-math.MaxFloat64)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64ANDI)
|
||||||
|
v.AuxInt = int64ToAuxInt(1)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpRISCV64FCLASSD, typ.Int64)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (FLTD (FMVDX (MOVDconst [int64(math.Float64bits(math.MaxFloat64))])) x)
|
||||||
|
// result: (SNEZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpRISCV64FMVDX {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0_0 := v_0.Args[0]
|
||||||
|
if v_0_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_0_0.AuxInt) != int64(math.Float64bits(math.MaxFloat64)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
x := v_1
|
||||||
|
v.reset(OpRISCV64SNEZ)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpRISCV64ANDI, typ.Int64)
|
||||||
|
v0.AuxInt = int64ToAuxInt(1 << 7)
|
||||||
|
v1 := b.NewValue0(v.Pos, OpRISCV64FCLASSD, typ.Int64)
|
||||||
|
v1.AddArg(x)
|
||||||
|
v0.AddArg(v1)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
func rewriteValueRISCV64_OpRISCV64FMADDD(v *Value) bool {
|
func rewriteValueRISCV64_OpRISCV64FMADDD(v *Value) bool {
|
||||||
v_2 := v.Args[2]
|
v_2 := v.Args[2]
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
|
|
@ -3844,6 +4003,250 @@ func rewriteValueRISCV64_OpRISCV64FMADDS(v *Value) bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
func rewriteValueRISCV64_OpRISCV64FMOVDload(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
b := v.Block
|
||||||
|
config := b.Func.Config
|
||||||
|
// match: (FMOVDload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem)
|
||||||
|
// cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)
|
||||||
|
// result: (FMOVDload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||||
|
for {
|
||||||
|
off1 := auxIntToInt32(v.AuxInt)
|
||||||
|
sym1 := auxToSym(v.Aux)
|
||||||
|
if v_0.Op != OpRISCV64MOVaddr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
off2 := auxIntToInt32(v_0.AuxInt)
|
||||||
|
sym2 := auxToSym(v_0.Aux)
|
||||||
|
base := v_0.Args[0]
|
||||||
|
mem := v_1
|
||||||
|
if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64FMOVDload)
|
||||||
|
v.AuxInt = int32ToAuxInt(off1 + off2)
|
||||||
|
v.Aux = symToAux(mergeSym(sym1, sym2))
|
||||||
|
v.AddArg2(base, mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (FMOVDload [off1] {sym} (ADDI [off2] base) mem)
|
||||||
|
// cond: is32Bit(int64(off1)+off2)
|
||||||
|
// result: (FMOVDload [off1+int32(off2)] {sym} base mem)
|
||||||
|
for {
|
||||||
|
off1 := auxIntToInt32(v.AuxInt)
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
if v_0.Op != OpRISCV64ADDI {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
off2 := auxIntToInt64(v_0.AuxInt)
|
||||||
|
base := v_0.Args[0]
|
||||||
|
mem := v_1
|
||||||
|
if !(is32Bit(int64(off1) + off2)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64FMOVDload)
|
||||||
|
v.AuxInt = int32ToAuxInt(off1 + int32(off2))
|
||||||
|
v.Aux = symToAux(sym)
|
||||||
|
v.AddArg2(base, mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (FMOVDload [off] {sym} ptr1 (MOVDstore [off] {sym} ptr2 x _))
|
||||||
|
// cond: isSamePtr(ptr1, ptr2)
|
||||||
|
// result: (FMVDX x)
|
||||||
|
for {
|
||||||
|
off := auxIntToInt32(v.AuxInt)
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
ptr1 := v_0
|
||||||
|
if v_1.Op != OpRISCV64MOVDstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
x := v_1.Args[1]
|
||||||
|
ptr2 := v_1.Args[0]
|
||||||
|
if !(isSamePtr(ptr1, ptr2)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64FMVDX)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func rewriteValueRISCV64_OpRISCV64FMOVDstore(v *Value) bool {
|
||||||
|
v_2 := v.Args[2]
|
||||||
|
v_1 := v.Args[1]
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
b := v.Block
|
||||||
|
config := b.Func.Config
|
||||||
|
// match: (FMOVDstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem)
|
||||||
|
// cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)
|
||||||
|
// result: (FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
|
||||||
|
for {
|
||||||
|
off1 := auxIntToInt32(v.AuxInt)
|
||||||
|
sym1 := auxToSym(v.Aux)
|
||||||
|
if v_0.Op != OpRISCV64MOVaddr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
off2 := auxIntToInt32(v_0.AuxInt)
|
||||||
|
sym2 := auxToSym(v_0.Aux)
|
||||||
|
base := v_0.Args[0]
|
||||||
|
val := v_1
|
||||||
|
mem := v_2
|
||||||
|
if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64FMOVDstore)
|
||||||
|
v.AuxInt = int32ToAuxInt(off1 + off2)
|
||||||
|
v.Aux = symToAux(mergeSym(sym1, sym2))
|
||||||
|
v.AddArg3(base, val, mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (FMOVDstore [off1] {sym} (ADDI [off2] base) val mem)
|
||||||
|
// cond: is32Bit(int64(off1)+off2)
|
||||||
|
// result: (FMOVDstore [off1+int32(off2)] {sym} base val mem)
|
||||||
|
for {
|
||||||
|
off1 := auxIntToInt32(v.AuxInt)
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
if v_0.Op != OpRISCV64ADDI {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
off2 := auxIntToInt64(v_0.AuxInt)
|
||||||
|
base := v_0.Args[0]
|
||||||
|
val := v_1
|
||||||
|
mem := v_2
|
||||||
|
if !(is32Bit(int64(off1) + off2)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64FMOVDstore)
|
||||||
|
v.AuxInt = int32ToAuxInt(off1 + int32(off2))
|
||||||
|
v.Aux = symToAux(sym)
|
||||||
|
v.AddArg3(base, val, mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func rewriteValueRISCV64_OpRISCV64FMOVWload(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
b := v.Block
|
||||||
|
config := b.Func.Config
|
||||||
|
// match: (FMOVWload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem)
|
||||||
|
// cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)
|
||||||
|
// result: (FMOVWload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||||
|
for {
|
||||||
|
off1 := auxIntToInt32(v.AuxInt)
|
||||||
|
sym1 := auxToSym(v.Aux)
|
||||||
|
if v_0.Op != OpRISCV64MOVaddr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
off2 := auxIntToInt32(v_0.AuxInt)
|
||||||
|
sym2 := auxToSym(v_0.Aux)
|
||||||
|
base := v_0.Args[0]
|
||||||
|
mem := v_1
|
||||||
|
if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64FMOVWload)
|
||||||
|
v.AuxInt = int32ToAuxInt(off1 + off2)
|
||||||
|
v.Aux = symToAux(mergeSym(sym1, sym2))
|
||||||
|
v.AddArg2(base, mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (FMOVWload [off1] {sym} (ADDI [off2] base) mem)
|
||||||
|
// cond: is32Bit(int64(off1)+off2)
|
||||||
|
// result: (FMOVWload [off1+int32(off2)] {sym} base mem)
|
||||||
|
for {
|
||||||
|
off1 := auxIntToInt32(v.AuxInt)
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
if v_0.Op != OpRISCV64ADDI {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
off2 := auxIntToInt64(v_0.AuxInt)
|
||||||
|
base := v_0.Args[0]
|
||||||
|
mem := v_1
|
||||||
|
if !(is32Bit(int64(off1) + off2)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64FMOVWload)
|
||||||
|
v.AuxInt = int32ToAuxInt(off1 + int32(off2))
|
||||||
|
v.Aux = symToAux(sym)
|
||||||
|
v.AddArg2(base, mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (FMOVWload [off] {sym} ptr1 (MOVWstore [off] {sym} ptr2 x _))
|
||||||
|
// cond: isSamePtr(ptr1, ptr2)
|
||||||
|
// result: (FMVSX x)
|
||||||
|
for {
|
||||||
|
off := auxIntToInt32(v.AuxInt)
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
ptr1 := v_0
|
||||||
|
if v_1.Op != OpRISCV64MOVWstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
x := v_1.Args[1]
|
||||||
|
ptr2 := v_1.Args[0]
|
||||||
|
if !(isSamePtr(ptr1, ptr2)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64FMVSX)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func rewriteValueRISCV64_OpRISCV64FMOVWstore(v *Value) bool {
|
||||||
|
v_2 := v.Args[2]
|
||||||
|
v_1 := v.Args[1]
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
b := v.Block
|
||||||
|
config := b.Func.Config
|
||||||
|
// match: (FMOVWstore [off1] {sym1} (MOVaddr [off2] {sym2} base) val mem)
|
||||||
|
// cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)
|
||||||
|
// result: (FMOVWstore [off1+off2] {mergeSym(sym1,sym2)} base val mem)
|
||||||
|
for {
|
||||||
|
off1 := auxIntToInt32(v.AuxInt)
|
||||||
|
sym1 := auxToSym(v.Aux)
|
||||||
|
if v_0.Op != OpRISCV64MOVaddr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
off2 := auxIntToInt32(v_0.AuxInt)
|
||||||
|
sym2 := auxToSym(v_0.Aux)
|
||||||
|
base := v_0.Args[0]
|
||||||
|
val := v_1
|
||||||
|
mem := v_2
|
||||||
|
if !(is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64FMOVWstore)
|
||||||
|
v.AuxInt = int32ToAuxInt(off1 + off2)
|
||||||
|
v.Aux = symToAux(mergeSym(sym1, sym2))
|
||||||
|
v.AddArg3(base, val, mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (FMOVWstore [off1] {sym} (ADDI [off2] base) val mem)
|
||||||
|
// cond: is32Bit(int64(off1)+off2)
|
||||||
|
// result: (FMOVWstore [off1+int32(off2)] {sym} base val mem)
|
||||||
|
for {
|
||||||
|
off1 := auxIntToInt32(v.AuxInt)
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
if v_0.Op != OpRISCV64ADDI {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
off2 := auxIntToInt64(v_0.AuxInt)
|
||||||
|
base := v_0.Args[0]
|
||||||
|
val := v_1
|
||||||
|
mem := v_2
|
||||||
|
if !(is32Bit(int64(off1) + off2)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64FMOVWstore)
|
||||||
|
v.AuxInt = int32ToAuxInt(off1 + int32(off2))
|
||||||
|
v.Aux = symToAux(sym)
|
||||||
|
v.AddArg3(base, val, mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
func rewriteValueRISCV64_OpRISCV64FMSUBD(v *Value) bool {
|
func rewriteValueRISCV64_OpRISCV64FMSUBD(v *Value) bool {
|
||||||
v_2 := v.Args[2]
|
v_2 := v.Args[2]
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
|
|
@ -3934,6 +4337,59 @@ func rewriteValueRISCV64_OpRISCV64FMSUBS(v *Value) bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
func rewriteValueRISCV64_OpRISCV64FNED(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
b := v.Block
|
||||||
|
typ := &b.Func.Config.Types
|
||||||
|
// match: (FNED x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(-1)))])))
|
||||||
|
// result: (SEQZ (ANDI <typ.Int64> [1] (FCLASSD x)))
|
||||||
|
for {
|
||||||
|
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||||
|
x := v_0
|
||||||
|
if v_1.Op != OpRISCV64FMVDX {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
v_1_0 := v_1.Args[0]
|
||||||
|
if v_1_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != int64(math.Float64bits(math.Inf(-1))) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64SEQZ)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpRISCV64ANDI, typ.Int64)
|
||||||
|
v0.AuxInt = int64ToAuxInt(1)
|
||||||
|
v1 := b.NewValue0(v.Pos, OpRISCV64FCLASSD, typ.Int64)
|
||||||
|
v1.AddArg(x)
|
||||||
|
v0.AddArg(v1)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// match: (FNED x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(1)))])))
|
||||||
|
// result: (SEQZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
|
||||||
|
for {
|
||||||
|
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||||
|
x := v_0
|
||||||
|
if v_1.Op != OpRISCV64FMVDX {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
v_1_0 := v_1.Args[0]
|
||||||
|
if v_1_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != int64(math.Float64bits(math.Inf(1))) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64SEQZ)
|
||||||
|
v0 := b.NewValue0(v.Pos, OpRISCV64ANDI, typ.Int64)
|
||||||
|
v0.AuxInt = int64ToAuxInt(1 << 7)
|
||||||
|
v1 := b.NewValue0(v.Pos, OpRISCV64FCLASSD, typ.Int64)
|
||||||
|
v1.AddArg(x)
|
||||||
|
v0.AddArg(v1)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
func rewriteValueRISCV64_OpRISCV64FNMADDD(v *Value) bool {
|
func rewriteValueRISCV64_OpRISCV64FNMADDD(v *Value) bool {
|
||||||
v_2 := v.Args[2]
|
v_2 := v.Args[2]
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
|
|
@ -4977,6 +5433,25 @@ func rewriteValueRISCV64_OpRISCV64MOVDload(v *Value) bool {
|
||||||
v.AddArg2(base, mem)
|
v.AddArg2(base, mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (MOVDload [off] {sym} ptr1 (FMOVDstore [off] {sym} ptr2 x _))
|
||||||
|
// cond: isSamePtr(ptr1, ptr2)
|
||||||
|
// result: (FMVXD x)
|
||||||
|
for {
|
||||||
|
off := auxIntToInt32(v.AuxInt)
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
ptr1 := v_0
|
||||||
|
if v_1.Op != OpRISCV64FMOVDstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
x := v_1.Args[1]
|
||||||
|
ptr2 := v_1.Args[0]
|
||||||
|
if !(isSamePtr(ptr1, ptr2)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64FMVXD)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueRISCV64_OpRISCV64MOVDnop(v *Value) bool {
|
func rewriteValueRISCV64_OpRISCV64MOVDnop(v *Value) bool {
|
||||||
|
|
@ -5658,6 +6133,7 @@ func rewriteValueRISCV64_OpRISCV64MOVWUload(v *Value) bool {
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
b := v.Block
|
b := v.Block
|
||||||
config := b.Func.Config
|
config := b.Func.Config
|
||||||
|
typ := &b.Func.Config.Types
|
||||||
// match: (MOVWUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem)
|
// match: (MOVWUload [off1] {sym1} (MOVaddr [off2] {sym2} base) mem)
|
||||||
// cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)
|
// cond: is32Bit(int64(off1)+int64(off2)) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_dynlink)
|
||||||
// result: (MOVWUload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
// result: (MOVWUload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||||
|
|
@ -5701,6 +6177,27 @@ func rewriteValueRISCV64_OpRISCV64MOVWUload(v *Value) bool {
|
||||||
v.AddArg2(base, mem)
|
v.AddArg2(base, mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (MOVWUload [off] {sym} ptr1 (FMOVWstore [off] {sym} ptr2 x _))
|
||||||
|
// cond: isSamePtr(ptr1, ptr2)
|
||||||
|
// result: (MOVWUreg (FMVXS x))
|
||||||
|
for {
|
||||||
|
off := auxIntToInt32(v.AuxInt)
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
ptr1 := v_0
|
||||||
|
if v_1.Op != OpRISCV64FMOVWstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
x := v_1.Args[1]
|
||||||
|
ptr2 := v_1.Args[0]
|
||||||
|
if !(isSamePtr(ptr1, ptr2)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64MOVWUreg)
|
||||||
|
v0 := b.NewValue0(v_1.Pos, OpRISCV64FMVXS, typ.Int32)
|
||||||
|
v0.AddArg(x)
|
||||||
|
v.AddArg(v0)
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueRISCV64_OpRISCV64MOVWUreg(v *Value) bool {
|
func rewriteValueRISCV64_OpRISCV64MOVWUreg(v *Value) bool {
|
||||||
|
|
@ -5891,6 +6388,25 @@ func rewriteValueRISCV64_OpRISCV64MOVWload(v *Value) bool {
|
||||||
v.AddArg2(base, mem)
|
v.AddArg2(base, mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (MOVWload [off] {sym} ptr1 (FMOVWstore [off] {sym} ptr2 x _))
|
||||||
|
// cond: isSamePtr(ptr1, ptr2)
|
||||||
|
// result: (FMVXS x)
|
||||||
|
for {
|
||||||
|
off := auxIntToInt32(v.AuxInt)
|
||||||
|
sym := auxToSym(v.Aux)
|
||||||
|
ptr1 := v_0
|
||||||
|
if v_1.Op != OpRISCV64FMOVWstore || auxIntToInt32(v_1.AuxInt) != off || auxToSym(v_1.Aux) != sym {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
x := v_1.Args[1]
|
||||||
|
ptr2 := v_1.Args[0]
|
||||||
|
if !(isSamePtr(ptr1, ptr2)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpRISCV64FMVXS)
|
||||||
|
v.AddArg(x)
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueRISCV64_OpRISCV64MOVWreg(v *Value) bool {
|
func rewriteValueRISCV64_OpRISCV64MOVWreg(v *Value) bool {
|
||||||
|
|
|
||||||
|
|
@ -184,42 +184,6 @@ func InitConfig() {
|
||||||
BoundsCheckFunc[ssa.BoundsSlice3C] = typecheck.LookupRuntimeFunc("goPanicSlice3C")
|
BoundsCheckFunc[ssa.BoundsSlice3C] = typecheck.LookupRuntimeFunc("goPanicSlice3C")
|
||||||
BoundsCheckFunc[ssa.BoundsSlice3CU] = typecheck.LookupRuntimeFunc("goPanicSlice3CU")
|
BoundsCheckFunc[ssa.BoundsSlice3CU] = typecheck.LookupRuntimeFunc("goPanicSlice3CU")
|
||||||
BoundsCheckFunc[ssa.BoundsConvert] = typecheck.LookupRuntimeFunc("goPanicSliceConvert")
|
BoundsCheckFunc[ssa.BoundsConvert] = typecheck.LookupRuntimeFunc("goPanicSliceConvert")
|
||||||
} else {
|
|
||||||
BoundsCheckFunc[ssa.BoundsIndex] = typecheck.LookupRuntimeFunc("panicIndex")
|
|
||||||
BoundsCheckFunc[ssa.BoundsIndexU] = typecheck.LookupRuntimeFunc("panicIndexU")
|
|
||||||
BoundsCheckFunc[ssa.BoundsSliceAlen] = typecheck.LookupRuntimeFunc("panicSliceAlen")
|
|
||||||
BoundsCheckFunc[ssa.BoundsSliceAlenU] = typecheck.LookupRuntimeFunc("panicSliceAlenU")
|
|
||||||
BoundsCheckFunc[ssa.BoundsSliceAcap] = typecheck.LookupRuntimeFunc("panicSliceAcap")
|
|
||||||
BoundsCheckFunc[ssa.BoundsSliceAcapU] = typecheck.LookupRuntimeFunc("panicSliceAcapU")
|
|
||||||
BoundsCheckFunc[ssa.BoundsSliceB] = typecheck.LookupRuntimeFunc("panicSliceB")
|
|
||||||
BoundsCheckFunc[ssa.BoundsSliceBU] = typecheck.LookupRuntimeFunc("panicSliceBU")
|
|
||||||
BoundsCheckFunc[ssa.BoundsSlice3Alen] = typecheck.LookupRuntimeFunc("panicSlice3Alen")
|
|
||||||
BoundsCheckFunc[ssa.BoundsSlice3AlenU] = typecheck.LookupRuntimeFunc("panicSlice3AlenU")
|
|
||||||
BoundsCheckFunc[ssa.BoundsSlice3Acap] = typecheck.LookupRuntimeFunc("panicSlice3Acap")
|
|
||||||
BoundsCheckFunc[ssa.BoundsSlice3AcapU] = typecheck.LookupRuntimeFunc("panicSlice3AcapU")
|
|
||||||
BoundsCheckFunc[ssa.BoundsSlice3B] = typecheck.LookupRuntimeFunc("panicSlice3B")
|
|
||||||
BoundsCheckFunc[ssa.BoundsSlice3BU] = typecheck.LookupRuntimeFunc("panicSlice3BU")
|
|
||||||
BoundsCheckFunc[ssa.BoundsSlice3C] = typecheck.LookupRuntimeFunc("panicSlice3C")
|
|
||||||
BoundsCheckFunc[ssa.BoundsSlice3CU] = typecheck.LookupRuntimeFunc("panicSlice3CU")
|
|
||||||
BoundsCheckFunc[ssa.BoundsConvert] = typecheck.LookupRuntimeFunc("panicSliceConvert")
|
|
||||||
}
|
|
||||||
if Arch.LinkArch.PtrSize == 4 {
|
|
||||||
ExtendCheckFunc[ssa.BoundsIndex] = typecheck.LookupRuntimeVar("panicExtendIndex")
|
|
||||||
ExtendCheckFunc[ssa.BoundsIndexU] = typecheck.LookupRuntimeVar("panicExtendIndexU")
|
|
||||||
ExtendCheckFunc[ssa.BoundsSliceAlen] = typecheck.LookupRuntimeVar("panicExtendSliceAlen")
|
|
||||||
ExtendCheckFunc[ssa.BoundsSliceAlenU] = typecheck.LookupRuntimeVar("panicExtendSliceAlenU")
|
|
||||||
ExtendCheckFunc[ssa.BoundsSliceAcap] = typecheck.LookupRuntimeVar("panicExtendSliceAcap")
|
|
||||||
ExtendCheckFunc[ssa.BoundsSliceAcapU] = typecheck.LookupRuntimeVar("panicExtendSliceAcapU")
|
|
||||||
ExtendCheckFunc[ssa.BoundsSliceB] = typecheck.LookupRuntimeVar("panicExtendSliceB")
|
|
||||||
ExtendCheckFunc[ssa.BoundsSliceBU] = typecheck.LookupRuntimeVar("panicExtendSliceBU")
|
|
||||||
ExtendCheckFunc[ssa.BoundsSlice3Alen] = typecheck.LookupRuntimeVar("panicExtendSlice3Alen")
|
|
||||||
ExtendCheckFunc[ssa.BoundsSlice3AlenU] = typecheck.LookupRuntimeVar("panicExtendSlice3AlenU")
|
|
||||||
ExtendCheckFunc[ssa.BoundsSlice3Acap] = typecheck.LookupRuntimeVar("panicExtendSlice3Acap")
|
|
||||||
ExtendCheckFunc[ssa.BoundsSlice3AcapU] = typecheck.LookupRuntimeVar("panicExtendSlice3AcapU")
|
|
||||||
ExtendCheckFunc[ssa.BoundsSlice3B] = typecheck.LookupRuntimeVar("panicExtendSlice3B")
|
|
||||||
ExtendCheckFunc[ssa.BoundsSlice3BU] = typecheck.LookupRuntimeVar("panicExtendSlice3BU")
|
|
||||||
ExtendCheckFunc[ssa.BoundsSlice3C] = typecheck.LookupRuntimeVar("panicExtendSlice3C")
|
|
||||||
ExtendCheckFunc[ssa.BoundsSlice3CU] = typecheck.LookupRuntimeVar("panicExtendSlice3CU")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wasm (all asm funcs with special ABIs)
|
// Wasm (all asm funcs with special ABIs)
|
||||||
|
|
@ -1366,9 +1330,6 @@ func (s *state) constInt(t *types.Type, c int64) *ssa.Value {
|
||||||
}
|
}
|
||||||
return s.constInt32(t, int32(c))
|
return s.constInt32(t, int32(c))
|
||||||
}
|
}
|
||||||
func (s *state) constOffPtrSP(t *types.Type, c int64) *ssa.Value {
|
|
||||||
return s.f.ConstOffPtrSP(t, c, s.sp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// newValueOrSfCall* are wrappers around newValue*, which may create a call to a
|
// newValueOrSfCall* are wrappers around newValue*, which may create a call to a
|
||||||
// soft-float runtime function instead (when emitting soft-float code).
|
// soft-float runtime function instead (when emitting soft-float code).
|
||||||
|
|
@ -5428,26 +5389,6 @@ func (s *state) putArg(n ir.Node, t *types.Type) *ssa.Value {
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *state) storeArgWithBase(n ir.Node, t *types.Type, base *ssa.Value, off int64) {
|
|
||||||
pt := types.NewPtr(t)
|
|
||||||
var addr *ssa.Value
|
|
||||||
if base == s.sp {
|
|
||||||
// Use special routine that avoids allocation on duplicate offsets.
|
|
||||||
addr = s.constOffPtrSP(pt, off)
|
|
||||||
} else {
|
|
||||||
addr = s.newValue1I(ssa.OpOffPtr, pt, off, base)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !ssa.CanSSA(t) {
|
|
||||||
a := s.addr(n)
|
|
||||||
s.move(t, addr, a)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
a := s.expr(n)
|
|
||||||
s.storeType(t, addr, a, 0, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// slice computes the slice v[i:j:k] and returns ptr, len, and cap of result.
|
// slice computes the slice v[i:j:k] and returns ptr, len, and cap of result.
|
||||||
// i,j,k may be nil, in which case they are set to their default value.
|
// i,j,k may be nil, in which case they are set to their default value.
|
||||||
// v may be a slice, string or pointer to an array.
|
// v may be a slice, string or pointer to an array.
|
||||||
|
|
@ -7772,7 +7713,5 @@ func isStructNotSIMD(t *types.Type) bool {
|
||||||
return t.IsStruct() && !t.IsSIMD()
|
return t.IsStruct() && !t.IsSIMD()
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var BoundsCheckFunc [ssa.BoundsKindCount]*obj.LSym
|
||||||
BoundsCheckFunc [ssa.BoundsKindCount]*obj.LSym
|
|
||||||
ExtendCheckFunc [ssa.BoundsKindCount]*obj.LSym
|
|
||||||
)
|
|
||||||
|
|
|
||||||
|
|
@ -622,12 +622,6 @@ func (s *Schedule) staticAssignInlinedCall(l *ir.Name, loff int64, call *ir.Inli
|
||||||
// INLCALL-ReturnVars
|
// INLCALL-ReturnVars
|
||||||
// . NAME-p.~R0 Class:PAUTO Offset:0 OnStack Used PTR-*T tc(1) # x.go:18:13
|
// . NAME-p.~R0 Class:PAUTO Offset:0 OnStack Used PTR-*T tc(1) # x.go:18:13
|
||||||
//
|
//
|
||||||
// In non-unified IR, the tree is slightly different:
|
|
||||||
// - if there are no arguments to the inlined function,
|
|
||||||
// the INLCALL-init omits the AS2.
|
|
||||||
// - the DCL inside BLOCK is on the AS2's init list,
|
|
||||||
// not its own statement in the top level of the BLOCK.
|
|
||||||
//
|
|
||||||
// If the init values are side-effect-free and each either only
|
// If the init values are side-effect-free and each either only
|
||||||
// appears once in the function body or is safely repeatable,
|
// appears once in the function body or is safely repeatable,
|
||||||
// then we inline the value expressions into the return argument
|
// then we inline the value expressions into the return argument
|
||||||
|
|
@ -647,39 +641,26 @@ func (s *Schedule) staticAssignInlinedCall(l *ir.Name, loff int64, call *ir.Inli
|
||||||
// is the most important case for us to get right.
|
// is the most important case for us to get right.
|
||||||
|
|
||||||
init := call.Init()
|
init := call.Init()
|
||||||
var as2init *ir.AssignListStmt
|
if len(init) != 2 || init[0].Op() != ir.OAS2 || init[1].Op() != ir.OINLMARK {
|
||||||
if len(init) == 2 && init[0].Op() == ir.OAS2 && init[1].Op() == ir.OINLMARK {
|
|
||||||
as2init = init[0].(*ir.AssignListStmt)
|
|
||||||
} else if len(init) == 1 && init[0].Op() == ir.OINLMARK {
|
|
||||||
as2init = new(ir.AssignListStmt)
|
|
||||||
} else {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
as2init := init[0].(*ir.AssignListStmt)
|
||||||
|
|
||||||
if len(call.Body) != 2 || call.Body[0].Op() != ir.OBLOCK || call.Body[1].Op() != ir.OLABEL {
|
if len(call.Body) != 2 || call.Body[0].Op() != ir.OBLOCK || call.Body[1].Op() != ir.OLABEL {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
label := call.Body[1].(*ir.LabelStmt).Label
|
label := call.Body[1].(*ir.LabelStmt).Label
|
||||||
block := call.Body[0].(*ir.BlockStmt)
|
block := call.Body[0].(*ir.BlockStmt)
|
||||||
list := block.List
|
list := block.List
|
||||||
var dcl *ir.Decl
|
if len(list) != 3 ||
|
||||||
if len(list) == 3 && list[0].Op() == ir.ODCL {
|
list[0].Op() != ir.ODCL ||
|
||||||
dcl = list[0].(*ir.Decl)
|
list[1].Op() != ir.OAS2 ||
|
||||||
list = list[1:]
|
list[2].Op() != ir.OGOTO ||
|
||||||
}
|
list[2].(*ir.BranchStmt).Label != label {
|
||||||
if len(list) != 2 ||
|
|
||||||
list[0].Op() != ir.OAS2 ||
|
|
||||||
list[1].Op() != ir.OGOTO ||
|
|
||||||
list[1].(*ir.BranchStmt).Label != label {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
as2body := list[0].(*ir.AssignListStmt)
|
dcl := list[0].(*ir.Decl)
|
||||||
if dcl == nil {
|
as2body := list[1].(*ir.AssignListStmt)
|
||||||
ainit := as2body.Init()
|
|
||||||
if len(ainit) != 1 || ainit[0].Op() != ir.ODCL {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
dcl = ainit[0].(*ir.Decl)
|
|
||||||
}
|
|
||||||
if len(as2body.Lhs) != 1 || as2body.Lhs[0] != dcl.X {
|
if len(as2body.Lhs) != 1 || as2body.Lhs[0] != dcl.X {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,10 +138,6 @@ func impliesSemi(tok token) bool {
|
||||||
|
|
||||||
// TODO(gri) provide table of []byte values for all tokens to avoid repeated string conversion
|
// TODO(gri) provide table of []byte values for all tokens to avoid repeated string conversion
|
||||||
|
|
||||||
func lineComment(text string) bool {
|
|
||||||
return strings.HasPrefix(text, "//")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *printer) addWhitespace(kind ctrlSymbol, text string) {
|
func (p *printer) addWhitespace(kind ctrlSymbol, text string) {
|
||||||
p.pending = append(p.pending, whitespace{p.lastTok, kind /*text*/})
|
p.pending = append(p.pending, whitespace{p.lastTok, kind /*text*/})
|
||||||
switch kind {
|
switch kind {
|
||||||
|
|
|
||||||
|
|
@ -122,3 +122,26 @@ func BenchmarkBitToggleConst(b *testing.B) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkMulNeg(b *testing.B) {
|
||||||
|
x := make([]int64, 1024)
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
var s int64
|
||||||
|
for i := range x {
|
||||||
|
s = (-x[i]) * 11
|
||||||
|
}
|
||||||
|
globl = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMul2Neg(b *testing.B) {
|
||||||
|
x := make([]int64, 1024)
|
||||||
|
y := make([]int64, 1024)
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
var s int64
|
||||||
|
for i := range x {
|
||||||
|
s = (-x[i]) * (-y[i])
|
||||||
|
}
|
||||||
|
globl = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -523,6 +523,106 @@ func TestFloatSignalingNaNConversionConst(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func isPosInf(x float64) bool {
|
||||||
|
return math.IsInf(x, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func isPosInfEq(x float64) bool {
|
||||||
|
return x == math.Inf(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func isPosInfCmp(x float64) bool {
|
||||||
|
return x > math.MaxFloat64
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func isNotPosInf(x float64) bool {
|
||||||
|
return !math.IsInf(x, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func isNotPosInfEq(x float64) bool {
|
||||||
|
return x != math.Inf(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func isNotPosInfCmp(x float64) bool {
|
||||||
|
return x <= math.MaxFloat64
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func isNegInf(x float64) bool {
|
||||||
|
return math.IsInf(x, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func isNegInfEq(x float64) bool {
|
||||||
|
return x == math.Inf(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func isNegInfCmp(x float64) bool {
|
||||||
|
return x < -math.MaxFloat64
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func isNotNegInf(x float64) bool {
|
||||||
|
return !math.IsInf(x, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func isNotNegInfEq(x float64) bool {
|
||||||
|
return x != math.Inf(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func isNotNegInfCmp(x float64) bool {
|
||||||
|
return x >= -math.MaxFloat64
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInf(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
value float64
|
||||||
|
isPosInf bool
|
||||||
|
isNegInf bool
|
||||||
|
isNaN bool
|
||||||
|
}{
|
||||||
|
{value: math.Inf(1), isPosInf: true},
|
||||||
|
{value: math.MaxFloat64},
|
||||||
|
{value: math.Inf(-1), isNegInf: true},
|
||||||
|
{value: -math.MaxFloat64},
|
||||||
|
{value: math.NaN(), isNaN: true},
|
||||||
|
}
|
||||||
|
|
||||||
|
check := func(name string, f func(x float64) bool, value float64, want bool) {
|
||||||
|
got := f(value)
|
||||||
|
if got != want {
|
||||||
|
t.Errorf("%v(%g): want %v, got %v", name, value, want, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
check("isPosInf", isPosInf, test.value, test.isPosInf)
|
||||||
|
check("isPosInfEq", isPosInfEq, test.value, test.isPosInf)
|
||||||
|
check("isPosInfCmp", isPosInfCmp, test.value, test.isPosInf)
|
||||||
|
|
||||||
|
check("isNotPosInf", isNotPosInf, test.value, !test.isPosInf)
|
||||||
|
check("isNotPosInfEq", isNotPosInfEq, test.value, !test.isPosInf)
|
||||||
|
check("isNotPosInfCmp", isNotPosInfCmp, test.value, !test.isPosInf && !test.isNaN)
|
||||||
|
|
||||||
|
check("isNegInf", isNegInf, test.value, test.isNegInf)
|
||||||
|
check("isNegInfEq", isNegInfEq, test.value, test.isNegInf)
|
||||||
|
check("isNegInfCmp", isNegInfCmp, test.value, test.isNegInf)
|
||||||
|
|
||||||
|
check("isNotNegInf", isNotNegInf, test.value, !test.isNegInf)
|
||||||
|
check("isNotNegInfEq", isNotNegInfEq, test.value, !test.isNegInf)
|
||||||
|
check("isNotNegInfCmp", isNotNegInfCmp, test.value, !test.isNegInf && !test.isNaN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var sinkFloat float64
|
var sinkFloat float64
|
||||||
|
|
||||||
func BenchmarkMul2(b *testing.B) {
|
func BenchmarkMul2(b *testing.B) {
|
||||||
|
|
|
||||||
|
|
@ -235,27 +235,7 @@
|
||||||
|
|
||||||
package typecheck
|
package typecheck
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
const blankMarker = "$"
|
const blankMarker = "$"
|
||||||
|
|
||||||
// TparamName returns the real name of a type parameter, after stripping its
|
|
||||||
// qualifying prefix and reverting blank-name encoding. See TparamExportName
|
|
||||||
// for details.
|
|
||||||
func TparamName(exportName string) string {
|
|
||||||
// Remove the "path" from the type param name that makes it unique.
|
|
||||||
ix := strings.LastIndex(exportName, ".")
|
|
||||||
if ix < 0 {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
name := exportName[ix+1:]
|
|
||||||
if strings.HasPrefix(name, blankMarker) {
|
|
||||||
return "_"
|
|
||||||
}
|
|
||||||
return name
|
|
||||||
}
|
|
||||||
|
|
||||||
// The name used for dictionary parameters or local variables.
|
// The name used for dictionary parameters or local variables.
|
||||||
const LocalDictName = ".dict"
|
const LocalDictName = ".dict"
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,6 @@ func RangeExprType(t *types.Type) *types.Type {
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func typecheckrangeExpr(n *ir.RangeStmt) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// type check assignment.
|
// type check assignment.
|
||||||
// if this assignment is the definition of a var on the left side,
|
// if this assignment is the definition of a var on the left side,
|
||||||
// fill in the var's type.
|
// fill in the var's type.
|
||||||
|
|
|
||||||
|
|
@ -1712,13 +1712,6 @@ func fieldsHasShape(fields []*Field) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// newBasic returns a new basic type of the given kind.
|
|
||||||
func newBasic(kind Kind, obj Object) *Type {
|
|
||||||
t := newType(kind)
|
|
||||||
t.obj = obj
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewInterface returns a new interface for the given methods and
|
// NewInterface returns a new interface for the given methods and
|
||||||
// embedded types. Embedded types are specified as fields with no Sym.
|
// embedded types. Embedded types are specified as fields with no Sym.
|
||||||
func NewInterface(methods []*Field) *Type {
|
func NewInterface(methods []*Field) *Type {
|
||||||
|
|
|
||||||
|
|
@ -187,10 +187,6 @@ type Config struct {
|
||||||
EnableAlias bool
|
EnableAlias bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func srcimporter_setUsesCgo(conf *Config) {
|
|
||||||
conf.go115UsesCgo = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Info holds result type information for a type-checked package.
|
// Info holds result type information for a type-checked package.
|
||||||
// Only the information for which a map is provided is collected.
|
// Only the information for which a map is provided is collected.
|
||||||
// If the package has type errors, the collected information may
|
// If the package has type errors, the collected information may
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ var nopos syntax.Pos
|
||||||
const debug = false // leave on during development
|
const debug = false // leave on during development
|
||||||
|
|
||||||
// position tracing for panics during type checking
|
// position tracing for panics during type checking
|
||||||
const tracePos = false // TODO(markfreeman): check performance implications
|
const tracePos = true
|
||||||
|
|
||||||
// _aliasAny changes the behavior of [Scope.Lookup] for "any" in the
|
// _aliasAny changes the behavior of [Scope.Lookup] for "any" in the
|
||||||
// [Universe] scope.
|
// [Universe] scope.
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,6 @@ func AsPointer(t Type) *Pointer {
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
// If t is a signature, AsSignature returns that type, otherwise it returns nil.
|
|
||||||
func AsSignature(t Type) *Signature {
|
|
||||||
u, _ := t.Underlying().(*Signature)
|
|
||||||
return u
|
|
||||||
}
|
|
||||||
|
|
||||||
// If typ is a type parameter, CoreType returns the single underlying
|
// If typ is a type parameter, CoreType returns the single underlying
|
||||||
// type of all types in the corresponding type constraint if it exists, or
|
// type of all types in the corresponding type constraint if it exists, or
|
||||||
// nil otherwise. If the type set contains only unrestricted and restricted
|
// nil otherwise. If the type set contains only unrestricted and restricted
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"cmd/compile/internal/syntax"
|
"cmd/compile/internal/syntax"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/constant"
|
"go/constant"
|
||||||
"internal/buildcfg"
|
|
||||||
. "internal/types/errors"
|
. "internal/types/errors"
|
||||||
"slices"
|
"slices"
|
||||||
)
|
)
|
||||||
|
|
@ -525,10 +524,6 @@ func (check *Checker) typeDecl(obj *TypeName, tdecl *syntax.TypeDecl, def *TypeN
|
||||||
|
|
||||||
// handle type parameters even if not allowed (Alias type is supported)
|
// handle type parameters even if not allowed (Alias type is supported)
|
||||||
if tparam0 != nil {
|
if tparam0 != nil {
|
||||||
if !versionErr && !buildcfg.Experiment.AliasTypeParams {
|
|
||||||
check.error(tdecl, UnsupportedFeature, "generic type alias requires GOEXPERIMENT=aliastypeparams")
|
|
||||||
versionErr = true
|
|
||||||
}
|
|
||||||
check.openScope(tdecl, "type parameters")
|
check.openScope(tdecl, "type parameters")
|
||||||
defer check.closeScope()
|
defer check.closeScope()
|
||||||
check.collectTypeParams(&alias.tparams, tdecl.TParamList)
|
check.collectTypeParams(&alias.tparams, tdecl.TParamList)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"cmd/compile/internal/syntax"
|
"cmd/compile/internal/syntax"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"internal/buildcfg"
|
|
||||||
. "internal/types/errors"
|
. "internal/types/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -130,10 +129,6 @@ func (check *Checker) instance(pos syntax.Pos, orig genericType, targs []Type, e
|
||||||
res = check.newNamedInstance(pos, orig, targs, expanding) // substituted lazily
|
res = check.newNamedInstance(pos, orig, targs, expanding) // substituted lazily
|
||||||
|
|
||||||
case *Alias:
|
case *Alias:
|
||||||
if !buildcfg.Experiment.AliasTypeParams {
|
|
||||||
assert(expanding == nil) // Alias instances cannot be reached from Named types
|
|
||||||
}
|
|
||||||
|
|
||||||
// verify type parameter count (see go.dev/issue/71198 for a test case)
|
// verify type parameter count (see go.dev/issue/71198 for a test case)
|
||||||
tparams := orig.TypeParams()
|
tparams := orig.TypeParams()
|
||||||
if !check.validateTArgLen(pos, orig.obj.Name(), tparams.Len(), len(targs)) {
|
if !check.validateTArgLen(pos, orig.obj.Name(), tparams.Len(), len(targs)) {
|
||||||
|
|
|
||||||
|
|
@ -99,8 +99,7 @@ var testObjects = []struct {
|
||||||
{"type t = struct{f int}", "t", "type p.t = struct{f int}", false},
|
{"type t = struct{f int}", "t", "type p.t = struct{f int}", false},
|
||||||
{"type t = func(int)", "t", "type p.t = func(int)", false},
|
{"type t = func(int)", "t", "type p.t = func(int)", false},
|
||||||
{"type A = B; type B = int", "A", "type p.A = p.B", true},
|
{"type A = B; type B = int", "A", "type p.A = p.B", true},
|
||||||
{"type A[P ~int] = struct{}", "A", "type p.A[P ~int] = struct{}", true}, // requires GOEXPERIMENT=aliastypeparams
|
{"type A[P ~int] = struct{}", "A", "type p.A[P ~int] = struct{}", true},
|
||||||
|
|
||||||
{"var v int", "v", "var p.v int", false},
|
{"var v int", "v", "var p.v int", false},
|
||||||
|
|
||||||
{"func f(int) string", "f", "func p.f(int) string", false},
|
{"func f(int) string", "f", "func p.f(int) string", false},
|
||||||
|
|
@ -114,10 +113,6 @@ func TestObjectString(t *testing.T) {
|
||||||
|
|
||||||
for i, test := range testObjects {
|
for i, test := range testObjects {
|
||||||
t.Run(fmt.Sprint(i), func(t *testing.T) {
|
t.Run(fmt.Sprint(i), func(t *testing.T) {
|
||||||
if test.alias {
|
|
||||||
revert := setGOEXPERIMENT("aliastypeparams")
|
|
||||||
defer revert()
|
|
||||||
}
|
|
||||||
src := "package p; " + test.src
|
src := "package p; " + test.src
|
||||||
conf := Config{Error: func(error) {}, Importer: defaultImporter(), EnableAlias: test.alias}
|
conf := Config{Error: func(error) {}, Importer: defaultImporter(), EnableAlias: test.alias}
|
||||||
pkg, err := typecheck(src, &conf, nil)
|
pkg, err := typecheck(src, &conf, nil)
|
||||||
|
|
|
||||||
|
|
@ -332,6 +332,8 @@ func TestStdFixed(t *testing.T) {
|
||||||
"issue49814.go", // go/types does not have constraints on array size
|
"issue49814.go", // go/types does not have constraints on array size
|
||||||
"issue56103.go", // anonymous interface cycles; will be a type checker error in 1.22
|
"issue56103.go", // anonymous interface cycles; will be a type checker error in 1.22
|
||||||
"issue52697.go", // types2 does not have constraints on stack size
|
"issue52697.go", // types2 does not have constraints on stack size
|
||||||
|
"issue68054.go", // this test requires GODEBUG=gotypesalias=1
|
||||||
|
"issue68580.go", // this test requires GODEBUG=gotypesalias=1
|
||||||
"issue73309.go", // this test requires GODEBUG=gotypesalias=1
|
"issue73309.go", // this test requires GODEBUG=gotypesalias=1
|
||||||
"issue73309b.go", // this test requires GODEBUG=gotypesalias=1
|
"issue73309b.go", // this test requires GODEBUG=gotypesalias=1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -131,6 +131,14 @@ func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node {
|
||||||
n := n.(*ir.BinaryExpr)
|
n := n.(*ir.BinaryExpr)
|
||||||
n.X = walkExpr(n.X, init)
|
n.X = walkExpr(n.X, init)
|
||||||
n.Y = walkExpr(n.Y, init)
|
n.Y = walkExpr(n.Y, init)
|
||||||
|
if n.Op() == ir.OUNSAFEADD && ir.ShouldCheckPtr(ir.CurFunc, 1) {
|
||||||
|
// For unsafe.Add(p, n), just walk "unsafe.Pointer(uintptr(p)+uintptr(n))"
|
||||||
|
// for the side effects of validating unsafe.Pointer rules.
|
||||||
|
x := typecheck.ConvNop(n.X, types.Types[types.TUINTPTR])
|
||||||
|
y := typecheck.Conv(n.Y, types.Types[types.TUINTPTR])
|
||||||
|
conv := typecheck.ConvNop(ir.NewBinaryExpr(n.Pos(), ir.OADD, x, y), types.Types[types.TUNSAFEPTR])
|
||||||
|
walkExpr(conv, init)
|
||||||
|
}
|
||||||
return n
|
return n
|
||||||
|
|
||||||
case ir.OUNSAFESLICE:
|
case ir.OUNSAFESLICE:
|
||||||
|
|
|
||||||
15
src/cmd/dist/README
vendored
15
src/cmd/dist/README
vendored
|
|
@ -4,18 +4,17 @@ As of Go 1.5, dist and other parts of the compiler toolchain are written
|
||||||
in Go, making bootstrapping a little more involved than in the past.
|
in Go, making bootstrapping a little more involved than in the past.
|
||||||
The approach is to build the current release of Go with an earlier one.
|
The approach is to build the current release of Go with an earlier one.
|
||||||
|
|
||||||
The process to install Go 1.x, for x ≥ 24, is:
|
The process to install Go 1.x, for x ≥ 26, is:
|
||||||
|
|
||||||
1. Build cmd/dist with Go 1.22.6.
|
1. Build cmd/dist with Go 1.24.6.
|
||||||
2. Using dist, build Go 1.x compiler toolchain with Go 1.22.6.
|
2. Using dist, build Go 1.x compiler toolchain with Go 1.24.6.
|
||||||
3. Using dist, rebuild Go 1.x compiler toolchain with itself.
|
3. Using dist, rebuild Go 1.x compiler toolchain with itself.
|
||||||
4. Using dist, build Go 1.x cmd/go (as go_bootstrap) with Go 1.x compiler toolchain.
|
4. Using dist, build Go 1.x cmd/go (as go_bootstrap) with Go 1.x compiler toolchain.
|
||||||
5. Using go_bootstrap, build the remaining Go 1.x standard library and commands.
|
5. Using go_bootstrap, build the remaining Go 1.x standard library and commands.
|
||||||
|
|
||||||
Because of backward compatibility, although the steps above say Go 1.22.6,
|
Because of backward compatibility, although the steps above say Go 1.24.6,
|
||||||
in practice any release ≥ Go 1.22.6 but < Go 1.x will work as the bootstrap base.
|
in practice any release ≥ Go 1.24.6 but < Go 1.x will work as the bootstrap base.
|
||||||
Releases ≥ Go 1.x are very likely to work as well.
|
Releases ≥ Go 1.x are very likely to work as well.
|
||||||
|
|
||||||
See https://go.dev/s/go15bootstrap for more details about the original bootstrap
|
See go.dev/s/go15bootstrap for more details about the original bootstrap
|
||||||
and https://go.dev/issue/54265 for details about later bootstrap version bumps.
|
and go.dev/issue/54265 for details about later bootstrap version bumps.
|
||||||
|
|
||||||
|
|
|
||||||
7
src/cmd/dist/build.go
vendored
7
src/cmd/dist/build.go
vendored
|
|
@ -1819,7 +1819,6 @@ var cgoEnabled = map[string]bool{
|
||||||
"solaris/amd64": true,
|
"solaris/amd64": true,
|
||||||
"windows/386": true,
|
"windows/386": true,
|
||||||
"windows/amd64": true,
|
"windows/amd64": true,
|
||||||
"windows/arm": false,
|
|
||||||
"windows/arm64": true,
|
"windows/arm64": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1828,9 +1827,9 @@ var cgoEnabled = map[string]bool{
|
||||||
// get filtered out of cgoEnabled for 'dist list'.
|
// get filtered out of cgoEnabled for 'dist list'.
|
||||||
// See go.dev/issue/56679.
|
// See go.dev/issue/56679.
|
||||||
var broken = map[string]bool{
|
var broken = map[string]bool{
|
||||||
"linux/sparc64": true, // An incomplete port. See CL 132155.
|
"freebsd/riscv64": true, // Broken: go.dev/issue/73568.
|
||||||
"openbsd/mips64": true, // Broken: go.dev/issue/58110.
|
"linux/sparc64": true, // An incomplete port. See CL 132155.
|
||||||
"windows/arm": true, // Broken: go.dev/issue/68552.
|
"openbsd/mips64": true, // Broken: go.dev/issue/58110.
|
||||||
}
|
}
|
||||||
|
|
||||||
// List of platforms which are first class ports. See go.dev/issue/38874.
|
// List of platforms which are first class ports. See go.dev/issue/38874.
|
||||||
|
|
|
||||||
2
src/cmd/dist/buildtool.go
vendored
2
src/cmd/dist/buildtool.go
vendored
|
|
@ -121,7 +121,7 @@ var ignoreSuffixes = []string{
|
||||||
"~",
|
"~",
|
||||||
}
|
}
|
||||||
|
|
||||||
const minBootstrap = "go1.22.6"
|
const minBootstrap = "go1.24.6"
|
||||||
|
|
||||||
var tryDirs = []string{
|
var tryDirs = []string{
|
||||||
"sdk/" + minBootstrap,
|
"sdk/" + minBootstrap,
|
||||||
|
|
|
||||||
12
src/cmd/dist/imports.go
vendored
12
src/cmd/dist/imports.go
vendored
|
|
@ -205,18 +205,6 @@ func (r *importReader) readImport(imports *[]string) {
|
||||||
r.readString(imports)
|
r.readString(imports)
|
||||||
}
|
}
|
||||||
|
|
||||||
// readComments is like ioutil.ReadAll, except that it only reads the leading
|
|
||||||
// block of comments in the file.
|
|
||||||
func readComments(f io.Reader) ([]byte, error) {
|
|
||||||
r := &importReader{b: bufio.NewReader(f)}
|
|
||||||
r.peekByte(true)
|
|
||||||
if r.err == nil && !r.eof {
|
|
||||||
// Didn't reach EOF, so must have found a non-space byte. Remove it.
|
|
||||||
r.buf = r.buf[:len(r.buf)-1]
|
|
||||||
}
|
|
||||||
return r.buf, r.err
|
|
||||||
}
|
|
||||||
|
|
||||||
// readimports returns the imports found in the named file.
|
// readimports returns the imports found in the named file.
|
||||||
func readimports(file string) []string {
|
func readimports(file string) []string {
|
||||||
var imports []string
|
var imports []string
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,20 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Go 1.24 and later requires Go 1.22.6 as the bootstrap toolchain.
|
// Go 1.26 and later requires Go 1.24.6 as the minimum bootstrap toolchain.
|
||||||
// If cmd/dist is built using an earlier Go version, this file will be
|
// If cmd/dist is built using an earlier Go version, this file will be
|
||||||
// included in the build and cause an error like:
|
// included in the build and cause an error like:
|
||||||
//
|
//
|
||||||
// % GOROOT_BOOTSTRAP=$HOME/sdk/go1.16 ./make.bash
|
// % GOROOT_BOOTSTRAP=$HOME/sdk/go1.16 ./make.bash
|
||||||
// Building Go cmd/dist using /Users/rsc/sdk/go1.16. (go1.16 darwin/amd64)
|
// Building Go cmd/dist using /Users/rsc/sdk/go1.16. (go1.16 darwin/amd64)
|
||||||
// found packages main (build.go) and building_Go_requires_Go_1_22_6_or_later (notgo122.go) in /Users/rsc/go/src/cmd/dist
|
// found packages main (build.go) and building_Go_requires_Go_1_24_6_or_later (notgo124.go) in /Users/rsc/go/src/cmd/dist
|
||||||
// %
|
// %
|
||||||
//
|
//
|
||||||
// which is the best we can do under the circumstances.
|
// which is the best we can do under the circumstances.
|
||||||
//
|
//
|
||||||
// See go.dev/issue/44505 for more background on
|
// See go.dev/issue/44505 and go.dev/issue/54265 for more
|
||||||
// why Go moved on from Go 1.4 for bootstrap.
|
// background on why Go moved on from Go 1.4 for bootstrap.
|
||||||
|
|
||||||
//go:build !go1.22
|
//go:build !go1.24
|
||||||
|
|
||||||
package building_Go_requires_Go_1_22_6_or_later
|
package building_Go_requires_Go_1_24_6_or_later
|
||||||
3
src/cmd/dist/sys_windows.go
vendored
3
src/cmd/dist/sys_windows.go
vendored
|
|
@ -33,7 +33,6 @@ type systeminfo struct {
|
||||||
const (
|
const (
|
||||||
PROCESSOR_ARCHITECTURE_AMD64 = 9
|
PROCESSOR_ARCHITECTURE_AMD64 = 9
|
||||||
PROCESSOR_ARCHITECTURE_INTEL = 0
|
PROCESSOR_ARCHITECTURE_INTEL = 0
|
||||||
PROCESSOR_ARCHITECTURE_ARM = 5
|
|
||||||
PROCESSOR_ARCHITECTURE_ARM64 = 12
|
PROCESSOR_ARCHITECTURE_ARM64 = 12
|
||||||
PROCESSOR_ARCHITECTURE_IA64 = 6
|
PROCESSOR_ARCHITECTURE_IA64 = 6
|
||||||
)
|
)
|
||||||
|
|
@ -47,8 +46,6 @@ func sysinit() {
|
||||||
gohostarch = "amd64"
|
gohostarch = "amd64"
|
||||||
case PROCESSOR_ARCHITECTURE_INTEL:
|
case PROCESSOR_ARCHITECTURE_INTEL:
|
||||||
gohostarch = "386"
|
gohostarch = "386"
|
||||||
case PROCESSOR_ARCHITECTURE_ARM:
|
|
||||||
gohostarch = "arm"
|
|
||||||
case PROCESSOR_ARCHITECTURE_ARM64:
|
case PROCESSOR_ARCHITECTURE_ARM64:
|
||||||
gohostarch = "arm64"
|
gohostarch = "arm64"
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
10
src/cmd/dist/util.go
vendored
10
src/cmd/dist/util.go
vendored
|
|
@ -362,16 +362,6 @@ func errprintf(format string, args ...interface{}) {
|
||||||
fmt.Fprintf(os.Stderr, format, args...)
|
fmt.Fprintf(os.Stderr, format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// xsamefile reports whether f1 and f2 are the same file (or dir).
|
|
||||||
func xsamefile(f1, f2 string) bool {
|
|
||||||
fi1, err1 := os.Stat(f1)
|
|
||||||
fi2, err2 := os.Stat(f2)
|
|
||||||
if err1 != nil || err2 != nil {
|
|
||||||
return f1 == f2
|
|
||||||
}
|
|
||||||
return os.SameFile(fi1, fi2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func xgetgoarm() string {
|
func xgetgoarm() string {
|
||||||
// If we're building on an actual arm system, and not building
|
// If we're building on an actual arm system, and not building
|
||||||
// a cross-compiling toolchain, try to exec ourselves
|
// a cross-compiling toolchain, try to exec ourselves
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
module cmd
|
module cmd
|
||||||
|
|
||||||
go 1.25
|
go 1.26
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/google/pprof v0.0.0-20250208200701-d0013a598941
|
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5
|
||||||
golang.org/x/arch v0.18.1-0.20250605182141-b2f4e2807dec
|
golang.org/x/arch v0.20.1-0.20250808194827-46ba08e3ae58
|
||||||
golang.org/x/build v0.0.0-20250606033421-8c8ff6f34a83
|
golang.org/x/build v0.0.0-20250806225920-b7c66c047964
|
||||||
golang.org/x/mod v0.25.0
|
golang.org/x/mod v0.27.0
|
||||||
golang.org/x/sync v0.15.0
|
golang.org/x/sync v0.16.0
|
||||||
golang.org/x/sys v0.33.0
|
golang.org/x/sys v0.35.0
|
||||||
golang.org/x/telemetry v0.0.0-20250606142133-60998feb31a8
|
golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488
|
||||||
golang.org/x/term v0.32.0
|
golang.org/x/term v0.34.0
|
||||||
golang.org/x/tools v0.34.0
|
golang.org/x/tools v0.36.1-0.20250808220315-8866876b956f
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20240912202439-0a2b6291aafd // indirect
|
github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b // indirect
|
||||||
golang.org/x/text v0.26.0 // indirect
|
golang.org/x/text v0.28.0 // indirect
|
||||||
rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef // indirect
|
rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,28 @@
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/pprof v0.0.0-20250208200701-d0013a598941 h1:43XjGa6toxLpeksjcxs1jIoIyr+vUfOqY2c6HB4bpoc=
|
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5 h1:xhMrHhTJ6zxu3gA4enFM9MLn9AY7613teCdFnlUVbSQ=
|
||||||
github.com/google/pprof v0.0.0-20250208200701-d0013a598941/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20240912202439-0a2b6291aafd h1:EVX1s+XNss9jkRW9K6XGJn2jL2lB1h5H804oKPsxOec=
|
github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b h1:ogbOPx86mIhFy764gGkqnkFC8m5PJA7sPzlk9ppLVQA=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20240912202439-0a2b6291aafd/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
github.com/ianlancetaylor/demangle v0.0.0-20250417193237-f615e6bd150b/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
||||||
github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68=
|
github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68=
|
||||||
github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
golang.org/x/arch v0.18.1-0.20250605182141-b2f4e2807dec h1:fCOjXc18tBlkVy4m+VuL1WU8VTukYOGtAk7nC5QYPRY=
|
golang.org/x/arch v0.20.1-0.20250808194827-46ba08e3ae58 h1:uxPa6+/WsUfzikIAPMqpTho10y4qtYpINBurU+6NrHE=
|
||||||
golang.org/x/arch v0.18.1-0.20250605182141-b2f4e2807dec/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
golang.org/x/arch v0.20.1-0.20250808194827-46ba08e3ae58/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
||||||
golang.org/x/build v0.0.0-20250606033421-8c8ff6f34a83 h1:IiFSc399rOkpudtnsTDKdtfFEsvd+dGfNfl+ytV267c=
|
golang.org/x/build v0.0.0-20250806225920-b7c66c047964 h1:yRs1K51GKq7hsIO+YHJ8LsslrvwFceNPIv0tYjpcBd0=
|
||||||
golang.org/x/build v0.0.0-20250606033421-8c8ff6f34a83/go.mod h1:SDzKvZFXqZyl3tLink1AnKsAocWm0yFc3UfmxR6aIOw=
|
golang.org/x/build v0.0.0-20250806225920-b7c66c047964/go.mod h1:i9Vx7+aOQUpYJRxSO+OpRStVBCVL/9ccI51xblWm5WY=
|
||||||
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||||
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||||
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/telemetry v0.0.0-20250606142133-60998feb31a8 h1:jBJ3nsFeGb1DzjhOg2ZgZTpnDnOZfHId7RNlBJUtkOM=
|
golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488 h1:3doPGa+Gg4snce233aCWnbZVFsyFMo/dR40KK/6skyE=
|
||||||
golang.org/x/telemetry v0.0.0-20250606142133-60998feb31a8/go.mod h1:mUcjA5g0luJpMYCLjhH91f4t4RAUNp+zq9ZmUoqPD7M=
|
golang.org/x/telemetry v0.0.0-20250807160809-1a19826ec488/go.mod h1:fGb/2+tgXXjhjHsTNdVEEMZNWA0quBnfrO+AfoDSAKw=
|
||||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
golang.org/x/tools v0.36.1-0.20250808220315-8866876b956f h1:9m2Iptt9ZZU5llKDJy1XUl5d13PN1ZYV16KwOvE6jOw=
|
||||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
golang.org/x/tools v0.36.1-0.20250808220315-8866876b956f/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||||
rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef h1:mqLYrXCXYEZOop9/Dbo6RPX11539nwiCNBb1icVPmw8=
|
rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef h1:mqLYrXCXYEZOop9/Dbo6RPX11539nwiCNBb1icVPmw8=
|
||||||
rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef/go.mod h1:8xcPgWmwlZONN1D9bjxtHEjrUtSEa3fakVF8iaewYKQ=
|
rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef/go.mod h1:8xcPgWmwlZONN1D9bjxtHEjrUtSEa3fakVF8iaewYKQ=
|
||||||
|
|
|
||||||
|
|
@ -2527,7 +2527,7 @@
|
||||||
// The default is GOFIPS140=off, which makes no FIPS-140 changes at all.
|
// The default is GOFIPS140=off, which makes no FIPS-140 changes at all.
|
||||||
// Other values enable FIPS-140 compliance measures and select alternate
|
// Other values enable FIPS-140 compliance measures and select alternate
|
||||||
// versions of the cryptography source code.
|
// versions of the cryptography source code.
|
||||||
// See https://go.dev/security/fips140 for details.
|
// See https://go.dev/doc/security/fips140 for details.
|
||||||
// GO_EXTLINK_ENABLED
|
// GO_EXTLINK_ENABLED
|
||||||
// Whether the linker should use external linking mode
|
// Whether the linker should use external linking mode
|
||||||
// when using -linkmode=auto with code that uses cgo.
|
// when using -linkmode=auto with code that uses cgo.
|
||||||
|
|
|
||||||
|
|
@ -52,16 +52,6 @@ func maybeToolchainVersion(name string) string {
|
||||||
return FromToolchain(name)
|
return FromToolchain(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToolchainMax returns the maximum of x and y interpreted as toolchain names,
|
|
||||||
// compared using Compare(FromToolchain(x), FromToolchain(y)).
|
|
||||||
// If x and y compare equal, Max returns x.
|
|
||||||
func ToolchainMax(x, y string) string {
|
|
||||||
if Compare(FromToolchain(x), FromToolchain(y)) < 0 {
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
// Startup records the information that went into the startup-time version switch.
|
// Startup records the information that went into the startup-time version switch.
|
||||||
// It is initialized by switchGoToolchain.
|
// It is initialized by switchGoToolchain.
|
||||||
var Startup struct {
|
var Startup struct {
|
||||||
|
|
|
||||||
|
|
@ -695,7 +695,7 @@ Special-purpose environment variables:
|
||||||
The default is GOFIPS140=off, which makes no FIPS-140 changes at all.
|
The default is GOFIPS140=off, which makes no FIPS-140 changes at all.
|
||||||
Other values enable FIPS-140 compliance measures and select alternate
|
Other values enable FIPS-140 compliance measures and select alternate
|
||||||
versions of the cryptography source code.
|
versions of the cryptography source code.
|
||||||
See https://go.dev/security/fips140 for details.
|
See https://go.dev/doc/security/fips140 for details.
|
||||||
GO_EXTLINK_ENABLED
|
GO_EXTLINK_ENABLED
|
||||||
Whether the linker should use external linking mode
|
Whether the linker should use external linking mode
|
||||||
when using -linkmode=auto with code that uses cgo.
|
when using -linkmode=auto with code that uses cgo.
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
package filelock
|
package filelock
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"io/fs"
|
"io/fs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -74,10 +73,3 @@ func (lt lockType) String() string {
|
||||||
return "Unlock"
|
return "Unlock"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNotSupported returns a boolean indicating whether the error is known to
|
|
||||||
// report that a function is not supported (possibly for a specific input).
|
|
||||||
// It is satisfied by errors.ErrUnsupported as well as some syscall errors.
|
|
||||||
func IsNotSupported(err error) bool {
|
|
||||||
return errors.Is(err, errors.ErrUnsupported)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -387,23 +387,6 @@ func (r *gitRepo) Latest(ctx context.Context) (*RevInfo, error) {
|
||||||
return info, nil
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// findRef finds some ref name for the given hash,
|
|
||||||
// for use when the server requires giving a ref instead of a hash.
|
|
||||||
// There may be multiple ref names for a given hash,
|
|
||||||
// in which case this returns some name - it doesn't matter which.
|
|
||||||
func (r *gitRepo) findRef(ctx context.Context, hash string) (ref string, ok bool) {
|
|
||||||
refs, err := r.loadRefs(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
for ref, h := range refs {
|
|
||||||
if h == hash {
|
|
||||||
return ref, true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *gitRepo) checkConfigSHA256(ctx context.Context) bool {
|
func (r *gitRepo) checkConfigSHA256(ctx context.Context) bool {
|
||||||
if hashType, sha256CfgErr := r.runGit(ctx, "git", "config", "extensions.objectformat"); sha256CfgErr == nil {
|
if hashType, sha256CfgErr := r.runGit(ctx, "git", "config", "extensions.objectformat"); sha256CfgErr == nil {
|
||||||
return "sha256" == strings.TrimSpace(string(hashType))
|
return "sha256" == strings.TrimSpace(string(hashType))
|
||||||
|
|
|
||||||
|
|
@ -1009,10 +1009,6 @@ func LegacyGoMod(modPath string) []byte {
|
||||||
return fmt.Appendf(nil, "module %s\n", modfile.AutoQuote(modPath))
|
return fmt.Appendf(nil, "module %s\n", modfile.AutoQuote(modPath))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *codeRepo) modPrefix(rev string) string {
|
|
||||||
return r.modPath + "@" + rev
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *codeRepo) retractedVersions(ctx context.Context) (func(string) bool, error) {
|
func (r *codeRepo) retractedVersions(ctx context.Context) (func(string) bool, error) {
|
||||||
vs, err := r.Versions(ctx, "")
|
vs, err := r.Versions(ctx, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -453,7 +453,7 @@ func updateTools(ctx context.Context, queries []*query, opts *modload.WriteOpts)
|
||||||
if queries[i].version == "none" {
|
if queries[i].version == "none" {
|
||||||
opts.DropTools = append(opts.DropTools, m.Pkgs...)
|
opts.DropTools = append(opts.DropTools, m.Pkgs...)
|
||||||
} else {
|
} else {
|
||||||
opts.AddTools = append(opts.DropTools, m.Pkgs...)
|
opts.AddTools = append(opts.AddTools, m.Pkgs...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ package modindex
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"cmd/go/internal/fsys"
|
"cmd/go/internal/fsys"
|
||||||
"cmd/go/internal/str"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
|
|
@ -118,96 +117,12 @@ func (ctxt *Context) joinPath(elem ...string) string {
|
||||||
return filepath.Join(elem...)
|
return filepath.Join(elem...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// splitPathList calls ctxt.SplitPathList (if not nil) or else filepath.SplitList.
|
|
||||||
func (ctxt *Context) splitPathList(s string) []string {
|
|
||||||
if f := ctxt.SplitPathList; f != nil {
|
|
||||||
return f(s)
|
|
||||||
}
|
|
||||||
return filepath.SplitList(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// isAbsPath calls ctxt.IsAbsPath (if not nil) or else filepath.IsAbs.
|
|
||||||
func (ctxt *Context) isAbsPath(path string) bool {
|
|
||||||
if f := ctxt.IsAbsPath; f != nil {
|
|
||||||
return f(path)
|
|
||||||
}
|
|
||||||
return filepath.IsAbs(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// isDir reports whether path is a directory.
|
// isDir reports whether path is a directory.
|
||||||
func isDir(path string) bool {
|
func isDir(path string) bool {
|
||||||
fi, err := fsys.Stat(path)
|
fi, err := fsys.Stat(path)
|
||||||
return err == nil && fi.IsDir()
|
return err == nil && fi.IsDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
// hasSubdir calls ctxt.HasSubdir (if not nil) or else uses
|
|
||||||
// the local file system to answer the question.
|
|
||||||
func (ctxt *Context) hasSubdir(root, dir string) (rel string, ok bool) {
|
|
||||||
if f := ctxt.HasSubdir; f != nil {
|
|
||||||
return f(root, dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try using paths we received.
|
|
||||||
if rel, ok = hasSubdir(root, dir); ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try expanding symlinks and comparing
|
|
||||||
// expanded against unexpanded and
|
|
||||||
// expanded against expanded.
|
|
||||||
rootSym, _ := filepath.EvalSymlinks(root)
|
|
||||||
dirSym, _ := filepath.EvalSymlinks(dir)
|
|
||||||
|
|
||||||
if rel, ok = hasSubdir(rootSym, dir); ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if rel, ok = hasSubdir(root, dirSym); ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return hasSubdir(rootSym, dirSym)
|
|
||||||
}
|
|
||||||
|
|
||||||
// hasSubdir reports if dir is within root by performing lexical analysis only.
|
|
||||||
func hasSubdir(root, dir string) (rel string, ok bool) {
|
|
||||||
root = str.WithFilePathSeparator(filepath.Clean(root))
|
|
||||||
dir = filepath.Clean(dir)
|
|
||||||
if !strings.HasPrefix(dir, root) {
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
return filepath.ToSlash(dir[len(root):]), true
|
|
||||||
}
|
|
||||||
|
|
||||||
// gopath returns the list of Go path directories.
|
|
||||||
func (ctxt *Context) gopath() []string {
|
|
||||||
var all []string
|
|
||||||
for _, p := range ctxt.splitPathList(ctxt.GOPATH) {
|
|
||||||
if p == "" || p == ctxt.GOROOT {
|
|
||||||
// Empty paths are uninteresting.
|
|
||||||
// If the path is the GOROOT, ignore it.
|
|
||||||
// People sometimes set GOPATH=$GOROOT.
|
|
||||||
// Do not get confused by this common mistake.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(p, "~") {
|
|
||||||
// Path segments starting with ~ on Unix are almost always
|
|
||||||
// users who have incorrectly quoted ~ while setting GOPATH,
|
|
||||||
// preventing it from expanding to $HOME.
|
|
||||||
// The situation is made more confusing by the fact that
|
|
||||||
// bash allows quoted ~ in $PATH (most shells do not).
|
|
||||||
// Do not get confused by this, and do not try to use the path.
|
|
||||||
// It does not exist, and printing errors about it confuses
|
|
||||||
// those users even more, because they think "sure ~ exists!".
|
|
||||||
// The go command diagnoses this situation and prints a
|
|
||||||
// useful error.
|
|
||||||
// On Windows, ~ is used in short names, such as c:\progra~1
|
|
||||||
// for c:\program files.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
all = append(all, p)
|
|
||||||
}
|
|
||||||
return all
|
|
||||||
}
|
|
||||||
|
|
||||||
var defaultToolTags, defaultReleaseTags []string
|
var defaultToolTags, defaultReleaseTags []string
|
||||||
|
|
||||||
// NoGoError is the error used by Import to describe a directory
|
// NoGoError is the error used by Import to describe a directory
|
||||||
|
|
@ -266,114 +181,12 @@ func fileListForExt(p *build.Package, ext string) *[]string {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var errNoModules = errors.New("not using modules")
|
|
||||||
|
|
||||||
func findImportComment(data []byte) (s string, line int) {
|
|
||||||
// expect keyword package
|
|
||||||
word, data := parseWord(data)
|
|
||||||
if string(word) != "package" {
|
|
||||||
return "", 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// expect package name
|
|
||||||
_, data = parseWord(data)
|
|
||||||
|
|
||||||
// now ready for import comment, a // or /* */ comment
|
|
||||||
// beginning and ending on the current line.
|
|
||||||
for len(data) > 0 && (data[0] == ' ' || data[0] == '\t' || data[0] == '\r') {
|
|
||||||
data = data[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
var comment []byte
|
|
||||||
switch {
|
|
||||||
case bytes.HasPrefix(data, slashSlash):
|
|
||||||
comment, _, _ = bytes.Cut(data[2:], newline)
|
|
||||||
case bytes.HasPrefix(data, slashStar):
|
|
||||||
var ok bool
|
|
||||||
comment, _, ok = bytes.Cut(data[2:], starSlash)
|
|
||||||
if !ok {
|
|
||||||
// malformed comment
|
|
||||||
return "", 0
|
|
||||||
}
|
|
||||||
if bytes.Contains(comment, newline) {
|
|
||||||
return "", 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
comment = bytes.TrimSpace(comment)
|
|
||||||
|
|
||||||
// split comment into `import`, `"pkg"`
|
|
||||||
word, arg := parseWord(comment)
|
|
||||||
if string(word) != "import" {
|
|
||||||
return "", 0
|
|
||||||
}
|
|
||||||
|
|
||||||
line = 1 + bytes.Count(data[:cap(data)-cap(arg)], newline)
|
|
||||||
return strings.TrimSpace(string(arg)), line
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
slashSlash = []byte("//")
|
slashSlash = []byte("//")
|
||||||
slashStar = []byte("/*")
|
slashStar = []byte("/*")
|
||||||
starSlash = []byte("*/")
|
starSlash = []byte("*/")
|
||||||
newline = []byte("\n")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// skipSpaceOrComment returns data with any leading spaces or comments removed.
|
|
||||||
func skipSpaceOrComment(data []byte) []byte {
|
|
||||||
for len(data) > 0 {
|
|
||||||
switch data[0] {
|
|
||||||
case ' ', '\t', '\r', '\n':
|
|
||||||
data = data[1:]
|
|
||||||
continue
|
|
||||||
case '/':
|
|
||||||
if bytes.HasPrefix(data, slashSlash) {
|
|
||||||
i := bytes.Index(data, newline)
|
|
||||||
if i < 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
data = data[i+1:]
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if bytes.HasPrefix(data, slashStar) {
|
|
||||||
data = data[2:]
|
|
||||||
i := bytes.Index(data, starSlash)
|
|
||||||
if i < 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
data = data[i+2:]
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseWord skips any leading spaces or comments in data
|
|
||||||
// and then parses the beginning of data as an identifier or keyword,
|
|
||||||
// returning that word and what remains after the word.
|
|
||||||
func parseWord(data []byte) (word, rest []byte) {
|
|
||||||
data = skipSpaceOrComment(data)
|
|
||||||
|
|
||||||
// Parse past leading word characters.
|
|
||||||
rest = data
|
|
||||||
for {
|
|
||||||
r, size := utf8.DecodeRune(rest)
|
|
||||||
if unicode.IsLetter(r) || '0' <= r && r <= '9' || r == '_' {
|
|
||||||
rest = rest[size:]
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
word = data[:len(data)-len(rest)]
|
|
||||||
if len(word) == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return word, rest
|
|
||||||
}
|
|
||||||
|
|
||||||
var dummyPkg build.Package
|
var dummyPkg build.Package
|
||||||
|
|
||||||
// fileInfo records information learned about a file included in a build.
|
// fileInfo records information learned about a file included in a build.
|
||||||
|
|
|
||||||
|
|
@ -1039,11 +1039,6 @@ func (r *reader) string() string {
|
||||||
return r.d.stringTableAt(r.int())
|
return r.d.stringTableAt(r.int())
|
||||||
}
|
}
|
||||||
|
|
||||||
// bool reads the next bool.
|
|
||||||
func (r *reader) bool() bool {
|
|
||||||
return r.int() != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// tokpos reads the next token.Position.
|
// tokpos reads the next token.Position.
|
||||||
func (r *reader) tokpos() token.Position {
|
func (r *reader) tokpos() token.Position {
|
||||||
return token.Position{
|
return token.Position{
|
||||||
|
|
|
||||||
|
|
@ -658,11 +658,6 @@ func EditBuildList(ctx context.Context, add, mustSelect []module.Version) (chang
|
||||||
return changed, nil
|
return changed, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// OverrideRoots edits the global requirement roots by replacing the specific module versions.
|
|
||||||
func OverrideRoots(ctx context.Context, replace []module.Version) {
|
|
||||||
requirements = overrideRoots(ctx, requirements, replace)
|
|
||||||
}
|
|
||||||
|
|
||||||
func overrideRoots(ctx context.Context, rs *Requirements, replace []module.Version) *Requirements {
|
func overrideRoots(ctx context.Context, rs *Requirements, replace []module.Version) *Requirements {
|
||||||
drop := make(map[string]bool)
|
drop := make(map[string]bool)
|
||||||
for _, m := range replace {
|
for _, m := range replace {
|
||||||
|
|
|
||||||
|
|
@ -305,30 +305,6 @@ func (mms *MainModuleSet) Godebugs() []*modfile.Godebug {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toolchain returns the toolchain set on the single module, in module mode,
|
|
||||||
// or the go.work file in workspace mode.
|
|
||||||
func (mms *MainModuleSet) Toolchain() string {
|
|
||||||
if inWorkspaceMode() {
|
|
||||||
if mms.workFile != nil && mms.workFile.Toolchain != nil {
|
|
||||||
return mms.workFile.Toolchain.Name
|
|
||||||
}
|
|
||||||
return "go" + mms.GoVersion()
|
|
||||||
}
|
|
||||||
if mms != nil && len(mms.versions) == 1 {
|
|
||||||
f := mms.ModFile(mms.mustGetSingleMainModule())
|
|
||||||
if f == nil {
|
|
||||||
// Special case: we are outside a module, like 'go run x.go'.
|
|
||||||
// Assume the local Go version.
|
|
||||||
// TODO(#49228): Clean this up; see loadModFile.
|
|
||||||
return gover.LocalToolchain()
|
|
||||||
}
|
|
||||||
if f.Toolchain != nil {
|
|
||||||
return f.Toolchain.Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "go" + mms.GoVersion()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mms *MainModuleSet) WorkFileReplaceMap() map[module.Version]module.Version {
|
func (mms *MainModuleSet) WorkFileReplaceMap() map[module.Version]module.Version {
|
||||||
return mms.workFileReplaceMap
|
return mms.workFileReplaceMap
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ package work
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"internal/buildcfg"
|
"internal/buildcfg"
|
||||||
"internal/platform"
|
"internal/platform"
|
||||||
|
|
@ -438,32 +437,6 @@ func (gcToolchain) symabis(b *Builder, a *Action, sfiles []string) (string, erro
|
||||||
return symabis, nil
|
return symabis, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// toolVerify checks that the command line args writes the same output file
|
|
||||||
// if run using newTool instead.
|
|
||||||
// Unused now but kept around for future use.
|
|
||||||
func toolVerify(a *Action, b *Builder, p *load.Package, newTool string, ofile string, args []any) error {
|
|
||||||
newArgs := make([]any, len(args))
|
|
||||||
copy(newArgs, args)
|
|
||||||
newArgs[1] = base.Tool(newTool)
|
|
||||||
newArgs[3] = ofile + ".new" // x.6 becomes x.6.new
|
|
||||||
if err := b.Shell(a).run(p.Dir, p.ImportPath, nil, newArgs...); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
data1, err := os.ReadFile(ofile)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
data2, err := os.ReadFile(ofile + ".new")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !bytes.Equal(data1, data2) {
|
|
||||||
return fmt.Errorf("%s and %s produced different output files:\n%s\n%s", filepath.Base(args[1].(string)), newTool, strings.Join(str.StringList(args...), " "), strings.Join(str.StringList(newArgs...), " "))
|
|
||||||
}
|
|
||||||
os.Remove(ofile + ".new")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (gcToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) error {
|
func (gcToolchain) pack(b *Builder, a *Action, afile string, ofiles []string) error {
|
||||||
absOfiles := make([]string, 0, len(ofiles))
|
absOfiles := make([]string, 0, len(ofiles))
|
||||||
for _, f := range ofiles {
|
for _, f := range ofiles {
|
||||||
|
|
|
||||||
25
src/cmd/go/testdata/script/mod_get_tool_issue74035.txt
vendored
Normal file
25
src/cmd/go/testdata/script/mod_get_tool_issue74035.txt
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
# Regression test for https://go.dev/issue/74035.
|
||||||
|
go get -tool example.com/foo/cmd/a example.com/foo/cmd/b
|
||||||
|
cmp go.mod go.mod.want
|
||||||
|
|
||||||
|
-- go.mod --
|
||||||
|
module example.com/foo
|
||||||
|
go 1.24
|
||||||
|
-- go.mod.want --
|
||||||
|
module example.com/foo
|
||||||
|
|
||||||
|
go 1.24
|
||||||
|
|
||||||
|
tool (
|
||||||
|
example.com/foo/cmd/a
|
||||||
|
example.com/foo/cmd/b
|
||||||
|
)
|
||||||
|
-- cmd/a/a.go --
|
||||||
|
package a
|
||||||
|
|
||||||
|
func main() {}
|
||||||
|
|
||||||
|
-- cmd/b/b.go --
|
||||||
|
package b
|
||||||
|
|
||||||
|
func main() {}
|
||||||
|
|
@ -498,20 +498,6 @@ func exactly16Bytes(s string) string {
|
||||||
// architecture-independent object file output
|
// architecture-independent object file output
|
||||||
const HeaderSize = 60
|
const HeaderSize = 60
|
||||||
|
|
||||||
func ReadHeader(b *bufio.Reader, name string) int {
|
|
||||||
var buf [HeaderSize]byte
|
|
||||||
if _, err := io.ReadFull(b, buf[:]); err != nil {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
aname := strings.Trim(string(buf[0:16]), " ")
|
|
||||||
if !strings.HasPrefix(aname, name) {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
asize := strings.Trim(string(buf[48:58]), " ")
|
|
||||||
i, _ := strconv.Atoi(asize)
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
|
|
||||||
func FormatHeader(arhdr []byte, name string, size int64) {
|
func FormatHeader(arhdr []byte, name string, size int64) {
|
||||||
copy(arhdr[:], fmt.Sprintf("%-16s%-12d%-6d%-6d%-8o%-10d`\n", name, 0, 0, 0, 0644, size))
|
copy(arhdr[:], fmt.Sprintf("%-16s%-12d%-6d%-6d%-8o%-10d`\n", name, 0, 0, 0, 0644, size))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,11 +56,6 @@ func (w *Writer) Debug(out io.Writer) {
|
||||||
w.debug = out
|
w.debug = out
|
||||||
}
|
}
|
||||||
|
|
||||||
// BitIndex returns the number of bits written to the bit stream so far.
|
|
||||||
func (w *Writer) BitIndex() int64 {
|
|
||||||
return w.index
|
|
||||||
}
|
|
||||||
|
|
||||||
// byte writes the byte x to the output.
|
// byte writes the byte x to the output.
|
||||||
func (w *Writer) byte(x byte) {
|
func (w *Writer) byte(x byte) {
|
||||||
if w.debug != nil {
|
if w.debug != nil {
|
||||||
|
|
@ -98,20 +93,6 @@ func (w *Writer) Ptr(index int64) {
|
||||||
w.lit(1)
|
w.lit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ShouldRepeat reports whether it would be worthwhile to
|
|
||||||
// use a Repeat to describe c elements of n bits each,
|
|
||||||
// compared to just emitting c copies of the n-bit description.
|
|
||||||
func (w *Writer) ShouldRepeat(n, c int64) bool {
|
|
||||||
// Should we lay out the bits directly instead of
|
|
||||||
// encoding them as a repetition? Certainly if count==1,
|
|
||||||
// since there's nothing to repeat, but also if the total
|
|
||||||
// size of the plain pointer bits for the type will fit in
|
|
||||||
// 4 or fewer bytes, since using a repetition will require
|
|
||||||
// flushing the current bits plus at least one byte for
|
|
||||||
// the repeat size and one for the repeat count.
|
|
||||||
return c > 1 && c*n > 4*8
|
|
||||||
}
|
|
||||||
|
|
||||||
// Repeat emits an instruction to repeat the description
|
// Repeat emits an instruction to repeat the description
|
||||||
// of the last n words c times (including the initial description, c+1 times in total).
|
// of the last n words c times (including the initial description, c+1 times in total).
|
||||||
func (w *Writer) Repeat(n, c int64) {
|
func (w *Writer) Repeat(n, c int64) {
|
||||||
|
|
@ -163,36 +144,6 @@ func (w *Writer) ZeroUntil(index int64) {
|
||||||
w.Repeat(1, skip-1)
|
w.Repeat(1, skip-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append emits the given GC program into the current output.
|
|
||||||
// The caller asserts that the program emits n bits (describes n words),
|
|
||||||
// and Append panics if that is not true.
|
|
||||||
func (w *Writer) Append(prog []byte, n int64) {
|
|
||||||
w.flushlit()
|
|
||||||
if w.debug != nil {
|
|
||||||
fmt.Fprintf(w.debug, "gcprog: append prog for %d ptrs\n", n)
|
|
||||||
fmt.Fprintf(w.debug, "\t")
|
|
||||||
}
|
|
||||||
n1 := progbits(prog)
|
|
||||||
if n1 != n {
|
|
||||||
panic("gcprog: wrong bit count in append")
|
|
||||||
}
|
|
||||||
// The last byte of the prog terminates the program.
|
|
||||||
// Don't emit that, or else our own program will end.
|
|
||||||
for i, x := range prog[:len(prog)-1] {
|
|
||||||
if w.debug != nil {
|
|
||||||
if i > 0 {
|
|
||||||
fmt.Fprintf(w.debug, " ")
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w.debug, "%02x", x)
|
|
||||||
}
|
|
||||||
w.byte(x)
|
|
||||||
}
|
|
||||||
if w.debug != nil {
|
|
||||||
fmt.Fprintf(w.debug, "\n")
|
|
||||||
}
|
|
||||||
w.index += n
|
|
||||||
}
|
|
||||||
|
|
||||||
// progbits returns the length of the bit stream encoded by the program p.
|
// progbits returns the length of the bit stream encoded by the program p.
|
||||||
func progbits(p []byte) int64 {
|
func progbits(p []byte) int64 {
|
||||||
var n int64
|
var n int64
|
||||||
|
|
|
||||||
|
|
@ -635,29 +635,11 @@ func (r *Reader) uint64At(off uint32) uint64 {
|
||||||
return binary.LittleEndian.Uint64(b)
|
return binary.LittleEndian.Uint64(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reader) int64At(off uint32) int64 {
|
|
||||||
return int64(r.uint64At(off))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Reader) uint32At(off uint32) uint32 {
|
func (r *Reader) uint32At(off uint32) uint32 {
|
||||||
b := r.BytesAt(off, 4)
|
b := r.BytesAt(off, 4)
|
||||||
return binary.LittleEndian.Uint32(b)
|
return binary.LittleEndian.Uint32(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reader) int32At(off uint32) int32 {
|
|
||||||
return int32(r.uint32At(off))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Reader) uint16At(off uint32) uint16 {
|
|
||||||
b := r.BytesAt(off, 2)
|
|
||||||
return binary.LittleEndian.Uint16(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Reader) uint8At(off uint32) uint8 {
|
|
||||||
b := r.BytesAt(off, 1)
|
|
||||||
return b[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *Reader) StringAt(off uint32, len uint32) string {
|
func (r *Reader) StringAt(off uint32, len uint32) string {
|
||||||
b := r.b[off : off+len]
|
b := r.b[off : off+len]
|
||||||
if r.readonly {
|
if r.readonly {
|
||||||
|
|
|
||||||
|
|
@ -1054,15 +1054,6 @@ var sysInstFields = map[SpecialOperand]struct {
|
||||||
// Used for padding NOOP instruction
|
// Used for padding NOOP instruction
|
||||||
const OP_NOOP = 0xd503201f
|
const OP_NOOP = 0xd503201f
|
||||||
|
|
||||||
// pcAlignPadLength returns the number of bytes required to align pc to alignedValue,
|
|
||||||
// reporting an error if alignedValue is not a power of two or is out of range.
|
|
||||||
func pcAlignPadLength(ctxt *obj.Link, pc int64, alignedValue int64) int {
|
|
||||||
if !((alignedValue&(alignedValue-1) == 0) && 8 <= alignedValue && alignedValue <= 2048) {
|
|
||||||
ctxt.Diag("alignment value of an instruction must be a power of two and in the range [8, 2048], got %d\n", alignedValue)
|
|
||||||
}
|
|
||||||
return int(-pc & (alignedValue - 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
// size returns the size of the sequence of machine instructions when p is encoded with o.
|
// size returns the size of the sequence of machine instructions when p is encoded with o.
|
||||||
// Usually it just returns o.size directly, in some cases it checks whether the optimization
|
// Usually it just returns o.size directly, in some cases it checks whether the optimization
|
||||||
// conditions are met, and if so returns the size of the optimized instruction sequence.
|
// conditions are met, and if so returns the size of the optimized instruction sequence.
|
||||||
|
|
@ -1209,10 +1200,6 @@ type codeBuffer struct {
|
||||||
data *[]byte
|
data *[]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cb *codeBuffer) pc() int64 {
|
|
||||||
return int64(len(*cb.data))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write a sequence of opcodes into the code buffer.
|
// Write a sequence of opcodes into the code buffer.
|
||||||
func (cb *codeBuffer) emit(op ...uint32) {
|
func (cb *codeBuffer) emit(op ...uint32) {
|
||||||
for _, o := range op {
|
for _, o := range op {
|
||||||
|
|
|
||||||
|
|
@ -567,6 +567,11 @@ const (
|
||||||
AMOVVF
|
AMOVVF
|
||||||
AMOVVD
|
AMOVVD
|
||||||
|
|
||||||
|
// 2.2.1.3
|
||||||
|
AALSLW
|
||||||
|
AALSLWU
|
||||||
|
AALSLV
|
||||||
|
|
||||||
// 2.2.1.8
|
// 2.2.1.8
|
||||||
AORN
|
AORN
|
||||||
AANDN
|
AANDN
|
||||||
|
|
@ -743,6 +748,9 @@ const (
|
||||||
AFTINTRNEVF
|
AFTINTRNEVF
|
||||||
AFTINTRNEVD
|
AFTINTRNEVD
|
||||||
|
|
||||||
|
// 3.2.4.2
|
||||||
|
AFSEL
|
||||||
|
|
||||||
// LSX and LASX memory access instructions
|
// LSX and LASX memory access instructions
|
||||||
AVMOVQ
|
AVMOVQ
|
||||||
AXVMOVQ
|
AXVMOVQ
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,9 @@ var Anames = []string{
|
||||||
"MOVDV",
|
"MOVDV",
|
||||||
"MOVVF",
|
"MOVVF",
|
||||||
"MOVVD",
|
"MOVVD",
|
||||||
|
"ALSLW",
|
||||||
|
"ALSLWU",
|
||||||
|
"ALSLV",
|
||||||
"ORN",
|
"ORN",
|
||||||
"ANDN",
|
"ANDN",
|
||||||
"AMSWAPB",
|
"AMSWAPB",
|
||||||
|
|
@ -261,6 +264,7 @@ var Anames = []string{
|
||||||
"FTINTRNEWD",
|
"FTINTRNEWD",
|
||||||
"FTINTRNEVF",
|
"FTINTRNEVF",
|
||||||
"FTINTRNEVD",
|
"FTINTRNEVD",
|
||||||
|
"FSEL",
|
||||||
"VMOVQ",
|
"VMOVQ",
|
||||||
"XVMOVQ",
|
"XVMOVQ",
|
||||||
"VADDB",
|
"VADDB",
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,9 @@ var optab = []Optab{
|
||||||
{AFMADDF, C_FREG, C_FREG, C_NONE, C_FREG, C_NONE, 37, 4, 0, 0},
|
{AFMADDF, C_FREG, C_FREG, C_NONE, C_FREG, C_NONE, 37, 4, 0, 0},
|
||||||
{AFMADDF, C_FREG, C_FREG, C_FREG, C_FREG, C_NONE, 37, 4, 0, 0},
|
{AFMADDF, C_FREG, C_FREG, C_FREG, C_FREG, C_NONE, 37, 4, 0, 0},
|
||||||
|
|
||||||
|
{AFSEL, C_FCCREG, C_FREG, C_FREG, C_FREG, C_NONE, 33, 4, 0, 0},
|
||||||
|
{AFSEL, C_FCCREG, C_FREG, C_NONE, C_FREG, C_NONE, 33, 4, 0, 0},
|
||||||
|
|
||||||
{AMOVW, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
|
{AMOVW, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
|
||||||
{AMOVWU, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
|
{AMOVWU, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
|
||||||
{AMOVV, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
|
{AMOVV, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
|
||||||
|
|
@ -422,6 +425,8 @@ var optab = []Optab{
|
||||||
{APRELD, C_SOREG, C_U5CON, C_NONE, C_NONE, C_NONE, 47, 4, 0, 0},
|
{APRELD, C_SOREG, C_U5CON, C_NONE, C_NONE, C_NONE, 47, 4, 0, 0},
|
||||||
{APRELDX, C_SOREG, C_DCON, C_U5CON, C_NONE, C_NONE, 48, 20, 0, 0},
|
{APRELDX, C_SOREG, C_DCON, C_U5CON, C_NONE, C_NONE, 48, 20, 0, 0},
|
||||||
|
|
||||||
|
{AALSLV, C_U3CON, C_REG, C_REG, C_REG, C_NONE, 64, 4, 0, 0},
|
||||||
|
|
||||||
{obj.APCALIGN, C_U12CON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
|
{obj.APCALIGN, C_U12CON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
|
||||||
{obj.APCDATA, C_32CON, C_NONE, C_NONE, C_32CON, C_NONE, 0, 0, 0, 0},
|
{obj.APCDATA, C_32CON, C_NONE, C_NONE, C_32CON, C_NONE, 0, 0, 0, 0},
|
||||||
{obj.APCDATA, C_DCON, C_NONE, C_NONE, C_DCON, C_NONE, 0, 0, 0, 0},
|
{obj.APCDATA, C_DCON, C_NONE, C_NONE, C_DCON, C_NONE, 0, 0, 0, 0},
|
||||||
|
|
@ -729,10 +734,6 @@ func isint32(v int64) bool {
|
||||||
return int64(int32(v)) == v
|
return int64(int32(v)) == v
|
||||||
}
|
}
|
||||||
|
|
||||||
func isuint32(v uint64) bool {
|
|
||||||
return uint64(uint32(v)) == v
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ctxt0) aclass(a *obj.Addr) int {
|
func (c *ctxt0) aclass(a *obj.Addr) int {
|
||||||
switch a.Type {
|
switch a.Type {
|
||||||
case obj.TYPE_NONE:
|
case obj.TYPE_NONE:
|
||||||
|
|
@ -1496,6 +1497,10 @@ func buildop(ctxt *obj.Link) {
|
||||||
case ABFPT:
|
case ABFPT:
|
||||||
opset(ABFPF, r0)
|
opset(ABFPF, r0)
|
||||||
|
|
||||||
|
case AALSLV:
|
||||||
|
opset(AALSLW, r0)
|
||||||
|
opset(AALSLWU, r0)
|
||||||
|
|
||||||
case AMOVW,
|
case AMOVW,
|
||||||
AMOVD,
|
AMOVD,
|
||||||
AMOVF,
|
AMOVF,
|
||||||
|
|
@ -1515,6 +1520,7 @@ func buildop(ctxt *obj.Link) {
|
||||||
AWORD,
|
AWORD,
|
||||||
APRELD,
|
APRELD,
|
||||||
APRELDX,
|
APRELDX,
|
||||||
|
AFSEL,
|
||||||
obj.ANOP,
|
obj.ANOP,
|
||||||
obj.ATEXT,
|
obj.ATEXT,
|
||||||
obj.AFUNCDATA,
|
obj.AFUNCDATA,
|
||||||
|
|
@ -1952,6 +1958,10 @@ func OP_RR(op uint32, r2 uint32, r3 uint32) uint32 {
|
||||||
return op | (r2&0x1F)<<5 | (r3&0x1F)<<0
|
return op | (r2&0x1F)<<5 | (r3&0x1F)<<0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func OP_2IRRR(op uint32, i uint32, r2 uint32, r3 uint32, r4 uint32) uint32 {
|
||||||
|
return op | (i&0x3)<<15 | (r2&0x1F)<<10 | (r3&0x1F)<<5 | (r4&0x1F)<<0
|
||||||
|
}
|
||||||
|
|
||||||
func OP_16IR_5I(op uint32, i uint32, r2 uint32) uint32 {
|
func OP_16IR_5I(op uint32, i uint32, r2 uint32) uint32 {
|
||||||
return op | (i&0xFFFF)<<10 | (r2&0x1F)<<5 | ((i >> 16) & 0x1F)
|
return op | (i&0xFFFF)<<10 | (r2&0x1F)<<5 | ((i >> 16) & 0x1F)
|
||||||
}
|
}
|
||||||
|
|
@ -2381,6 +2391,16 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
||||||
}
|
}
|
||||||
o1 = OP_6IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
|
o1 = OP_6IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
|
||||||
|
|
||||||
|
case 33: // fsel ca, fk, [fj], fd
|
||||||
|
ca := uint32(p.From.Reg)
|
||||||
|
fk := uint32(p.Reg)
|
||||||
|
fd := uint32(p.To.Reg)
|
||||||
|
fj := fd
|
||||||
|
if len(p.RestArgs) > 0 {
|
||||||
|
fj = uint32(p.GetFrom3().Reg)
|
||||||
|
}
|
||||||
|
o1 = 0x340<<18 | (ca&0x7)<<15 | (fk&0x1F)<<10 | (fj&0x1F)<<5 | (fd & 0x1F)
|
||||||
|
|
||||||
case 34: // mov $con,fr
|
case 34: // mov $con,fr
|
||||||
v := c.regoff(&p.From)
|
v := c.regoff(&p.From)
|
||||||
a := AADDU
|
a := AADDU
|
||||||
|
|
@ -2721,6 +2741,14 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
||||||
case 62: // rdtimex rd, rj
|
case 62: // rdtimex rd, rj
|
||||||
o1 = OP_RR(c.oprr(p.As), uint32(p.To.Reg), uint32(p.RegTo2))
|
o1 = OP_RR(c.oprr(p.As), uint32(p.To.Reg), uint32(p.RegTo2))
|
||||||
|
|
||||||
|
case 64: // alsl rd, rj, rk, sa2
|
||||||
|
sa := p.From.Offset - 1
|
||||||
|
if sa < 0 || sa > 3 {
|
||||||
|
c.ctxt.Diag("%v: shift amount out of range[1, 4].\n", p)
|
||||||
|
}
|
||||||
|
r := p.GetFrom3().Reg
|
||||||
|
o1 = OP_2IRRR(c.opirrr(p.As), uint32(sa), uint32(r), uint32(p.Reg), uint32(p.To.Reg))
|
||||||
|
|
||||||
case 65: // mov sym@GOT, r ==> pcalau12i + ld.d
|
case 65: // mov sym@GOT, r ==> pcalau12i + ld.d
|
||||||
o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(p.To.Reg))
|
o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(p.To.Reg))
|
||||||
c.cursym.AddRel(c.ctxt, obj.Reloc{
|
c.cursym.AddRel(c.ctxt, obj.Reloc{
|
||||||
|
|
@ -4248,6 +4276,19 @@ func (c *ctxt0) opirr(a obj.As) uint32 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ctxt0) opirrr(a obj.As) uint32 {
|
||||||
|
switch a {
|
||||||
|
case AALSLW:
|
||||||
|
return 0x2 << 17 // alsl.w
|
||||||
|
case AALSLWU:
|
||||||
|
return 0x3 << 17 // alsl.wu
|
||||||
|
case AALSLV:
|
||||||
|
return 0x16 << 17 // alsl.d
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ctxt0) opirir(a obj.As) uint32 {
|
func (c *ctxt0) opirir(a obj.As) uint32 {
|
||||||
switch a {
|
switch a {
|
||||||
case ABSTRINSW:
|
case ABSTRINSW:
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,27 @@ Note: In the following sections 3.1 to 3.6, "ui4" (4-bit unsigned int immediate)
|
||||||
bits[11:1]: block size, the value range is [16, 1024], and it must be an integer multiple of 16
|
bits[11:1]: block size, the value range is [16, 1024], and it must be an integer multiple of 16
|
||||||
bits[20:12]: block num, the value range is [1, 256]
|
bits[20:12]: block num, the value range is [1, 256]
|
||||||
bits[36:21]: stride, the value range is [0, 0xffff]
|
bits[36:21]: stride, the value range is [0, 0xffff]
|
||||||
|
|
||||||
|
4. ShiftAdd instructions
|
||||||
|
Mapping between Go and platform assembly:
|
||||||
|
Go assembly | platform assembly
|
||||||
|
ALSL.W/WU/V $Imm, Rj, Rk, Rd | alsl.w/wu/d rd, rj, rk, $imm
|
||||||
|
|
||||||
|
Instruction encoding format is as follows:
|
||||||
|
|
||||||
|
| 31 ~ 17 | 16 ~ 15 | 14 ~ 10 | 9 ~ 5 | 4 ~ 0 |
|
||||||
|
| opcode | sa2 | rk | rj | rd |
|
||||||
|
|
||||||
|
The alsl.w/wu/v series of instructions shift the data in rj left by sa+1, add the value
|
||||||
|
in rk, and write the result to rd.
|
||||||
|
|
||||||
|
To allow programmers to directly write the desired shift amount in assembly code, we actually write
|
||||||
|
the value of sa2+1 in the assembly code and then include the value of sa2 in the instruction encoding.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
Go assembly | instruction Encoding
|
||||||
|
ALSLV $4, r4, r5, R6 | 002d9486
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package loong64
|
package loong64
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue