(MOVLQZX x:(MOVQload [off] {sym} ptr mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVLload <v.Type> [off] {sym} ptr mem)
(MOVLQZX x) && zeroUpper32Bits(x,3) -> x
+(MOVWQZX x) && zeroUpper48Bits(x,3) -> x
+(MOVBQZX x) && zeroUpper56Bits(x,3) -> x
(MOVBQZX x:(MOVBloadidx1 [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVBloadidx1 <v.Type> [off] {sym} ptr idx mem)
(MOVWQZX x:(MOVWloadidx1 [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWloadidx1 <v.Type> [off] {sym} ptr idx mem)
return false
}
+// zeroUpper48Bits is similar to zeroUpper32Bits, but for upper 48 bits
+func zeroUpper48Bits(x *Value, depth int) bool {
+ switch x.Op {
+ case OpAMD64MOVWQZX, OpAMD64MOVWload, OpAMD64MOVWloadidx1, OpAMD64MOVWloadidx2:
+ return true
+ case OpArg:
+ return x.Type.Width == 2
+ case OpPhi, OpSelect0, OpSelect1:
+ // Phis can use each-other as an arguments, instead of tracking visited values,
+ // just limit recursion depth.
+ if depth <= 0 {
+ return false
+ }
+ for i := range x.Args {
+ if !zeroUpper48Bits(x.Args[i], depth-1) {
+ return false
+ }
+ }
+ return true
+
+ }
+ return false
+}
+
+// zeroUpper56Bits is similar to zeroUpper32Bits, but for upper 56 bits
+func zeroUpper56Bits(x *Value, depth int) bool {
+ switch x.Op {
+ case OpAMD64MOVBQZX, OpAMD64MOVBload, OpAMD64MOVBloadidx1:
+ return true
+ case OpArg:
+ return x.Type.Width == 1
+ case OpPhi, OpSelect0, OpSelect1:
+ // Phis can use each-other as an arguments, instead of tracking visited values,
+ // just limit recursion depth.
+ if depth <= 0 {
+ return false
+ }
+ for i := range x.Args {
+ if !zeroUpper56Bits(x.Args[i], depth-1) {
+ return false
+ }
+ }
+ return true
+
+ }
+ return false
+}
+
// isInlinableMemmove reports whether the given arch performs a Move of the given size
// faster than memmove. It will only return true if replacing the memmove with a Move is
// safe, either because Move is small or because the arguments are disjoint.
v0.AddArg(mem)
return true
}
+ // match: (MOVBQZX x)
+ // cond: zeroUpper56Bits(x,3)
+ // result: x
+ for {
+ x := v.Args[0]
+ if !(zeroUpper56Bits(x, 3)) {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
// match: (MOVBQZX x:(MOVBloadidx1 [off] {sym} ptr idx mem))
// cond: x.Uses == 1 && clobber(x)
// result: @x.Block (MOVBloadidx1 <v.Type> [off] {sym} ptr idx mem)
v0.AddArg(mem)
return true
}
+ // match: (MOVWQZX x)
+ // cond: zeroUpper48Bits(x,3)
+ // result: x
+ for {
+ x := v.Args[0]
+ if !(zeroUpper48Bits(x, 3)) {
+ break
+ }
+ v.reset(OpCopy)
+ v.Type = x.Type
+ v.AddArg(x)
+ return true
+ }
// match: (MOVWQZX x:(MOVWloadidx1 [off] {sym} ptr idx mem))
// cond: x.Uses == 1 && clobber(x)
// result: @x.Block (MOVWloadidx1 <v.Type> [off] {sym} ptr idx mem)
--- /dev/null
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+var wsp = [256]bool{
+ ' ': true,
+ '\t': true,
+ '\n': true,
+ '\r': true,
+}
+
+func zeroExtArgByte(ch byte) bool {
+ return wsp[ch] // amd64:-"MOVBLZX\t..,.."
+}
+
+func zeroExtArgUint16(ch uint16) bool {
+ return wsp[ch] // amd64:-"MOVWLZX\t..,.."
+}