Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/compile: internal compiler error: can't find source for b12->b4: v31 = MOVBload <bool> v14 v1 : DX #49122

Closed
ALTree opened this issue Oct 22, 2021 · 10 comments
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done. release-blocker
Milestone

Comments

@ALTree
Copy link
Member

ALTree commented Oct 22, 2021

$ gotip version
go version devel go1.18-ff8115d1a1 Fri Oct 22 14:05:31 2021 +0000 linux/amd64
package p

var B []bool
var N int

func f(p bool, m map[bool]bool) bool {
	var q bool
	_ = p || N&N < N || B[0] || B[0]
	return p && q && m[q]
}
$ gotip build crash.go
# command-line-arguments
./crash.go:8:8: internal compiler error: 'f': can't find source for b12->b4: v31 = MOVBload <bool> v14 v1 : DX

goroutine 8 [running]:
runtime/debug.Stack()
	/home/alberto/go/src/runtime/debug/stack.go:24 +0x65
cmd/compile/internal/base.FatalfAt({0xc63880, 0x0}, {0xc0000e4120, 0x27}, {0xc0000a4300, 0x4, 0x4})
	/home/alberto/go/src/cmd/compile/internal/base/print.go:227 +0x1ca
cmd/compile/internal/base.Fatalf(...)
	/home/alberto/go/src/cmd/compile/internal/base/print.go:196
cmd/compile/internal/ssagen.(*ssafn).Fatalf(0x8, {0x21f015b8, 0x7fa5}, {0xcfa986, 0x21}, {0xc0005d2ab0, 0x3, 0x0})
	/home/alberto/go/src/cmd/compile/internal/ssagen/ssa.go:7621 +0x17d
cmd/compile/internal/ssa.(*Func).Fatalf(0xc0005e2000, {0xcfa986, 0x21}, {0xc0005d2ab0, 0x3, 0x3})
	/home/alberto/go/src/cmd/compile/internal/ssa/func.go:773 +0x279
cmd/compile/internal/ssa.(*edgeState).processDest(0xc0000cf280, {0xe3e720, 0x1275c00}, 0x1f, 0xc0004ce660, {0x2, 0x0})
	/home/alberto/go/src/cmd/compile/internal/ssa/regalloc.go:2267 +0x99b
...

The program compiles fine in Go1.17.

git bisect points to ed647b1. I'm tentatively labeling this as a release blocker since it's a compiler crasher on a valid program introduced during the current development cycle.

cc @mdempsky
cc @randall77 @dr2chase for regalloc.

@ALTree ALTree added NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. release-blocker labels Oct 22, 2021
@ALTree ALTree added this to the Go1.18 milestone Oct 22, 2021
@cuonglm
Copy link
Member

cuonglm commented Oct 23, 2021

Pre ed647b1, we use the first autotmp and swap the last to the first position. With order.free["bool"] have [autotmp1 autotmp2 autotmp3], we pick autotmp1, swap autotmp3 to autotmp1 position, order.free["bool"] becomes [autotmp3 autotmp2].

With ed647b1 we changed the order to use the last free autotmp first. With order.free["bool"] have [autotmp1 autotmp2 autotmp3], we pick autotmp3, order.free["bool"] becomes [autotmp1 autotmp2].

If I changed order to always use the first autotmp, and prune it from the free list, that means we pick autotmp1, then free list becomes [autotmp2 autotmp3], the program compile ok, go run run.go passes. But I don't understand the reason yet.

Kindly ask @randall77, since when you added the original approach in https://go-review.googlesource.com/c/go/+/140301/

With this program:

package x

var B []bool
var N int

func f(p bool, m map[bool]bool) bool {
	var q bool
	// _ = p || N&N < N || B[0] || B[0]
	_ = p || N&N < N || B[0] || B[1]
	return p && q && m[q]
}

Checking the diff (full diff below), this one seems interesting:

.   AS tc(1) # p.go:9:19										.   AS tc(1) # p.go:9:19
.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19	.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19
.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8     |	.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 Addrtaken AutoTemp OnStack Used bool tc(1) # p.

So autotmp_6 is marked address taken with the patch, but not with current tip.

