https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78354
Bug ID: 78354 Summary: range information lost after unsigned conversion 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: --- Assigning a variable whose range is strictly within the bounds of a narrower unsigned is converted to that type the range is preserved. However, when one of the bounds of a variable exceeds the corresponding bound of the narrower type converting it to that narrower type loses both bounds (and the range after conversion becomes VARYING) even though the other bound is within the destination type's range and could be preserved. Since such conversions are common enhancing the VRP engine to recognize this and preserve the bound is likely to improve generated code. The following test case demonstrates this using variables of unsigned int and unsigned short but other types are subject to the same limitation. $ cat c.c && gcc -O2 -S -Wall -fdump-tree-vrp=/dev/stdout c.c void f (unsigned x) { if (x < 123 || 123456 < x) x = 123; unsigned short y = x; if (y < 123) __builtin_abort (); } ;; Function f (f, funcdef_no=0, decl_uid=1795, 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 6 ;; 2 succs { 3 4 } ;; 3 succs { 4 } ;; 4 succs { 5 6 } ;; 5 succs { } ;; 6 succs { 1 } Adding assert for x_3(D) from x_3(D) + 4294967173 Adding assert for x_3(D) from x_3(D) + 4294967173 SSA replacement table N_i -> { O_1 ... O_j } means that N_i replaces O_1, ..., O_j x_7 -> { x_3(D) } x_8 -> { x_3(D) } Incremental SSA update started at block: 2 Number of blocks in CFG: 8 Number of blocks to update: 4 ( 50%) Value ranges after VRP: _1: [0, +INF] x_2: [123, 123456] EQUIVALENCES: { } (0 elements) x_3(D): VARYING y_4: [0, +INF] x_7: ~[123, 123456] EQUIVALENCES: { x_3(D) } (1 elements) x_8: [123, 123456] EQUIVALENCES: { x_3(D) } (1 elements) Removing basic block 3 Removing basic block 7 SSA replacement table N_i -> { O_1 ... O_j } means that N_i replaces O_1, ..., O_j x_9 -> { x_2 } y_10 -> { y_4 } Incremental SSA update started at block: 2 Number of blocks in CFG: 7 Number of blocks to update: 3 ( 43%) f (unsigned int x) { short unsigned int y; unsigned int _1; <bb 2>: _1 = x_3(D) + 4294967173; if (_1 > 123333) goto <bb 6>; else goto <bb 3>; <bb 3>: # x_2 = PHI <x_3(D)(2)> y_4 = (short unsigned int) x_2; if (y_4 <= 122) goto <bb 4>; else goto <bb 5>; <bb 4>: __builtin_abort (); <bb 5>: return; <bb 6>: # x_9 = PHI <123(2)> y_10 = (short unsigned int) x_9; goto <bb 5>; } ;; Function f (f, funcdef_no=0, decl_uid=1795, 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 { 5 3 } ;; 3 succs { 4 5 } ;; 4 succs { } ;; 5 succs { 1 } Adding assert for x_3(D) from x_3(D) + 4294967173 SSA replacement table N_i -> { O_1 ... O_j } means that N_i replaces O_1, ..., O_j x_2 -> { x_3(D) } Incremental SSA update started at block: 2 Number of blocks in CFG: 6 Number of blocks to update: 2 ( 33%) Value ranges after VRP: _1: [0, +INF] x_2: [123, 123456] EQUIVALENCES: { x_3(D) } (1 elements) x_3(D): VARYING y_4: [0, +INF] f (unsigned int x) { short unsigned int y; unsigned int _1; <bb 2>: _1 = x_3(D) + 4294967173; if (_1 > 123333) goto <bb 5>; else goto <bb 3>; <bb 3>: y_4 = (short unsigned int) x_3(D); if (y_4 <= 122) goto <bb 4>; else goto <bb 5>; <bb 4>: __builtin_abort (); <bb 5>: return; }