https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79054
Bug ID: 79054
Summary: missing range information with INT_MAX
Product: gcc
Version: 7.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: msebor at gcc dot gnu.org
Target Milestone: ---
This is a test case reduced from bug 79051 showing that GCC seems to "lose"
range information for expressions in functions that contain other expressions
involving limits such as INT_MAX in unrelated statement. In the test program,
function foobar() contains the two statements from functions foo() and bar().
In each of foo() and bar(), GCC correctly represents the range of the argument
in the call to the function alloc(). But in foobar(), unlike in foo(), the
range of the argument in the first call to alloc() is lost (it's VR_VARYING).
This can be seen in both the VRP dumps and by the absence of the
-Walloc-size-larger-than warning for that call in foobar().
$ cat t.c && gcc -O2 -S -Wall -Walloc-size-larger-than=1234
-fdump-tree-vrp=/dev/stdout t.c
#define INT_MAX __INT_MAX__
#define INT_MIN (-INT_MAX - 1)
void sink (void*);
void* alloc (int) __attribute__ ((alloc_size (1)));
int anti_range (int min, int max)
{
extern int value (void);
int val = value ();
if (min <= val && val <= max)
val = min - 1;
return val;
}
void foo (int n)
{
sink (alloc (anti_range (INT_MIN + 2, 1235)));
}
void bar (int n)
{
sink (alloc (anti_range (0, INT_MAX)));
}
void foobar (int n)
{
sink (alloc (anti_range (INT_MIN + 2, 1235)));
sink (alloc (anti_range (0, INT_MAX)));
}
;; Function anti_range (anti_range, funcdef_no=0, decl_uid=2522, cgraph_uid=0,
symbol_order=0)
;; 1 loops found
;;
;; Loop 0
;; header 0, latch 1
;; depth 0, outer -1
;; nodes: 0 1 2 3 4 5
;; 2 succs { 3 5 }
;; 3 succs { 4 5 }
;; 4 succs { 5 }
;; 5 succs { 1 }
SSA replacement table
N_i -> { O_1 ... O_j } means that N_i replaces O_1, ..., O_j
val_8 -> { val_4 }
val_9 -> { val_4 }
val_10 -> { val_4 }
val_11 -> { val_4 }
min_12 -> { min_5(D) }
Incremental SSA update started at block: 2
Number of blocks in CFG: 8
Number of blocks to update: 6 ( 75%)
Value ranges after VRP:
val_1: VARYING
val_4: VARYING
min_5(D): VARYING
max_6(D): VARYING
val_7: VARYING
val_8: [-INF, max_6(D)] EQUIVALENCES: { val_4 val_10 } (2 elements)
val_9: [max_6(D) + 1, +INF] EQUIVALENCES: { val_4 val_10 } (2 elements)
val_10: [min_5(D), +INF] EQUIVALENCES: { val_4 } (1 elements)
val_11: [-INF, min_5(D) + -1] EQUIVALENCES: { val_4 } (1 elements)
min_12: [-INF, val_10] EQUIVALENCES: { min_5(D) } (1 elements)
Removing basic block 6
Removing basic block 7
anti_range (int min, int max)
{
int val;
<bb 2> [100.00%]:
val_4 = value ();
if (val_4 >= min_5(D))
goto <bb 3>; [54.00%]
else
goto <bb 5>; [46.00%]
<bb 3> [54.00%]:
if (val_4 <= max_6(D))
goto <bb 4>; [54.00%]
else
goto <bb 5>; [46.00%]
<bb 4> [29.16%]:
val_7 = min_5(D) + -1;
<bb 5> [100.00%]:
# val_1 = PHI <val_4(2), val_4(3), val_7(4)>
return val_1;
}
;; Function anti_range (anti_range, funcdef_no=0, decl_uid=2522, cgraph_uid=0,
symbol_order=0)
;; 1 loops found
;;
;; Loop 0
;; header 0, latch 1
;; depth 0, outer -1
;; nodes: 0 1 2 3 4 5
;; 2 succs { 3 5 }
;; 3 succs { 4 5 }
;; 4 succs { 5 }
;; 5 succs { 1 }
SSA replacement table
N_i -> { O_1 ... O_j } means that N_i replaces O_1, ..., O_j
val_8 -> { val_4 }
val_9 -> { val_4 }
val_10 -> { val_4 }
min_11 -> { min_5(D) }
val_12 -> { val_4 }
Incremental SSA update started at block: 2
Number of blocks in CFG: 8
Number of blocks to update: 6 ( 75%)
Value ranges after VRP:
val_1: VARYING
val_4: VARYING
min_5(D): VARYING
max_6(D): VARYING
val_7: VARYING
val_8: [-INF, max_6(D)] EQUIVALENCES: { val_4 val_12 } (2 elements)
val_9: [max_6(D) + 1, +INF] EQUIVALENCES: { val_4 val_12 } (2 elements)
val_10: [-INF, min_5(D) + -1] EQUIVALENCES: { val_4 } (1 elements)
min_11: [-INF, val_12] EQUIVALENCES: { min_5(D) } (1 elements)
val_12: [min_5(D), +INF] EQUIVALENCES: { val_4 } (1 elements)
Removing basic block 6
Removing basic block 7
anti_range (int min, int max)
{
int val;
<bb 2> [100.00%]:
val_4 = value ();
if (val_4 >= min_5(D))
goto <bb 3>; [54.00%]
else
goto <bb 5>; [46.00%]
<bb 3> [54.00%]:
if (val_4 <= max_6(D))
goto <bb 4>; [54.00%]
else
goto <bb 5>; [46.00%]
<bb 4> [29.16%]:
val_7 = min_5(D) + -1;
<bb 5> [100.00%]:
# val_1 = PHI <val_4(2), val_4(3), val_7(4)>
return val_1;
}
;; Function foo (foo, funcdef_no=1, decl_uid=2529, cgraph_uid=1,
symbol_order=1)
;; 1 loops found
;;
;; Loop 0
;; header 0, latch 1
;; depth 0, outer -1
;; nodes: 0 1 2 3 4 5
;; 2 succs { 3 5 }
;; 3 succs { 4 5 }
;; 4 succs { 5 }
;; 5 succs { 1 }
SSA replacement table
N_i -> { O_1 ... O_j } means that N_i replaces O_1, ..., O_j
val_8 -> { val_5 }
val_9 -> { val_5 }
val_10 -> { val_5 }
val_11 -> { val_5 }
Incremental SSA update started at block: 2
Number of blocks in CFG: 8
Number of blocks to update: 6 ( 75%)
Value ranges after VRP:
_1: VARYING
val_5: VARYING
val_6: ~[-2147483646, 1235] EQUIVALENCES: { } (0 elements)
val_8: [-2147483646, 1235] EQUIVALENCES: { val_5 val_10 } (2 elements)
val_9: [1236, +INF] EQUIVALENCES: { val_5 val_10 } (2 elements)
val_10: [-2147483646, +INF] EQUIVALENCES: { val_5 } (1 elements)
val_11: [-INF, -2147483647] EQUIVALENCES: { val_5 } (1 elements)
Removing basic block 4
Removing basic block 6
foo (int n)
{
int val;
void * _1;
<bb 2> [100.00%]:
val_5 = value ();
if (val_5 >= -2147483646)
goto <bb 3>; [54.00%]
else
goto <bb 5>; [46.00%]
<bb 3> [54.00%]:
if (val_5 <= 1235)
goto <bb 5>; [54.00%]
else
goto <bb 4>; [46.00%]
<bb 4> [24.84%]:
<bb 5> [100.00%]:
# val_6 = PHI <val_5(2), val_5(4), -2147483647(3)>
_1 = alloc (val_6);
sink (_1);
return;
}
;; Function foo (foo, funcdef_no=1, decl_uid=2529, cgraph_uid=1,
symbol_order=1)
;; 1 loops found
;;
;; Loop 0
;; header 0, latch 1
;; depth 0, outer -1
;; nodes: 0 1 2 3 4
;; 2 succs { 3 4 }
;; 3 succs { 4 }
;; 4 succs { 1 }
Value ranges after VRP:
_1: VARYING
val_5: VARYING
val_6: ~[-2147483646, 1235]
_8: [0, +INF]
_9: [0, +INF]
_10: [0, +INF]
foo (int n)
{
int val;
void * _1;
unsigned int _8;
unsigned int _9;
_Bool _10;
<bb 2> [100.00%]:
val_5 = value ();
_8 = (unsigned int) val_5;
_9 = _8 + 2147483646;
_10 = _9 <= 2147484881;
if (_10 != 0)
goto <bb 3>; [54.00%]
else
goto <bb 4>; [46.00%]
<bb 3> [29.16%]:
<bb 4> [100.00%]:
# val_6 = PHI <-2147483647(3), val_5(2)>
_1 = alloc (val_6);
sink (_1);
return;
}
t.c: In function ‘foo’:
t.c:18:3: warning: argument 1 range [1236, 2147483647] exceeds maximum object
size 1234 [-Walloc-size-larger-than=]
sink (alloc (anti_range (INT_MIN + 2, 1235)));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t.c:5:7: note: in a call to allocation function ‘alloc’ declared here
void* alloc (int) __attribute__ ((alloc_size (1)));
^~~~~
;; Function bar (bar, funcdef_no=2, decl_uid=2532, cgraph_uid=2,
symbol_order=2)
;; 1 loops found
;;
;; Loop 0
;; header 0, latch 1
;; depth 0, outer -1
;; nodes: 0 1 2 3 4
;; 2 succs { 3 4 }
;; 3 succs { 4 }
;; 4 succs { 1 }
SSA replacement table
N_i -> { O_1 ... O_j } means that N_i replaces O_1, ..., O_j
val_8 -> { val_5 }
val_9 -> { val_5 }
Incremental SSA update started at block: 2
Number of blocks in CFG: 6
Number of blocks to update: 4 ( 67%)
Value ranges after VRP:
_1: VARYING
val_5: VARYING
val_6: [-INF, -1] EQUIVALENCES: { } (0 elements)
val_8: [0, +INF] EQUIVALENCES: { val_5 } (1 elements)
val_9: [-INF, -1] EQUIVALENCES: { val_5 } (1 elements)
Removing basic block 3
bar (int n)
{
int val;
void * _1;
<bb 2> [100.00%]:
val_5 = value ();
if (val_5 >= 0)
goto <bb 4>; [67.61%]
else
goto <bb 3>; [32.39%]
<bb 3> [32.39%]:
<bb 4> [100.00%]:
# val_6 = PHI <val_5(3), -1(2)>
_1 = alloc (val_6);
sink (_1);
return;
}
;; Function bar (bar, funcdef_no=2, decl_uid=2532, cgraph_uid=2,
symbol_order=2)
;; 1 loops found
;;
;; Loop 0
;; header 0, latch 1
;; depth 0, outer -1
;; nodes: 0 1 2
;; 2 succs { 1 }
Value ranges after VRP:
_1: VARYING
val_5: VARYING
val_8: [-INF, -1]
bar (int n)
{
int val;
void * _1;
<bb 2> [100.00%]:
val_5 = value ();
val_8 = MIN_EXPR <val_5, -1>;
_1 = alloc (val_8);
sink (_1);
return;
}
t.c: In function ‘bar’:
t.c:23:3: warning: argument 1 range [-2147483648, -1] is negative
[-Walloc-size-larger-than=]
sink (alloc (anti_range (0, INT_MAX)));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t.c:5:7: note: in a call to allocation function ‘alloc’ declared here
void* alloc (int) __attribute__ ((alloc_size (1)));
^~~~~
;; Function foobar (foobar, funcdef_no=3, decl_uid=2535, cgraph_uid=3,
symbol_order=3)
;; 1 loops found
;;
;; Loop 0
;; header 0, latch 1
;; depth 0, outer -1
;; nodes: 0 1 2 3 4 5 6 7
;; 2 succs { 3 5 }
;; 3 succs { 4 5 }
;; 4 succs { 5 }
;; 5 succs { 6 7 }
;; 6 succs { 7 }
;; 7 succs { 1 }
SSA replacement table
N_i -> { O_1 ... O_j } means that N_i replaces O_1, ..., O_j
val_14 -> { val_8 }
val_15 -> { val_8 }
val_16 -> { val_10 }
val_17 -> { val_10 }
val_18 -> { val_10 }
val_19 -> { val_10 }
Incremental SSA update started at block: 2
Number of blocks in CFG: 11
Number of blocks to update: 9 ( 82%)
Value ranges after VRP:
_1: VARYING
_2: VARYING
val_8: VARYING
val_9: [-INF, -1] EQUIVALENCES: { } (0 elements)
val_10: VARYING
val_11: ~[-2147483646, 1235] EQUIVALENCES: { } (0 elements)
val_14: [0, +INF] EQUIVALENCES: { val_8 } (1 elements)
val_15: [-INF, -1] EQUIVALENCES: { val_8 } (1 elements)
val_16: [-2147483646, 1235] EQUIVALENCES: { val_10 val_18 } (2 elements)
val_17: [1236, +INF] EQUIVALENCES: { val_10 val_18 } (2 elements)
val_18: [-2147483646, +INF] EQUIVALENCES: { val_10 } (1 elements)
val_19: [-INF, -2147483647] EQUIVALENCES: { val_10 } (1 elements)
Removing basic block 4
Removing basic block 6
Removing basic block 8
foobar (int n)
{
int val;
int val;
void * _1;
void * _2;
<bb 2> [100.00%]:
val_10 = value ();
if (val_10 >= -2147483646)
goto <bb 3>; [50.00%]
else
goto <bb 5>; [50.00%]
<bb 3> [50.00%]:
if (val_10 <= 1235)
goto <bb 5>; [50.00%]
else
goto <bb 4>; [50.00%]
<bb 4> [25.00%]:
<bb 5> [100.00%]:
# val_11 = PHI <val_10(2), val_10(4), -2147483647(3)>
_1 = alloc (val_11);
sink (_1);
val_8 = value ();
if (val_8 >= 0)
goto <bb 7>; [67.61%]
else
goto <bb 6>; [32.39%]
<bb 6> [32.39%]:
<bb 7> [100.00%]:
# val_9 = PHI <val_8(6), -1(5)>
_2 = alloc (val_9);
sink (_2);
return;
}
;; Function foobar (foobar, funcdef_no=3, decl_uid=2535, cgraph_uid=3,
symbol_order=3)
;; 1 loops found
;;
;; Loop 0
;; header 0, latch 1
;; depth 0, outer -1
;; nodes: 0 1 2 3 4
;; 2 succs { 3 4 }
;; 3 succs { 4 }
;; 4 succs { 1 }
Value ranges after VRP:
_1: VARYING
_2: VARYING
val_8: VARYING
_9: [0, +INF]
val_10: VARYING
val_11: VARYING
val_14: [-INF, -1]
_15: [0, +INF]
_16: [0, +INF]
foobar (int n)
{
int val;
int val;
void * _1;
void * _2;
unsigned int _9;
unsigned int _15;
_Bool _16;
<bb 2> [100.00%]:
val_10 = value ();
_9 = (unsigned int) val_10;
_15 = _9 + 2147483646;
_16 = _15 <= 2147484881;
if (_16 != 0)
goto <bb 3>; [50.00%]
else
goto <bb 4>; [50.00%]
<bb 3> [25.00%]:
<bb 4> [100.00%]:
# val_11 = PHI <-2147483647(3), val_10(2)>
_1 = alloc (val_11);
sink (_1);
val_8 = value ();
val_14 = MIN_EXPR <val_8, -1>;
_2 = alloc (val_14);
sink (_2);
return;
}
t.c: In function ‘foobar’:
t.c:29:3: warning: argument 1 range [-2147483648, -1] is negative
[-Walloc-size-larger-than=]
sink (alloc (anti_range (0, INT_MAX)));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t.c:5:7: note: in a call to allocation function ‘alloc’ declared here
void* alloc (int) __attribute__ ((alloc_size (1)));
^~~~~