On 22/06/2026 09:41, Richard Biener wrote:
On Fri, Jun 19, 2026 at 4:54 PM Christopher Bazley <[email protected]> wrote:
On 17/06/2026 08:47, Richard Biener wrote:
On Tue, Jun 16, 2026 at 5:52 PM Christopher Bazley <[email protected]> wrote:
Hi Richard,
On 09/06/2026 10:40, Richard Biener wrote:
On Wed, Jun 3, 2026 at 5:21 PM Christopher Bazley <[email protected]> wrote:
@@ -8075,7 +8078,12 @@ store_constructor (tree exp, rtx target, int cleared,
poly_int64 size,
similarly non-const type vectors. */
icode = convert_optab_handler (vec_init_optab, mode,
eltmode);
}
-
+ else
+ {
+ /* Handle variable-length vector types. */
+ icode = convert_optab_handler (vec_init_optab, mode, eltmode);
+ const_n_elts = constant_lower_bound (n_elts);
+ }
And here I'd like to see
gcc_assert (icode != CODE_FOR_nothing);
Unfortunately, I cannot make this requested change because it causes the
compiler to crash in an existing test case, even if I restrict the scope
of the assertion to the new 'else' block.
The 'else' block was where I wanted the assert to be, of course.
Reproducer:
make check-gcc RUNTESTFLAGS="aarch64-sve-acle.exp=cops_bool.c"
Variable values:
mode = E_VNx16BImode
eltmode = E_QImode
icode = CODE_FOR_nothing
Backtrace:
#0 fancy_abort (file=file@entry=0x255f858
"/work/results_sc/src-patched/gcc/expr.cc", line=line@entry=8085,
function=function@entry=0x25602a0 "store_constructor")
at /work/results_sc/src-patched/gcc/diagnostics/context.h:558
#1 0x0000000000be9c98 in store_constructor
(exp=exp@entry=0xfffff6577e58, target=target@entry=0xfffff605d408,
cleared=cleared@entry=0, size=..., reverse=reverse@entry=false)
at /work/results_sc/src-patched/gcc/expr.cc:8085
#2 0x0000000000bec00c in expand_constructor
(exp=exp@entry=0xfffff6577e58, target=0xfffff605d408,
target@entry=0xfffff605d3f0, modifier=modifier@entry=EXPAND_NORMAL,
avoid_temp_mem=avoid_temp_mem@entry=false)
at /work/results_sc/src-patched/gcc/poly-int.h:470
#3 0x0000000000bd21b8 in expand_expr_real_1 (exp=0xfffff6577e58,
target=<optimized out>, tmode=E_VNx16BImode, modifier=EXPAND_NORMAL,
alt_rtl=0x0, inner_reference_p=<optimized out>)
at /work/results_sc/src-patched/gcc/expr.cc:11943
#4 0x0000000000bd845c in expand_expr_real_gassign
(g=g@entry=0xfffff65a88f0, target=target@entry=0xfffff605d3f0,
tmode=tmode@entry=E_VNx16BImode, modifier=modifier@entry=EXPAND_NORMAL,
alt_rtl=alt_rtl@entry=0x0,
inner_reference_p=inner_reference_p@entry=false) at
/work/results_sc/src-patched/gcc/gimple.h:2728
#5 0x0000000000bd5604 in expand_expr_real_1
(exp=exp@entry=0xfffff65bf318, target=<optimized out>,
tmode=E_VNx16BImode, modifier=EXPAND_NORMAL, alt_rtl=0x0,
inner_reference_p=<optimized out>)
at /work/results_sc/src-patched/gcc/expr.cc:11552
#6 0x0000000000bd8298 in expand_expr_real
(exp=exp@entry=0xfffff65bf318, target=<optimized out>, tmode=<optimized
out>, modifier=modifier@entry=EXPAND_NORMAL, alt_rtl=alt_rtl@entry=0x0,
inner_reference_p=inner_reference_p@entry=false) at
/work/results_sc/src-patched/gcc/expr.cc:9628
#7 0x0000000000a86328 in expand_expr (exp=0xfffff65bf318,
target=<optimized out>, mode=<optimized out>, modifier=EXPAND_NORMAL) at
/work/results_sc/src-patched/gcc/expr.h:323
#8 expand_return (retval=0xfffff74c9a28) at
/work/results_sc/src-patched/gcc/cfgexpand.cc:4172
#9 expand_gimple_stmt_1 (stmt=0xfffff65a89a0) at
/work/results_sc/src-patched/gcc/cfgexpand.cc:4281
#10 expand_gimple_stmt (stmt=stmt@entry=0xfffff65a89a0) at
/work/results_sc/src-patched/gcc/cfgexpand.cc:4390
#11 0x0000000000a88938 in expand_gimple_basic_block (bb=<optimized out>,
asan_epilog_seq=asan_epilog_seq@entry=0x0) at
/work/results_sc/src-patched/gcc/cfgexpand.cc:6507
--Type <RET> for more, q to quit, c to continue without paging--
#12 0x0000000000a8a568 in (anonymous namespace)::pass_expand::execute
(this=<optimized out>, fun=0xfffff6591000) at
/work/results_sc/src-patched/gcc/cfgexpand.cc:7254
#13 0x0000000000f7ce98 in execute_one_pass (pass=pass@entry=0x3297c70)
at /work/results_sc/src-patched/gcc/passes.cc:2646
#14 0x0000000000f7d8d4 in execute_pass_list_1 (pass=0x3297c70) at
/work/results_sc/src-patched/gcc/passes.cc:2757
#15 0x0000000000f7d948 in execute_pass_list (fn=<optimized out>,
pass=<optimized out>) at /work/results_sc/src-patched/gcc/passes.cc:2768
#16 0x0000000000aced24 in cgraph_node::expand (this=0xfffff6588aa0) at
/work/results_sc/src-patched/gcc/context.h:49
#17 cgraph_node::expand (this=0xfffff6588aa0) at
/work/results_sc/src-patched/gcc/cgraphunit.cc:1827
#18 0x0000000000ad0dc0 in expand_all_functions () at
/work/results_sc/src-patched/gcc/cgraphunit.cc:2057
#19 symbol_table::compile (this=this@entry=0xfffff7406000) at
/work/results_sc/src-patched/gcc/cgraphunit.cc:2435
#20 0x0000000000ad3a48 in symbol_table::compile (this=0xfffff7406000) at
/work/results_sc/src-patched/gcc/cgraphunit.cc:2348
#21 symbol_table::finalize_compilation_unit (this=0xfffff7406000) at
/work/results_sc/src-patched/gcc/cgraphunit.cc:2626
#22 0x00000000010bf96c in compile_file () at
/work/results_sc/src-patched/gcc/toplev.cc:482
#23 0x000000000086baac in do_compile () at
/work/results_sc/src-patched/gcc/toplev.cc:2228
#24 toplev::main (this=this@entry=0xfffffffff078, argc=<optimized out>,
argc@entry=35, argv=<optimized out>, argv@entry=0xfffffffff1f8) at
/work/results_sc/src-patched/gcc/toplev.cc:2392
#25 0x000000000086d094 in main (argc=35, argv=0xfffffffff1f8) at
/work/results_sc/src-patched/gcc/main.cc:39
(gdb) up
#1 0x0000000000be9c98 in store_constructor
(exp=exp@entry=0xfffff6577e58, target=target@entry=0xfffff605d408,
cleared=cleared@entry=0, size=..., reverse=reverse@entry=false)
at /work/results_sc/src-patched/gcc/expr.cc:8085
8085 gcc_assert (icode != CODE_FOR_nothing);
Context:
8080 }
8081 else
8082 {
8083 /* Handle variable-length vector types. */
8084 icode = convert_optab_handler (vec_init_optab,
mode, eltmode);
8085 gcc_assert (icode != CODE_FOR_nothing);
8086 const_n_elts = constant_lower_bound (n_elts);
8087 }
8088
8089 if (const_n_elts && icode != CODE_FOR_nothing)
As far as I can tell, store_constructor is designed to handle the case
where vector is null. For example, it calls the store_constructor_field
function per element instead of assigning values to RTVEC_ELT (vector,
eltpos).
But right here it does
vector = rtvec_alloc (const_n_elts);
That statement is in a secondary block that is only entered if
const_n_elts && icode != CODE_FOR_nothing.
In the specific failing test case, the only effect of my proposed change
is to set const_n_elts to a non-zero value; 'vector' keeps its initial
value because icode is still equal to CODE_FOR_nothing:
rtvec vector = NULL;
const_n_elts is not used outside the secondary block that is not
entered, therefore the non-zero value of const_n_elts is irrelevant to
the failing test case.
so not sure what you mean with 'vector is null'. Or is
constant_lower_bound == 0?
constant_lower_bound (n_elts) is 16, as expected for mode = E_VNx16BImode.
The only case that might be relevant is a {} CTOR, one without elements. But
CONSTRUCTOR_NELTS (exp) is also 16, so I think that the {} case does not
apply here.
we should have special-paths for that - are they possibly not taken for VLA
vector modes?
I'll note that in general vector CTORs for BImode vectors that are not constant
are a red herring - totally inefficent - and we should avoid those at all cost.
As far as I can tell, the vector is constant, and the generated code
looks acceptable to me, e.g.
ptrue p0.b, vl3
ptrue p1.b, all
from this macro body (when n == 3):
svbool_t pg = svptrue_b8 (); \
svbool_t data1 = svptrue_pat_b8 (SV_VL ## n); \
But yes, the requirement outlined is that the target needs to support
vec_init with E_VNx16BImode, E_QImode. If it does not the vectorizer
should not have created such CTOR.
I don't think the vectoriser did create it, at least not in this case.
The cops_bool.c.200t.slp2 file is full of "***** Analysis failed
with..." messages. The test does not seem to contain any loops, either.
My understanding is that the vector constructor is created by a call to
a function such as svptrue_b8 (), e.g.
svbool_t all_true = svptrue_b8 ();
becomes { -1, ... } in
cmp_35 = sveor_b_z ({ -1, ... }, init1_30, res_init1_34);
which is the GIMPLE version of
svbool_t cmp = sveor_b_z (all_true, init1, res_init1);
But {-1, ...} is a VECTOR_CST, not a CONSTRUCTOR.
You are right. I was looking at the wrong part of the dump file. I think
this is the right part:
__attribute__((noipa, noinline, noclone, no_icf))
svbool_t func_init4 ()
{
svbool_t temp;
int _1;
<signed-boolean:1> _2;
int _3;
<signed-boolean:1> _4;
<bb 2> [local count: 1073741824]:
_1 = t ();
_2 = _1 != 0;
_3 = f ();
_4 = _3 != 0;
temp_8 = {-1, _2, 0, -1, 0, _4, 0, 0, 0, -1, 0, -1, 0, -1, 0, -1};
return temp_8;
}
For which the source code is:
svbool_t __attribute__ ((noipa)) \
func_init4 () { \
svbool_t temp = VECT_CSTN; \
return temp; \
} \
using:
#define VECT_CSTN { -1, t (), 0, -1, 0, f (), 0, 0, 0, -1, 0, -1, 0, -1,
0, -1 } /* { dg-warning "overflow in conversion from" "" { target c } } */
/* { dg-warning "narrowing conversion of" "" { target c++ } .-1 } */
which does indeed compile to very inefficient-looking code:
func_init4:
.LFB24:
.cfi_startproc
addvl sp, sp, #-1
.cfi_escape 0xf,0x8,0x8f,0,0x92,0x2e,0,0x38,0x1e,0x22
sub sp, sp, #32
.cfi_escape 0xf,0xa,0x8f,0,0x92,0x2e,0,0x38,0x1e,0x23,0x20,0x22
stp x29, x30, [sp]
.cfi_escape 0x10,0x1d,0x2,0x8f,0
.cfi_escape 0x10,0x1e,0x2,0x8f,0x8
mov x29, sp
str x19, [sp, 16]
addvl sp, sp, #-18
.cfi_escape 0xf,0xb,0x8f,0,0x92,0x2e,0,0x8,0x98,0x1e,0x23,0x20,0x22
.cfi_escape
0x10,0x13,0xb,0x8f,0,0x92,0x2e,0,0x8,0x90,0x1e,0x23,0x10,0x22
str z8, [sp, #2, mul vl]
str z9, [sp, #3, mul vl]
str z10, [sp, #4, mul vl]
str z11, [sp, #5, mul vl]
str p15, [sp, #11, mul vl]
str p5, [sp, #1, mul vl]
str p6, [sp, #2, mul vl]
str p7, [sp, #3, mul vl]
str p8, [sp, #4, mul vl]
str p9, [sp, #5, mul vl]
str p10, [sp, #6, mul vl]
str p11, [sp, #7, mul vl]
str p12, [sp, #8, mul vl]
str p13, [sp, #9, mul vl]
str p14, [sp, #10, mul vl]
str z12, [sp, #6, mul vl]
str z13, [sp, #7, mul vl]
str z14, [sp, #8, mul vl]
str z15, [sp, #9, mul vl]
str z16, [sp, #10, mul vl]
str z17, [sp, #11, mul vl]
str z18, [sp, #12, mul vl]
str z19, [sp, #13, mul vl]
str z20, [sp, #14, mul vl]
str z21, [sp, #15, mul vl]
str p4, [sp]
str z22, [sp, #16, mul vl]
str z23, [sp, #17, mul vl]
.cfi_escape 0x10,0x48,0x8,0x8f,0,0x92,0x2e,0,0x40,0x1e,0x22
.cfi_escape 0x10,0x49,0x8,0x8f,0,0x92,0x2e,0,0x48,0x1e,0x22
.cfi_escape 0x10,0x4a,0x9,0x8f,0,0x92,0x2e,0,0x8,0x20,0x1e,0x22
.cfi_escape 0x10,0x4b,0x9,0x8f,0,0x92,0x2e,0,0x8,0x28,0x1e,0x22
.cfi_escape 0x10,0x4c,0x9,0x8f,0,0x92,0x2e,0,0x8,0x30,0x1e,0x22
.cfi_escape 0x10,0x4d,0x9,0x8f,0,0x92,0x2e,0,0x8,0x38,0x1e,0x22
.cfi_escape 0x10,0x4e,0x9,0x8f,0,0x92,0x2e,0,0x8,0x40,0x1e,0x22
.cfi_escape 0x10,0x4f,0x9,0x8f,0,0x92,0x2e,0,0x8,0x48,0x1e,0x22
bl t
mov w19, w0
bl f
mov w2, 151
cntd x1
pfalse p15.b
mov w3, 151
cmp w19, 0
mul x1, x1, x2
cntd x2
mul x2, x2, x3
add x1, x1, 32
add x1, sp, x1
str p15, [x1]
add x2, sp, x2
mov w1, 1
strh w1, [x2, 32]
cntd x1
rdvl x2, #20
mul x1, x1, x3
rdvl x3, #20
add x1, x1, 32
add x1, sp, x1
ldr p15, [x1]
addpl x1, x2, #-10
rdvl x2, #20
add x1, x1, 32
add x1, sp, x1
str p15, [x1]
addpl x1, x2, #-10
csetm w2, ne
add x1, x1, 32
cmp w0, 0
ldrh w1, [sp, x1]
bfi w1, w2, 1, 1
addpl x2, x3, #-10
add x2, x2, 32
add x2, sp, x2
strh w1, [x2]
addpl x1, x3, #-10
add x1, x1, 32
mov w2, 149
add x1, sp, x1
ldr p15, [x1]
mov w3, 149
cntd x1
mul x1, x1, x2
add x1, x1, 32
add x1, sp, x1
str p15, [x1]
etc..
I have confirmed that the same (bad) code generation occurs without my
changes in this patchset, and also at the commit upon which my patch
series is based (i.e., without any of my BB SLP patches).
I think it would be worthwhile to improve store_constructor for most
types even if it still has pathological behavior for one type, so I am
tempted to report it as a bug and move on. I can also note in the commit
log that the described non-fallback behaviour of store_constructor
relies on vec_init having been implemented for the mode and eltmode.
Please consider approving the latest version of this patch without the
bugfix:
https://forge.sourceware.org/gcc/gcc-TEST/pulls/177
https://inbox.sourceware.org/gcc-patches/bmm.hjj7t7yaru.gcc.gcc-test.chris.bazley.177....@forge-stage.sourceware.org/
--
Christopher Bazley
Staff Software Engineer, GNU Tools Team.
Arm Ltd, 110 Fulbourn Road, Cambridge, CB1 9NJ, UK.
http://www.arm.com/