1 /* { dg-do run } */
2 /* { dg-options "-O2" } */
3 /* { dg-require-effective-target int32plus } */
4 
5 struct tree_decl
6 {
7   union tree_decl_u1 {
8     int f;
9     long i;
10     struct tree_decl_u1_a {
11       unsigned int align : 24;
12       unsigned int off_align : 8;
13     } a;
14   } u1;
15 };
16 
17 extern void abort (void);
18 
19 unsigned int
assemble_variable(struct tree_decl decl)20 assemble_variable (struct tree_decl decl)
21 {
22   unsigned int align;
23 
24   align = decl.u1.a.align;
25 
26   if (align > (1 << ((8 * 4) < 64 ? (8 * 4) - 2 : 62)))
27     align = (1 << ((8 * 4) < 64 ? (8 * 4) - 2 : 62));
28 
29   /* VRP should not be propagating 0 to the RHS of this assignment.
30      But it was erroneously applying a cast operation between types of
31      different precision.  align is an unsigned int with range [0,
32      0x4000000] but the .align field holds only 24 bits.  So the cast
33      was returning a [0, 0] range.  */
34   decl.u1.a.align = align;
35 
36   return decl.u1.a.align;
37 }
38 
39 int
main()40 main ()
41 {
42   struct tree_decl decl;
43   decl.u1.a.align = 13;
44   unsigned int x = assemble_variable (decl);
45   if (x == 0)
46     abort ();
47   return 0;
48 }
49