complex support when using -std=c++11

2015-11-12 Thread D Haley

Dear List,

I am currently trying to understand an issue to do with complex number 
support in gcc.


Consider the following code:

#include 
int main()
{
float _Complex  a = _Complex_I;

}

Attempting to compile this with  these commands is fine:
$ g++ tmp.cpp -std=gnu++11
$ g++ tmp.cpp

Clang is also fine:
$ clang tmp.cpp -std=c++11

Attempting to compile with c++11 is not:
$ g++ tmp.cpp -std=c++11
In file included from /usr/include/c++/5/complex.h:36:0,
 from tmp.cpp:2:
tmp.cpp: In function ‘int main()’:
tmp.cpp:5:29: error: unable to find numeric literal operator ‘operator""iF’
 float _Complex  a = _Complex_I;
 ^
tmp.cpp:5:29: note: use -std=gnu++11 or -fext-numeric-literals to enable 
more built-in suffixes


I'm using debian testing's gcc:
$ gcc --version
gcc (Debian 5.2.1-17) 5.2.1 20150911
...


I discussed this on #gcc, and it was suggested (or I misunderstood) that 
this is intentional, and the library should not support c-type C++ 
primitives - however I can find no deprecation notice for this, nor does 
it appear that the c++11 standard (as far as I can see from a quick 
skim) has changed the behaviour in this regard.


Is this intended behaviour, or is this a bug? This behaviour was noticed 
when troubleshooting compilation behaviours in mathgl.


https://groups.google.com/forum/?_escaped_fragment_=topic/mathgl/cl4uYygPmOU#!topic/mathgl/cl4uYygPmOU


Thanks.




VRP causing extra register usage

2015-11-12 Thread Senthil Kumar Selvaraj
Hi,

  When analyzing code size differences between a 4.9.x compiler and
  trunk for the AVR target, I found quite a few cases where extra
  registers were being used to hold smaller types (two 8 bit registers
  for a uint8_t, for example).

  On deeper analysis, I found that the VRP pass (gcc/tree-vrp.c) was the point
  at which the dumps start to diverge.

  For code like this

#include 

uint16_t get(const uint16_t wvalue)
{
  const uint8_t type = (wvalue >> 8);
  uint16_t size = 0;

  if (type == 1)
  {
size = 20;
  }
  else if (type == 2)
  {
size = 32;
  }
  return size;
}

  VRP substitutes wvalue for the type variable in the conditionals 
  (simplify_cond_using_ranges:9506), as it figures out that the range 
  of wvalue is the same as a uint8_t). That is, code goes from

:
_3 = wvalue_2(D) >> 8;
type_4 = (const uint8_t) _3;
if (type_4 == 1)
  goto ;
else
  goto ;

to

:
_3 = wvalue_2(D) >> 8;
type_4 = (const uint8_t) _3;
if (_3 == 1)
  goto ;
else
  goto ;

  This "widening" causes later passes to allocate extra registers 
  (holding zeros for the extra bits) and generate extra comparisons
  for the AVR target.

  I found that in the 4.9.2 compiler I was benchmarking against, VRP
  didn't figure out the range for wvalue and therefore the folding
  didn't happen, which was why the code was better.

  With the native compiler on my machine (gcc 5.2 x86_64) - replacing 
  uint8_t by uint32_t and uint16_t by uint64_t, and shifting right by 
  32 bits instead of 8 shows the same effect - the generated code uses
  rdi instead of just di to hold the type variable.

  Is this a bug? Should the folding happen only if the type
  conversion was from a smaller type to a bigger one? Or is the backend
  supposed to detect this pattern and deal with it?

Regards
Senthil


details-raw vrp1 dump

;; Function get (get, funcdef_no=0, decl_uid=1522, 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 }
;; 5 succs { 1 }

ASSERT_EXPRs to be inserted

Assertions to be inserted for type_4
if (type_4 == 1)

BB #3
EDGE 2->3 2 [55.9%]  (FALSE_VALUE,EXECUTABLE)
PREDICATE: type_4 ne_expr 1




