summaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/torture/pr40924.C
blob: 9140da3ba3bc72765ad83302a77c79cbe0149104 (plain)
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// PR rtl-optimization/40924
// { dg-do run }

extern "C" void abort (void);

#define MAY_ALIAS __attribute__((__may_alias__))

typedef struct { float v[2]; } floata;
typedef struct { int v[2]; } inta;

typedef unsigned int uint MAY_ALIAS;
typedef signed int sint MAY_ALIAS;
typedef float flt MAY_ALIAS;

static inline unsigned short
less_than (inta a, inta b)
{
  unsigned short r = 0;
  const uint *p1 = (const uint *) &a;
  const uint *p2 = (const uint *) &b;
  for (int i=0; i < 2; i++)
    if (p1[i] < p2[i]) r |= (1 << i);
  return r;
}

static inline inta
multiply (inta b, inta c)
{
  inta r;
  sint *p3 = (sint *) &c;
  for (int i=0; i < 2; i++)
    r.v[i] = (int) (b.v[i] * p3[i] & 0xFFFFFFFF);
  return r;
}

static inline floata
gather (inta indexes, const void *baseAddr)
{
  floata r;

  sint *idx = (sint *) &indexes;
  flt *src = (flt *) baseAddr;
  for (int i=0; i < 2; i++)
    r.v[i] = *(src + idx[i]);
  return r;
}

static inline inta
add (const inta &b, const inta &c)
{
  inta result;
  sint *r = (sint *) &result;

  for (int i=0; i < 2; i++)
    r[i] = b.v[i] + c.v[i];
  return result;
}

struct uintv
{
  inta data;
  inline uintv () { data.v[0] = 0; data.v[1] = 1; }
  inline uintv (unsigned int a)
  {
    for (int i=0; i < 2; i++)
      *(uint *) &data.v[i] = a;
  }
  inline uintv (inta x) : data (x) {}
  inline uintv operator* (const uintv &x) const
  { return multiply (data, x.data); }
  inline uintv operator+ (const uintv &x) const
  { return uintv (add (data, x.data)); }
  inline unsigned short operator< (const uintv &x) const
  { return less_than (data, x.data); }
};

struct floatv
{
  floata data;
  explicit inline floatv (const uintv &x)
  {
    uint *p2 = (uint *) &x.data;
    for (int i=0; i < 2; i++)
      data.v[i] = p2[i];
  }
  inline floatv (const float *array, const uintv &indexes)
  {
    const uintv &offsets = indexes * uintv (1);
    data = gather (offsets.data, array);
  }
  unsigned short operator== (const floatv &x) const
  {
    unsigned short r = 0;
    for (int i=0; i < 2; i++)
      if (data.v[i] == x.data.v[i]) r |= (1 << i);
    return r;
  }
};

int
main ()
{
  const float array[2] = { 2, 3 };
  for (uintv i; (i < 2) == 3; i = i + 2)
    {
      const floatv ii (i + 2);
      floatv a (array, i);
      if ((a == ii) != 3)
	abort ();
    }
}