From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1855 invoked by alias); 27 May 2011 20:41:31 -0000 Received: (qmail 1780 invoked by uid 22791); 27 May 2011 20:41:22 -0000 X-SWARE-Spam-Status: No, hits=0.6 required=5.0 tests=AWL,BAYES_50,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SARE_OBFU_ALL,SARE_OBFU_PART_CIA,SPF_HELO_PASS,TW_CP,TW_FC,TW_FN,TW_IV,TW_XF,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.44.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 27 May 2011 20:40:56 +0000 Received: from hpaq12.eem.corp.google.com (hpaq12.eem.corp.google.com [172.25.149.12]) by smtp-out.google.com with ESMTP id p4RKesO2020961; Fri, 27 May 2011 13:40:54 -0700 Received: from topo.tor.corp.google.com (topo.tor.corp.google.com [172.29.41.2]) by hpaq12.eem.corp.google.com with ESMTP id p4RKekPh029443; Fri, 27 May 2011 13:40:47 -0700 Received: by topo.tor.corp.google.com (Postfix, from userid 54752) id 29FA41DA1CA; Fri, 27 May 2011 16:40:46 -0400 (EDT) To: reply@codereview.appspotmail.com, crowl@google.com, gcc-patches@gcc.gnu.org Subject: [pph] Add C-level tests (issue4528104) Message-Id: <20110527204046.29FA41DA1CA@topo.tor.corp.google.com> Date: Sat, 28 May 2011 00:52:00 -0000 From: dnovillo@google.com (Diego Novillo) X-System-Of-Record: true X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2011-05/txt/msg02216.txt.bz2 More C tests that used to fail. There is roughly one test per class of failure that I fixed with previous patches. Committed to branch. Diego. * g++.dg/pph/c1attr-warn-unused-result.cc: New. * g++.dg/pph/c1attr-warn-unused-result.h: New. * g++.dg/pph/c1builtin-integral-1.cc: New. * g++.dg/pph/c1builtin-integral-1.h: New. * g++.dg/pph/c1builtin-object-size-2.cc: New. * g++.dg/pph/c1builtin-object-size-2.h: New. * g++.dg/pph/c1eabi1.cc: New. * g++.dg/pph/c1eabi1.h: New. * g++.dg/pph/c1meteor-contest.cc: New. * g++.dg/pph/c1meteor-contest.h: New. * g++.dg/pph/c1pr36533.cc: New. * g++.dg/pph/c1pr36533.h: New. * g++.dg/pph/c1pr44948-1a.cc: New. * g++.dg/pph/c1pr44948-1a.h: New. diff --git a/gcc/testsuite/g++.dg/pph/c1attr-warn-unused-result.cc b/gcc/testsuite/g++.dg/pph/c1attr-warn-unused-result.cc new file mode 100644 index 0000000..921d294 --- /dev/null +++ b/gcc/testsuite/g++.dg/pph/c1attr-warn-unused-result.cc @@ -0,0 +1,2 @@ +/* { dg-options "-w" } */ +#include "c1attr-warn-unused-result.h" diff --git a/gcc/testsuite/g++.dg/pph/c1attr-warn-unused-result.h b/gcc/testsuite/g++.dg/pph/c1attr-warn-unused-result.h new file mode 100644 index 0000000..bfa2903 --- /dev/null +++ b/gcc/testsuite/g++.dg/pph/c1attr-warn-unused-result.h @@ -0,0 +1,189 @@ +#ifndef __PPH_GUARD_H +#define __PPH_GUARD_H +/* { dg-options "-w" } */ + +#define WUR __attribute__((warn_unused_result)) +#define WURAI __attribute__((warn_unused_result, always_inline)) inline +typedef WUR int (*fnt) (void); + +typedef struct { long i; } A; +typedef struct { long i; long j; } B; +typedef struct { char big[1024]; fnt fn; } C; + +WUR int check1 (void); +WUR void check2 (void); +int foo WUR; +int bar (void); +extern WURAI int check3 (void) { return bar (); } +WUR A check4 (void); +WUR B check5 (void); +WUR C check6 (void); +A bar7 (void); +B bar8 (void); +C bar9 (void); +extern WURAI A check7 (void) { return bar7 (); } +extern WURAI B check8 (void) { return bar8 (); } +extern WURAI C check9 (void) { return bar9 (); } +/* This is useful for checking whether return value of statement + expressions (returning int in this case) is used. */ +extern WURAI int check_int_result (int res) { return res; } +#define GU(v) ({ int e = 0; (v) = bar (); if ((v) < 23) e = 14; e; }) +fnt fnptr; +WUR int check10 (void); +int baz (void); +extern WURAI int check11 (void) { return baz (); } +int k; + +void +test (void) +{ + int i = 0, j; + const fnt pcheck1 = check1; + const fnt pcheck3 = check3; + A a; + B b; + C c; + if (check1 ()) + return; + i += check1 (); + i += ({ check1 (); }); + check1 (); + (void) check1 (); + check1 (), bar (); + check2 (); + (void) check2 (); + check2 (), bar (); + if (check3 ()) + return; + i += check3 (); + i += ({ check3 (); }); + check3 (); + (void) check3 (); + check3 (), bar (); + a = check4 (); + if (a.i) + return; + if (check4 ().i) + return; + if (({ check4 (); }).i) + return; + check4 (); + (void) check4 (); + check4 (), bar (); + b = check5 (); + if (b.i + b.j) + return; + if (check5 ().j) + return; + if (({ check5 (); }).j) + return; + check5 (); + (void) check5 (); + check5 (), bar (); + c = check6 (); + if (c.big[12] + c.big[29]) + return; + if (check6 ().big[27]) + return; + if (({ check6 (); }).big[0]) + return; + check6 (); + (void) check6 (); + check6 (), bar (); + a = check7 (); + if (a.i) + return; + if (check7 ().i) + return; + if (({ check7 (); }).i) + return; + check7 (); + (void) check7 (); + check7 (), bar (); + b = check8 (); + if (b.i + b.j) + return; + if (check8 ().j) + return; + if (({ check8 (); }).j) + return; + check8 (); + (void) check8 (); + check8 (), bar (); + c = check9 (); + if (c.big[12] + c.big[29]) + return; + if (check9 ().big[27]) + return; + if (({ check9 (); }).big[0]) + return; + check9 (); + (void) check9 (); + check9 (), bar (); + if (check_int_result (GU (j))) + return; + i += check_int_result (GU (j)); + i += ({ check_int_result (GU (j)); }); + check_int_result (GU (j)); + (void) check_int_result (GU (j)); + check_int_result (GU (j)), bar (); + if (fnptr ()) + return; + i += fnptr (); + i += ({ fnptr (); }); + fnptr (); + (void) fnptr (); + fnptr (), bar (); + fnptr = check1; + if (fnptr ()) + return; + i += fnptr (); + i += ({ fnptr (); }); + fnptr (); + (void) fnptr (); + fnptr (), bar (); + fnptr = check3; + if (fnptr ()) + return; + i += fnptr (); + i += ({ fnptr (); }); + fnptr (); + (void) fnptr (); + fnptr (), bar (); + if (bar9 ().fn ()) + return; + i += bar9 ().fn (); + i += ({ bar9 ().fn (); }); + bar9 ().fn (); + (void) bar9 ().fn (); + bar9 ().fn (), bar (); + if ((k ? check1 : check10) ()) + return; + i += (k ? check1 : check10) (); + i += ({ (k ? check1 : check10) (); }); + (k ? check1 : check10) (); + (void) (k ? check1 : check10) (); + (k ? check1 : check10) (), bar (); + if ((k ? check3 : check11) ()) + return; + i += (k ? check3 : check11) (); + i += ({ (k ? check3 : check11) (); }); + (k ? check3 : check11) (); + (void) (k ? check3 : check11) (); + (k ? check3 : check11) (), bar (); + if (pcheck1 ()) + return; + i += pcheck1 (); + i += ({ pcheck1 (); }); + pcheck1 (); + (void) pcheck1 (); + pcheck1 (), bar (); + if (pcheck3 ()) + return; + i += pcheck3 (); + i += ({ pcheck3 (); }); + pcheck3 (); + (void) pcheck3 (); + pcheck3 (), bar (); +} +#endif diff --git a/gcc/testsuite/g++.dg/pph/c1builtin-integral-1.cc b/gcc/testsuite/g++.dg/pph/c1builtin-integral-1.cc new file mode 100644 index 0000000..bf53219 --- /dev/null +++ b/gcc/testsuite/g++.dg/pph/c1builtin-integral-1.cc @@ -0,0 +1 @@ +#include "c1builtin-integral-1.h" diff --git a/gcc/testsuite/g++.dg/pph/c1builtin-integral-1.h b/gcc/testsuite/g++.dg/pph/c1builtin-integral-1.h new file mode 100644 index 0000000..46577b8 --- /dev/null +++ b/gcc/testsuite/g++.dg/pph/c1builtin-integral-1.h @@ -0,0 +1,71 @@ +#ifndef __PPH_GUARD_H +#define __PPH_GUARD_H +/* Copyright (C) 2004 Free Software Foundation. + + Verify that integral FP expressions are optimized. + + Written by Kaveh Ghazi, 2004-03-16. */ + +/* We need -ffinite-math-only so that we can fold "foo != foo", where + foo is a floating point expression. We need -fno-math-errno so + that various math functions are marked const/pure and can be + folded. */ +/* { dg-options "-ffinite-math-only -fno-math-errno" } */ + +extern int link_failure (int); + +/* Test that the various FP truncation builtins detect integral + arguments. */ +#define CHECK_FN(MATHFN) \ + if (__builtin_##MATHFN(i1) != i1) link_failure (__LINE__); \ + if (__builtin_##MATHFN##f(i1) != i1) link_failure (__LINE__); \ + if (__builtin_##MATHFN##l(i1) != i1) link_failure (__LINE__); + +#define CHECK_FN_RET(MATHFN, RET) \ + if (__builtin_##MATHFN(i1) != (RET)(double)i1) link_failure (__LINE__); \ + if (__builtin_##MATHFN##f(i1) != (RET)(float)i1) link_failure (__LINE__); \ + if (__builtin_##MATHFN##l(i1) != (RET)(long double)i1) link_failure (__LINE__); + + /* Check that various other integral expressions are detected. */ +#define CHECK_EXPR(EXPR,NAME) \ + if (__builtin_ceill(EXPR) != (EXPR)) link_failure (__LINE__); \ + if (__builtin_lroundl(EXPR) != (long)(long double)(EXPR)) link_failure (__LINE__); + +void __attribute__ ((__noinline__)) test (int i1, int i2) +{ + CHECK_FN(ceil); + CHECK_FN(floor); + CHECK_FN(nearbyint); + CHECK_FN(rint); + CHECK_FN(round); + CHECK_FN(trunc); + CHECK_FN_RET(lround, long); + CHECK_FN_RET(llround, long long); + CHECK_FN_RET(lrint, long); + CHECK_FN_RET(llrint, long long); + CHECK_FN_RET(lceil, long); + CHECK_FN_RET(llceil, long long); + CHECK_FN_RET(lfloor, long); + CHECK_FN_RET(llfloor, long long); + + CHECK_EXPR (5.0, REAL_CST); + CHECK_EXPR (5.0F, REAL_CSTf); + CHECK_EXPR (5.0L, REAL_CSTl); + CHECK_EXPR ((double)i1, FLOAT_EXPR); + CHECK_EXPR ((float)i1, FLOAT_EXPRf); + CHECK_EXPR ((long double)i1, FLOAT_EXPRl); + CHECK_EXPR (__builtin_fabs(i1), ABS_EXPR); + CHECK_EXPR (__builtin_fabsf(i1), ABS_EXPRf); + CHECK_EXPR (__builtin_fabsl(i1), ABS_EXPRl); + CHECK_EXPR (((void)i1,(double)i2), COMPOUND_EXPR); + CHECK_EXPR ((double)i1+i2, PLUS_EXPR); + CHECK_EXPR ((double)i1-i2, MINUS_EXPR); + CHECK_EXPR ((double)i1*i2, MULT_EXPR); +} + +int main (void) +{ + test (1, 2); + return 0; +} +#endif diff --git a/gcc/testsuite/g++.dg/pph/c1builtin-object-size-2.cc b/gcc/testsuite/g++.dg/pph/c1builtin-object-size-2.cc new file mode 100644 index 0000000..615e7da --- /dev/null +++ b/gcc/testsuite/g++.dg/pph/c1builtin-object-size-2.cc @@ -0,0 +1,2 @@ +/* { dg-options "-O2 -w -fpermissive" } */ +#include "c1builtin-object-size-2.h" diff --git a/gcc/testsuite/g++.dg/pph/c1builtin-object-size-2.h b/gcc/testsuite/g++.dg/pph/c1builtin-object-size-2.h new file mode 100644 index 0000000..a1636e9 --- /dev/null +++ b/gcc/testsuite/g++.dg/pph/c1builtin-object-size-2.h @@ -0,0 +1,395 @@ +#ifndef __PPH_GUARD_H +#define __PPH_GUARD_H +/* { dg-options "-w -fpermissive" } */ + +typedef __SIZE_TYPE__ size_t; +extern void abort (void); +extern void exit (int); +extern void *malloc (size_t); +extern void *calloc (size_t, size_t); +extern void *alloca (size_t); +extern void *memcpy (void *, const void *, size_t); +extern void *memset (void *, int, size_t); +extern char *strcpy (char *, const char *); + +struct A +{ + char a[10]; + int b; + char c[10]; +} y, w[4]; + +extern char exta[]; +extern char extb[30]; +extern struct A extc[]; +struct A zerol[0]; + +void +__attribute__ ((noinline)) +test1 (void *q, int x) +{ + struct A a; + void *p = &a.a[3], *r; + char var[x + 10]; + struct A vara[x + 10]; + if (x < 0) + r = &a.a[9]; + else + r = &a.c[1]; + if (__builtin_object_size (p, 1) != sizeof (a.a) - 3) + abort (); + if (__builtin_object_size (&a.c[9], 1) + != sizeof (a.c) - 9) + abort (); + if (__builtin_object_size (q, 1) != (size_t) -1) + abort (); + if (__builtin_object_size (r, 1) != sizeof (a.c) - 1) + abort (); + if (x < 6) + r = &w[2].a[1]; + else + r = &a.a[6]; + if (__builtin_object_size (&y, 1) != sizeof (y)) + abort (); + if (__builtin_object_size (w, 1) != sizeof (w)) + abort (); + if (__builtin_object_size (&y.b, 1) != sizeof (a.b)) + abort (); + if (__builtin_object_size (r, 1) != sizeof (a.a) - 1) + abort (); + if (x < 20) + r = malloc (30); + else + r = calloc (2, 16); + if (__builtin_object_size (r, 1) != 2 * 16) + abort (); + if (x < 20) + r = malloc (30); + else + r = calloc (2, 14); + if (__builtin_object_size (r, 1) != 30) + abort (); + if (x < 30) + r = malloc (sizeof (a)); + else + r = &a.a[3]; + if (__builtin_object_size (r, 1) != sizeof (a)) + abort (); + r = memcpy (r, "a", 2); + if (__builtin_object_size (r, 1) != sizeof (a)) + abort (); + r = memcpy (r + 2, "b", 2) + 2; + if (__builtin_object_size (r, 1) != sizeof (a) - 4) + abort (); + r = &a.a[4]; + r = memset (r, 'a', 2); + if (__builtin_object_size (r, 1) != sizeof (a.a) - 4) + abort (); + r = memset (r + 2, 'b', 2) + 2; + if (__builtin_object_size (r, 1) != sizeof (a.a) - 8) + abort (); + r = &a.a[1]; + r = strcpy (r, "ab"); + if (__builtin_object_size (r, 1) != sizeof (a.a) - 1) + abort (); + r = strcpy (r + 2, "cd") + 2; + if (__builtin_object_size (r, 1) != sizeof (a.a) - 5) + abort (); + if (__builtin_object_size (exta, 1) != (size_t) -1) + abort (); + if (__builtin_object_size (exta + 10, 1) != (size_t) -1) + abort (); + if (__builtin_object_size (&exta[5], 1) != (size_t) -1) + abort (); + if (__builtin_object_size (extb, 1) != sizeof (extb)) + abort (); + if (__builtin_object_size (extb + 10, 1) != sizeof (extb) - 10) + abort (); + if (__builtin_object_size (&extb[5], 1) != sizeof (extb) - 5) + abort (); + if (__builtin_object_size (extc, 1) != (size_t) -1) + abort (); + if (__builtin_object_size (extc + 10, 1) != (size_t) -1) + abort (); + if (__builtin_object_size (&extc[5], 1) != (size_t) -1) + abort (); + if (__builtin_object_size (&extc->a, 1) != (size_t) -1) + abort (); + if (__builtin_object_size (&(extc + 10)->b, 1) != (size_t) -1) + abort (); + if (__builtin_object_size (&extc[5].c[3], 1) != (size_t) -1) + abort (); + if (__builtin_object_size (var, 1) != (size_t) -1) + abort (); + if (__builtin_object_size (var + 10, 1) != (size_t) -1) + abort (); + if (__builtin_object_size (&var[5], 1) != (size_t) -1) + abort (); + if (__builtin_object_size (vara, 1) != (size_t) -1) + abort (); + if (__builtin_object_size (vara + 10, 1) != (size_t) -1) + abort (); + if (__builtin_object_size (&vara[5], 1) != (size_t) -1) + abort (); + if (__builtin_object_size (&vara[0].a, 1) != sizeof (vara[0].a)) + abort (); + if (__builtin_object_size (&vara[10].a[0], 1) != sizeof (vara[0].a)) + abort (); + if (__builtin_object_size (&vara[5].a[4], 1) != sizeof (vara[0].a) - 4) + abort (); + if (__builtin_object_size (&vara[5].b, 1) != sizeof (vara[0].b)) + abort (); + if (__builtin_object_size (&vara[7].c[7], 1) != sizeof (vara[0].c) - 7) + abort (); + if (__builtin_object_size (zerol, 1) != 0) + abort (); + if (__builtin_object_size (&zerol, 1) != 0) + abort (); + if (__builtin_object_size (&zerol[0], 1) != 0) + abort (); + if (__builtin_object_size (zerol[0].a, 1) != 0) + abort (); + if (__builtin_object_size (&zerol[0].a[0], 1) != 0) + abort (); + if (__builtin_object_size (&zerol[0].b, 1) != 0) + abort (); + if (__builtin_object_size ("abcdefg", 1) != sizeof ("abcdefg")) + abort (); + if (__builtin_object_size ("abcd\0efg", 1) != sizeof ("abcd\0efg")) + abort (); + if (__builtin_object_size (&"abcd\0efg", 1) != sizeof ("abcd\0efg")) + abort (); + if (__builtin_object_size (&"abcd\0efg"[0], 1) != sizeof ("abcd\0efg")) + abort (); + if (__builtin_object_size (&"abcd\0efg"[4], 1) != sizeof ("abcd\0efg") - 4) + abort (); + if (__builtin_object_size ("abcd\0efg" + 5, 1) != sizeof ("abcd\0efg") - 5) + abort (); + if (__builtin_object_size (L"abcdefg", 1) != sizeof (L"abcdefg")) + abort (); + r = (char *) L"abcd\0efg"; + if (__builtin_object_size (r + 2, 1) != sizeof (L"abcd\0efg") - 2) + abort (); +} + +size_t l1 = 1; + +void +__attribute__ ((noinline)) +test2 (void) +{ + struct B { char buf1[10]; char buf2[10]; } a; + char *r, buf3[20]; + int i; + + if (sizeof (a) != 20) + return; + + r = buf3; + for (i = 0; i < 4; ++i) + { + if (i == l1 - 1) + r = &a.buf1[1]; + else if (i == l1) + r = &a.buf2[7]; + else if (i == l1 + 1) + r = &buf3[5]; + else if (i == l1 + 2) + r = &a.buf1[9]; + } + if (__builtin_object_size (r, 1) != sizeof (buf3)) + abort (); + r = &buf3[20]; + for (i = 0; i < 4; ++i) + { + if (i == l1 - 1) + r = &a.buf1[7]; + else if (i == l1) + r = &a.buf2[7]; + else if (i == l1 + 1) + r = &buf3[5]; + else if (i == l1 + 2) + r = &a.buf1[9]; + } + if (__builtin_object_size (r, 1) != sizeof (buf3) - 5) + abort (); + r += 8; + if (__builtin_object_size (r, 1) != sizeof (buf3) - 13) + abort (); + if (__builtin_object_size (r + 6, 1) != sizeof (buf3) - 19) + abort (); +} + +void +__attribute__ ((noinline)) +test3 (void) +{ + char buf4[10]; + struct B { struct A a[2]; struct A b; char c[4]; char d; double e; + _Complex double f; } x; + double y; + _Complex double z; + double *dp; + + if (__builtin_object_size (buf4, 1) != sizeof (buf4)) + abort (); + if (__builtin_object_size (&buf4, 1) != sizeof (buf4)) + abort (); + if (__builtin_object_size (&buf4[0], 1) != sizeof (buf4)) + abort (); + if (__builtin_object_size (&buf4[1], 1) != sizeof (buf4) - 1) + abort (); + if (__builtin_object_size (&x, 1) != sizeof (x)) + abort (); + if (__builtin_object_size (&x.a, 1) != sizeof (x.a)) + abort (); + if (__builtin_object_size (&x.a[0], 1) != sizeof (x.a)) + abort (); + if (__builtin_object_size (&x.a[0].a, 1) != sizeof (x.a[0].a)) + abort (); + if (__builtin_object_size (&x.a[0].a[0], 1) != sizeof (x.a[0].a)) + abort (); + if (__builtin_object_size (&x.a[0].a[3], 1) != sizeof (x.a[0].a) - 3) + abort (); + if (__builtin_object_size (&x.a[0].b, 1) != sizeof (x.a[0].b)) + abort (); + if (__builtin_object_size (&x.a[1].c, 1) != sizeof (x.a[1].c)) + abort (); + if (__builtin_object_size (&x.a[1].c[0], 1) != sizeof (x.a[1].c)) + abort (); + if (__builtin_object_size (&x.a[1].c[3], 1) != sizeof (x.a[1].c) - 3) + abort (); + if (__builtin_object_size (&x.b, 1) != sizeof (x.b)) + abort (); + if (__builtin_object_size (&x.b.a, 1) != sizeof (x.b.a)) + abort (); + if (__builtin_object_size (&x.b.a[0], 1) != sizeof (x.b.a)) + abort (); + if (__builtin_object_size (&x.b.a[3], 1) != sizeof (x.b.a) - 3) + abort (); + if (__builtin_object_size (&x.b.b, 1) != sizeof (x.b.b)) + abort (); + if (__builtin_object_size (&x.b.c, 1) != sizeof (x.b.c)) + abort (); + if (__builtin_object_size (&x.b.c[0], 1) != sizeof (x.b.c)) + abort (); + if (__builtin_object_size (&x.b.c[3], 1) != sizeof (x.b.c) - 3) + abort (); + if (__builtin_object_size (&x.c, 1) != sizeof (x.c)) + abort (); + if (__builtin_object_size (&x.c[0], 1) != sizeof (x.c)) + abort (); + if (__builtin_object_size (&x.c[1], 1) != sizeof (x.c) - 1) + abort (); + if (__builtin_object_size (&x.d, 1) != sizeof (x.d)) + abort (); + if (__builtin_object_size (&x.e, 1) != sizeof (x.e)) + abort (); + if (__builtin_object_size (&x.f, 1) != sizeof (x.f)) + abort (); + dp = &__real__ x.f; + if (__builtin_object_size (dp, 1) != sizeof (x.f) / 2) + abort (); + dp = &__imag__ x.f; + if (__builtin_object_size (dp, 1) != sizeof (x.f) / 2) + abort (); + dp = &y; + if (__builtin_object_size (dp, 1) != sizeof (y)) + abort (); + if (__builtin_object_size (&z, 1) != sizeof (z)) + abort (); + dp = &__real__ z; + if (__builtin_object_size (dp, 1) != sizeof (z) / 2) + abort (); + dp = &__imag__ z; + if (__builtin_object_size (dp, 1) != sizeof (z) / 2) + abort (); +} + +struct S { unsigned int a; }; + +char * +__attribute__ ((noinline)) +test4 (char *x, int y) +{ + register int i; + struct A *p; + + for (i = 0; i < y; i++) + { + p = (struct A *) x; + x = (char *) &p[1]; + if (__builtin_object_size (p, 1) != (size_t) -1) + abort (); + } + return x; +} + +void +__attribute__ ((noinline)) +test5 (size_t x) +{ + struct T { char buf[64]; char buf2[64]; } t; + char *p = &t.buf[8]; + size_t i; + + for (i = 0; i < x; ++i) + p = p + 4; + if (__builtin_object_size (p, 1) != sizeof (t.buf) - 8) + abort (); + memset (p, ' ', sizeof (t.buf) - 8 - 4 * 4); +} + +void +__attribute__ ((noinline)) +test6 (void) +{ + char buf[64]; + struct T { char buf[64]; char buf2[64]; } t; + char *p = &buf[64], *q = &t.buf[64]; + + if (__builtin_object_size (p + 64, 1) != 0) + abort (); + if (__builtin_object_size (q + 0, 1) != 0) + abort (); + if (__builtin_object_size (q + 64, 1) != 0) + abort (); +} + +void +__attribute__ ((noinline)) +test7 (void) +{ + struct T { char buf[10]; char buf2[10]; } t; + char *p = &t.buf2[-4]; + char *q = &t.buf2[0]; + if (__builtin_object_size (p, 1) != 0) + abort (); + if (__builtin_object_size (q, 1) != sizeof (t.buf2)) + abort (); + q = &t.buf[10]; + if (__builtin_object_size (q, 1) != 0) + abort (); + q = &t.buf[11]; + if (__builtin_object_size (q, 1) != 0) + abort (); + p = &t.buf[-4]; + if (__builtin_object_size (p, 1) != 0) + abort (); +} + +int +main (void) +{ + struct S s[10]; + __asm ("" : "=r" (l1) : "0" (l1)); + test1 (main, 6); + test2 (); + test3 (); + test4 ((char *) s, 10); + test5 (4); + test6 (); + test7 (); + exit (0); +} +#endif diff --git a/gcc/testsuite/g++.dg/pph/c1eabi1.cc b/gcc/testsuite/g++.dg/pph/c1eabi1.cc new file mode 100644 index 0000000..5680787 --- /dev/null +++ b/gcc/testsuite/g++.dg/pph/c1eabi1.cc @@ -0,0 +1,4 @@ +/* { dg-options "-w -fpermissive" } */ +/* { dg-xfail-if "ICEs the compiler during PPH read" { "*-*-*" } } */ +/* { dg-prune-output "In file included.*" } */ +#include "c1eabi1.h" diff --git a/gcc/testsuite/g++.dg/pph/c1eabi1.h b/gcc/testsuite/g++.dg/pph/c1eabi1.h new file mode 100644 index 0000000..3ac35ce --- /dev/null +++ b/gcc/testsuite/g++.dg/pph/c1eabi1.h @@ -0,0 +1,345 @@ +#ifndef __PPH_GUARD_H +#define __PPH_GUARD_H +/* { dg-options "-w -fpermissive" } */ +/* { dg-xfail-if "ICEs the compiler during PPH read" { "*-*-*" } } */ +/* { dg-prune-output "In file included.*" } */ +/* This file tests most of the non-C++ run-time helper functions + described in Section 4 of the "Run-Time ABI for the ARM + Architecture". These are basic tests; they do not try to validate + all of the corner cases in these routines. + + The functions not tested here are: + + __aeabi_cdcmpeq + __aeabi_cdcmple + __aeabi_cdrcmple + __aeabi_cfcmpeq + __aeabi_cfcmple + __aeabi_cfrcmple + __aeabi_ldivmod + __aeabi_uldivmod + __aeabi_idivmod + __aeabi_uidivmod + + These functions have non-standard calling conventions that would + require the use of inline assembly to test. It would be good to + add such tests, but they have not yet been implemented. + + There are also no tests for the "division by zero", "memory copying, + clearing, and setting" functions. */ + +#include +#include +#include + +/* All these functions are defined to use the base ABI, so use the + attribute to ensure the tests use the base ABI to call them even + when the VFP ABI is otherwise in effect. */ +#define PCS __attribute__((pcs("aapcs"))) + +#define decl_float(code, type) \ + extern type __aeabi_ ## code ## add (type, type) PCS; \ + extern type __aeabi_ ## code ## div (type, type) PCS; \ + extern type __aeabi_ ## code ## mul (type, type) PCS; \ + extern type __aeabi_ ## code ## neg (type) PCS; \ + extern type __aeabi_ ## code ## rsub (type, type) PCS; \ + extern type __aeabi_ ## code ## sub (type, type) PCS; \ + extern int __aeabi_ ## code ## cmpeq (type, type) PCS; \ + extern int __aeabi_ ## code ## cmplt (type, type) PCS; \ + extern int __aeabi_ ## code ## cmple (type, type) PCS; \ + extern int __aeabi_ ## code ## cmpge (type, type) PCS; \ + extern int __aeabi_ ## code ## cmpgt (type, type) PCS; \ + extern int __aeabi_ ## code ## cmpun (type, type) PCS; \ + extern int __aeabi_ ## code ## 2iz (type) PCS; \ + extern unsigned int __aeabi_ ## code ## 2uiz (type) PCS; \ + extern long long __aeabi_ ## code ## 2lz (type) PCS; \ + extern unsigned long long __aeabi_ ## code ## 2ulz (type) PCS; \ + extern type __aeabi_i2 ## code (int) PCS; \ + extern type __aeabi_ui2 ## code (int) PCS; \ + extern type __aeabi_l2 ## code (long long) PCS; \ + extern type __aeabi_ul2 ## code (unsigned long long) PCS; \ + \ + type code ## zero = 0.0; \ + type code ## one = 1.0; \ + type code ## two = 2.0; \ + type code ## four = 4.0; \ + type code ## minus_one = -1.0; \ + type code ## minus_two = -2.0; \ + type code ## minus_four = -4.0; \ + type code ## epsilon = 1E-32; \ + type code ## NaN = 0.0 / 0.0; + +decl_float (d, double) +decl_float (f, float) + +extern float __aeabi_d2f (double) PCS; +extern double __aeabi_f2d (float) PCS; +extern long long __aeabi_lmul (long long, long long); +extern long long __aeabi_llsl (long long, int); +extern long long __aeabi_llsr (long long, int); +extern long long __aeabi_lasr (long long, int); +extern int __aeabi_lcmp (long long, long long); +extern int __aeabi_ulcmp (unsigned long long, unsigned long long); +extern int __aeabi_idiv (int, int); +extern unsigned int __aeabi_uidiv (unsigned int, unsigned int); +extern int __aeabi_uread4 (void *); +extern int __aeabi_uwrite4 (int, void *); +extern long long __aeabi_uread8 (void *); +extern long long __aeabi_uwrite8 (long long, void *); + +#define eq(a, b, type, abs, epsilon, format) \ + { \ + type a1; \ + type b1; \ + \ + a1 = a; \ + b1 = b; \ + if (abs (a1 - b1) > epsilon) \ + { \ + fprintf (stderr, "%d: Test %s == %s\n", __LINE__, #a, #b); \ + fprintf (stderr, "%d: " format " != " format "\n", \ + __LINE__, a1, b1); \ + abort (); \ + } \ + } + +#define ieq(a, b) eq (a, b, int, abs, 0, "%d") +#define ueq(a, b) eq (a, b, unsigned int, abs, 0, "%u") +#define leq(a, b) eq (a, b, long long, abs, 0, "%lld") +#define uleq(a, b) eq (a, b, unsigned long long, abs, 0, "%llu") +#define feq(a, b) eq (a, b, float, fabs, fepsilon, "%f") +#define deq(a, b) eq (a, b, double, fabs, depsilon, "%g") + +#define NUM_CMP_VALUES 6 + +/* Values picked to cover a range of small, large, positive and negative. */ +static unsigned int cmp_val[NUM_CMP_VALUES] = +{ + 0, + 1, + 0x40000000, + 0x80000000, + 0xc0000000, + 0xffffffff +}; + +/* All combinations for each of the above values. */ +#define ulcmp(l, s, m) \ + s, l, l, l, l, l, m, s, l, l, l, l, \ + m, m, s, l, l, l, m, m, m, s, l, l, \ + m, m, m, m, s, l, m, m, m, m, m, s + +#define lcmp(l, s, m) \ + s, l, l, m, m, m, m, s, l, m, m, m, \ + m, m, s, m, m, m, l, l, l, s, l, l, \ + l, l, l, m, s, l, l, l, l, m, m, s + +/* All combinations of the above for high/low words. */ +static int lcmp_results[] = +{ + lcmp(ulcmp(-1, -1, -1), ulcmp(-1, 0, 1), ulcmp(1, 1, 1)) +}; + +static int ulcmp_results[] = +{ + ulcmp(ulcmp(-1, -1, -1), ulcmp(-1, 0, 1), ulcmp(1, 1, 1)) +}; + +static int signof(int i) +{ + if (i < 0) + return -1; + + if (i == 0) + return 0; + + return 1; +} + +int main () { + unsigned char bytes[256]; + int i, j, k, n; + int *result; + + /* Table 2. Double-precision floating-point arithmetic. */ + deq (__aeabi_dadd (dzero, done), done); + deq (__aeabi_dadd (done, done), dtwo); + deq (__aeabi_ddiv (dminus_four, dminus_two), dtwo); + deq (__aeabi_ddiv (dminus_two, dtwo), dminus_one); + deq (__aeabi_dmul (dtwo, dtwo), dfour); + deq (__aeabi_dmul (dminus_one, dminus_two), dtwo); + deq (__aeabi_dneg (dminus_one), done); + deq (__aeabi_dneg (dfour), dminus_four); + deq (__aeabi_drsub (done, dzero), dminus_one); + deq (__aeabi_drsub (dtwo, dminus_two), dminus_four); + deq (__aeabi_dsub (dzero, done), dminus_one); + deq (__aeabi_dsub (dminus_two, dtwo), dminus_four); + + /* Table 3. Double-precision floating-point comparisons. */ + ieq (__aeabi_dcmpeq (done, done), 1); + ieq (__aeabi_dcmpeq (done, dzero), 0); + ieq (__aeabi_dcmpeq (dNaN, dzero), 0); + ieq (__aeabi_dcmpeq (dNaN, dNaN), 0); + + ieq (__aeabi_dcmplt (dzero, done), 1); + ieq (__aeabi_dcmplt (done, dzero), 0); + ieq (__aeabi_dcmplt (dzero, dzero), 0); + ieq (__aeabi_dcmplt (dzero, dNaN), 0); + ieq (__aeabi_dcmplt (dNaN, dNaN), 0); + + ieq (__aeabi_dcmple (dzero, done), 1); + ieq (__aeabi_dcmple (done, dzero), 0); + ieq (__aeabi_dcmple (dzero, dzero), 1); + ieq (__aeabi_dcmple (dzero, dNaN), 0); + ieq (__aeabi_dcmple (dNaN, dNaN), 0); + + ieq (__aeabi_dcmpge (dzero, done), 0); + ieq (__aeabi_dcmpge (done, dzero), 1); + ieq (__aeabi_dcmpge (dzero, dzero), 1); + ieq (__aeabi_dcmpge (dzero, dNaN), 0); + ieq (__aeabi_dcmpge (dNaN, dNaN), 0); + + ieq (__aeabi_dcmpgt (dzero, done), 0); + ieq (__aeabi_dcmpgt (done, dzero), 1); + ieq (__aeabi_dcmplt (dzero, dzero), 0); + ieq (__aeabi_dcmpgt (dzero, dNaN), 0); + ieq (__aeabi_dcmpgt (dNaN, dNaN), 0); + + ieq (__aeabi_dcmpun (done, done), 0); + ieq (__aeabi_dcmpun (done, dzero), 0); + ieq (__aeabi_dcmpun (dNaN, dzero), 1); + ieq (__aeabi_dcmpun (dNaN, dNaN), 1); + + /* Table 4. Single-precision floating-point arithmetic. */ + feq (__aeabi_fadd (fzero, fone), fone); + feq (__aeabi_fadd (fone, fone), ftwo); + feq (__aeabi_fdiv (fminus_four, fminus_two), ftwo); + feq (__aeabi_fdiv (fminus_two, ftwo), fminus_one); + feq (__aeabi_fmul (ftwo, ftwo), ffour); + feq (__aeabi_fmul (fminus_one, fminus_two), ftwo); + feq (__aeabi_fneg (fminus_one), fone); + feq (__aeabi_fneg (ffour), fminus_four); + feq (__aeabi_frsub (fone, fzero), fminus_one); + feq (__aeabi_frsub (ftwo, fminus_two), fminus_four); + feq (__aeabi_fsub (fzero, fone), fminus_one); + feq (__aeabi_fsub (fminus_two, ftwo), fminus_four); + + /* Table 5. Single-precision floating-point comparisons. */ + ieq (__aeabi_fcmpeq (fone, fone), 1); + ieq (__aeabi_fcmpeq (fone, fzero), 0); + ieq (__aeabi_fcmpeq (fNaN, fzero), 0); + ieq (__aeabi_fcmpeq (fNaN, fNaN), 0); + + ieq (__aeabi_fcmplt (fzero, fone), 1); + ieq (__aeabi_fcmplt (fone, fzero), 0); + ieq (__aeabi_fcmplt (fzero, fzero), 0); + ieq (__aeabi_fcmplt (fzero, fNaN), 0); + ieq (__aeabi_fcmplt (fNaN, fNaN), 0); + + ieq (__aeabi_fcmple (fzero, fone), 1); + ieq (__aeabi_fcmple (fone, fzero), 0); + ieq (__aeabi_fcmple (fzero, fzero), 1); + ieq (__aeabi_fcmple (fzero, fNaN), 0); + ieq (__aeabi_fcmple (fNaN, fNaN), 0); + + ieq (__aeabi_fcmpge (fzero, fone), 0); + ieq (__aeabi_fcmpge (fone, fzero), 1); + ieq (__aeabi_fcmpge (fzero, fzero), 1); + ieq (__aeabi_fcmpge (fzero, fNaN), 0); + ieq (__aeabi_fcmpge (fNaN, fNaN), 0); + + ieq (__aeabi_fcmpgt (fzero, fone), 0); + ieq (__aeabi_fcmpgt (fone, fzero), 1); + ieq (__aeabi_fcmplt (fzero, fzero), 0); + ieq (__aeabi_fcmpgt (fzero, fNaN), 0); + ieq (__aeabi_fcmpgt (fNaN, fNaN), 0); + + ieq (__aeabi_fcmpun (fone, fone), 0); + ieq (__aeabi_fcmpun (fone, fzero), 0); + ieq (__aeabi_fcmpun (fNaN, fzero), 1); + ieq (__aeabi_fcmpun (fNaN, fNaN), 1); + + /* Table 6. Floating-point to integer conversions. */ + ieq (__aeabi_d2iz (dminus_one), -1); + ueq (__aeabi_d2uiz (done), 1); + leq (__aeabi_d2lz (dminus_two), -2LL); + uleq (__aeabi_d2ulz (dfour), 4LL); + ieq (__aeabi_f2iz (fminus_one), -1); + ueq (__aeabi_f2uiz (fone), 1); + leq (__aeabi_f2lz (fminus_two), -2LL); + uleq (__aeabi_f2ulz (ffour), 4LL); + + /* Table 7. Conversions between floating types. */ + feq (__aeabi_d2f (dtwo), ftwo); + deq (__aeabi_f2d (fminus_four), dminus_four); + + /* Table 8. Integer to floating-point conversions. */ + deq (__aeabi_i2d (-1), dminus_one); + deq (__aeabi_ui2d (2), dtwo); + deq (__aeabi_l2d (-1), dminus_one); + deq (__aeabi_ul2d (2ULL), dtwo); + feq (__aeabi_i2f (-1), fminus_one); + feq (__aeabi_ui2f (2), ftwo); + feq (__aeabi_l2f (-1), fminus_one); + feq (__aeabi_ul2f (2ULL), ftwo); + + /* Table 9. Long long functions. */ + leq (__aeabi_lmul (4LL, -1LL), -4LL); + leq (__aeabi_llsl (2LL, 1), 4LL); + leq (__aeabi_llsr (-1LL, 63), 1); + leq (__aeabi_lasr (-1LL, 63), -1); + + result = lcmp_results; + for (i = 0; i < NUM_CMP_VALUES; i++) + for (j = 0; j < NUM_CMP_VALUES; j++) + for (k = 0; k < NUM_CMP_VALUES; k++) + for (n = 0; n < NUM_CMP_VALUES; n++) + { + ieq (signof (__aeabi_lcmp + (((long long)cmp_val[i] << 32) | cmp_val[k], + ((long long)cmp_val[j] << 32) | cmp_val[n])), + *result); + result++; + } + result = ulcmp_results; + for (i = 0; i < NUM_CMP_VALUES; i++) + for (j = 0; j < NUM_CMP_VALUES; j++) + for (k = 0; k < NUM_CMP_VALUES; k++) + for (n = 0; n < NUM_CMP_VALUES; n++) + { + ieq (signof (__aeabi_ulcmp + (((long long)cmp_val[i] << 32) | cmp_val[k], + ((long long)cmp_val[j] << 32) | cmp_val[n])), + *result); + result++; + } + + ieq (__aeabi_idiv (-550, 11), -50); + ueq (__aeabi_uidiv (4000000000U, 1000000U), 4000U); + + for (i = 0; i < 256; i++) + bytes[i] = i; + +#ifdef __ARMEB__ + ieq (__aeabi_uread4 (bytes + 1), 0x01020304U); + leq (__aeabi_uread8 (bytes + 3), 0x030405060708090aLL); + ieq (__aeabi_uwrite4 (0x66778899U, bytes + 5), 0x66778899U); + leq (__aeabi_uwrite8 (0x2030405060708090LL, bytes + 15), + 0x2030405060708090LL); +#else + ieq (__aeabi_uread4 (bytes + 1), 0x04030201U); + leq (__aeabi_uread8 (bytes + 3), 0x0a09080706050403LL); + ieq (__aeabi_uwrite4 (0x99887766U, bytes + 5), 0x99887766U); + leq (__aeabi_uwrite8 (0x9080706050403020LL, bytes + 15), + 0x9080706050403020LL); +#endif + + for (i = 0; i < 4; i++) + ieq (bytes[5 + i], (6 + i) * 0x11); + + for (i = 0; i < 8; i++) + ieq (bytes[15 + i], (2 + i) * 0x10); + + exit (0); +} +#endif diff --git a/gcc/testsuite/g++.dg/pph/c1meteor-contest.cc b/gcc/testsuite/g++.dg/pph/c1meteor-contest.cc new file mode 100644 index 0000000..bb097ac --- /dev/null +++ b/gcc/testsuite/g++.dg/pph/c1meteor-contest.cc @@ -0,0 +1,2 @@ +/* { dg-options "-w" } */ +#include "c1meteor-contest.h" diff --git a/gcc/testsuite/g++.dg/pph/c1meteor-contest.h b/gcc/testsuite/g++.dg/pph/c1meteor-contest.h new file mode 100644 index 0000000..3c465ab --- /dev/null +++ b/gcc/testsuite/g++.dg/pph/c1meteor-contest.h @@ -0,0 +1,630 @@ +/* { dg-options "-w" } */ +#ifndef __PPH_GUARD_H +#define __PPH_GUARD_H +/* +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of "The Computer Language Benchmarks Game" nor the + name of "The Computer Language Shootout Benchmarks" nor the names of + its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/* The Computer Language Benchmarks Game + * http://shootout.alioth.debian.org/ + * + * contributed by Christian Vosteen + */ + +#include +#include +#define TRUE 1 +#define FALSE 0 + +/* The board is a 50 cell hexagonal pattern. For . . . . . + * maximum speed the board will be implemented as . . . . . + * 50 bits, which will fit into a 64 bit long long . . . . . + * int. . . . . . + * . . . . . + * I will represent 0's as empty cells and 1's . . . . . + * as full cells. . . . . . + * . . . . . + * . . . . . + * . . . . . + */ + +unsigned long long board = 0xFFFC000000000000ULL; + +/* The puzzle pieces must be specified by the path followed + * from one end to the other along 12 hexagonal directions. + * + * Piece 0 Piece 1 Piece 2 Piece 3 Piece 4 + * + * O O O O O O O O O O O O O O O + * O O O O O O O + * O O O + * + * Piece 5 Piece 6 Piece 7 Piece 8 Piece 9 + * + * O O O O O O O O O O O O O + * O O O O O O O O O + * O O O + * + * I had to make it 12 directions because I wanted all of the + * piece definitions to fit into the same size arrays. It is + * not possible to define piece 4 in terms of the 6 cardinal + * directions in 4 moves. + */ + +#define E 0 +#define ESE 1 +#define SE 2 +#define S 3 +#define SW 4 +#define WSW 5 +#define W 6 +#define WNW 7 +#define NW 8 +#define N 9 +#define NE 10 +#define ENE 11 +#define PIVOT 12 + +char piece_def[10][4] = { + { E, E, E, SE}, + { SE, E, NE, E}, + { E, E, SE, SW}, + { E, E, SW, SE}, + { SE, E, NE, S}, + { E, E, SW, E}, + { E, SE, SE, NE}, + { E, SE, SE, W}, + { E, SE, E, E}, + { E, E, E, SW} +}; + + +/* To minimize the amount of work done in the recursive solve function below, + * I'm going to allocate enough space for all legal rotations of each piece + * at each position on the board. That's 10 pieces x 50 board positions x + * 12 rotations. However, not all 12 rotations will fit on every cell, so + * I'll have to keep count of the actual number that do. + * The pieces are going to be unsigned long long ints just like the board so + * they can be bitwise-anded with the board to determine if they fit. + * I'm also going to record the next possible open cell for each piece and + * location to reduce the burden on the solve function. + */ +unsigned long long pieces[10][50][12]; +int piece_counts[10][50]; +char next_cell[10][50][12]; + +/* Returns the direction rotated 60 degrees clockwise */ +char rotate(char dir) { + return (dir + 2) % PIVOT; +} + +/* Returns the direction flipped on the horizontal axis */ +char flip(char dir) { + return (PIVOT - dir) % PIVOT; +} + + +/* Returns the new cell index from the specified cell in the + * specified direction. The index is only valid if the + * starting cell and direction have been checked by the + * out_of_bounds function first. + */ +char shift(char cell, char dir) { + switch(dir) { + case E: + return cell + 1; + case ESE: + if((cell / 5) % 2) + return cell + 7; + else + return cell + 6; + case SE: + if((cell / 5) % 2) + return cell + 6; + else + return cell + 5; + case S: + return cell + 10; + case SW: + if((cell / 5) % 2) + return cell + 5; + else + return cell + 4; + case WSW: + if((cell / 5) % 2) + return cell + 4; + else + return cell + 3; + case W: + return cell - 1; + case WNW: + if((cell / 5) % 2) + return cell - 6; + else + return cell - 7; + case NW: + if((cell / 5) % 2) + return cell - 5; + else + return cell - 6; + case N: + return cell - 10; + case NE: + if((cell / 5) % 2) + return cell - 4; + else + return cell - 5; + case ENE: + if((cell / 5) % 2) + return cell - 3; + else + return cell - 4; + default: + return cell; + } +} + +/* Returns wether the specified cell and direction will land outside + * of the board. Used to determine if a piece is at a legal board + * location or not. + */ +char out_of_bounds(char cell, char dir) { + char i; + switch(dir) { + case E: + return cell % 5 == 4; + case ESE: + i = cell % 10; + return i == 4 || i == 8 || i == 9 || cell >= 45; + case SE: + return cell % 10 == 9 || cell >= 45; + case S: + return cell >= 40; + case SW: + return cell % 10 == 0 || cell >= 45; + case WSW: + i = cell % 10; + return i == 0 || i == 1 || i == 5 || cell >= 45; + case W: + return cell % 5 == 0; + case WNW: + i = cell % 10; + return i == 0 || i == 1 || i == 5 || cell < 5; + case NW: + return cell % 10 == 0 || cell < 5; + case N: + return cell < 10; + case NE: + return cell % 10 == 9 || cell < 5; + case ENE: + i = cell % 10; + return i == 4 || i == 8 || i == 9 || cell < 5; + default: + return FALSE; + } +} + +/* Rotate a piece 60 degrees clockwise */ +void rotate_piece(int piece) { + int i; + for(i = 0; i < 4; i++) + piece_def[piece][i] = rotate(piece_def[piece][i]); +} + +/* Flip a piece along the horizontal axis */ +void flip_piece(int piece) { + int i; + for(i = 0; i < 4; i++) + piece_def[piece][i] = flip(piece_def[piece][i]); +} + +/* Convenience function to quickly calculate all of the indices for a piece */ +void calc_cell_indices(char *cell, int piece, char index) { + cell[0] = index; + cell[1] = shift(cell[0], piece_def[piece][0]); + cell[2] = shift(cell[1], piece_def[piece][1]); + cell[3] = shift(cell[2], piece_def[piece][2]); + cell[4] = shift(cell[3], piece_def[piece][3]); +} + +/* Convenience function to quickly calculate if a piece fits on the board */ +int cells_fit_on_board(char *cell, int piece) { + return (!out_of_bounds(cell[0], piece_def[piece][0]) && + !out_of_bounds(cell[1], piece_def[piece][1]) && + !out_of_bounds(cell[2], piece_def[piece][2]) && + !out_of_bounds(cell[3], piece_def[piece][3])); +} + +/* Returns the lowest index of the cells of a piece. + * I use the lowest index that a piece occupies as the index for looking up + * the piece in the solve function. + */ +char minimum_of_cells(char *cell) { + char minimum = cell[0]; + minimum = cell[1] < minimum ? cell[1] : minimum; + minimum = cell[2] < minimum ? cell[2] : minimum; + minimum = cell[3] < minimum ? cell[3] : minimum; + minimum = cell[4] < minimum ? cell[4] : minimum; + return minimum; +} + +/* Calculate the lowest possible open cell if the piece is placed on the board. + * Used to later reduce the amount of time searching for open cells in the + * solve function. + */ +char first_empty_cell(char *cell, char minimum) { + char first_empty = minimum; + while(first_empty == cell[0] || first_empty == cell[1] || + first_empty == cell[2] || first_empty == cell[3] || + first_empty == cell[4]) + first_empty++; + return first_empty; +} + +/* Generate the unsigned long long int that will later be anded with the + * board to determine if it fits. + */ +unsigned long long bitmask_from_cells(char *cell) { + unsigned long long piece_mask = 0ULL; + int i; + for(i = 0; i < 5; i++) + piece_mask |= 1ULL << cell[i]; + return piece_mask; +} + +/* Record the piece and other important information in arrays that will + * later be used by the solve function. + */ +void record_piece(int piece, int minimum, char first_empty, + unsigned long long piece_mask) { + pieces[piece][minimum][piece_counts[piece][minimum]] = piece_mask; + next_cell[piece][minimum][piece_counts[piece][minimum]] = first_empty; + piece_counts[piece][minimum]++; +} + + +/* Fill the entire board going cell by cell. If any cells are "trapped" + * they will be left alone. + */ +void fill_contiguous_space(char *board, int index) { + if(board[index] == 1) + return; + board[index] = 1; + if(!out_of_bounds(index, E)) + fill_contiguous_space(board, shift(index, E)); + if(!out_of_bounds(index, SE)) + fill_contiguous_space(board, shift(index, SE)); + if(!out_of_bounds(index, SW)) + fill_contiguous_space(board, shift(index, SW)); + if(!out_of_bounds(index, W)) + fill_contiguous_space(board, shift(index, W)); + if(!out_of_bounds(index, NW)) + fill_contiguous_space(board, shift(index, NW)); + if(!out_of_bounds(index, NE)) + fill_contiguous_space(board, shift(index, NE)); +} + + +/* To thin the number of pieces, I calculate if any of them trap any empty + * cells at the edges. There are only a handful of exceptions where the + * the board can be solved with the trapped cells. For example: piece 8 can + * trap 5 cells in the corner, but piece 3 can fit in those cells, or piece 0 + * can split the board in half where both halves are viable. + */ +int has_island(char *cell, int piece) { + char temp_board[50]; + char c; + int i; + for(i = 0; i < 50; i++) + temp_board[i] = 0; + for(i = 0; i < 5; i++) + temp_board[((int)cell[i])] = 1; + i = 49; + while(temp_board[i] == 1) + i--; + fill_contiguous_space(temp_board, i); + c = 0; + for(i = 0; i < 50; i++) + if(temp_board[i] == 0) + c++; + if(c == 0 || (c == 5 && piece == 8) || (c == 40 && piece == 8) || + (c % 5 == 0 && piece == 0)) + return FALSE; + else + return TRUE; +} + + +/* Calculate all six rotations of the specified piece at the specified index. + * We calculate only half of piece 3's rotations. This is because any solution + * found has an identical solution rotated 180 degrees. Thus we can reduce the + * number of attempted pieces in the solve algorithm by not including the 180- + * degree-rotated pieces of ONE of the pieces. I chose piece 3 because it gave + * me the best time ;) + */ + void calc_six_rotations(char piece, char index) { + char rotation, cell[5]; + char minimum, first_empty; + unsigned long long piece_mask; + + for(rotation = 0; rotation < 6; rotation++) { + if(piece != 3 || rotation < 3) { + calc_cell_indices(cell, piece, index); + if(cells_fit_on_board(cell, piece) && !has_island(cell, piece)) { + minimum = minimum_of_cells(cell); + first_empty = first_empty_cell(cell, minimum); + piece_mask = bitmask_from_cells(cell); + record_piece(piece, minimum, first_empty, piece_mask); + } + } + rotate_piece(piece); + } +} + +/* Calculate every legal rotation for each piece at each board location. */ +void calc_pieces(void) { + char piece, index; + + for(piece = 0; piece < 10; piece++) { + for(index = 0; index < 50; index++) { + calc_six_rotations(piece, index); + flip_piece(piece); + calc_six_rotations(piece, index); + } + } +} + + + +/* Calculate all 32 possible states for a 5-bit row and all rows that will + * create islands that follow any of the 32 possible rows. These pre- + * calculated 5-bit rows will be used to find islands in a partially solved + * board in the solve function. + */ +#define ROW_MASK 0x1F +#define TRIPLE_MASK 0x7FFF +char all_rows[32] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; +int bad_even_rows[32][32]; +int bad_odd_rows[32][32]; +int bad_even_triple[32768]; +int bad_odd_triple[32768]; + +int rows_bad(char row1, char row2, int even) { + /* even is referring to row1 */ + int i, in_zeroes, group_okay; + char block, row2_shift; + /* Test for blockages at same index and shifted index */ + if(even) + row2_shift = ((row2 << 1) & ROW_MASK) | 0x01; + else + row2_shift = (row2 >> 1) | 0x10; + block = ((row1 ^ row2) & row2) & ((row1 ^ row2_shift) & row2_shift); + /* Test for groups of 0's */ + in_zeroes = FALSE; + group_okay = FALSE; + for(i = 0; i < 5; i++) { + if(row1 & (1 << i)) { + if(in_zeroes) { + if(!group_okay) + return TRUE; + in_zeroes = FALSE; + group_okay = FALSE; + } + } else { + if(!in_zeroes) + in_zeroes = TRUE; + if(!(block & (1 << i))) + group_okay = TRUE; + } + } + if(in_zeroes) + return !group_okay; + else + return FALSE; +} + +/* Check for cases where three rows checked sequentially cause a false + * positive. One scenario is when 5 cells may be surrounded where piece 5 + * or 7 can fit. The other scenario is when piece 2 creates a hook shape. + */ +int triple_is_okay(char row1, char row2, char row3, int even) { + if(even) { + /* There are four cases: + * row1: 00011 00001 11001 10101 + * row2: 01011 00101 10001 10001 + * row3: 011?? 00110 ????? ????? + */ + return ((row1 == 0x03) && (row2 == 0x0B) && ((row3 & 0x1C) == 0x0C)) || + ((row1 == 0x01) && (row2 == 0x05) && (row3 == 0x06)) || + ((row1 == 0x19) && (row2 == 0x11)) || + ((row1 == 0x15) && (row2 == 0x11)); + } else { + /* There are two cases: + * row1: 10011 10101 + * row2: 10001 10001 + * row3: ????? ????? + */ + return ((row1 == 0x13) && (row2 == 0x11)) || + ((row1 == 0x15) && (row2 == 0x11)); + } +} + + +void calc_rows(void) { + int row1, row2, row3; + int result1, result2; + for(row1 = 0; row1 < 32; row1++) { + for(row2 = 0; row2 < 32; row2++) { + bad_even_rows[row1][row2] = rows_bad(row1, row2, TRUE); + bad_odd_rows[row1][row2] = rows_bad(row1, row2, FALSE); + } + } + for(row1 = 0; row1 < 32; row1++) { + for(row2 = 0; row2 < 32; row2++) { + for(row3 = 0; row3 < 32; row3++) { + result1 = bad_even_rows[row1][row2]; + result2 = bad_odd_rows[row2][row3]; + if(result1 == FALSE && result2 == TRUE + && triple_is_okay(row1, row2, row3, TRUE)) + bad_even_triple[row1+(row2*32)+(row3*1024)] = FALSE; + else + bad_even_triple[row1+(row2*32)+(row3*1024)] = result1 || result2; + + result1 = bad_odd_rows[row1][row2]; + result2 = bad_even_rows[row2][row3]; + if(result1 == FALSE && result2 == TRUE + && triple_is_okay(row1, row2, row3, FALSE)) + bad_odd_triple[row1+(row2*32)+(row3*1024)] = FALSE; + else + bad_odd_triple[row1+(row2*32)+(row3*1024)] = result1 || result2; + } + } + } +} + + + +/* Calculate islands while solving the board. + */ +int boardHasIslands(char cell) { + /* Too low on board, don't bother checking */ + if(cell >= 40) + return FALSE; + int current_triple = (board >> ((cell / 5) * 5)) & TRIPLE_MASK; + if((cell / 5) % 2) + return bad_odd_triple[current_triple]; + else + return bad_even_triple[current_triple]; +} + + +/* The recursive solve algorithm. Try to place each permutation in the upper- + * leftmost empty cell. Mark off available pieces as it goes along. + * Because the board is a bit mask, the piece number and bit mask must be saved + * at each successful piece placement. This data is used to create a 50 char + * array if a solution is found. + */ +short avail = 0x03FF; +char sol_nums[10]; +unsigned long long sol_masks[10]; +signed char solutions[2100][50]; +int solution_count = 0; +int max_solutions = 2100; + +void record_solution(void) { + int sol_no, index; + unsigned long long sol_mask; + for(sol_no = 0; sol_no < 10; sol_no++) { + sol_mask = sol_masks[sol_no]; + for(index = 0; index < 50; index++) { + if(sol_mask & 1ULL) { + solutions[solution_count][index] = sol_nums[sol_no]; + /* Board rotated 180 degrees is a solution too! */ + solutions[solution_count+1][49-index] = sol_nums[sol_no]; + } + sol_mask = sol_mask >> 1; + } + } + solution_count += 2; +} + +void solve(int depth, int cell) { + int piece, rotation, max_rots; + unsigned long long *piece_mask; + short piece_no_mask; + + if(solution_count >= max_solutions) + return; + + while(board & (1ULL << cell)) + cell++; + + for(piece = 0; piece < 10; piece++) { + piece_no_mask = 1 << piece; + if(!(avail & piece_no_mask)) + continue; + avail ^= piece_no_mask; + max_rots = piece_counts[piece][cell]; + piece_mask = pieces[piece][cell]; + for(rotation = 0; rotation < max_rots; rotation++) { + if(!(board & *(piece_mask + rotation))) { + sol_nums[depth] = piece; + sol_masks[depth] = *(piece_mask + rotation); + if(depth == 9) { + /* Solution found!!!!!11!!ONE! */ + record_solution(); + avail ^= piece_no_mask; + return; + } + board |= *(piece_mask + rotation); + if(!boardHasIslands(next_cell[piece][cell][rotation])) + solve(depth + 1, next_cell[piece][cell][rotation]); + board ^= *(piece_mask + rotation); + } + } + avail ^= piece_no_mask; + } +} + + +/* qsort comparator - used to find first and last solutions */ +int solution_sort(const void *elem1, const void *elem2) { + signed char *char1 = (signed char *) elem1; + signed char *char2 = (signed char *) elem2; + int i = 0; + while(i < 50 && char1[i] == char2[i]) + i++; + return char1[i] - char2[i]; +} + + +/* pretty print a board in the specified hexagonal format */ +void pretty(signed char *b) { + int i; + for(i = 0; i < 50; i += 10) { + printf("%c %c %c %c %c \n %c %c %c %c %c \n", b[i]+'0', b[i+1]+'0', + b[i+2]+'0', b[i+3]+'0', b[i+4]+'0', b[i+5]+'0', b[i+6]+'0', + b[i+7]+'0', b[i+8]+'0', b[i+9]+'0'); + } + printf("\n"); +} + +int main(int argc, char **argv) { + if(argc > 1) + max_solutions = atoi(argv[1]); + calc_pieces(); + calc_rows(); + solve(0, 0); + printf("%d solutions found\n\n", solution_count); + qsort(solutions, solution_count, 50 * sizeof(signed char), solution_sort); + pretty(solutions[0]); + pretty(solutions[solution_count-1]); + return 0; +} +#endif diff --git a/gcc/testsuite/g++.dg/pph/c1pr36533.cc b/gcc/testsuite/g++.dg/pph/c1pr36533.cc new file mode 100644 index 0000000..b44e8c9 --- /dev/null +++ b/gcc/testsuite/g++.dg/pph/c1pr36533.cc @@ -0,0 +1,2 @@ +/* { dg-options "-w -fpermissive" } */ +#include "c1pr36533.h" diff --git a/gcc/testsuite/g++.dg/pph/c1pr36533.h b/gcc/testsuite/g++.dg/pph/c1pr36533.h new file mode 100644 index 0000000..6c6a6ae --- /dev/null +++ b/gcc/testsuite/g++.dg/pph/c1pr36533.h @@ -0,0 +1,176 @@ +#ifndef __PPH_GUARD_H +#define __PPH_GUARD_H +/* PR target/36533 */ +/* { dg-options "-w -fpermissive" } */ +#include +#include +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + +typedef struct S1 +{ + unsigned long s1; + struct S1 *s2; + char *s3; +} S1; + +typedef struct +{ + unsigned int s4; + unsigned int s5; + int s6; + unsigned int *s7; +} S2; + +typedef struct +{ + unsigned int s8; + unsigned short s9; + unsigned char s10; + unsigned char s11; + char s12[255]; +} S3; + +typedef struct +{ + unsigned int s4; + unsigned short s13; + unsigned short s14; +} S4; + +typedef struct +{ + char s15[16]; + unsigned long s16; +} S5; + +typedef struct +{ + char s15[48]; + S5 *s17; +} S6; + +typedef struct +{ + S1 *s18; +} S7; + +__attribute__((regparm (3), noinline)) int +fn1 (const char *x, void *y, S1 *z) +{ + asm volatile ("" : : : "memory"); + return *x + (y != 0); +} + +__attribute__((regparm (3), noinline)) int +fn2 (const char *x, int y, S2 *z) +{ + asm volatile ("" : : : "memory"); + return 0; +} + +static inline __attribute__ ((always_inline)) unsigned int +fn4 (unsigned short x) +{ + unsigned len = x; + if (len == ((1 << 16) - 1)) + return 1 << 16; + return len; +} + +static inline __attribute__ ((always_inline)) S3 * +fn3 (S3 *p) +{ + return (S3 *) ((char *) p + fn4 (p->s9)); +} + +__attribute__((regparm (3), noinline)) int +fn5 (void) +{ + asm volatile ("" : : : "memory"); + return 0; +} + +static inline __attribute__ ((always_inline)) int +fn6 (S3 *w, int x, S2 *y, S4 *z) +{ + int a = 2; + char *b = (char *) w; + S2 c = *y; + + while ((char *) w < b + x - 2 * sizeof (S4)) + { + if (w->s10 && w->s8) + { + fn2 (w->s12, w->s10, &c); + z--; + z->s4 = c.s4; + z->s13 = (unsigned short) ((char *) w - b); + z->s14 = w->s9; + a++; + fn5 (); + } + + w = fn3 (w); + } + return a; +} + +__attribute__((regparm (3), noinline)) unsigned int +test (void *u, S6 *v, S1 **w, S7 *x, S2 *y, S1 *z) +{ + unsigned b = v->s17->s16; + unsigned a; + S4 *c; + unsigned d, e, f, i; + + fn1 (__func__, u, x->s18); + c = (S4 *) (z->s3 + b); + a = fn6 ((S3 *) (*w)->s3, b, y, c); + c -= a; + f = 0; + e = 2; + for (i = a - 1; ; i--) + { + if (f + (unsigned short) (c[i].s14 / 2) > b / 2) + break; + f += c[i].s14; + e++; + } + d = a - e; + return c[d].s4; +} + +int main (void) +{ + char *p = mmap (NULL, 131072, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + S1 wb, z, *w; + S6 v; + S7 x; + S2 y; + S5 vb; + S4 s4; + if (p == MAP_FAILED) + return 0; + if (munmap (p + 65536, 65536) < 0) + return 0; + memset (&wb, 0, sizeof (wb)); + memset (&z, 0, sizeof (z)); + memset (&v, 0, sizeof (v)); + memset (&x, 0, sizeof (x)); + memset (&y, 0, sizeof (y)); + memset (&vb, 0, sizeof (vb)); + memset (&s4, 0, sizeof (s4)); + s4.s14 = 254; + z.s3 = p + 65536 - 2 * sizeof (S4); + w = &wb; + v.s17 = &vb; + vb.s16 = 2 * sizeof (S4); + memcpy (z.s3, &s4, sizeof (s4)); + memcpy (z.s3 + sizeof (s4), &s4, sizeof (s4)); + test ((void *) 0, &v, &w, &x, &y, &z); + return 0; +} +#endif diff --git a/gcc/testsuite/g++.dg/pph/c1pr44948-1a.cc b/gcc/testsuite/g++.dg/pph/c1pr44948-1a.cc new file mode 100644 index 0000000..f3f0427 --- /dev/null +++ b/gcc/testsuite/g++.dg/pph/c1pr44948-1a.cc @@ -0,0 +1 @@ +#include "c1pr44948-1a.h" diff --git a/gcc/testsuite/g++.dg/pph/c1pr44948-1a.h b/gcc/testsuite/g++.dg/pph/c1pr44948-1a.h new file mode 100644 index 0000000..0f69443 --- /dev/null +++ b/gcc/testsuite/g++.dg/pph/c1pr44948-1a.h @@ -0,0 +1,18 @@ +#ifndef __PPH_GUARD_H +#define __PPH_GUARD_H +/* PR target/44948 */ +/* { dg-options "-O -Wno-psabi -mtune=generic" } */ + +#pragma GCC target ("avx") + +struct A { long b[8] __attribute__((aligned (32))); }; +void foo (long double, struct A); + +int +main (void) +{ + struct A a = { { 0, 1, 2, 3, 4, 5, 6, 7 } }; + foo (8.0L, a); + return 0; +} +#endif -- This patch is available for review at http://codereview.appspot.com/4528104