mirror of
https://github.com/golang/go
synced 2024-10-06 08:00:07 +00:00
cmd/compile: remove duplicate nilchecks
Mark nil check operations as faulting if their arg is zero. This lets the late nilcheck pass remove duplicates. Fixes #17242. Change-Id: I4c9938d8a5a1e43edd85b4a66f0b34004860bcd9 Reviewed-on: https://go-review.googlesource.com/29952 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
ba94dd3438
commit
98938189a1
|
@ -439,7 +439,7 @@ func init() {
|
||||||
// use of DX (the closure pointer)
|
// use of DX (the closure pointer)
|
||||||
{name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("DX")}}},
|
{name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("DX")}}},
|
||||||
//arg0=ptr,arg1=mem, returns void. Faults if ptr is nil.
|
//arg0=ptr,arg1=mem, returns void. Faults if ptr is nil.
|
||||||
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpsp}}, clobberFlags: true, nilCheck: true},
|
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpsp}}, clobberFlags: true, nilCheck: true, faultOnNilArg0: true},
|
||||||
|
|
||||||
// MOVLconvert converts between pointers and integers.
|
// MOVLconvert converts between pointers and integers.
|
||||||
// We have a special op for this so as to not confuse GC
|
// We have a special op for this so as to not confuse GC
|
||||||
|
|
|
@ -486,7 +486,7 @@ func init() {
|
||||||
// use of DX (the closure pointer)
|
// use of DX (the closure pointer)
|
||||||
{name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("DX")}}},
|
{name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("DX")}}},
|
||||||
//arg0=ptr,arg1=mem, returns void. Faults if ptr is nil.
|
//arg0=ptr,arg1=mem, returns void. Faults if ptr is nil.
|
||||||
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpsp}}, clobberFlags: true, nilCheck: true},
|
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpsp}}, clobberFlags: true, nilCheck: true, faultOnNilArg0: true},
|
||||||
|
|
||||||
// MOVQconvert converts between pointers and integers.
|
// MOVQconvert converts between pointers and integers.
|
||||||
// We have a special op for this so as to not confuse GC
|
// We have a special op for this so as to not confuse GC
|
||||||
|
|
|
@ -325,7 +325,7 @@ func init() {
|
||||||
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||||
|
|
||||||
// pseudo-ops
|
// pseudo-ops
|
||||||
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true}, // panic if arg0 is nil. arg1=mem.
|
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true, faultOnNilArg0: true}, // panic if arg0 is nil. arg1=mem.
|
||||||
|
|
||||||
{name: "Equal", argLength: 1, reg: readflags}, // bool, true flags encode x==y false otherwise.
|
{name: "Equal", argLength: 1, reg: readflags}, // bool, true flags encode x==y false otherwise.
|
||||||
{name: "NotEqual", argLength: 1, reg: readflags}, // bool, true flags encode x!=y false otherwise.
|
{name: "NotEqual", argLength: 1, reg: readflags}, // bool, true flags encode x!=y false otherwise.
|
||||||
|
|
|
@ -381,7 +381,7 @@ func init() {
|
||||||
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
{name: "CALLinter", argLength: 2, reg: regInfo{inputs: []regMask{gp}, clobbers: callerSave}, aux: "Int64", clobberFlags: true, call: true}, // call fn by pointer. arg0=codeptr, arg1=mem, auxint=argsize, returns mem
|
||||||
|
|
||||||
// pseudo-ops
|
// pseudo-ops
|
||||||
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true}, // panic if arg0 is nil. arg1=mem.
|
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true, faultOnNilArg0: true}, // panic if arg0 is nil. arg1=mem.
|
||||||
|
|
||||||
{name: "Equal", argLength: 1, reg: readflags}, // bool, true flags encode x==y false otherwise.
|
{name: "Equal", argLength: 1, reg: readflags}, // bool, true flags encode x==y false otherwise.
|
||||||
{name: "NotEqual", argLength: 1, reg: readflags}, // bool, true flags encode x!=y false otherwise.
|
{name: "NotEqual", argLength: 1, reg: readflags}, // bool, true flags encode x!=y false otherwise.
|
||||||
|
|
|
@ -336,7 +336,7 @@ func init() {
|
||||||
},
|
},
|
||||||
|
|
||||||
// pseudo-ops
|
// pseudo-ops
|
||||||
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true}, // panic if arg0 is nil. arg1=mem.
|
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpg}}, nilCheck: true, faultOnNilArg0: true}, // panic if arg0 is nil. arg1=mem.
|
||||||
|
|
||||||
{name: "FPFlagTrue", argLength: 1, reg: readflags}, // bool, true if FP flag is true
|
{name: "FPFlagTrue", argLength: 1, reg: readflags}, // bool, true if FP flag is true
|
||||||
{name: "FPFlagFalse", argLength: 1, reg: readflags}, // bool, true if FP flag is false
|
{name: "FPFlagFalse", argLength: 1, reg: readflags}, // bool, true if FP flag is false
|
||||||
|
|
|
@ -288,7 +288,7 @@ func init() {
|
||||||
{name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{ctxt}}},
|
{name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{ctxt}}},
|
||||||
|
|
||||||
//arg0=ptr,arg1=mem, returns void. Faults if ptr is nil.
|
//arg0=ptr,arg1=mem, returns void. Faults if ptr is nil.
|
||||||
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gp | sp | sb}, clobbers: tmp}, clobberFlags: true, nilCheck: true},
|
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gp | sp | sb}, clobbers: tmp}, clobberFlags: true, nilCheck: true, faultOnNilArg0: true},
|
||||||
|
|
||||||
// Convert pointer to integer, takes a memory operand for ordering.
|
// Convert pointer to integer, takes a memory operand for ordering.
|
||||||
{name: "MOVDconvert", argLength: 2, reg: gp11, asm: "MOVD"},
|
{name: "MOVDconvert", argLength: 2, reg: gp11, asm: "MOVD"},
|
||||||
|
|
|
@ -370,7 +370,7 @@ func init() {
|
||||||
// use of R12 (the closure pointer)
|
// use of R12 (the closure pointer)
|
||||||
{name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("R12")}}},
|
{name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("R12")}}},
|
||||||
// arg0=ptr,arg1=mem, returns void. Faults if ptr is nil.
|
// arg0=ptr,arg1=mem, returns void. Faults if ptr is nil.
|
||||||
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{ptrsp}}, clobberFlags: true, nilCheck: true},
|
{name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{ptrsp}}, clobberFlags: true, nilCheck: true, faultOnNilArg0: true},
|
||||||
|
|
||||||
// MOVDconvert converts between pointers and integers.
|
// MOVDconvert converts between pointers and integers.
|
||||||
// We have a special op for this so as to not confuse GC
|
// We have a special op for this so as to not confuse GC
|
||||||
|
|
|
@ -4027,6 +4027,7 @@ var opcodeTable = [...]opInfo{
|
||||||
argLen: 2,
|
argLen: 2,
|
||||||
clobberFlags: true,
|
clobberFlags: true,
|
||||||
nilCheck: true,
|
nilCheck: true,
|
||||||
|
faultOnNilArg0: true,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 255}, // AX CX DX BX SP BP SI DI
|
{0, 255}, // AX CX DX BX SP BP SI DI
|
||||||
|
@ -6996,6 +6997,7 @@ var opcodeTable = [...]opInfo{
|
||||||
argLen: 2,
|
argLen: 2,
|
||||||
clobberFlags: true,
|
clobberFlags: true,
|
||||||
nilCheck: true,
|
nilCheck: true,
|
||||||
|
faultOnNilArg0: true,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 65535}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
{0, 65535}, // AX CX DX BX SP BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
|
||||||
|
@ -10084,6 +10086,7 @@ var opcodeTable = [...]opInfo{
|
||||||
name: "LoweredNilCheck",
|
name: "LoweredNilCheck",
|
||||||
argLen: 2,
|
argLen: 2,
|
||||||
nilCheck: true,
|
nilCheck: true,
|
||||||
|
faultOnNilArg0: true,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
|
{0, 6143}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 g R12
|
||||||
|
@ -12203,6 +12206,7 @@ var opcodeTable = [...]opInfo{
|
||||||
name: "LoweredNilCheck",
|
name: "LoweredNilCheck",
|
||||||
argLen: 2,
|
argLen: 2,
|
||||||
nilCheck: true,
|
nilCheck: true,
|
||||||
|
faultOnNilArg0: true,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 268173311}, // 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 g
|
{0, 268173311}, // 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 g
|
||||||
|
@ -13820,6 +13824,7 @@ var opcodeTable = [...]opInfo{
|
||||||
name: "LoweredNilCheck",
|
name: "LoweredNilCheck",
|
||||||
argLen: 2,
|
argLen: 2,
|
||||||
nilCheck: true,
|
nilCheck: true,
|
||||||
|
faultOnNilArg0: true,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 100663294}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g
|
{0, 100663294}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 g
|
||||||
|
@ -15199,6 +15204,7 @@ var opcodeTable = [...]opInfo{
|
||||||
argLen: 2,
|
argLen: 2,
|
||||||
clobberFlags: true,
|
clobberFlags: true,
|
||||||
nilCheck: true,
|
nilCheck: true,
|
||||||
|
faultOnNilArg0: true,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
{0, 1073733630}, // SP SB R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R16 R17 R18 R19 R20 R21 R22 R23 R24 R25 R26 R27 R28 R29
|
||||||
|
@ -17515,6 +17521,7 @@ var opcodeTable = [...]opInfo{
|
||||||
argLen: 2,
|
argLen: 2,
|
||||||
clobberFlags: true,
|
clobberFlags: true,
|
||||||
nilCheck: true,
|
nilCheck: true,
|
||||||
|
faultOnNilArg0: true,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 37886}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP
|
{0, 37886}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 SP
|
||||||
|
|
|
@ -233,3 +233,17 @@ func c1() {
|
||||||
var x Struct
|
var x Struct
|
||||||
func() { x.m() }() // ERROR "removed nil check"
|
func() { x.m() }() // ERROR "removed nil check"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SS struct {
|
||||||
|
x byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type TT struct {
|
||||||
|
SS
|
||||||
|
}
|
||||||
|
|
||||||
|
func f(t *TT) *byte {
|
||||||
|
// See issue 17242.
|
||||||
|
s := &t.SS // ERROR "removed nil check"
|
||||||
|
return &s.x // ERROR "generated nil check"
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue