pr45678-2.c ICEs for msp430-elf with -mlarge, because an alignment of POINTER_SIZE is attempted. POINTER_SIZE with -mlarge is 20-bits, so further code in the middle-end that expects this to be a power or 2 causes odd alignments to be set, in this case eventually resulting in an ICE.
The test ICEs on gcc-7-branch, gcc-8-branch, and current trunk. It successfully builds on gcc-6-branch. The failure is caused by r235172. Successfully bootstrapped and regtested the attached patch for x86-64-pc-linux-gnu, and msp430-elf with -mlarge, on trunk. Ok for gcc-7-branch, gcc-8-branch and trunk?
>From e655a518a06a848dc398504f28272750e1a2be9f Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz <jozefl.open...@gmail.com> Date: Tue, 13 Mar 2018 11:25:56 +0000 Subject: [PATCH] When aligning to POINTER_SIZE, round alignment to largest power of 2 that is <= POINTER_SIZE PR middle-end/86705 * gcc/cfgexpand.c (set_parm_rtl): Before using POINTER_SIZE as an alignment value, round it to the largest power of 2 less than or equal to itself. (expand_one_ssa_partition): Likewise. (expand_one_var): Likewise. --- gcc/cfgexpand.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index d6e3c38..a56db7a 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -1258,9 +1258,12 @@ set_parm_rtl (tree parm, rtx x) pointer. ??? We've got a pseudo for sure here, do we actually dynamically allocate its spilling area if needed? ??? Isn't it a problem when POINTER_SIZE also exceeds - MAX_SUPPORTED_STACK_ALIGNMENT, as on cris and lm32? */ + MAX_SUPPORTED_STACK_ALIGNMENT, as on cris and lm32? + POINTER_SIZE may not be a power of 2 e.g. for msp430-elf with the large + data model, so align to the largest power of 2 that is + <= POINTER_SIZE. */ if (align > MAX_SUPPORTED_STACK_ALIGNMENT) - align = POINTER_SIZE; + align = (unsigned)1 << floor_log2 (POINTER_SIZE); record_alignment_for_reg_var (align); } @@ -1381,7 +1384,7 @@ expand_one_ssa_partition (tree var) /* If the variable alignment is very large we'll dynamicaly allocate it, which means that in-frame portion is just a pointer. */ if (align > MAX_SUPPORTED_STACK_ALIGNMENT) - align = POINTER_SIZE; + align = (unsigned)1 << floor_log2 (POINTER_SIZE); record_alignment_for_reg_var (align); @@ -1608,7 +1611,7 @@ expand_one_var (tree var, bool toplevel, bool really_expand) /* If the variable alignment is very large we'll dynamicaly allocate it, which means that in-frame portion is just a pointer. */ if (align > MAX_SUPPORTED_STACK_ALIGNMENT) - align = POINTER_SIZE; + align = (unsigned)1 << floor_log2 (POINTER_SIZE); } record_alignment_for_reg_var (align); -- 2.7.4