1 /* { dg-do run } */
2 /* { dg-options "-O2 -fwrapv" } */
3 
4 /* PR tree-optimization/21029
5 
6    f() used to get optimized to an infinite loop by tree-vrp, because
7    j is assumed to be non-negative.  Even though the conversion from
8    unsigned to signed has unspecified results if the expression value
9    is not representable in the signed type, the compiler itself (e.g.,
10    the Ada front end) depends on wrap-around behavior.  */
11 
f(void)12 unsigned int f(void) {
13   unsigned char i = 123;
14   signed char j;
15 
16   do
17     if ((j = (signed char) i) < 0)
18       break;
19     else
20       i++;
21   while (1);
22 
23   return i;
24 }
25 
26 /* Now let's torture it a bit further.  Narrowing conversions need
27    similar treatment.  */
28 
f1(void)29 unsigned int f1 (void) {
30   unsigned short i = 123;
31   signed char j;
32 
33   do
34     if ((j = (signed char) i) < 0)
35       break;
36     else
37       i++;
38   while (1);
39 
40   return i;
41 }
42 
43 /* And so do widening conversions.  */
44 
f2(void)45 unsigned int f2 (void) {
46   unsigned char i = 123;
47   signed short j;
48 
49   do
50     if ((j = (signed short) (signed char) i) < 0)
51       break;
52     else
53       i++;
54   while (1);
55 
56   return i;
57 }
58 
59 /* Check same-sign truncations with an increment that turns into
60    decrements.  */
61 
f3(void)62 unsigned int f3 (void) {
63   signed short i = 5;
64   signed char j;
65 
66   do
67     if ((j = (signed char) i) < 0)
68       break;
69     else
70       i += 255;
71   while (1);
72 
73   return i;
74 }
75 
76 /* Check that the truncation above doesn't confuse the result of the
77    test after a widening conversion.  */
78 
f4(void)79 unsigned int f4 (void) {
80   signed short i = -123;
81   signed int j;
82 
83   do
84     if ((j = (signed int) (signed char) i) > 0)
85       break;
86     else
87       i += 255;
88   while (1);
89 
90   return i;
91 }
92 
93 /* Even if we omit the widening truncation, the narrowing truncation
94    is implementation-defined.  */
95 
f5(void)96 unsigned int f5 (void) {
97   signed long i = -123;
98   signed char j;
99 
100   do
101     if ((j = (signed char) i) > 0)
102       break;
103     else
104       i += 255;
105   while (1);
106 
107   return i;
108 }
109 
main(void)110 int main (void) {
111   f ();
112   f1 ();
113   f2 ();
114   f3 ();
115   f4 ();
116   f5 ();
117   return 0;
118 }
119