golang/go

cmd/compile: internal compiler error: Op...LECall and OpDereference have mismatched mem

ALTree opened this issue · 9 comments

$ gotip version
go version devel go1.18-088bb4bf4a Tue Nov 2 06:25:39 2021 +0000 windows/amd64
package p

func f[G uint]() {
	var a, m []int
	var s struct {
		a, b, c, d, e int
	}

	func(G) {
		_ = a
		_ = m
		_ = s
		func() {
			for i := 0; i < 5; i++ {
				_ = a
				_ = m
				_, _ = s, s
			}
		}()
	}(G(1.0))

	defer func() uint {
		return 0
	}()
}

func g() {
	f[uint]()
}
$ gotip tool compile crash.go

crash.go:22:2: internal compiler error: 'f[%2eshape.uint_0]': Op...LECall and OpDereference have mismatched mem, v26 = StaticLECall <mem> {AuxCall{"".f[%2eshape.uint_0].func1}} [104] v9 v10 v10 v15 v19 v59 and v15 = Dereference <struct { a int; b int; c int; d int; e int }> v14 v13

goroutine 1 [running]:
runtime/debug.Stack()
        D:/users/f65362c/alberto/other/gotip/src/runtime/debug/stack.go:24 +0x65
cmd/compile/internal/base.FatalfAt({0x1a6cc00?, 0x0?}, {0xc00001c910, 0x42}, {0xc0003f7620, 0x3, 0x3})
        D:/users/f65362c/alberto/other/gotip/src/cmd/compile/internal/base/print.go:227 +0x1ca
cmd/compile/internal/base.Fatalf(...)
        D:/users/f65362c/alberto/other/gotip/src/cmd/compile/internal/base/print.go:196
cmd/compile/internal/ssagen.(*ssafn).Fatalf(0x8?, {0x8e70108?, 0x2ad?}, {0x1b161bb, 0x3c}, {0xc0003c9e20, 0x2, 0x0?})
        D:/users/f65362c/alberto/other/gotip/src/cmd/compile/internal/ssagen/ssa.go:7650 +0x17d
cmd/compile/internal/ssa.(*Func).Fatalf(0xc0004061c0, {0x1b161bb, 0x3c}, {0xc0003c9e20, 0x2, 0x2})
        D:/users/f65362c/alberto/other/gotip/src/cmd/compile/internal/ssa/func.go:773 +0x279
cmd/compile/internal/ssa.(*expandState).rewriteArgs(0xc0000797e8, 0xc000480b60, 0x0)
        D:/users/f65362c/alberto/other/gotip/src/cmd/compile/internal/ssa/expand_calls.go:1099 +0x53e
...

Tentatively labeling as a release blocker since it's a compiler crasher on a valid program with typeparameters.

cc @randall77 @danscales

Looks like there is a vardef/varlive pair that is masking the fact that the two memory args are the same. The expand_calls pass doesn't like that for some reason.

@drchase can you look at this? I don't think it is directly related to generics.

Looks like there is a vardef/varlive pair that is masking the fact that the two memory args are the same. The expand_calls pass doesn't like that for some reason.

@drchase can you look at this? I don't think it is directly related to generics.

Seems right, look at the SSA:

