RISC-V: vsetvl: elide abnormal edges from LCM computations [PR119533]

vsetvl phase4 uses LCM guided info to insert VSETVL insns, including a
straggler loop for "mising vsetvls" on certain edges. Currently it
asserts on encountering EDGE_ABNORMAL.

When enabling go frontend with V enabled, libgo build hits the assert.

The solution is to prevent abnormal edges from getting into LCM at all
(my prior attempt at this just ignored them after LCM which is not
right). Existing invalid_opt_bb_p () current does this for BB predecessors
but not for successors which is what the patch adds.

Crucially, the ICE/fix also depends on avoiding vsetvl hoisting past
non-transparent blocks: That is taken care of by Robin's patch
"RISC-V: Do not lift up vsetvl into non-transparent blocks [PR119547]"
for a different yet related issue.

Reported-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
Signed-off-by: Vineet Gupta <vineetg@rivosinc.com>

	PR target/119533

gcc/ChangeLog:

	* config/riscv/riscv-vsetvl.cc (invalid_opt_bb_p): Check for
	EDGE_ABNOMAL.
	(pre_vsetvl::compute_lcm_local_properties): Initialize kill
	bitmap.
	Debug dump skipped edge.

gcc/testsuite/ChangeLog:

	* go.dg/pr119533-riscv.go: New test.
	* go.dg/pr119533-riscv-2.go: New test.
This commit is contained in:
Vineet Gupta 2025-04-15 09:29:08 -07:00
parent 517f7e3f02
commit edb4867412
3 changed files with 168 additions and 1 deletions

View file

@ -685,7 +685,7 @@ invalid_opt_bb_p (basic_block cfg_bb)
/* We only do LCM optimizations on blocks that are post dominated by
EXIT block, that is, we don't do LCM optimizations on infinite loop. */
FOR_EACH_EDGE (e, ei, cfg_bb->succs)
if (e->flags & EDGE_FAKE)
if ((e->flags & EDGE_FAKE) || (e->flags & EDGE_ABNORMAL))
return true;
return false;
@ -2698,6 +2698,7 @@ pre_vsetvl::compute_lcm_local_properties ()
m_avout = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), num_exprs);
bitmap_vector_clear (m_avloc, last_basic_block_for_fn (cfun));
bitmap_vector_clear (m_kill, last_basic_block_for_fn (cfun));
bitmap_vector_clear (m_antloc, last_basic_block_for_fn (cfun));
bitmap_vector_ones (m_transp, last_basic_block_for_fn (cfun));
@ -2749,6 +2750,10 @@ pre_vsetvl::compute_lcm_local_properties ()
if (invalid_opt_bb_p (bb->cfg_bb ()))
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "\n --- skipping bb %u due to weird edge",
bb->index ());
bitmap_clear (m_antloc[bb_index]);
bitmap_clear (m_transp[bb_index]);
}

View file

@ -0,0 +1,42 @@
// { dg-do compile { target riscv64*-*-* } }
// { dg-options "-O2 -march=rv64gcv -mabi=lp64d" }
package ast
type as struct {
bt []struct{}
an string
}
func bj(a *as) string {
if b := a.bt; len(a.an) == 1 {
_ = b[0]
}
return a.an
}
func MergePackageFiles(f map[string][]interface{}, g uint) []interface{} {
bl := make([]string, len(f))
var bo []interface{}
bu := make(map[string]int)
for _, bm := range bl {
a := f[bm]
for _, d := range a {
if g != 0 {
if a, p := d.(*as); p {
n := bj(a)
if j, bp := bu[n]; bp {
_ = j
}
}
}
}
}
for _, bm := range bl {
_ = bm
}
for _, bm := range bl {
_ = f[bm]
}
return bo
}

View file

@ -0,0 +1,120 @@
// { dg-do compile { target riscv64*-*-* } }
// { dg-options "-O2 -march=rv64gcv -mabi=lp64d" }
// Reduced from libgo build (multi-file reduction, merged mnaully
// and hand reduced again).
package ast
import (
"go/token"
"go/scanner"
"reflect"
)
type v struct {}
type w func( string, reflect.Value) bool
func x( string, reflect.Value) bool
type r struct {
scanner.ErrorList
}
type ab interface {}
type ae interface {}
type af interface {}
type ag struct {}
func (ag) Pos() token.Pos
func (ag) ah() token.Pos
type c struct {
aj ae }
type ak struct {
al []c }
type (
am struct {
an string }
bs struct {
Value string
}
)
func ao(string) *am
type (
ap interface {}
aq struct {
ar bs }
as struct {
bt ak
an am }
)
type File struct {
*ag
token.Pos
*am
at []af
*v
au []*aq
av *am
aw []*ag }
type ax struct {
an string
*v
ay map[string]File }
func a(az *token.FileSet, b token.Pos) int
type k struct {
l token.Pos
ah token.Pos
}
type m struct {
bb bool
bc *ag
}
type bi uint
func bj(a *as) string {
if b := a.bt; len(b.al) == 1 {
c := b.al[0].aj
if e := c; e != nil {}
}
return a.an.an
}
func MergePackageFiles(f ax, g bi) *File {
h := 0
bk := 0
k := 0
bl := make([]string, len(f.ay))
i := 0
for bm, a := range f.ay {
bl[i] = bm
k += len(a.at)
}
var bn *ag
var l token.Pos
if h > 0 {}
var bo []af
bu := make(map[string]int)
m := 0
for _, bm := range bl {
a := f.ay[bm]
for _, d := range a.at {
if g!= 0 {
if a, p := d.(*as); p {
n := bj(a)
if j, bp := bu[n]; bp {
if bo != nil && bo[j]== nil {}
}
}
}
}
}
if m > 0 {}
var bq []*aq
q := make(map[string]bool)
for _, bm := range bl {
a := f.ay[bm]
for _, br := range a.au {
if o := br.ar.Value; q[o] {}
}
}
var bh = make([]*ag, bk)
for _, bm := range bl {
a := f.ay[bm]
copy(bh, a.aw)
}
return &File{bn, l, ao(f.an), bo, f.v, bq, nil, bh}
}