Updating SSA:
Registering new PHI nodes in block #2
Updating SSA information for statement type_4 = (const uint8_t) _3;
Updating SSA information for statement if (type_4 == 1)
Registering new PHI nodes in block #3
Updating SSA information for statement type_6 = ASSERT_EXPR ;
Updating SSA information for statement if (type_4 == 2)
Registering new PHI nodes in block #4
Registering new PHI nodes in block #5

SSA replacement table
N_i -> { O_1 ... O_j } means that N_i replaces O_1, ..., O_j

type_6 -> { type_4 }
Incremental SSA update started at block: 2
Number of blocks in CFG: 6
Number of blocks to update: 2 ( 33%)
Affected blocks: 2 3



SSA form after inserting ASSERT_EXPRs
get (const uint16_t wvalue, const uint8_t windex, const void * * const address)
{
  uint16_t size;
  const uint8_t type;
  unsigned int _3;

  :
  _3 = wvalue_2(D) >> 8;
  type_4 = (const uint8_t) _3;
  if (type_4 == 1)
goto ;
  else
goto ;

  :
  type_6 = ASSERT_EXPR ;
  if (type_6 == 2)
goto ;
  else
goto ;

  :

  :
  # size_1 = PHI <20(2), 0(3), 32(4)>
  return size_1;

}


Immediate_uses: 

size_1 : --> single use.
return size_1;

wvalue_2(D) : --> single use.
_3 = wvalue_2(D) >> 8;

_3 : --> single use.
type_4 = (const uint8_t) _3;

type_4 : -->3 uses.
type_6 = ASSERT_EXPR ;
type_6 = ASSERT_EXPR ;
if (type_4 == 1)

.MEM_5(D) : --> single use.
# VUSE <.MEM_5(D)>
return size_1;

type_6 : --> single use.
if (type_6 == 2)

Adding destination of edge (0 -> 2) to worklist

Simulating block 2

Visiting statement:
_3 = wvalue_2(D) >> 8;
Intersecting
  [0, 255]
and
  [0, +INF]
to
  [0, 255]
Found new range for _3: [0, 255]
interesting_ssa_edges: adding SSA use in type_4 = (const uint8_t) _3;
marking stmt to be not simulated again

Visiting statement:
type_4 = (const uint8_t) _3;
Found new range for type_4: [0, +INF]
interesting_ssa_edges: adding SSA use in type_6 = ASSERT_EXPR ;
interesting_ssa_edges: adding SSA use in if (type_4 == 1)
marking stmt to be not simulated again

Visiting statement:
if (type_4 == 1)

Visiting conditional with predicate: if (type_4 == 1)

With known ranges
type_4: [0, +INF]

Predicate evaluates to: DON'T KNOW
Adding destination of edge (2 -> 5) to worklist
Adding destination of edge (2 -> 3) to worklist

Simulating block 3

Visiting statement:
type_6 = ASSERT_EXPR ;
Intersecting
  ~[1, 1]  EQUIVALENCES: { type_4 } (1 elements)
and
  [0, +INF]
to
  ~[1, 1]  EQUIVALENCES: { type_4 } (1 elements)
Found new range for type_6: ~[1, 1]
interesting_ssa_edges: adding SSA use in if (type_6 == 2)
marking stmt to be not simulated again

Visiting statement:
if (type_6 == 2)

Visiting conditional with predicate: if (type_6 == 2)