f[go.shape.uint_0] func(uintptr)
  b1: DEAD
    BlockInvalid
  b2: DEAD
    BlockInvalid
  b5: DEAD
    BlockInvalid
  b6: DEAD
    BlockInvalid
  b7:
    (?) v1 = InitMem <mem>
    (?) v2 = SP <uintptr>
    (?) v3 = SB <uintptr>
    (?) v4 = Const8 <uint8> [0]
    (-3) v5 = LocalAddr <*uint8> {.autotmp_10} v2 v1
    (+3) v6 = Store <mem> {uint8} v5 v4 v1
    (-3) v7 = VarLive <mem> {.autotmp_10} v6
    (-3) v9 = Arg <uintptr> {.dict} (.dict[uintptr])
    (-5) v11 = VarDef <mem> {s} v7
    (5) v12 = LocalAddr <*struct { a int; b int; c int; d int; e int }> {s} v2 v11
    (+5) v13 = Zero <mem> {struct { a int; b int; c int; d int; e int }} [40] v12 v11
    (21) v14 = LocalAddr <*struct { a int; b int; c int; d int; e int }> {s} v2 v13
    (+21) v15 = Dereference <struct { a int; b int; c int; d int; e int }> v14 v13
    (?) v30 = Const64 <uintptr> [0]
    (?) v35 = Addr <uintptr> {"".f[go.shape.uint_0].func2} v3
    (?) v45 = ConstNil <func() uint>
    (?) v50 = Addr <uintptr> {"".f[go.shape.uint_0].func3} v3
    (?) v58 = VarDef <mem> {.autotmp_11} v13
    (?) v59 = VarLive <mem> {.autotmp_11} v58
    (?) v60 = LocalAddr <*func()> {.autotmp_11} v2 v59
    (?) v72 = ConstNil <*int> (a.ptr[*int], m.ptr[*int])
    (?) v67 = Const64 <int> [0] (a.cap[int], a.len[int], m.cap[int], m.len[int])
    (21) v19 = Const64 <go.shape.uint_0> [1]
    (23) v64 = Const8 <uint8> [1]
    (?) v54 = Const64 <int64> [0] DEAD
    (-3) v51 = ArgIntReg <uintptr> {.dict+0} [0] DEAD
    (?) v10 = SliceMake <[]int> v72 v67 v67
    (21) v26 = StaticLECall <mem> {AuxCall{"".f[go.shape.uint_0].func1}} [104] v9 v10 v10 v15 v19 v59

The mismatch between v59 (is the m0) and v13 (is the a.MemoryArg()) causes the ICE. We do elide the VarDef for results, but not for args.

Can we add this code right after L1084 to find the correct m0?

	for m0.Op == OpVarLive || m0.Op == OpVarDef {
		m0 = m0.MemoryArg()
	}

I found the cause of the problem: Before the pass of insert phi, the mem chain of the StaticLECall args in the first block is broken by the vardef/varlive pair inserted by openDeferRecord, trying to fix it.

Change https://golang.org/cl/361410 mentions this issue: cmd/compile: avoid adding LECall to the entry block when has opendefers

FYI, a no-generics reproducer:

package p

//go:noinline
func g(d uintptr, a, m []int, s struct {
	a, b, c, d, e int
}, u uint) {
	_ = a
	_ = m
	_ = s
	func() {
		for i := 0; i < 5; i++ {
			_ = a
			_ = m
			_, _ = s, s
		}
	}()
}

var One float64 = 1.0

func f(d uintptr) {
	var a, m []int
	var s struct {
		a, b, c, d, e int
	}

	g(d, a, m, s, uint(One)) // Uint of not-a-constant inserts a conditional, necessary to bug

	defer func() uint {
		return 0
	}()
}

var d uintptr

func h() {
	f(d)
}

which also fails in 1.16

FYI, a no-generics reproducer:

package p

//go:noinline
func g(d uintptr, a, m []int, s struct {
	a, b, c, d, e int
}, u uint) {
	_ = a
	_ = m
	_ = s
	func() {
		for i := 0; i < 5; i++ {
			_ = a
			_ = m
			_, _ = s, s
		}
	}()
}

var One float64 = 1.0

func f(d uintptr) {
	var a, m []int
	var s struct {
		a, b, c, d, e int
	}

	g(d, a, m, s, uint(One)) // Uint of not-a-constant inserts a conditional, necessary to bug

	defer func() uint {
		return 0
	}()
}

var d uintptr

func h() {
	f(d)
}

Thanks for the the non-generic reproducer, i will use your code to replace the test.

@gopherbot Please open backport to 1.16 and 1.17

Backport issue(s) opened: #49412 (for 1.16), #49413 (for 1.17).

Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://golang.org/wiki/MinorReleases.