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))); ^~~~~