From 084c0f849467d5e45b7242cda3dd957352e86b8f Mon Sep 17 00:00:00 2001 From: Michael Munday Date: Wed, 6 Aug 2025 22:43:05 +0100 Subject: [PATCH] cmd/compile: allow InlMark operations to be speculatively executed Although InlMark takes a memory argument it ultimately becomes a NOP and therefore is safe to speculatively execute. Fixes #74915 Change-Id: I64317dd433e300ac28de2bcf201845083ec2ac82 Reviewed-on: https://go-review.googlesource.com/c/go/+/693795 LUCI-TryBot-Result: Go LUCI Reviewed-by: Keith Randall Reviewed-by: Keith Randall Reviewed-by: Dmitri Shuralyov --- src/cmd/compile/internal/ssa/branchelim.go | 11 +++++++++-- test/codegen/fuse.go | 21 +++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/ssa/branchelim.go b/src/cmd/compile/internal/ssa/branchelim.go index f16959dd57..a7d339cad0 100644 --- a/src/cmd/compile/internal/ssa/branchelim.go +++ b/src/cmd/compile/internal/ssa/branchelim.go @@ -436,8 +436,15 @@ func canSpeculativelyExecute(b *Block) bool { // don't fuse memory ops, Phi ops, divides (can panic), // or anything else with side-effects for _, v := range b.Values { - if v.Op == OpPhi || isDivMod(v.Op) || isPtrArithmetic(v.Op) || v.Type.IsMemory() || - v.MemoryArg() != nil || opcodeTable[v.Op].hasSideEffects { + if v.Op == OpPhi || isDivMod(v.Op) || isPtrArithmetic(v.Op) || + v.Type.IsMemory() || opcodeTable[v.Op].hasSideEffects { + return false + } + + // Allow inlining markers to be speculatively executed + // even though they have a memory argument. + // See issue #74915. + if v.Op != OpInlMark && v.MemoryArg() != nil { return false } } diff --git a/test/codegen/fuse.go b/test/codegen/fuse.go index 79dd337dee..8d6ea3c5c7 100644 --- a/test/codegen/fuse.go +++ b/test/codegen/fuse.go @@ -195,3 +195,24 @@ func ui4d(c <-chan uint8) { for x := <-c; x < 126 || x >= 128; x = <-c { } } + +// ------------------------------------ // +// regressions // +// ------------------------------------ // + +func gte4(x uint64) bool { + return x >= 4 +} + +func lt20(x uint64) bool { + return x < 20 +} + +func issue74915(c <-chan uint64) { + // Check that the optimization is not blocked by function inlining. + + // amd64:"CMPQ\t.+, [$]16","ADDQ\t[$]-4," + // s390x:"CLGIJ\t[$]4, R[0-9]+, [$]16","ADD\t[$]-4," + for x := <-c; gte4(x) && lt20(x); x = <-c { + } +} -- 2.51.0