With known ranges
type_6: ~[1,

Re: VRP causing extra register usage

2015-11-12 Thread Richard Biener
On November 12, 2015 8:10:05 PM GMT+01:00, Senthil Kumar Selvaraj 
 wrote:
>Hi,
>
>  When analyzing code size differences between a 4.9.x compiler and
>  trunk for the AVR target, I found quite a few cases where extra
>  registers were being used to hold smaller types (two 8 bit registers
>  for a uint8_t, for example).
>
>On deeper analysis, I found that the VRP pass (gcc/tree-vrp.c) was the
>point
>  at which the dumps start to diverge.
>
>  For code like this
>
>#include 
>
>uint16_t get(const uint16_t wvalue)
>{
>  const uint8_t type = (wvalue >> 8);
>  uint16_t size = 0;
>
>  if (type == 1)
>  {
>size = 20;
>  }
>  else if (type == 2)
>  {
>size = 32;
>  }
>  return size;
>}
>
>  VRP substitutes wvalue for the type variable in the conditionals 
>  (simplify_cond_using_ranges:9506), as it figures out that the range 
>  of wvalue is the same as a uint8_t). That is, code goes from
>
>:
>_3 = wvalue_2(D) >> 8;
>type_4 = (const uint8_t) _3;
>if (type_4 == 1)
>  goto ;
>else
>  goto ;
>
>to
>
>:
>_3 = wvalue_2(D) >> 8;
>type_4 = (const uint8_t) _3;
>if (_3 == 1)
>  goto ;
>else
>  goto ;
>
>  This "widening" causes later passes to allocate extra registers 
>  (holding zeros for the extra bits) and generate extra comparisons
>  for the AVR target.
>
>  I found that in the 4.9.2 compiler I was benchmarking against, VRP
>  didn't figure out the range for wvalue and therefore the folding
>  didn't happen, which was why the code was better.
>
>  With the native compiler on my machine (gcc 5.2 x86_64) - replacing 
>  uint8_t by uint32_t and uint16_t by uint64_t, and shifting right by 
>  32 bits instead of 8 shows the same effect - the generated code uses
>  rdi instead of just di to hold the type variable.
>
>  Is this a bug? Should the folding happen only if the type
>  conversion was from a smaller type to a bigger one? Or is the backend
>  supposed to detect this pattern and deal with it?

We should probably avoid widening beyond word_mode (or sth else if there is sth 
suitable).

Richard.

>Regards
>Senthil
>
>
>details-raw vrp1 dump
>
>;; Function get (get, funcdef_no=0, decl_uid=1522, 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 }
>;; 5 succs { 1 }
>
>ASSERT_EXPRs to be inserted
>
>Assertions to be inserted for type_4
>   if (type_4 == 1)
>
>   BB #3
>   EDGE 2->3 2 [55.9%]  (FALSE_VALUE,EXECUTABLE)
>   PREDICATE: type_4 ne_expr 1
>
>
>
>
>Updating SSA:
>Registering new PHI nodes in block #2
>Updating SSA information for statement type_4 = (const uint8_t) _3;
>Updating SSA information for statement if (type_4 == 1)
>Registering new PHI nodes in block #3
>Updating SSA information for statement type_6 = ASSERT_EXPR type_4 != 1>;
>Updating SSA information for statement if (type_4 == 2)
>Registering new PHI nodes in block #4
>Registering new PHI nodes in block #5
>
>SSA replacement table
>N_i -> { O_1 ... O_j } means that N_i replaces O_1, ..., O_j
>
>type_6 -> { type_4 }
>Incremental SSA update started at block: 2
>Number of blocks in CFG: 6
>Number of blocks to update: 2 ( 33%)
>Affected blocks: 2 3
>
>
>
>SSA form after inserting ASSERT_EXPRs
>get (const uint16_t wvalue, const uint8_t windex, const void * * const
>address)
>{
>  uint16_t size;
>  const uint8_t type;
>  unsigned int _3;
>
>  :
>  _3 = wvalue_2(D) >> 8;
>  type_4 = (const uint8_t) _3;
>  if (type_4 == 1)
>goto ;
>  else
>goto ;
>
>  :
>  type_6 = ASSERT_EXPR ;
>  if (type_6 == 2)
>goto ;
>  else
>goto ;
>
>  :
>
>  :
>  # size_1 = PHI <20(2), 0(3), 32(4)>
>  return size_1;
>
>}
>
>
>Immediate_uses: 
>
>size_1 : --> single use.
>return size_1;
>
>wvalue_2(D) : --> single use.
>_3 = wvalue_2(D) >> 8;
>
>_3 : --> single use.
>type_4 = (const uint8_t) _3;
>
>type_4 : -->3 uses.
>type_6 = ASSERT_EXPR ;
>type_6 = ASSERT_EXPR ;
>if (type_4 == 1)
>
>.MEM_5(D) : --> single use.
># VUSE <.MEM_5(D)>
>return size_1;
>
>type_6 : --> single use.
>if (type_6 == 2)
>
>Adding destination of edge (0 -> 2) to worklist
>
>Simulating block 2
>
>Visiting statement:
>_3 = wvalue_2(D) >> 8;
>Intersecting
>  [0, 255]
>and
>  [0, +INF]
>to
>  [0, 255]
>Found new range for _3: [0, 255]
>interesting_ssa_edges: adding SSA use in type_4 = (const uint8_t) _3;
>marking stmt to be not simulated again
>
>Visiting statement:
>type_4 = (const uint8_t) _3;
>Found new range for type_4: [0, +INF]
>interesting_ssa_edges: adding SSA use in type_6 = ASSERT_EXPR type_4 != 1>;
>interesting_ssa_edges: adding SSA use in if (type_4 == 1)
>marking stmt to be not simulated again
>
>Visiting statement:
>if (type_4 == 1)
>
>Visiting conditional with predicate: if (type_4 == 1)
>
>With known ranges
>   type_4: [0, +INF]
>
>Predicate evaluates to: DON'T KNOW
>Adding destination of edge (2 -> 5) to worklist
>Adding destination of edge (2 -> 3) to worklist
>
>Simulating block 3
>
>Visiting statement:
>type_6 

