[PING] PR middle-end/95126: Expand small const structs as immediate constants
Commit Message
I'd like to ping my patch for PR middle-end/95126 from February:
https://gcc.gnu.org/pipermail/gcc-patches/2022-February/590949.html
As a regression fix, this has missed GCC 12, but hopefully its suitable
for 13 now we're back in stage1.
The patch has been refreshed and retested against gcc 13 trunk on
x86_64-pc-linux-gnu with make bootstrap and make -k check, both
with and without --target_board=unix{-m32} with no new failures.
Ok for mainline?
2022-05-21 Roger Sayle <roger@nextmovesoftware.com>
gcc/ChangeLog
PR middle-end/95126
* calls.cc (load_register_parameters): When loading a suitable
immediate_const_ctor_p VAR_DECL into a single word_mode register,
construct it directly in a pseudo rather than read it (by parts)
from memory.
* expr.cc (int_expr_size): Make tree argument a const_tree.
(immediate_const_ctor_p): Helper predicate. Return true for
simple constructors that may be materialized in a register.
(expand_expr_real_1) [VAR_DECL]: When expanding a constant
VAR_DECL with a suitable immediate_const_ctor_p constructor
use store_constructor to materialize it directly in a pseudo.
* expr.h (immediate_const_ctor_p): Prototype here.
* varasm.cc (initializer_constant_valid_for_bitfield_p): Change
VALUE argument from tree to const_tree.
* varasm.h (initializer_constant_valid_for_bitfield_p): Update
prototype.
gcc/testsuite/ChangeLog
PR middle-end/95126
* gcc.target/i386/pr95126-m32-1.c: New test case.
* gcc.target/i386/pr95126-m32-2.c: New test case.
* gcc.target/i386/pr95126-m32-3.c: New test case.
* gcc.target/i386/pr95126-m32-4.c: New test case.
* gcc.target/i386/pr95126-m64-1.c: New test case.
* gcc.target/i386/pr95126-m64-2.c: New test case.
* gcc.target/i386/pr95126-m64-3.c: New test case.
* gcc.target/i386/pr95126-m64-4.c: New test case.
Thanks in advance,
Roger
--
Comments
This breaks Ada on aarch64 in stage3, probably a miscompiled stage2
compiler. For example:
/opt/gcc/gcc-20220605/Build/./prev-gcc/xgcc -B/opt/gcc/gcc-20220605/Build/./prev-gcc/ -B/usr/aarch64-suse-linux/bin/ -B/usr/aarch64-suse-linux/bin/ -B/usr/aarch64-suse-linux/lib/ -isystem /usr/aarch64-suse-linux/include -isystem /usr/aarch64-suse-linux/sys-include -fchecking=1 -c -g -O2 -fchecking=1 -gnatpg -gnata -W -Wall -nostdinc -I- -I. -Iada/generated -Iada -I../../gcc/ada -Iada/libgnat -I../../gcc/ada/libgnat -Iada/gcc-interface -I../../gcc/ada/gcc-interface ../../gcc/ada/spark_xrefs.adb -o ada/spark_xrefs.o
+===========================GNAT BUG DETECTED==============================+
| 13.0.0 20220605 (experimental) [master ad6919374be] (aarch64-suse-linux) |
| Assert_Failure failed precondition from sinfo-nodes.ads:5419 |
| Error detected at types.ads:53:28 |
| Compiling ../../gcc/ada/spark_xrefs.adb |
| Please submit a bug report; see https://gcc.gnu.org/bugs/ . |
| Use a subject line meaningful to you and us to track the bug. |
| Include the entire contents of this bug box in the report. |
| Include the exact command that you entered. |
| Also include sources listed below. |
+==========================================================================+
Andreas Schwab <schwab@linux-m68k.org> writes:
> This breaks Ada on aarch64 in stage3, probably a miscompiled stage2
> compiler. For example:
>
> /opt/gcc/gcc-20220605/Build/./prev-gcc/xgcc
> -B/opt/gcc/gcc-20220605/Build/./prev-gcc/ -B/usr/aarch64-suse-linux/bin/
> -B/usr/aarch64-suse-linux/bin/ -B/usr/aarch64-suse-linux/lib/ -isystem
> /usr/aarch64-suse-linux/include -isystem
> /usr/aarch64-suse-linux/sys-include -fchecking=1 -c -g -O2 -fchecking=1
> -gnatpg -gnata -W -Wall -nostdinc -I- -I. -Iada/generated -Iada
> -I../../gcc/ada -Iada/libgnat -I../../gcc/ada/libgnat -Iada/gcc-interface
> -I../../gcc/ada/gcc-interface ../../gcc/ada/spark_xrefs.adb -o
> ada/spark_xrefs.o
> +===========================GNAT BUG DETECTED==============================+
> | 13.0.0 20220605 (experimental) [master ad6919374be] (aarch64-suse-linux) |
> | Assert_Failure failed precondition from sinfo-nodes.ads:5419 |
> | Error detected at types.ads:53:28 |
> | Compiling ../../gcc/ada/spark_xrefs.adb |
> | Please submit a bug report; see https://gcc.gnu.org/bugs/ . |
> | Use a subject line meaningful to you and us to track the bug. |
> | Include the entire contents of this bug box in the report. |
> | Include the exact command that you entered. |
> | Also include sources listed below. |
> +==========================================================================+
Confirmed: this also happens on i386-pc-solaris2.11,
sparc-sun-solaris2.11, and x86_64-pc-linux-gnu.
Hi Rainer (and Andreas),
My sincere apologies for the breakage. I'm currently regression testing a
solution to the ICEs introduced by my "small const struct" patch, which
fingers-crossed might also fix this Ada bootstrap. For a while when
Rainer also reported the bootstrap failure is visible, on
x86_64-pc-linux-gnu,
I thought I'd be able to diagnose and fix the issue myself, but alas my
--enable-languages="all" builds (still) fail earlier with:
gcc -std=gnu99 -c -g -gnatpg -gnatwns -gnata -W -Wall -I- -I.
-Iada/generated -Iada -I../../gcc/gcc/ada ../../gcc/gcc/ada/osint.adb -o
ada/osint.o
osint.adb:438:31: "strlen" not declared in "CRTL"
osint.adb:441:14: "strncpy" not declared in "CRTL"
osint.adb:675:21: "strlen" not declared in "CRTL"
osint.adb:728:16: "Open_Append" is undefined
osint.adb:1108:41: "int64" not declared in "CRTL"
osint.adb:3144:28: "strlen" not declared in "CRTL"
osint.adb:3147:11: "strncpy" not declared in "CRTL"
The one experiment I'd like to be able to try, to investigate the cause/cure
of this, is:
diff --git a/gcc/calls.cc b/gcc/calls.cc
index a4336c1..05fdd24 100644
--- a/gcc/calls.cc
+++ b/gcc/calls.cc
@@ -2177,7 +2177,7 @@ load_register_parameters (struct arg_data *args, int
num_a
VAR_DECL with a simple constructor, expand that constructor
via a pseudo rather than read from (possibly misaligned)
memory. PR middle-end/95126. */
- else if (nregs == 1
+ else if (0 && nregs == 1
&& partial == 0
&& !args[i].pass_on_stack
&& VAR_P (tree_value)
My "small const structs" patch affected code generation in three places, and
identifying
which of these is causing the miscompilation issue for gnat will help narrow
down the
problem, or worst case allow reverting less of the problematic patch.
Again my deep apologies for the breakage. Hopefully the fix I'm testing
will cure this as
well (but an ICE is different symptom to a silent miscompilation).
Sorry again,
Roger
--
> -----Original Message-----
> From: Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
> Sent: 05 June 2022 21:31
> To: Andreas Schwab <schwab@linux-m68k.org>
> Cc: Roger Sayle <roger@nextmovesoftware.com>; gcc-patches@gcc.gnu.org
> Subject: Re: [PING] PR middle-end/95126: Expand small const structs as
> immediate constants
>
> Andreas Schwab <schwab@linux-m68k.org> writes:
>
> > This breaks Ada on aarch64 in stage3, probably a miscompiled stage2
> > compiler. For example:
> >
> > /opt/gcc/gcc-20220605/Build/./prev-gcc/xgcc
> > -B/opt/gcc/gcc-20220605/Build/./prev-gcc/
> > -B/usr/aarch64-suse-linux/bin/ -B/usr/aarch64-suse-linux/bin/
> > -B/usr/aarch64-suse-linux/lib/ -isystem
> > /usr/aarch64-suse-linux/include -isystem
> > /usr/aarch64-suse-linux/sys-include -fchecking=1 -c -g -O2
> > -fchecking=1 -gnatpg -gnata -W -Wall -nostdinc -I- -I. -Iada/generated
> > -Iada -I../../gcc/ada -Iada/libgnat -I../../gcc/ada/libgnat
> > -Iada/gcc-interface -I../../gcc/ada/gcc-interface
> > ../../gcc/ada/spark_xrefs.adb -o ada/spark_xrefs.o
> > +===========================GNAT BUG
> > +DETECTED==============================+
> > | 13.0.0 20220605 (experimental) [master ad6919374be]
(aarch64-suse-linux)
> |
> > | Assert_Failure failed precondition from sinfo-nodes.ads:5419
|
> > | Error detected at types.ads:53:28
|
> > | Compiling ../../gcc/ada/spark_xrefs.adb
|
> > | Please submit a bug report; see https://gcc.gnu.org/bugs/ .
|
> > | Use a subject line meaningful to you and us to track the bug.
|
> > | Include the entire contents of this bug box in the report.
|
> > | Include the exact command that you entered.
|
> > | Also include sources listed below.
|
> >
> +================================================================
> =====
> > +=====+
>
> Confirmed: this also happens on i386-pc-solaris2.11,
sparc-sun-solaris2.11, and
> x86_64-pc-linux-gnu.
On Jun 06 2022, Roger Sayle wrote:
> gcc -std=gnu99 -c -g -gnatpg -gnatwns -gnata -W -Wall -I- -I.
> -Iada/generated -Iada -I../../gcc/gcc/ada ../../gcc/gcc/ada/osint.adb -o
> ada/osint.o
> osint.adb:438:31: "strlen" not declared in "CRTL"
> osint.adb:441:14: "strncpy" not declared in "CRTL"
> osint.adb:675:21: "strlen" not declared in "CRTL"
> osint.adb:728:16: "Open_Append" is undefined
> osint.adb:1108:41: "int64" not declared in "CRTL"
> osint.adb:3144:28: "strlen" not declared in "CRTL"
> osint.adb:3147:11: "strncpy" not declared in "CRTL"
What's your bootstrap compiler?
Hi Andreas,
> > gcc -std=gnu99 -c -g -gnatpg -gnatwns -gnata -W -Wall -I- -I.
> > -Iada/generated -Iada -I../../gcc/gcc/ada ../../gcc/gcc/ada/osint.adb
> > -o ada/osint.o
> > osint.adb:438:31: "strlen" not declared in "CRTL"
> > osint.adb:441:14: "strncpy" not declared in "CRTL"
> > osint.adb:675:21: "strlen" not declared in "CRTL"
> > osint.adb:728:16: "Open_Append" is undefined
> > osint.adb:1108:41: "int64" not declared in "CRTL"
> > osint.adb:3144:28: "strlen" not declared in "CRTL"
> > osint.adb:3147:11: "strncpy" not declared in "CRTL"
>
> What's your bootstrap compiler?
GNAT 4.8.5 20150623 (Red Hat 4.8.5-44)
I'm currently investigating other options...
On Jun 06 2022, Roger Sayle wrote:
> Hi Andreas,
>> > gcc -std=gnu99 -c -g -gnatpg -gnatwns -gnata -W -Wall -I- -I.
>> > -Iada/generated -Iada -I../../gcc/gcc/ada ../../gcc/gcc/ada/osint.adb
>> > -o ada/osint.o
>> > osint.adb:438:31: "strlen" not declared in "CRTL"
>> > osint.adb:441:14: "strncpy" not declared in "CRTL"
>> > osint.adb:675:21: "strlen" not declared in "CRTL"
>> > osint.adb:728:16: "Open_Append" is undefined
>> > osint.adb:1108:41: "int64" not declared in "CRTL"
>> > osint.adb:3144:28: "strlen" not declared in "CRTL"
>> > osint.adb:3147:11: "strncpy" not declared in "CRTL"
>>
>> What's your bootstrap compiler?
>
> GNAT 4.8.5 20150623 (Red Hat 4.8.5-44)
That's very much out of date.
In order to build GNAT, the Ada compiler, you need a working GNAT
compiler (GCC version 5.1 or later).
Hi Roger,
> My sincere apologies for the breakage. I'm currently regression testing a
> solution to the ICEs introduced by my "small const struct" patch, which
> fingers-crossed might also fix this Ada bootstrap. For a while when
> Rainer also reported the bootstrap failure is visible, on
> x86_64-pc-linux-gnu,
> I thought I'd be able to diagnose and fix the issue myself, but alas my
> --enable-languages="all" builds (still) fail earlier with:
>
> gcc -std=gnu99 -c -g -gnatpg -gnatwns -gnata -W -Wall -I- -I.
> -Iada/generated -Iada -I../../gcc/gcc/ada ../../gcc/gcc/ada/osint.adb -o
> ada/osint.o
> osint.adb:438:31: "strlen" not declared in "CRTL"
> osint.adb:441:14: "strncpy" not declared in "CRTL"
> osint.adb:675:21: "strlen" not declared in "CRTL"
> osint.adb:728:16: "Open_Append" is undefined
> osint.adb:1108:41: "int64" not declared in "CRTL"
> osint.adb:3144:28: "strlen" not declared in "CRTL"
> osint.adb:3147:11: "strncpy" not declared in "CRTL"
>
> The one experiment I'd like to be able to try, to investigate the cause/cure
> of this, is:
>
> diff --git a/gcc/calls.cc b/gcc/calls.cc
> index a4336c1..05fdd24 100644
> --- a/gcc/calls.cc
> +++ b/gcc/calls.cc
> @@ -2177,7 +2177,7 @@ load_register_parameters (struct arg_data *args, int
> num_a
> VAR_DECL with a simple constructor, expand that constructor
> via a pseudo rather than read from (possibly misaligned)
> memory. PR middle-end/95126. */
> - else if (nregs == 1
> + else if (0 && nregs == 1
> && partial == 0
> && !args[i].pass_on_stack
> && VAR_P (tree_value)
>
> My "small const structs" patch affected code generation in three places, and
> identifying
> which of these is causing the miscompilation issue for gnat will help narrow
> down the
> problem, or worst case allow reverting less of the problematic patch.
I just tried this on i386-pc-solaris2.11: unfortunately, it made no
difference.
Rainer
Andreas Schwab <schwab@linux-m68k.org> writes:
> On Jun 06 2022, Roger Sayle wrote:
>
>> gcc -std=gnu99 -c -g -gnatpg -gnatwns -gnata -W -Wall -I- -I.
>> -Iada/generated -Iada -I../../gcc/gcc/ada ../../gcc/gcc/ada/osint.adb -o
>> ada/osint.o
>> osint.adb:438:31: "strlen" not declared in "CRTL"
>> osint.adb:441:14: "strncpy" not declared in "CRTL"
>> osint.adb:675:21: "strlen" not declared in "CRTL"
>> osint.adb:728:16: "Open_Append" is undefined
>> osint.adb:1108:41: "int64" not declared in "CRTL"
>> osint.adb:3144:28: "strlen" not declared in "CRTL"
>> osint.adb:3147:11: "strncpy" not declared in "CRTL"
>
> What's your bootstrap compiler?
FWIW, I'm using GCC 9 (9.4.0 on Solaris/x86, 9.3.0 on Linux/x86_64) as
bootstrap compiler.
Rainer
Hi Rainer,
> > The one experiment I'd like to be able to try, to investigate the
> > cause/cure of this, is:
> >
> > diff --git a/gcc/calls.cc b/gcc/calls.cc index a4336c1..05fdd24 100644
> > --- a/gcc/calls.cc
> > +++ b/gcc/calls.cc
> > @@ -2177,7 +2177,7 @@ load_register_parameters (struct arg_data *args,
> > int num_a
> > VAR_DECL with a simple constructor, expand that constructor
> > via a pseudo rather than read from (possibly misaligned)
> > memory. PR middle-end/95126. */
> > - else if (nregs == 1
> > + else if (0 && nregs == 1
> > && partial == 0
> > && !args[i].pass_on_stack
> > && VAR_P (tree_value)
> >
> > My "small const structs" patch affected code generation in three
> > places, and identifying which of these is causing the miscompilation
> > issue for gnat will help narrow down the problem, or worst case allow
> > reverting less of the problematic patch.
>
> I just tried this on i386-pc-solaris2.11: unfortunately, it made no
difference.
Awesome! Very many thanks for trying this. Alas it confirms that the patch
I'm currently spinning won't have any affect. So by a process of
elimination,
the miscompilation must be triggered by one of the other two changes:
diff --git a/gcc/expr.cc b/gcc/expr.cc
index fb062dc..37f1405 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -4871,7 +4871,7 @@ emit_push_insn (rtx x, machine_mode mode, tree type,
rtx s
/* If source is a constant VAR_DECL with a simple constructor,
store the constructor to the stack instead of moving it. */
const_tree decl;
- if (partial == 0
+ if (0 && partial == 0
&& MEM_P (xinner)
&& SYMBOL_REF_P (XEXP (xinner, 0))
&& (decl = SYMBOL_REF_DECL (XEXP (xinner, 0))) != NULL_TREE
@@ -10603,7 +10603,7 @@ expand_expr_real_1 (tree exp, rtx target,
machine_mode t
}
/* Expand const VAR_DECLs with CONSTRUCTOR initializers that
have scalar integer modes to a reg via store_constructor. */
- if (TREE_READONLY (exp)
+ if (0 && TREE_READONLY (exp)
&& !TREE_SIDE_EFFECTS (exp)
&& (modifier == EXPAND_NORMAL || modifier == EXPAND_STACK_PARM)
&& immediate_const_ctor_p (DECL_INITIAL (exp))
p.s. I've just set up a build environment on another machine where I'm
using
GNAT 11.3.1 20220421 (Red Hat 11.3.1-2)
as the bootstrap compiler, but it'll be a few hours before I'm investigating
in
gdb.
Many thanks again for your help. Sorry again for the
breakage/inconvenience.
Roger
==
Hi Roger,
>> I just tried this on i386-pc-solaris2.11: unfortunately, it made no
> difference.
>
> Awesome! Very many thanks for trying this. Alas it confirms that the patch
> I'm currently spinning won't have any affect. So by a process of
> elimination,
> the miscompilation must be triggered by one of the other two changes:
>
> diff --git a/gcc/expr.cc b/gcc/expr.cc
> index fb062dc..37f1405 100644
> --- a/gcc/expr.cc
> +++ b/gcc/expr.cc
> @@ -4871,7 +4871,7 @@ emit_push_insn (rtx x, machine_mode mode, tree type,
> rtx s
> /* If source is a constant VAR_DECL with a simple constructor,
> store the constructor to the stack instead of moving it. */
> const_tree decl;
> - if (partial == 0
> + if (0 && partial == 0
> && MEM_P (xinner)
> && SYMBOL_REF_P (XEXP (xinner, 0))
> && (decl = SYMBOL_REF_DECL (XEXP (xinner, 0))) != NULL_TREE
> @@ -10603,7 +10603,7 @@ expand_expr_real_1 (tree exp, rtx target,
> machine_mode t
> }
> /* Expand const VAR_DECLs with CONSTRUCTOR initializers that
> have scalar integer modes to a reg via store_constructor. */
> - if (TREE_READONLY (exp)
> + if (0 && TREE_READONLY (exp)
> && !TREE_SIDE_EFFECTS (exp)
> && (modifier == EXPAND_NORMAL || modifier == EXPAND_STACK_PARM)
> && immediate_const_ctor_p (DECL_INITIAL (exp))
I've tried both chunks individually: the second one allowed the build to
finish successfully.
Thanks.
Rainer
@@ -2095,7 +2095,8 @@ load_register_parameters (struct arg_data *args, int num_actuals,
poly_int64 size = 0;
HOST_WIDE_INT const_size = 0;
rtx_insn *before_arg = get_last_insn ();
- tree type = TREE_TYPE (args[i].tree_value);
+ tree tree_value = args[i].tree_value;
+ tree type = TREE_TYPE (tree_value);
if (RECORD_OR_UNION_TYPE_P (type) && TYPE_TRANSPARENT_AGGR (type))
type = TREE_TYPE (first_field (type));
/* Set non-negative if we must move a word at a time, even if
@@ -2172,6 +2173,24 @@ load_register_parameters (struct arg_data *args, int num_actuals,
emit_move_insn (gen_rtx_REG (word_mode, REGNO (reg) + j),
args[i].aligned_regs[j]);
+ /* If we need a single register and the source is a constant
+ VAR_DECL with a simple constructor, expand that constructor
+ via a pseudo rather than read from (possibly misaligned)
+ memory. PR middle-end/95126. */
+ else if (nregs == 1
+ && partial == 0
+ && !args[i].pass_on_stack
+ && VAR_P (tree_value)
+ && TREE_READONLY (tree_value)
+ && !TREE_SIDE_EFFECTS (tree_value)
+ && immediate_const_ctor_p (DECL_INITIAL (tree_value)))
+ {
+ rtx target = gen_reg_rtx (word_mode);
+ rtx x = expand_expr (DECL_INITIAL (tree_value),
+ target, word_mode, EXPAND_NORMAL);
+ reg = gen_rtx_REG (word_mode, REGNO (reg));
+ emit_move_insn (reg, x);
+ }
else if (partial == 0 || args[i].pass_on_stack)
{
/* SIZE and CONST_SIZE are 0 for partial arguments and
@@ -100,7 +100,7 @@ static void do_tablejump (rtx, machine_mode, rtx, rtx, rtx,
profile_probability);
static rtx const_vector_from_tree (tree);
static tree tree_expr_size (const_tree);
-static HOST_WIDE_INT int_expr_size (tree);
+static HOST_WIDE_INT int_expr_size (const_tree);
static void convert_mode_scalar (rtx, rtx, int);
@@ -4867,7 +4867,22 @@ emit_push_insn (rtx x, machine_mode mode, tree type, rtx size,
return false;
}
}
- emit_block_move (target, xinner, size, BLOCK_OP_CALL_PARM);
+
+ /* If source is a constant VAR_DECL with a simple constructor,
+ store the constructor to the stack instead of moving it. */
+ const_tree decl;
+ if (partial == 0
+ && MEM_P (xinner)
+ && SYMBOL_REF_P (XEXP (xinner, 0))
+ && (decl = SYMBOL_REF_DECL (XEXP (xinner, 0))) != NULL_TREE
+ && VAR_P (decl)
+ && TREE_READONLY (decl)
+ && !TREE_SIDE_EFFECTS (decl)
+ && immediate_const_ctor_p (DECL_INITIAL (decl), 2))
+ store_constructor (DECL_INITIAL (decl), target, 0,
+ int_expr_size (DECL_INITIAL (decl)), false);
+ else
+ emit_block_move (target, xinner, size, BLOCK_OP_CALL_PARM);
}
}
else if (partial > 0)
@@ -6576,6 +6591,25 @@ categorize_ctor_elements (const_tree ctor, HOST_WIDE_INT *p_nz_elts,
p_init_elts, p_complete);
}
+/* Return true if constructor CTOR is simple enough to be materialized
+ in an integer mode register. Limit the size to WORDS words, which
+ is 1 by default. */
+
+bool
+immediate_const_ctor_p (const_tree ctor, unsigned int words)
+{
+ /* Allow function to be called with a VAR_DECL's DECL_INITIAL. */
+ if (!ctor || TREE_CODE (ctor) != CONSTRUCTOR)
+ return false;
+
+ return TREE_CONSTANT (ctor)
+ && !TREE_ADDRESSABLE (ctor)
+ && CONSTRUCTOR_NELTS (ctor)
+ && TREE_CODE (TREE_TYPE (ctor)) != ARRAY_TYPE
+ && int_expr_size (ctor) <= words * UNITS_PER_WORD
+ && initializer_constant_valid_for_bitfield_p (ctor);
+}
+
/* TYPE is initialized by a constructor with NUM_ELTS elements, the last
of which had type LAST_TYPE. Each element was itself a complete
initializer, in the sense that every meaningful byte was explicitly
@@ -10535,6 +10569,21 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
if (temp)
return temp;
}
+ /* Expand const VAR_DECLs with CONSTRUCTOR initializers that
+ have scalar integer modes to a reg via store_constructor. */
+ if (TREE_READONLY (exp)
+ && !TREE_SIDE_EFFECTS (exp)
+ && (modifier == EXPAND_NORMAL || modifier == EXPAND_STACK_PARM)
+ && immediate_const_ctor_p (DECL_INITIAL (exp))
+ && SCALAR_INT_MODE_P (TYPE_MODE (TREE_TYPE (exp)))
+ && crtl->emit.regno_pointer_align_length
+ && !target)
+ {
+ target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
+ store_constructor (DECL_INITIAL (exp), target, 0,
+ int_expr_size (DECL_INITIAL (exp)), false);
+ return target;
+ }
/* ... fall through ... */
case PARM_DECL:
@@ -13129,7 +13178,7 @@ expr_size (tree exp)
if the size can vary or is larger than an integer. */
static HOST_WIDE_INT
-int_expr_size (tree exp)
+int_expr_size (const_tree exp)
{
tree size;
@@ -338,6 +338,7 @@ extern unsigned HOST_WIDE_INT highest_pow2_factor (const_tree);
extern bool categorize_ctor_elements (const_tree, HOST_WIDE_INT *,
HOST_WIDE_INT *, HOST_WIDE_INT *,
bool *);
+extern bool immediate_const_ctor_p (const_tree, unsigned int words = 1);
extern void expand_operands (tree, tree, rtx, rtx*, rtx*,
enum expand_modifier);
@@ -5069,7 +5069,7 @@ initializer_constant_valid_p (tree value, tree endtype, bool reverse)
an element of a "constant" initializer. */
bool
-initializer_constant_valid_for_bitfield_p (tree value)
+initializer_constant_valid_for_bitfield_p (const_tree value)
{
/* For bitfields we support integer constants or possibly nested aggregates
of such. */
@@ -5078,7 +5078,7 @@ initializer_constant_valid_for_bitfield_p (tree value)
case CONSTRUCTOR:
{
unsigned HOST_WIDE_INT idx;
- tree elt;
+ const_tree elt;
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (value), idx, elt)
if (!initializer_constant_valid_for_bitfield_p (elt))
@@ -65,7 +65,7 @@ extern tree initializer_constant_valid_p (tree, tree, bool = false);
/* Return true if VALUE is a valid constant-valued expression
for use in initializing a static bit-field; one that can be
an element of a "constant" initializer. */
-extern bool initializer_constant_valid_for_bitfield_p (tree);
+extern bool initializer_constant_valid_for_bitfield_p (const_tree);
/* Whether a constructor CTOR is a valid static constant initializer if all
its elements are. This used to be internal to initializer_constant_valid_p
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { ia32 } } } */
+/* { dg-options "-O2" } */
+
+struct small{ short a,b; signed char c; };
+
+void call_func(void)
+{
+ extern int func(struct small X);
+ static struct small const s = { 1,2,0 };
+ func(s);
+}
+
+/* { dg-final { scan-assembler "movl\[ \\t]*\\\$" } } */
+/* { dg-final { scan-assembler "movb\[ \\t]*\\\$0, " } } */
+/* { dg-final { scan-assembler-not "movzwl" } } */
+
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do compile { target { ia32 } } } */
+/* { dg-options "-O2" } */
+
+struct small{ short a,b; signed char c; };
+static const struct small s = { 1,2,0 };
+extern int func(struct small X);
+
+void call_func(void)
+{
+ func(s);
+}
+
+/* { dg-final { scan-assembler "movl\[ \\t]*\\\$" } } */
+/* { dg-final { scan-assembler "movb\[ \\t]*\\\$0, " } } */
+/* { dg-final { scan-assembler-not "movzwl" } } */
+
new file mode 100644
@@ -0,0 +1,15 @@
+/* { dg-do compile { target { ia32 } } } */
+/* { dg-options "-O2" } */
+
+struct small{ short a; };
+
+void call_func(void)
+{
+ extern int func(struct small X);
+ static struct small const s = { 2 };
+ func(s);
+}
+
+/* { dg-final { scan-assembler "pushl\[ \\t]*\\\$2" } } */
+/* { dg-final { scan-assembler-not "movzwl" } } */
+
new file mode 100644
@@ -0,0 +1,13 @@
+/* { dg-do compile { target { ia32 } } } */
+/* { dg-options "-O2" } */
+
+struct small{ short a,b; };
+
+void call_func(void)
+{
+ extern int func(struct small X);
+ static struct small const s = { 1,2 };
+ func(s);
+}
+
+/* { dg-final { scan-assembler "pushl\[ \\t]*\\\$131073" } } */
new file mode 100644
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2" } */
+
+struct small{ short a,b; signed char c; };
+
+void call_func(void)
+{
+ extern int func(struct small X);
+ static struct small const s = { 1,2,0 };
+ func(s);
+}
+
+/* { dg-final { scan-assembler "movl\[ \\t]*\\\$131073, " } } */
+/* { dg-final { scan-assembler-not "movzwl" } } */
+/* { dg-final { scan-assembler-not "salq" } } */
+/* { dg-final { scan-assembler-not "orq" } } */
+
new file mode 100644
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2" } */
+
+struct small{ short a,b; signed char c; };
+static const struct small s = { 1,2,0 };
+extern int func(struct small X);
+
+void call_func(void)
+{
+ func(s);
+}
+
+/* { dg-final { scan-assembler "movl\[ \\t]*\\\$131073, " } } */
+/* { dg-final { scan-assembler-not "movzwl" } } */
+/* { dg-final { scan-assembler-not "salq" } } */
+/* { dg-final { scan-assembler-not "orq" } } */
+
new file mode 100644
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2" } */
+
+struct small{ short a; };
+
+void call_func(void)
+{
+ extern int func(struct small X);
+ static struct small const s = { 2 };
+ func(s);
+}
+
+/* { dg-final { scan-assembler "movl\[ \\t]*\\\$2, " } } */
+/* { dg-final { scan-assembler-not "movzwl" } } */
new file mode 100644
@@ -0,0 +1,13 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2" } */
+
+struct small{ short a,b; };
+
+void call_func(void)
+{
+ extern int func(struct small X);
+ static struct small const s = { 1,2 };
+ func(s);
+}
+
+/* { dg-final { scan-assembler "movl\[ \\t]*\\\$131073, " } } */