public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/53792] New: [C++11][constexpr] improving compiler-time constexpr evaluation
@ 2012-06-28 6:59 vincenzo.innocente at cern dot ch
2012-06-28 9:34 ` [Bug c++/53792] " rguenth at gcc dot gnu.org
` (7 more replies)
0 siblings, 8 replies; 9+ messages in thread
From: vincenzo.innocente at cern dot ch @ 2012-06-28 6:59 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53792
Bug #: 53792
Summary: [C++11][constexpr] improving compiler-time constexpr
evaluation
Classification: Unclassified
Product: gcc
Version: 4.8.0
Status: UNCONFIRMED
Severity: enhancement
Priority: P3
Component: c++
AssignedTo: unassigned@gcc.gnu.org
ReportedBy: vincenzo.innocente@cern.ch
Filed under c++ even if it is most probably an optimization issue.
At the moment it looks like that constexpr are evaluated at compile time only
if explicitly assigned to a constexpr constant. There are cases though where
the compiler can infer that the expression can still be evaluated at compile
time even if used in a run-time context.
Take the following quite realistic example of a consexpr "indexing table" used
to access a non-const array using string literals though an inline function.
In principle foo and bar are equivalent.
At the moment gcc evaluates "getIndex" at compile time for bar (where the marco
expansion explicitly instantiates a constexpr int, while it generates runtime
code for foo that uses the inlined function getV.
Would the compiler be able to transform getV in something like the code in the
macro?
constexpr entry theMap[] = {
{"a", 0},
{"b", 1},
{nullptr,2}
};
// filled at run time
double v[3];
constexpr bool same(char const *x, char const *y) {
return !*x && !*y ? true : (*x == *y && same(x+1, y+1));
}
constexpr int getIndex(char const *label, entry const *entries) {
return !entries->label ? entries->index : same(entries->label, label) ?
entries->index : getIndex(label, entries+1);
}
inline double __attribute__((always_inline)) getV(const char * name ) {
return v[getIndex(name,theMap)];
}
#define SetV(X,NAME) \
constexpr int i_##X = getIndex(NAME, theMap);\
const double X = v[i_##X]
int foo() {
const double a = getV("a");
const double b = getV("b");
if (a==b) return 1;
return 0;
}
int bar() {
SetV(a,"a");
SetV(b,"b");
if (a==b) return 1;
return 0;
}
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/53792] [C++11][constexpr] improving compiler-time constexpr evaluation
2012-06-28 6:59 [Bug c++/53792] New: [C++11][constexpr] improving compiler-time constexpr evaluation vincenzo.innocente at cern dot ch
@ 2012-06-28 9:34 ` rguenth at gcc dot gnu.org
2012-06-28 11:08 ` vincenzo.innocente at cern dot ch
` (6 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: rguenth at gcc dot gnu.org @ 2012-06-28 9:34 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53792
Richard Guenther <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|UNCONFIRMED |NEW
Last reconfirmed| |2012-06-28
Ever Confirmed|0 |1
--- Comment #1 from Richard Guenther <rguenth at gcc dot gnu.org> 2012-06-28 09:34:20 UTC ---
Does the C++ standard require getIndex to be evaluated to a constant in getV?
Or is 'constexpr' only telling you that it is required in a context where
evaluation to a constant is required (and thus arguments to a constexpr
function are constrained)?
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/53792] [C++11][constexpr] improving compiler-time constexpr evaluation
2012-06-28 6:59 [Bug c++/53792] New: [C++11][constexpr] improving compiler-time constexpr evaluation vincenzo.innocente at cern dot ch
2012-06-28 9:34 ` [Bug c++/53792] " rguenth at gcc dot gnu.org
@ 2012-06-28 11:08 ` vincenzo.innocente at cern dot ch
2012-07-19 14:28 ` jason at gcc dot gnu.org
` (5 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: vincenzo.innocente at cern dot ch @ 2012-06-28 11:08 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53792
--- Comment #2 from vincenzo Innocente <vincenzo.innocente at cern dot ch> 2012-06-28 11:08:38 UTC ---
On 28 Jun, 2012, at 11:34 AM, rguenth at gcc dot gnu.org wrote:
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53792
>
> Richard Guenther <rguenth at gcc dot gnu.org> changed:
>
> What |Removed |Added
> ----------------------------------------------------------------------------
> Status|UNCONFIRMED |NEW
> Last reconfirmed| |2012-06-28
> Ever Confirmed|0 |1
>
> --- Comment #1 from Richard Guenther <rguenth at gcc dot gnu.org> 2012-06-28 09:34:20 UTC ---
> Does the C++ standard require getIndex to be evaluated to a constant in getV?
No, a constexpr function can be used as a "normal" function. For instance if
getV was not inlined
the correct behaviour is what we observe
> Or is 'constexpr' only telling you that it is required ina context where
> evaluation to a constant is required (and thus arguments to a constexpr
> function are constrained)?
I would say yes (a constant needs to be evaluated using a constexpr function.
see page 148-150 (166-168 of my pdf) of the standard (7.1.5 point 3 and
following)
>
My point is that the compiler does not identify that "getIndex" is a constant
expression in the context of foo
nor in context of the following foo2 that indeed produce (as it should)
identical code to foo
int foo2() {
const double a = v[getIndex("a",theMap)];
const double b = v[getIndex("b",theMap)];
if (a==b) return 1;
return 0;
}
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/53792] [C++11][constexpr] improving compiler-time constexpr evaluation
2012-06-28 6:59 [Bug c++/53792] New: [C++11][constexpr] improving compiler-time constexpr evaluation vincenzo.innocente at cern dot ch
2012-06-28 9:34 ` [Bug c++/53792] " rguenth at gcc dot gnu.org
2012-06-28 11:08 ` vincenzo.innocente at cern dot ch
@ 2012-07-19 14:28 ` jason at gcc dot gnu.org
2012-07-27 10:48 ` vincenzo.innocente at cern dot ch
` (4 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: jason at gcc dot gnu.org @ 2012-07-19 14:28 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53792
Jason Merrill <jason at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |jason at gcc dot gnu.org
--- Comment #3 from Jason Merrill <jason at gcc dot gnu.org> 2012-07-19 14:27:49 UTC ---
Since getV is not constexpr, constexpr doesn't help with optimization of foo,
so it relies on inlining. constexpr should help with foo2, however.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/53792] [C++11][constexpr] improving compiler-time constexpr evaluation
2012-06-28 6:59 [Bug c++/53792] New: [C++11][constexpr] improving compiler-time constexpr evaluation vincenzo.innocente at cern dot ch
` (2 preceding siblings ...)
2012-07-19 14:28 ` jason at gcc dot gnu.org
@ 2012-07-27 10:48 ` vincenzo.innocente at cern dot ch
2012-07-27 15:06 ` jason at redhat dot com
` (3 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: vincenzo.innocente at cern dot ch @ 2012-07-27 10:48 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53792
--- Comment #4 from vincenzo Innocente <vincenzo.innocente at cern dot ch> 2012-07-27 10:47:49 UTC ---
is "__attribute__((always_inline)) " not making foo to transform in foo2 in a
very early compiler's stage?
I can make getV a macro if helps: I do not like SetV due to its "not natural"
syntax
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/53792] [C++11][constexpr] improving compiler-time constexpr evaluation
2012-06-28 6:59 [Bug c++/53792] New: [C++11][constexpr] improving compiler-time constexpr evaluation vincenzo.innocente at cern dot ch
` (3 preceding siblings ...)
2012-07-27 10:48 ` vincenzo.innocente at cern dot ch
@ 2012-07-27 15:06 ` jason at redhat dot com
2012-08-08 11:18 ` giulio.eulisse at cern dot ch
` (2 subsequent siblings)
7 siblings, 0 replies; 9+ messages in thread
From: jason at redhat dot com @ 2012-07-27 15:06 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53792
--- Comment #5 from Jason Merrill <jason at redhat dot com> 2012-07-27 15:06:31 UTC ---
On 07/27/2012 06:47 AM, vincenzo.innocente at cern dot ch wrote:
> is "__attribute__((always_inline)) " not making foo to transform in foo2 in a
> very early compiler's stage?
Fairly early, but not as early as constant expression folding.
Jason
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/53792] [C++11][constexpr] improving compiler-time constexpr evaluation
2012-06-28 6:59 [Bug c++/53792] New: [C++11][constexpr] improving compiler-time constexpr evaluation vincenzo.innocente at cern dot ch
` (4 preceding siblings ...)
2012-07-27 15:06 ` jason at redhat dot com
@ 2012-08-08 11:18 ` giulio.eulisse at cern dot ch
2012-08-08 18:19 ` paolo.carlini at oracle dot com
2015-05-06 15:03 ` [Bug c++/53792] [C++11] " balakrishnan.erode at gmail dot com
7 siblings, 0 replies; 9+ messages in thread
From: giulio.eulisse at cern dot ch @ 2012-08-08 11:18 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53792
Giulio Eulisse <giulio.eulisse at cern dot ch> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |giulio.eulisse at cern dot
| |ch
--- Comment #6 from Giulio Eulisse <giulio.eulisse at cern dot ch> 2012-08-08 11:17:58 UTC ---
A simpler testcase for the underlying problem is the following.
struct entry {
char const* label;
int value;
};
constexpr bool same(char const *x, char const *y) {
return !*x && !*y ? true
: /* default */ (*x == *y && same(x+1, y+1));
}
constexpr int keyToValue(char const *label, entry const *entries) {
return !entries->label ? entries->value
: same(entries->label, label) ? entries->value
: /*default*/ keyToValue(label, entries+1);
}
constexpr entry foo[] = {{"Foo", 0}, {"Bar", 1}, {"FooBar", 2}, {0, -1}};
int
bar()
{
/* constexpr */ int result = keyToValue("Foo", foo); // Uncomment constexpr
for optimized version.
return result;
}
Without the constexpr the code is fully expanded as if the arguments were
generic:
0000000000000000 <_Z3barv>:
0: 53 push %rbx
1: bf 00 00 00 00 mov $0x0,%edi
6: bb 00 00 00 00 mov $0x0,%ebx
b: eb 0f jmp 1c <_Z3barv+0x1c>
d: 0f 1f 00 nopl (%rax)
10: 48 83 c3 10 add $0x10,%rbx
14: 48 8b 3b mov (%rbx),%rdi
17: 48 85 ff test %rdi,%rdi
1a: 74 1d je 39 <_Z3barv+0x39>
1c: 80 3f 46 cmpb $0x46,(%rdi)
1f: 75 ef jne 10 <_Z3barv+0x10>
21: 80 7f 01 6f cmpb $0x6f,0x1(%rdi)
25: 75 e9 jne 10 <_Z3barv+0x10>
27: 48 83 c7 02 add $0x2,%rdi
2b: be 00 00 00 00 mov $0x0,%esi
30: e8 00 00 00 00 callq 35 <_Z3barv+0x35>
35: 84 c0 test %al,%al
37: 74 d7 je 10 <_Z3barv+0x10>
39: 8b 43 08 mov 0x8(%rbx),%eax
3c: 5b pop %rbx
3d: c3 retq
Disassembly of section .text._Z4samePKcS0_:
0000000000000000 <_Z4samePKcS0_>:
0: 0f b6 17 movzbl (%rdi),%edx
3: 84 d2 test %dl,%dl
5: 75 09 jne 10 <_Z4samePKcS0_+0x10>
7: 80 3e 00 cmpb $0x0,(%rsi)
a: 0f 94 c0 sete %al
d: c3 retq
e: 66 90 xchg %ax,%ax
10: 31 c0 xor %eax,%eax
12: 3a 16 cmp (%rsi),%dl
14: 74 0a je 20 <_Z4samePKcS0_+0x20>
16: c3 retq
17: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
1e: 00 00
20: 0f b6 47 01 movzbl 0x1(%rdi),%eax
24: 84 c0 test %al,%al
26: 75 10 jne 38 <_Z4samePKcS0_+0x38>
28: 80 7e 01 00 cmpb $0x0,0x1(%rsi)
2c: b8 01 00 00 00 mov $0x1,%eax
31: 75 0a jne 3d <_Z4samePKcS0_+0x3d>
33: f3 c3 repz retq
35: 0f 1f 00 nopl (%rax)
38: 3a 46 01 cmp 0x1(%rsi),%al
3b: 74 0b je 48 <_Z4samePKcS0_+0x48>
3d: 31 c0 xor %eax,%eax
3f: 90 nop
40: c3 retq
41: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
48: 48 83 ec 08 sub $0x8,%rsp
4c: 48 83 c6 02 add $0x2,%rsi
50: 48 83 c7 02 add $0x2,%rdi
54: e8 00 00 00 00 callq 59 <_Z4samePKcS0_+0x59>
59: 84 c0 test %al,%al
5b: 74 10 je 6d <_Z4samePKcS0_+0x6d>
5d: b8 01 00 00 00 mov $0x1,%eax
62: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
68: 48 83 c4 08 add $0x8,%rsp
6c: c3 retq
6d: 31 c0 xor %eax,%eax
6f: eb f7 jmp 68 <_Z4samePKcS0_+0x68>
while with constexpr on results everything is optimized out:
0000000000000000 <_Z3barv>:
0: 31 c0 xor %eax,%eax
2: c3 retq
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/53792] [C++11][constexpr] improving compiler-time constexpr evaluation
2012-06-28 6:59 [Bug c++/53792] New: [C++11][constexpr] improving compiler-time constexpr evaluation vincenzo.innocente at cern dot ch
` (5 preceding siblings ...)
2012-08-08 11:18 ` giulio.eulisse at cern dot ch
@ 2012-08-08 18:19 ` paolo.carlini at oracle dot com
2015-05-06 15:03 ` [Bug c++/53792] [C++11] " balakrishnan.erode at gmail dot com
7 siblings, 0 replies; 9+ messages in thread
From: paolo.carlini at oracle dot com @ 2012-08-08 18:19 UTC (permalink / raw)
To: gcc-bugs
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53792
--- Comment #7 from Paolo Carlini <paolo.carlini at oracle dot com> 2012-08-08 18:18:51 UTC ---
Thanks Giulio!
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Bug c++/53792] [C++11] improving compiler-time constexpr evaluation
2012-06-28 6:59 [Bug c++/53792] New: [C++11][constexpr] improving compiler-time constexpr evaluation vincenzo.innocente at cern dot ch
` (6 preceding siblings ...)
2012-08-08 18:19 ` paolo.carlini at oracle dot com
@ 2015-05-06 15:03 ` balakrishnan.erode at gmail dot com
7 siblings, 0 replies; 9+ messages in thread
From: balakrishnan.erode at gmail dot com @ 2015-05-06 15:03 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53792
Balakrishnan B <balakrishnan.erode at gmail dot com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |balakrishnan.erode at gmail dot co
| |m
--- Comment #8 from Balakrishnan B <balakrishnan.erode at gmail dot com> ---
Another testcase with c++14 extended constexpr (i.e supports loops and more
than one statement).
Code:
template<class T>
void sink(T);
constexpr unsigned foo(){
unsigned i = 1;
while((i<<1) > i){
i = i<<1;
}
return i;
}
template<unsigned i>
struct Foo
{
};
void bar(){
sink(foo());
sink(Foo<foo()>{});
}
Assembly for bar:
clang3.5.1 -O3 -std=c++14
bar(): # @bar()
pushq %rax
movl $-2147483648, %edi # imm = 0xFFFFFFFF80000000
callq void sink<unsigned int>(unsigned int)
popq %rax
jmp void sink<Foo<2147483648u> >(Foo<2147483648u>) # TAILCALL
gcc5.1.0 -O3 -std=c++14
bar():
movl $32, %eax
movl $1, %edi
jmp .L2
.L3:
movl %edx, %edi
.L2:
subl $1, %eax
leal (%rdi,%rdi), %edx
jne .L3
subq $8, %rsp
call void sink<unsigned int>(unsigned int)
subq $8, %rsp
pushq $0
call void sink<Foo<2147483648u> >(Foo<2147483648u>)
addq $24, %rsp
ret
Live demo: http://goo.gl/b56Q5k
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2015-05-06 15:03 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-28 6:59 [Bug c++/53792] New: [C++11][constexpr] improving compiler-time constexpr evaluation vincenzo.innocente at cern dot ch
2012-06-28 9:34 ` [Bug c++/53792] " rguenth at gcc dot gnu.org
2012-06-28 11:08 ` vincenzo.innocente at cern dot ch
2012-07-19 14:28 ` jason at gcc dot gnu.org
2012-07-27 10:48 ` vincenzo.innocente at cern dot ch
2012-07-27 15:06 ` jason at redhat dot com
2012-08-08 11:18 ` giulio.eulisse at cern dot ch
2012-08-08 18:19 ` paolo.carlini at oracle dot com
2015-05-06 15:03 ` [Bug c++/53792] [C++11] " balakrishnan.erode at gmail dot com
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).