Re: complex support when using -std=c++11

2015-11-12 Thread Marc Glisse

On Thu, 12 Nov 2015, D Haley wrote:

I am currently trying to understand an issue to do with complex number 
support in gcc.


Consider the following code:

#include 
int main()
{
   float _Complex  a = _Complex_I;

}

Attempting to compile this with  these commands is fine:
$ g++ tmp.cpp -std=gnu++11
$ g++ tmp.cpp

Clang is also fine:
$ clang tmp.cpp -std=c++11


Not here, I am getting the same error with clang (or "use of undeclared 
identifier '_Complex_I'" with libc++). This probably depends more on your 
libc.



Attempting to compile with c++11 is not:
$ g++ tmp.cpp -std=c++11
In file included from /usr/include/c++/5/complex.h:36:0,
from tmp.cpp:2:
tmp.cpp: In function ‘int main()’:
tmp.cpp:5:29: error: unable to find numeric literal operator ‘operator""iF’
float _Complex  a = _Complex_I;
^
tmp.cpp:5:29: note: use -std=gnu++11 or -fext-numeric-literals to enable more 
built-in suffixes


I'm using debian testing's gcc:
$ gcc --version
gcc (Debian 5.2.1-17) 5.2.1 20150911
...


I discussed this on #gcc, and it was suggested (or I misunderstood) that this 
is intentional, and the library should not support c-type C++ primitives - 
however I can find no deprecation notice for this, nor does it appear that 
the c++11 standard (as far as I can see from a quick skim) has changed the 
behaviour in this regard.


Is this intended behaviour, or is this a bug? This behaviour was noticed when 
troubleshooting compilation behaviours in mathgl.


https://groups.google.com/forum/?_escaped_fragment_=topic/mathgl/cl4uYygPmOU#!topic/mathgl/cl4uYygPmOU


C++11, for some unknown reason, decided to hijack the C header complex.h 
and make it equivalent to the C++ header complex. The fact that you are 
still getting _Complex_I defined is already a gcc extension, as is 
providing _Complex in C++.


The C++ standard introduced User Defined Literals, which prevents the 
compiler from recognizing extra suffixes like iF in standard mode (why are 
so many people using c++11 and not gnu++11?).


Our support for complex.h in C++11 in gcc is kind of best-effort. In this 
case, I can think of a couple ways we could improve this


* _Complex_I is defined as (__extension__ 1.0iF). Maybe __extension__ 
could imply -fext-numeric-literals?


* glibc could define _Complex_I some other way, or libstdc++ could 
redefine it to some other safer form (for some reason __builtin_complex is 
currently C-only).


--
Marc Glisse