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

Reply via email to