mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
cmd/compile: defer lowering OANDNOT until SSA
Currently, "x &^ y" gets rewriten into "x & ^y" during walk. It adds unnecessary complexity to other parts, which must aware about this. Instead, we can just implement "&^" in the conversion to SSA, so "&^" can be handled like other binary operators. However, this CL does not pass toolstash-check. It seems that implements "&^" in the conversion to SSA causes registers allocation change. With the parent: obj: 00212 (.../src/runtime/complex.go:47) MOVQ X0, AX obj: 00213 (.../src/runtime/complex.go:47) BTRQ $63, AX obj: 00214 (.../src/runtime/complex.go:47) MOVQ "".n(SP), CX obj: 00215 (.../src/runtime/complex.go:47) MOVQ $-9223372036854775808, DX obj: 00216 (.../src/runtime/complex.go:47) ANDQ DX, CX obj: 00217 (.../src/runtime/complex.go:47) ORQ AX, CX With this CL: obj: 00212 (.../src/runtime/complex.go:47) MOVQ X0, AX obj: 00213 (.../src/runtime/complex.go:47) BTRQ $63, AX obj: 00214 (.../src/runtime/complex.go:47) MOVQ $-9223372036854775808, CX obj: 00215 (.../src/runtime/complex.go:47) MOVQ "".n(SP), DX obj: 00216 (.../src/runtime/complex.go:47) ANDQ CX, DX obj: 00217 (.../src/runtime/complex.go:47) ORQ AX, DX Change-Id: I80acf8496a91be4804fb7ef3df04c19baae2754c Reviewed-on: https://go-review.googlesource.com/c/go/+/264660 Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com> Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
fb7134e4e3
commit
a19cf510af
@ -2472,6 +2472,11 @@ func (s *state) expr(n *Node) *ssa.Value {
|
|||||||
a := s.expr(n.Left)
|
a := s.expr(n.Left)
|
||||||
b := s.expr(n.Right)
|
b := s.expr(n.Right)
|
||||||
return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b)
|
return s.newValue2(s.ssaOp(n.Op, n.Type), a.Type, a, b)
|
||||||
|
case OANDNOT:
|
||||||
|
a := s.expr(n.Left)
|
||||||
|
b := s.expr(n.Right)
|
||||||
|
b = s.newValue1(s.ssaOp(OBITNOT, b.Type), b.Type, b)
|
||||||
|
return s.newValue2(s.ssaOp(OAND, n.Type), a.Type, a, b)
|
||||||
case OLSH, ORSH:
|
case OLSH, ORSH:
|
||||||
a := s.expr(n.Left)
|
a := s.expr(n.Left)
|
||||||
b := s.expr(n.Right)
|
b := s.expr(n.Right)
|
||||||
|
@ -142,7 +142,7 @@ const (
|
|||||||
_, _ // second nodeInitorder bit
|
_, _ // second nodeInitorder bit
|
||||||
_, nodeHasBreak
|
_, nodeHasBreak
|
||||||
_, nodeNoInline // used internally by inliner to indicate that a function call should not be inlined; set for OCALLFUNC and OCALLMETH only
|
_, nodeNoInline // used internally by inliner to indicate that a function call should not be inlined; set for OCALLFUNC and OCALLMETH only
|
||||||
_, nodeImplicit // implicit OADDR or ODEREF; ++/-- statement represented as OASOP; or ANDNOT lowered to OAND
|
_, nodeImplicit // implicit OADDR or ODEREF; ++/-- statement represented as OASOP
|
||||||
_, nodeIsDDD // is the argument variadic
|
_, nodeIsDDD // is the argument variadic
|
||||||
_, nodeDiag // already printed error about this
|
_, nodeDiag // already printed error about this
|
||||||
_, nodeColas // OAS resulting from :=
|
_, nodeColas // OAS resulting from :=
|
||||||
|
@ -474,7 +474,7 @@ opswitch:
|
|||||||
ODEREF, OSPTR, OITAB, OIDATA, OADDR:
|
ODEREF, OSPTR, OITAB, OIDATA, OADDR:
|
||||||
n.Left = walkexpr(n.Left, init)
|
n.Left = walkexpr(n.Left, init)
|
||||||
|
|
||||||
case OEFACE, OAND, OSUB, OMUL, OADD, OOR, OXOR, OLSH, ORSH:
|
case OEFACE, OAND, OANDNOT, OSUB, OMUL, OADD, OOR, OXOR, OLSH, ORSH:
|
||||||
n.Left = walkexpr(n.Left, init)
|
n.Left = walkexpr(n.Left, init)
|
||||||
n.Right = walkexpr(n.Right, init)
|
n.Right = walkexpr(n.Right, init)
|
||||||
|
|
||||||
@ -965,14 +965,6 @@ opswitch:
|
|||||||
fn := basicnames[param] + "to" + basicnames[result]
|
fn := basicnames[param] + "to" + basicnames[result]
|
||||||
n = conv(mkcall(fn, types.Types[result], init, conv(n.Left, types.Types[param])), n.Type)
|
n = conv(mkcall(fn, types.Types[result], init, conv(n.Left, types.Types[param])), n.Type)
|
||||||
|
|
||||||
case OANDNOT:
|
|
||||||
n.Left = walkexpr(n.Left, init)
|
|
||||||
n.Op = OAND
|
|
||||||
n.SetImplicit(true) // for walkCheckPtrArithmetic
|
|
||||||
n.Right = nod(OBITNOT, n.Right, nil)
|
|
||||||
n.Right = typecheck(n.Right, ctxExpr)
|
|
||||||
n.Right = walkexpr(n.Right, init)
|
|
||||||
|
|
||||||
case ODIV, OMOD:
|
case ODIV, OMOD:
|
||||||
n.Left = walkexpr(n.Left, init)
|
n.Left = walkexpr(n.Left, init)
|
||||||
n.Right = walkexpr(n.Right, init)
|
n.Right = walkexpr(n.Right, init)
|
||||||
@ -3609,14 +3601,20 @@ func bounded(n *Node, max int64) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch n.Op {
|
switch n.Op {
|
||||||
case OAND:
|
case OAND, OANDNOT:
|
||||||
v := int64(-1)
|
v := int64(-1)
|
||||||
if smallintconst(n.Left) {
|
switch {
|
||||||
|
case smallintconst(n.Left):
|
||||||
v = n.Left.Int64Val()
|
v = n.Left.Int64Val()
|
||||||
} else if smallintconst(n.Right) {
|
case smallintconst(n.Right):
|
||||||
v = n.Right.Int64Val()
|
v = n.Right.Int64Val()
|
||||||
|
if n.Op == OANDNOT {
|
||||||
|
v = ^v
|
||||||
|
if !sign {
|
||||||
|
v &= 1<<uint(bits) - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if 0 <= v && v < max {
|
if 0 <= v && v < max {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -4045,12 +4043,8 @@ func walkCheckPtrArithmetic(n *Node, init *Nodes) *Node {
|
|||||||
case OADD:
|
case OADD:
|
||||||
walk(n.Left)
|
walk(n.Left)
|
||||||
walk(n.Right)
|
walk(n.Right)
|
||||||
case OSUB:
|
case OSUB, OANDNOT:
|
||||||
walk(n.Left)
|
walk(n.Left)
|
||||||
case OAND:
|
|
||||||
if n.Implicit() { // was OANDNOT
|
|
||||||
walk(n.Left)
|
|
||||||
}
|
|
||||||
case OCONVNOP:
|
case OCONVNOP:
|
||||||
if n.Left.Type.IsUnsafePtr() {
|
if n.Left.Type.IsUnsafePtr() {
|
||||||
n.Left = cheapexpr(n.Left, init)
|
n.Left = cheapexpr(n.Left, init)
|
||||||
|
@ -209,6 +209,11 @@ func main() {
|
|||||||
use(a1k[i&^0])
|
use(a1k[i&^0])
|
||||||
use(a1k[i&^-2]) // ERROR "index bounds check elided"
|
use(a1k[i&^-2]) // ERROR "index bounds check elided"
|
||||||
use(a1k[i&^1])
|
use(a1k[i&^1])
|
||||||
|
use(a1k[i8&^0])
|
||||||
|
use(a1k[i8&^-128]) // ERROR "index bounds check elided"
|
||||||
|
use(a1k[ui8&^1]) // ERROR "index bounds check elided"
|
||||||
|
use(a1k[ui16&^0xf000])
|
||||||
|
use(a1k[ui16&^0xff00]) // ERROR "index bounds check elided"
|
||||||
|
|
||||||
// Right shift cuts the effective number of bits in the index,
|
// Right shift cuts the effective number of bits in the index,
|
||||||
// but only for unsigned (signed stays negative).
|
// but only for unsigned (signed stays negative).
|
||||||
|
Loading…
x
Reference in New Issue
Block a user