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)
|
||||
b := s.expr(n.Right)
|
||||
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:
|
||||
a := s.expr(n.Left)
|
||||
b := s.expr(n.Right)
|
||||
|
@ -142,7 +142,7 @@ const (
|
||||
_, _ // second nodeInitorder bit
|
||||
_, nodeHasBreak
|
||||
_, 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
|
||||
_, nodeDiag // already printed error about this
|
||||
_, nodeColas // OAS resulting from :=
|
||||
|
@ -474,7 +474,7 @@ opswitch:
|
||||
ODEREF, OSPTR, OITAB, OIDATA, OADDR:
|
||||
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.Right = walkexpr(n.Right, init)
|
||||
|
||||
@ -965,14 +965,6 @@ opswitch:
|
||||
fn := basicnames[param] + "to" + basicnames[result]
|
||||
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:
|
||||
n.Left = walkexpr(n.Left, init)
|
||||
n.Right = walkexpr(n.Right, init)
|
||||
@ -3609,14 +3601,20 @@ func bounded(n *Node, max int64) bool {
|
||||
}
|
||||
|
||||
switch n.Op {
|
||||
case OAND:
|
||||
case OAND, OANDNOT:
|
||||
v := int64(-1)
|
||||
if smallintconst(n.Left) {
|
||||
switch {
|
||||
case smallintconst(n.Left):
|
||||
v = n.Left.Int64Val()
|
||||
} else if smallintconst(n.Right) {
|
||||
case smallintconst(n.Right):
|
||||
v = n.Right.Int64Val()
|
||||
if n.Op == OANDNOT {
|
||||
v = ^v
|
||||
if !sign {
|
||||
v &= 1<<uint(bits) - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if 0 <= v && v < max {
|
||||
return true
|
||||
}
|
||||
@ -4045,12 +4043,8 @@ func walkCheckPtrArithmetic(n *Node, init *Nodes) *Node {
|
||||
case OADD:
|
||||
walk(n.Left)
|
||||
walk(n.Right)
|
||||
case OSUB:
|
||||
case OSUB, OANDNOT:
|
||||
walk(n.Left)
|
||||
case OAND:
|
||||
if n.Implicit() { // was OANDNOT
|
||||
walk(n.Left)
|
||||
}
|
||||
case OCONVNOP:
|
||||
if n.Left.Type.IsUnsafePtr() {
|
||||
n.Left = cheapexpr(n.Left, init)
|
||||
|
@ -209,6 +209,11 @@ func main() {
|
||||
use(a1k[i&^0])
|
||||
use(a1k[i&^-2]) // ERROR "index bounds check elided"
|
||||
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,
|
||||
// but only for unsigned (signed stays negative).
|
||||
|
Loading…
x
Reference in New Issue
Block a user