Here's the diff with the current tip and my patch to always use the first autotmp
before walk f												before walk f
.   DCL # p.go:7:6											.   DCL # p.go:7:6
.   .   NAME-x.q esc(no) Class:PAUTO Offset:0 OnStack Used bool tc(1) # p.go:7:6			.   .   NAME-x.q esc(no) Class:PAUTO Offset:0 OnStack Used bool tc(1) # p.go:7:6
.   AS tc(1) # p.go:7:6											.   AS tc(1) # p.go:7:6
.   .   NAME-x.q esc(no) Class:PAUTO Offset:0 OnStack Used bool tc(1) # p.go:7:6			.   .   NAME-x.q esc(no) Class:PAUTO Offset:0 OnStack Used bool tc(1) # p.go:7:6
.   AS tc(1) # p.go:9:8											.   AS tc(1) # p.go:9:8
.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8	.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8
.   .   NAME-x.p esc(no) Class:PPARAM Offset:0 OnStack Used bool tc(1) # p.go:6:8			.   .   NAME-x.p esc(no) Class:PPARAM Offset:0 OnStack Used bool tc(1) # p.go:6:8
.   IF # p.go:9:8											.   IF # p.go:9:8
.   IF-Cond												.   IF-Cond
.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8	.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8
.   IF-Else												.   IF-Else
.   .   AS tc(1) # p.go:9:8										.   .   AS tc(1) # p.go:9:8
.   .   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8	.   .   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8
.   .   .   LT bool tc(1) # p.go:9:15									.   .   .   LT bool tc(1) # p.go:9:15
.   .   .   .   AND int tc(1) # p.go:9:12								.   .   .   .   AND int tc(1) # p.go:9:12
.   .   .   .   .   NAME-x.N Class:PEXTERN Offset:0 int tc(1) # p.go:4:5				.   .   .   .   .   NAME-x.N Class:PEXTERN Offset:0 int tc(1) # p.go:4:5
.   .   .   .   .   NAME-x.N Class:PEXTERN Offset:0 int tc(1) # p.go:4:5				.   .   .   .   .   NAME-x.N Class:PEXTERN Offset:0 int tc(1) # p.go:4:5
.   .   .   .   NAME-x.N Class:PEXTERN Offset:0 int tc(1) # p.go:4:5					.   .   .   .   NAME-x.N Class:PEXTERN Offset:0 int tc(1) # p.go:4:5
.   AS tc(1) # p.go:9:19										.   AS tc(1) # p.go:9:19
.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19	.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19
.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8	.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8
.   IF # p.go:9:19											.   IF # p.go:9:19
.   IF-Cond												.   IF-Cond
.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19	.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19
.   IF-Else												.   IF-Else
.   .   AS tc(1) # p.go:9:19										.   .   AS tc(1) # p.go:9:19
.   .   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:1	.   .   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:1
.   .   .   INDEX bool tc(1) # p.go:9:23								.   .   .   INDEX bool tc(1) # p.go:9:23
.   .   .   .   NAME-x.B Class:PEXTERN Offset:0 SLICE-[]bool tc(1) # p.go:3:5				.   .   .   .   NAME-x.B Class:PEXTERN Offset:0 SLICE-[]bool tc(1) # p.go:3:5
.   .   .   .   LITERAL-0 int tc(1) # p.go:9:24								.   .   .   .   LITERAL-0 int tc(1) # p.go:9:24
.   AS tc(1) # p.go:9:27										.   AS tc(1) # p.go:9:27
.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27	.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27
.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19	.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19
.   IF # p.go:9:27											.   IF # p.go:9:27
.   IF-Cond												.   IF-Cond
.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27	.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27
.   IF-Else												.   IF-Else
.   .   AS tc(1) # p.go:9:27										.   .   AS tc(1) # p.go:9:27
.   .   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:2	.   .   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:2
.   .   .   INDEX bool tc(1) # p.go:9:31								.   .   .   INDEX bool tc(1) # p.go:9:31
.   .   .   .   NAME-x.B Class:PEXTERN Offset:0 SLICE-[]bool tc(1) # p.go:3:5				.   .   .   .   NAME-x.B Class:PEXTERN Offset:0 SLICE-[]bool tc(1) # p.go:3:5
.   .   .   .   LITERAL-1 int tc(1) # p.go:9:32								.   .   .   .   LITERAL-1 int tc(1) # p.go:9:32
.   AS tc(1) # p.go:9:4											.   AS tc(1) # p.go:9:4
.   .   NAME-x._ Offset:0 blank tc(1)									.   .   NAME-x._ Offset:0 blank tc(1)
.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27	.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27
.   VARKILL tc(1) # p.go:9:4										.   VARKILL tc(1) # p.go:9:4
.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8	.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8
.   VARKILL tc(1) # p.go:9:4										.   VARKILL tc(1) # p.go:9:4
.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19	.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19
.   VARKILL tc(1) # p.go:9:4										.   VARKILL tc(1) # p.go:9:4
.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27	.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27
.   AS tc(1) # p.go:10:11										.   AS tc(1) # p.go:10:11
.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19	.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19
.   .   NAME-x.p esc(no) Class:PPARAM Offset:0 OnStack Used bool tc(1) # p.go:6:8			.   .   NAME-x.p esc(no) Class:PPARAM Offset:0 OnStack Used bool tc(1) # p.go:6:8
.   IF # p.go:10:11											.   IF # p.go:10:11
.   IF-Cond												.   IF-Cond
.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19	.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19
.   IF-Body												.   IF-Body
.   .   AS tc(1) # p.go:10:11										.   .   AS tc(1) # p.go:10:11
.   .   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:1	.   .   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:1
.   .   .   NAME-x.q esc(no) Class:PAUTO Offset:0 OnStack Used bool tc(1) # p.go:7:6			.   .   .   NAME-x.q esc(no) Class:PAUTO Offset:0 OnStack Used bool tc(1) # p.go:7:6
.   AS tc(1) # p.go:10:16										.   AS tc(1) # p.go:10:16
.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8     |	.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27
.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19	.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19
.   IF # p.go:10:16											.   IF # p.go:10:16
.   IF-Cond												.   IF-Cond
.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8     |	.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27
.   IF-Body												.   IF-Body
.   .   AS tc(1) # p.go:10:20										.   .   AS tc(1) # p.go:10:20
.   .   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:2 |	.   .   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8
.   .   .   NAME-x.q esc(no) Class:PAUTO Offset:0 OnStack Used bool tc(1) # p.go:7:6			.   .   .   NAME-x.q esc(no) Class:PAUTO Offset:0 OnStack Used bool tc(1) # p.go:7:6
.   .   AS tc(1) # p.go:10:16										.   .   AS tc(1) # p.go:10:16
.   .   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8 |	.   .   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:2
.   .   .   INDEXMAP bool tc(1) # p.go:10:20								.   .   .   INDEXMAP bool tc(1) # p.go:10:20
.   .   .   .   NAME-x.m esc(no) Class:PPARAM Offset:0 OnStack MAP-map[bool]bool tc(1) # p.go:6:16	.   .   .   .   NAME-x.m esc(no) Class:PPARAM Offset:0 OnStack MAP-map[bool]bool tc(1) # p.go:6:16
.   .   .   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go |	.   .   .   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go
.   .   VARKILL tc(1) # p.go:10:16									.   .   VARKILL tc(1) # p.go:10:16
.   .   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:2 |	.   .   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8
.   RETURN tc(1) # p.go:10:2										.   RETURN tc(1) # p.go:10:2
.   RETURN-Results											.   RETURN-Results
.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8     |	.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27
.   VARKILL tc(1) # p.go:3:5										.   VARKILL tc(1) # p.go:3:5
.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19	.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19
.   VARKILL tc(1) # p.go:3:5										.   VARKILL tc(1) # p.go:3:5
.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8     |	.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27
after walk f												after walk f
.   DCL # p.go:7:6											.   DCL # p.go:7:6
.   .   NAME-x.q esc(no) Class:PAUTO Offset:0 OnStack Used bool tc(1) # p.go:7:6			.   .   NAME-x.q esc(no) Class:PAUTO Offset:0 OnStack Used bool tc(1) # p.go:7:6
.   AS tc(1) # p.go:7:6											.   AS tc(1) # p.go:7:6
.   .   NAME-x.q esc(no) Class:PAUTO Offset:0 OnStack Used bool tc(1) # p.go:7:6			.   .   NAME-x.q esc(no) Class:PAUTO Offset:0 OnStack Used bool tc(1) # p.go:7:6
.   AS tc(1) # p.go:9:8											.   AS tc(1) # p.go:9:8
.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8     |	.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 Addrtaken AutoTemp OnStack Used bool tc(1) # p.
.   .   NAME-x.p esc(no) Class:PPARAM Offset:0 OnStack Used bool tc(1) # p.go:6:8			.   .   NAME-x.p esc(no) Class:PPARAM Offset:0 OnStack Used bool tc(1) # p.go:6:8
.   IF # p.go:9:8											.   IF # p.go:9:8
.   IF-Cond												.   IF-Cond
.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8     |	.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 Addrtaken AutoTemp OnStack Used bool tc(1) # p.
.   IF-Else												.   IF-Else
.   .   AS tc(1) # p.go:9:8										.   .   AS tc(1) # p.go:9:8
.   .   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8 |	.   .   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 Addrtaken AutoTemp OnStack Used bool tc(1)
.   .   .   LT bool tc(1) # p.go:9:15									.   .   .   LT bool tc(1) # p.go:9:15
.   .   .   .   AND int tc(1) # p.go:9:12								.   .   .   .   AND int tc(1) # p.go:9:12
.   .   .   .   .   NAME-x.N Class:PEXTERN Offset:0 int tc(1) # p.go:4:5				.   .   .   .   .   NAME-x.N Class:PEXTERN Offset:0 int tc(1) # p.go:4:5
.   .   .   .   .   NAME-x.N Class:PEXTERN Offset:0 int tc(1) # p.go:4:5				.   .   .   .   .   NAME-x.N Class:PEXTERN Offset:0 int tc(1) # p.go:4:5
.   .   .   .   NAME-x.N Class:PEXTERN Offset:0 int tc(1) # p.go:4:5					.   .   .   .   NAME-x.N Class:PEXTERN Offset:0 int tc(1) # p.go:4:5
.   AS tc(1) # p.go:9:19										.   AS tc(1) # p.go:9:19
.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19	.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19
.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8     |	.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 Addrtaken AutoTemp OnStack Used bool tc(1) # p.
.   IF # p.go:9:19											.   IF # p.go:9:19
.   IF-Cond												.   IF-Cond
.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19	.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19
.   IF-Else												.   IF-Else
.   .   AS tc(1) # p.go:9:19										.   .   AS tc(1) # p.go:9:19
.   .   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:1	.   .   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:1
.   .   .   INDEX bool tc(1) # p.go:9:23								.   .   .   INDEX bool tc(1) # p.go:9:23
.   .   .   .   NAME-x.B Class:PEXTERN Offset:0 SLICE-[]bool tc(1) # p.go:3:5				.   .   .   .   NAME-x.B Class:PEXTERN Offset:0 SLICE-[]bool tc(1) # p.go:3:5
.   .   .   .   LITERAL-0 int tc(1) # p.go:9:24								.   .   .   .   LITERAL-0 int tc(1) # p.go:9:24
.   AS tc(1) # p.go:9:27										.   AS tc(1) # p.go:9:27
.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 Addrtaken AutoTemp OnStack Used bool tc(1) # p. |	.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27
.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19	.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19
.   IF # p.go:9:27											.   IF # p.go:9:27
.   IF-Cond												.   IF-Cond
.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 Addrtaken AutoTemp OnStack Used bool tc(1) # p. |	.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27
.   IF-Else												.   IF-Else
.   .   AS tc(1) # p.go:9:27										.   .   AS tc(1) # p.go:9:27
.   .   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 Addrtaken AutoTemp OnStack Used bool tc(1)  |	.   .   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:2
.   .   .   INDEX bool tc(1) # p.go:9:31								.   .   .   INDEX bool tc(1) # p.go:9:31
.   .   .   .   NAME-x.B Class:PEXTERN Offset:0 SLICE-[]bool tc(1) # p.go:3:5				.   .   .   .   NAME-x.B Class:PEXTERN Offset:0 SLICE-[]bool tc(1) # p.go:3:5
.   .   .   .   LITERAL-1 int tc(1) # p.go:9:32								.   .   .   .   LITERAL-1 int tc(1) # p.go:9:32
.   AS tc(1) # p.go:9:4											.   AS tc(1) # p.go:9:4
.   .   NAME-x._ Offset:0 blank tc(1)									.   .   NAME-x._ Offset:0 blank tc(1)
.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 Addrtaken AutoTemp OnStack Used bool tc(1) # p. |	.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27
.   VARKILL tc(1) # p.go:9:4										.   VARKILL tc(1) # p.go:9:4
.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8     |	.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 Addrtaken AutoTemp OnStack Used bool tc(1) # p.
.   VARKILL tc(1) # p.go:9:4										.   VARKILL tc(1) # p.go:9:4
.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19	.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19
.   VARKILL tc(1) # p.go:9:4										.   VARKILL tc(1) # p.go:9:4
.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 Addrtaken AutoTemp OnStack Used bool tc(1) # p. |	.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27
.   AS tc(1) # p.go:10:11										.   AS tc(1) # p.go:10:11
.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19	.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19
.   .   NAME-x.p esc(no) Class:PPARAM Offset:0 OnStack Used bool tc(1) # p.go:6:8			.   .   NAME-x.p esc(no) Class:PPARAM Offset:0 OnStack Used bool tc(1) # p.go:6:8
.   IF # p.go:10:11											.   IF # p.go:10:11
.   IF-Cond												.   IF-Cond
.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19	.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19
.   IF-Body												.   IF-Body
.   .   AS tc(1) # p.go:10:11										.   .   AS tc(1) # p.go:10:11
.   .   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:1	.   .   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:1
.   .   .   NAME-x.q esc(no) Class:PAUTO Offset:0 OnStack Used bool tc(1) # p.go:7:6			.   .   .   NAME-x.q esc(no) Class:PAUTO Offset:0 OnStack Used bool tc(1) # p.go:7:6
.   AS tc(1) # p.go:10:16										.   AS tc(1) # p.go:10:16
.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8     |	.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27
.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19	.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19
.   IF # p.go:10:16											.   IF # p.go:10:16
.   IF-Cond												.   IF-Cond
.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8     |	.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27
.   IF-Body												.   IF-Body
.   .   AS tc(1) # p.go:10:20										.   .   AS tc(1) # p.go:10:20
.   .   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 Addrtaken AutoTemp OnStack Used bool tc(1)  |	.   .   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 Addrtaken AutoTemp OnStack Used bool tc(1)
.   .   .   NAME-x.q esc(no) Class:PAUTO Offset:0 OnStack Used bool tc(1) # p.go:7:6			.   .   .   NAME-x.q esc(no) Class:PAUTO Offset:0 OnStack Used bool tc(1) # p.go:7:6
.   .   AS tc(1) # p.go:10:16										.   .   AS tc(1) # p.go:10:16
.   .   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8 |	.   .   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:2
.   .   .   DEREF bool tc(1) # p.go:10:20								.   .   .   DEREF bool tc(1) # p.go:10:20
.   .   .   .   CALLFUNC NonNil Walked PTR-*bool tc(1) # p.go:10:20					.   .   .   .   CALLFUNC NonNil Walked PTR-*bool tc(1) # p.go:10:20
.   .   .   .   .   NAME-runtime.mapaccess1 Class:PFUNC Offset:0 Used FUNC-func(*byte, map[bool]bool,	.   .   .   .   .   NAME-runtime.mapaccess1 Class:PFUNC Offset:0 Used FUNC-func(*byte, map[bool]bool,
.   .   .   .   CALLFUNC-Args										.   .   .   .   CALLFUNC-Args
.   .   .   .   .   ADDR PTR-*uint8 tc(1) # p.go:10:20							.   .   .   .   .   ADDR PTR-*uint8 tc(1) # p.go:10:20
.   .   .   .   .   .   LINKSYMOFFSET Offset:0 uint8 tc(1)						.   .   .   .   .   .   LINKSYMOFFSET Offset:0 uint8 tc(1)
.   .   .   .   .   NAME-x.m esc(no) Class:PPARAM Offset:0 OnStack Used MAP-map[bool]bool tc(1) # p.g	.   .   .   .   .   NAME-x.m esc(no) Class:PPARAM Offset:0 OnStack Used MAP-map[bool]bool tc(1) # p.g
.   .   .   .   .   ADDR PTR-*bool tc(1) # p.go:10:20							.   .   .   .   .   ADDR PTR-*bool tc(1) # p.go:10:20
.   .   .   .   .   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 Addrtaken AutoTemp OnStack Used |	.   .   .   .   .   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 Addrtaken AutoTemp OnStack Used
.   .   VARKILL tc(1) # p.go:10:16									.   .   VARKILL tc(1) # p.go:10:16
.   .   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 Addrtaken AutoTemp OnStack Used bool tc(1)  |	.   .   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 Addrtaken AutoTemp OnStack Used bool tc(1)
.   RETURN tc(1) # p.go:10:2										.   RETURN tc(1) # p.go:10:2
.   RETURN-Results											.   RETURN-Results
.   .   AS tc(1) # p.go:10:2										.   .   AS tc(1) # p.go:10:2
.   .   .   NAME-x.~r0 esc(no) Class:PPARAMOUT Offset:0 OnStack bool tc(1) # p.go:6:33			.   .   .   NAME-x.~r0 esc(no) Class:PPARAMOUT Offset:0 OnStack bool tc(1) # p.go:6:33
.   .   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8 |	.   .   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:2
.   VARKILL tc(1) # p.go:3:5										.   VARKILL tc(1) # p.go:3:5
.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19	.   .   NAME-x..autotmp_5 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:19
.   VARKILL tc(1) # p.go:3:5										.   VARKILL tc(1) # p.go:3:5
.   .   NAME-x..autotmp_6 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:8     |	.   .   NAME-x..autotmp_4 esc(N) Class:PAUTO Offset:0 AutoTemp OnStack Used bool tc(1) # p.go:9:27

before walk init before walk init
after walk init after walk init after walk init

@gopherbot
Copy link

Change https://golang.org/cl/357961 mentions this issue: cmd/compile: always use first autotmp from free list

@randall77
Copy link
Contributor

I don't think the autotmp ordering thing is the problem, it just tickles the compiler in the right way to hit an existing bug.

It looks to me like this is a problem with the late fuse pass. Before the pass, I see:

b4: ← b2 b6 b1-
v32 (8) = Phi <bool> v66 v31 v66

After that pass, I see:

b4: ← b1 b6-
v32 (8) = Phi <bool> v31 v66

Note that v31 was the input coming from b6, but now it is coming from b1. That's not right, as v31 is computed in b6. When this gets to regalloc, it gets mightily confused.

If you run with -d=ssa/check/on, it dies with a report:

/Users/khr/gowork/issue49122.go:8:8: internal compiler error: 'f': arg 0 of value v32 = Phi <bool> v31 v60 does not dominate, arg=v31 = Load <bool> v14 v1

@erifan who touched fuse last and might have some ideas.
(That last touch made it into 1.17, so not clear if those last changes had anything to do with it.)

@cuonglm
Copy link
Member

cuonglm commented Oct 23, 2021

So it's likely that 92d1afe is the culprit. I can compile the program after reverting it.

@randall77
Copy link
Contributor

Yeah, I found the bug. In fuse_branchredirect.go, when we get to doing CFG surgery, we do

b.removePred(k)
for _, v := range b.Values {
    v.removeArg(k)
}

But removePred and removeArg do different things. removePred moves the last predecessor to index k, whereas removeArg slides all the args k or greater down by 1 index.

Kind of unfortunate different behavior in things named similarly.

@cuonglm
Copy link
Member

cuonglm commented Oct 23, 2021

Yeah, I found the bug. In fuse_branchredirect.go, when we get to doing CFG surgery, we do

b.removePred(k)
for _, v := range b.Values {
    v.removeArg(k)
}

But removePred and removeArg do different things. removePred moves the last predecessor to index k, whereas removeArg slides all the args k or greater down by 1 index.

Kind of unfortunate different behavior in things named similarly.

Huh, tricky. Seems that all we need to do is:

n := len(b.Preds)
v.Args[i].Uses--
v.Args[i] = v.Args[n]
v.Args[n] = nil
v.Args = v.Args[:n]

instead of v.removeArg(k).

@randall77
Copy link
Contributor

Yep.

@gopherbot
Copy link

Change https://golang.org/cl/358117 mentions this issue: cmd/compile: fix fuse pass to do CFG surgery correctly

@randall77
Copy link
Contributor

@gopherbot please open a backport issue for 1.17.

@gopherbot
Copy link

Backport issue(s) opened: #49129 (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.

@dmitshur dmitshur added NeedsFix The path to resolution is known, but the work has not been done. and removed NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels Oct 27, 2021
@golang golang locked and limited conversation to collaborators Oct 27, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done. release-blocker
Projects
None yet
Development

No branches or pull requests

5 participants