re PR target/77728 (Miscompilation multiple vector iteration on ARM)
PR target/77728 * config/arm/arm.c: Include gimple.h. (aapcs_layout_arg): Emit -Wpsabi note if arm_needs_doubleword_align returns negative, increment ncrn only if it returned positive. (arm_needs_doubleword_align): Return int instead of bool, ignore DECL_ALIGN of non-FIELD_DECL TYPE_FIELDS chain members, but if there is any such non-FIELD_DECL > PARM_BOUNDARY aligned decl, return -1 instead of false. (arm_function_arg): Emit -Wpsabi note if arm_needs_doubleword_align returns negative, increment nregs only if it returned positive. (arm_setup_incoming_varargs): Likewise. (arm_function_arg_boundary): Emit -Wpsabi note if arm_needs_doubleword_align returns negative, return DOUBLEWORD_ALIGNMENT only if it returned positive. testsuite/ * g++.dg/abi/pr77728-1.C: New test. Co-Authored-By: Jakub Jelinek <jakub@redhat.com> From-SVN: r247258
This commit is contained in:
parent
2ef42cf924
commit
7629ae90d8
@ -1,3 +1,21 @@
|
||||
2017-04-25 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
|
||||
Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR target/77728
|
||||
* config/arm/arm.c: Include gimple.h.
|
||||
(aapcs_layout_arg): Emit -Wpsabi note if arm_needs_doubleword_align
|
||||
returns negative, increment ncrn only if it returned positive.
|
||||
(arm_needs_doubleword_align): Return int instead of bool,
|
||||
ignore DECL_ALIGN of non-FIELD_DECL TYPE_FIELDS chain
|
||||
members, but if there is any such non-FIELD_DECL
|
||||
> PARM_BOUNDARY aligned decl, return -1 instead of false.
|
||||
(arm_function_arg): Emit -Wpsabi note if arm_needs_doubleword_align
|
||||
returns negative, increment nregs only if it returned positive.
|
||||
(arm_setup_incoming_varargs): Likewise.
|
||||
(arm_function_arg_boundary): Emit -Wpsabi note if
|
||||
arm_needs_doubleword_align returns negative, return
|
||||
DOUBLEWORD_ALIGNMENT only if it returned positive.
|
||||
|
||||
2017-04-25 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR sanitizer/80349
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include "rtl-iter.h"
|
||||
#include "optabs-libfuncs.h"
|
||||
#include "gimplify.h"
|
||||
#include "gimple.h"
|
||||
|
||||
/* This file should be included last. */
|
||||
#include "target-def.h"
|
||||
@ -81,7 +82,7 @@ struct four_ints
|
||||
|
||||
/* Forward function declarations. */
|
||||
static bool arm_const_not_ok_for_debug_p (rtx);
|
||||
static bool arm_needs_doubleword_align (machine_mode, const_tree);
|
||||
static int arm_needs_doubleword_align (machine_mode, const_tree);
|
||||
static int arm_compute_static_chain_stack_bytes (void);
|
||||
static arm_stack_offsets *arm_get_frame_offsets (void);
|
||||
static void arm_add_gc_roots (void);
|
||||
@ -6349,8 +6350,20 @@ aapcs_layout_arg (CUMULATIVE_ARGS *pcum, machine_mode mode,
|
||||
/* C3 - For double-word aligned arguments, round the NCRN up to the
|
||||
next even number. */
|
||||
ncrn = pcum->aapcs_ncrn;
|
||||
if ((ncrn & 1) && arm_needs_doubleword_align (mode, type))
|
||||
ncrn++;
|
||||
if (ncrn & 1)
|
||||
{
|
||||
int res = arm_needs_doubleword_align (mode, type);
|
||||
/* Only warn during RTL expansion of call stmts, otherwise we would
|
||||
warn e.g. during gimplification even on functions that will be
|
||||
always inlined, and we'd warn multiple times. Don't warn when
|
||||
called in expand_function_start either, as we warn instead in
|
||||
arm_function_arg_boundary in that case. */
|
||||
if (res < 0 && warn_psabi && currently_expanding_gimple_stmt)
|
||||
inform (input_location, "parameter passing for argument of type "
|
||||
"%qT changed in GCC 7.1", type);
|
||||
else if (res > 0)
|
||||
ncrn++;
|
||||
}
|
||||
|
||||
nregs = ARM_NUM_REGS2(mode, type);
|
||||
|
||||
@ -6455,12 +6468,16 @@ arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
|
||||
}
|
||||
}
|
||||
|
||||
/* Return true if mode/type need doubleword alignment. */
|
||||
static bool
|
||||
/* Return 1 if double word alignment is required for argument passing.
|
||||
Return -1 if double word alignment used to be required for argument
|
||||
passing before PR77728 ABI fix, but is not required anymore.
|
||||
Return 0 if double word alignment is not required and wasn't requried
|
||||
before either. */
|
||||
static int
|
||||
arm_needs_doubleword_align (machine_mode mode, const_tree type)
|
||||
{
|
||||
if (!type)
|
||||
return PARM_BOUNDARY < GET_MODE_ALIGNMENT (mode);
|
||||
return GET_MODE_ALIGNMENT (mode) > PARM_BOUNDARY;
|
||||
|
||||
/* Scalar and vector types: Use natural alignment, i.e. of base type. */
|
||||
if (!AGGREGATE_TYPE_P (type))
|
||||
@ -6470,12 +6487,21 @@ arm_needs_doubleword_align (machine_mode mode, const_tree type)
|
||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||
return TYPE_ALIGN (TREE_TYPE (type)) > PARM_BOUNDARY;
|
||||
|
||||
int ret = 0;
|
||||
/* Record/aggregate types: Use greatest member alignment of any member. */
|
||||
for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
|
||||
if (DECL_ALIGN (field) > PARM_BOUNDARY)
|
||||
return true;
|
||||
{
|
||||
if (TREE_CODE (field) == FIELD_DECL)
|
||||
return 1;
|
||||
else
|
||||
/* Before PR77728 fix, we were incorrectly considering also
|
||||
other aggregate fields, like VAR_DECLs, TYPE_DECLs etc.
|
||||
Make sure we can warn about that with -Wpsabi. */
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -6532,10 +6558,15 @@ arm_function_arg (cumulative_args_t pcum_v, machine_mode mode,
|
||||
}
|
||||
|
||||
/* Put doubleword aligned quantities in even register pairs. */
|
||||
if (pcum->nregs & 1
|
||||
&& ARM_DOUBLEWORD_ALIGN
|
||||
&& arm_needs_doubleword_align (mode, type))
|
||||
pcum->nregs++;
|
||||
if ((pcum->nregs & 1) && ARM_DOUBLEWORD_ALIGN)
|
||||
{
|
||||
int res = arm_needs_doubleword_align (mode, type);
|
||||
if (res < 0 && warn_psabi)
|
||||
inform (input_location, "parameter passing for argument of type "
|
||||
"%qT changed in GCC 7.1", type);
|
||||
else if (res > 0)
|
||||
pcum->nregs++;
|
||||
}
|
||||
|
||||
/* Only allow splitting an arg between regs and memory if all preceding
|
||||
args were allocated to regs. For args passed by reference we only count
|
||||
@ -6554,9 +6585,15 @@ arm_function_arg (cumulative_args_t pcum_v, machine_mode mode,
|
||||
static unsigned int
|
||||
arm_function_arg_boundary (machine_mode mode, const_tree type)
|
||||
{
|
||||
return (ARM_DOUBLEWORD_ALIGN && arm_needs_doubleword_align (mode, type)
|
||||
? DOUBLEWORD_ALIGNMENT
|
||||
: PARM_BOUNDARY);
|
||||
if (!ARM_DOUBLEWORD_ALIGN)
|
||||
return PARM_BOUNDARY;
|
||||
|
||||
int res = arm_needs_doubleword_align (mode, type);
|
||||
if (res < 0 && warn_psabi)
|
||||
inform (input_location, "parameter passing for argument of type %qT "
|
||||
"changed in GCC 7.1", type);
|
||||
|
||||
return res > 0 ? DOUBLEWORD_ALIGNMENT : PARM_BOUNDARY;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -26516,8 +26553,15 @@ arm_setup_incoming_varargs (cumulative_args_t pcum_v,
|
||||
if (pcum->pcs_variant <= ARM_PCS_AAPCS_LOCAL)
|
||||
{
|
||||
nregs = pcum->aapcs_ncrn;
|
||||
if ((nregs & 1) && arm_needs_doubleword_align (mode, type))
|
||||
nregs++;
|
||||
if (nregs & 1)
|
||||
{
|
||||
int res = arm_needs_doubleword_align (mode, type);
|
||||
if (res < 0 && warn_psabi)
|
||||
inform (input_location, "parameter passing for argument of "
|
||||
"type %qT changed in GCC 7.1", type);
|
||||
else if (res > 0)
|
||||
nregs++;
|
||||
}
|
||||
}
|
||||
else
|
||||
nregs = pcum->nregs;
|
||||
|
@ -1,3 +1,9 @@
|
||||
2017-04-25 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
|
||||
Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR target/77728
|
||||
* g++.dg/abi/pr77728-1.C: New test.
|
||||
|
||||
2017-04-25 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR sanitizer/80349
|
||||
|
171
gcc/testsuite/g++.dg/abi/pr77728-1.C
Normal file
171
gcc/testsuite/g++.dg/abi/pr77728-1.C
Normal file
@ -0,0 +1,171 @@
|
||||
// { dg-do compile { target arm_eabi } }
|
||||
// { dg-options "-Wpsabi" }
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
template <int N>
|
||||
struct A { double p; };
|
||||
|
||||
A<0> v;
|
||||
|
||||
template <int N>
|
||||
struct B
|
||||
{
|
||||
typedef A<N> T;
|
||||
int i, j;
|
||||
};
|
||||
|
||||
struct C : public B<0> {};
|
||||
struct D {};
|
||||
struct E : public D, C {};
|
||||
struct F : public B<1> {};
|
||||
struct G : public F { static double y; };
|
||||
struct H : public G {};
|
||||
struct I : public D { long long z; };
|
||||
struct J : public D { static double z; int i, j; };
|
||||
|
||||
template <int N>
|
||||
struct K : public D { typedef A<N> T; int i, j; };
|
||||
|
||||
struct L { static double h; int i, j; };
|
||||
|
||||
int
|
||||
fn1 (int a, B<0> b) // { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" }
|
||||
{
|
||||
return a + b.i;
|
||||
}
|
||||
|
||||
int
|
||||
fn2 (int a, B<1> b)
|
||||
{
|
||||
return a + b.i;
|
||||
}
|
||||
|
||||
int
|
||||
fn3 (int a, L b) // { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" }
|
||||
{
|
||||
return a + b.i;
|
||||
}
|
||||
|
||||
int
|
||||
fn4 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, B<0> n, ...)
|
||||
// { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 }
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, n);
|
||||
int x = va_arg (ap, int);
|
||||
va_end (ap);
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
fn5 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, B<1> n, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, n);
|
||||
int x = va_arg (ap, int);
|
||||
va_end (ap);
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
fn6 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, C n, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, n);
|
||||
int x = va_arg (ap, int);
|
||||
va_end (ap);
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
fn7 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, E n, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, n);
|
||||
int x = va_arg (ap, int);
|
||||
va_end (ap);
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
fn8 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, H n, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, n);
|
||||
int x = va_arg (ap, int);
|
||||
va_end (ap);
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
fn9 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, I n, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, n);
|
||||
int x = va_arg (ap, int);
|
||||
va_end (ap);
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
fn10 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, J n, ...)
|
||||
// { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 }
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, n);
|
||||
int x = va_arg (ap, int);
|
||||
va_end (ap);
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
fn11 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, K<0> n, ...)
|
||||
// { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 }
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, n);
|
||||
int x = va_arg (ap, int);
|
||||
va_end (ap);
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
fn12 (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, K<2> n, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start (ap, n);
|
||||
int x = va_arg (ap, int);
|
||||
va_end (ap);
|
||||
return x;
|
||||
}
|
||||
|
||||
void
|
||||
test ()
|
||||
{
|
||||
static B<0> b0;
|
||||
static B<1> b1;
|
||||
static L l;
|
||||
static C c;
|
||||
static E e;
|
||||
static H h;
|
||||
static I i;
|
||||
static J j;
|
||||
static K<0> k0;
|
||||
static K<2> k2;
|
||||
fn1 (1, b0); // { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" }
|
||||
fn2 (1, b1);
|
||||
fn3 (1, l); // { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" }
|
||||
fn4 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, b0, 1, 2, 3, 4);
|
||||
// { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 }
|
||||
fn5 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, b1, 1, 2, 3, 4);
|
||||
fn6 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, c, 1, 2, 3, 4);
|
||||
fn7 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, e, 1, 2, 3, 4);
|
||||
fn8 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, h, 1, 2, 3, 4);
|
||||
fn9 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, i, 1, 2, 3, 4);
|
||||
fn10 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, j, 1, 2, 3, 4);
|
||||
// { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 }
|
||||
fn11 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, k0, 1, 2, 3, 4);
|
||||
// { dg-message "note: parameter passing for argument of type \[^\n\r]* changed in GCC 7\.1" "" { target *-*-* } .-1 }
|
||||
fn12 (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, k2, 1, 2, 3, 4);
|
||||
}
|
Loading…
Reference in New Issue
Block a user