bootstrap error on ppc64
Hello, I get the following error while bootstrapping on ppc64 -r128289: cc/../include -I../../gcc/gcc/../libcpp/include -I../../gcc/gcc/../libdecnumber -I../../gcc/gcc/../libdecnumber/dpd -I../libdecnumber\ -DTARGET_NAME=\"powerpc64-unknown-linux-gnu\" \ -c ../../gcc/gcc/toplev.c -o toplev.o ../../gcc/gcc/toplev.c: In function גgeneral_initג: ../../gcc/gcc/toplev.c:1670: error: גstruct line_mapsג has no member named גreallocatorג make[3]: *** [toplev.o] Error 1 make[3]: Leaving directory `/home/revitale/check_in_sms/build/gcc' make[2]: *** [all-stage1-gcc] Error 2 Thanks, Revital
Which RTL pass should handle REG_EQUAL notes?
Hello! I would like to bring a strange optimization problem to the attention of RTL expert. The problem is outlined in PR rtl-optimization/33353, the core of the problem is that passes that follow RTL fwprop1 pass simply don't process REG_EQUAL notes that mark constant result. For the testcase in PR 33353, following sequence can be found in _.137r.fwprop1 dump, just before the loop: --cut here-- (insn 11 10 12 3 t.c:6 (set (reg:V4SI 64 [ vect_cst_.15 ]) (mem/u/c/i:V4SI (symbol_ref/u:DI ("*.LC0") [flags 0x2]) [3 S16 A128])) 9 60 {*movv4si_internal} (expr_list:REG_EQUAL (const_vector:V4SI [ (const_int 0 [0x0]) (const_int 1 [0x1]) (const_int 2 [0x2]) (const_int 3 [0x3]) ]) (nil))) (insn 12 11 13 3 t.c:6 (parallel [ (set (reg/f:DI 63 [ vect_ptabs.25 ]) (plus:DI (reg/f:DI 20 frame) (const_int -32 [0xffe0]))) (clobber (reg:CC 17 flags)) ]) 230 {*adddi_1_rex64} (nil)) (insn 13 12 14 3 t.c:13 (set (reg:V4SI 65) (mem/u/c/i:V4SI (symbol_ref/u:DI ("*.LC1") [flags 0x2]) [3 S16 A128])) 9 60 {*movv4si_internal} (expr_list:REG_EQUAL (const_vector:V4SI [ (const_int 2 [0x2]) (const_int 2 [0x2]) (const_int 2 [0x2]) (const_int 2 [0x2]) ]) (nil))) (insn 14 13 15 3 t.c:13 (set (reg:V4SI 66) (mult:V4SI (reg:V4SI 64 [ vect_cst_.15 ]) (reg:V4SI 65))) 1137 {*sse2_mulv4si3} (expr_list:REG_EQUAL (const_ve ctor:V4SI [ (const_int 0 [0x0]) (const_int 2 [0x2]) (const_int 4 [0x4]) (const_int 6 [0x6]) ]) (nil))) (insn 15 14 16 3 t.c:13 (set (mem:V4SI (reg/f:DI 63 [ vect_ptabs.25 ]) [3 S16 A1 28]) (reg:V4SI 66)) 960 {*movv4si_internal} (nil)) (insn 16 15 17 3 t.c:13 (set (reg:V4SI 67) (mem/u/c/i:V4SI (symbol_ref/u:DI ("*.LC2") [flags 0x2]) [3 S16 A128])) 9 60 {*movv4si_internal} (expr_list:REG_EQUAL (const_vector:V4SI [ (const_int 4 [0x4]) (const_int 4 [0x4]) (const_int 4 [0x4]) (const_int 4 [0x4]) ]) (nil))) (insn 17 16 19 3 t.c:13 (set (reg:V4SI 68) (plus:V4SI (reg:V4SI 64 [ vect_cst_.15 ]) (reg:V4SI 67))) 1115 {*addv4si3} (expr_list:REG_EQUAL (const_vector: V4SI [ (const_int 4 [0x4]) (const_int 5 [0x5]) (const_int 6 [0x6]) (const_int 7 [0x7]) ]) (nil))) (insn 19 17 20 3 t.c:13 (set (reg:V4SI 70) (mult:V4SI (reg:V4SI 68) (reg:V4SI 65))) 1137 {*sse2_mulv4si3} (expr_list:REG_EQUAL (const_ve ctor:V4SI [ (const_int 8 [0x8]) (const_int 10 [0xa]) (const_int 12 [0xc]) (const_int 14 [0xe]) ]) (nil))) (insn 20 19 22 3 t.c:13 (set (mem:V4SI (plus:DI (reg/f:DI 63 [ vect_ptabs.25 ]) (const_int 16 [0x10])) [3 S16 A128]) (reg:V4SI 70)) 960 {*movv4si_internal} (nil)) --cut here-- As can be seen from above sequence, every relevant insn gets REG_EQUAL attached, as the result is indeed constant. (insn 15) and (insn 20) then push the result to the stack before calling function "g". However, it looks that GCC doesn't know what to do with the constants. One of following passes (which?) should add calculated constant into the constant pool and change (insn 15) and (insn 20) to directly load constants into (reg 66) and (reg 70), without calculating it. Fortunately, loop optimization pass detects that these insns are loop invariant and moves them out of loop, resulting in: .LCFI2: movdqa .LC0(%rip), %xmm1 leaq16(%rsp), %rbp movdqa .LC1(%rip), %xmm0 paddd .LC2(%rip), %xmm1 pmulld %xmm1, %xmm0 movdqa %xmm0, (%rsp) .L2: The question that would shine some light on this issue is, which pass should handle REG_EQUAL notes to substitute calculation with a load from constant pool? Uros.
Re: Bootstrap failure (on FreeBSD)
> On Sat, 8 Sep 2007, Andrew Pinski wrote: > > Rerun the command without the ">/dev/null 2>&1", libtool likes to say > > that PIC mode will give the same output as non PIC mode (which is not > > always true). > > Blind me. Obviously that redirection removed all traces of the real > error. Ahem. Thanks, Andrew. > > Turns out it is an RTL sharing issue on i386. Jan, that's probably one > for you? I can definitly take alook on it, however i386-linux bootstrap fine for me. Can I have testcase? Honza > > > [bootstrap/33352] invalid rtl sharing -- bootstrap failure compiling > libgomp/team.c on i386 > > /sw/test/GCC/trunk/libgomp/team.c: In function 'gomp_thread_start': > /sw/test/GCC/trunk/libgomp/team.c:131: error: invalid rtl sharing found in > the insn > (insn 22 21 23 2 /sw/test/GCC/trunk/libgomp/team.c:89 (parallel [ > (set (reg:SI 74) > (plus:SI (reg:SI 70) > (const:SI (plus:SI (unspec:SI [ > (symbol_ref:SI ("gomp_tls_data") [flags > 0x22] ) > ] 5) > (const_int 8 [0x8]) > (clobber (reg:CC 17 flags)) > ]) 170 {*addsi_1} (nil)) > /sw/test/GCC/trunk/libgomp/team.c:131: error: shared rtx (const:SI (plus:SI > (unspec:SI [ > (symbol_ref:SI ("gomp_tls_data") [flags 0x22] 0x48954ac8 gomp_tls_data>) > ] 5) > (const_int 8 [0x8]))) > /sw/test/GCC/trunk/libgomp/team.c:131: internal compiler error: internal > consistency failure > > Gerald
RE: Does g++ have a intel/msdn __COUNTER__ macro equivalent??
On Tue, 4 Sep 2007, Dave Korn wrote: > On 04 September 2007 10:05, me wrote: >> The point of this is that __COUNTER__ would assign consecutive numbers > >> I can not find g++'s equivalent & wonder how I could achieve the same >> thing? > This feature was just added recently. It will be in all upcoming gcc-4.3 > and later series releases. See > http://gcc.gnu.org/ml/gcc-patches/2007-05/msg01579.html Hmm, I just noticed that we do not indicate so in our release notes, though. Ollie, would you mind adding a snippet to htdocs/gcc-4.3/changes.html in the wwwdocs module of our CVS repository? If you need any help with that, please let me know. Gerald
Re: can't reinterpret_cast to/from the same type
On 08/09/2007, Joe Buck <[EMAIL PROTECTED]> wrote: > > It still seems odd, and this restriction could make the coding of > templates more complex. Agreed, but I'm not sure making reinterpret_cast convenient to use is a noble aim :-) It should be used a last resort, in the knowledge that the result is implementation-defined. Reinterpret_cast isn't generic, it only works with a subset of types, which sounds to me like a definite case for a set of template specialisations. If needed anyone can write a reinterpret_cast wrapper specialised for all the legal reinterpret_cast conversions, as well as various int->long and int->int conversions if they want to allow them. So I don't think GCC needs to do anything. The standard is clear: "No other conversion can be performed explicitly using reinterpret_cast." so any GCC extension to reinterpret_cast would conflict with that. It could also break code that used failure to compile a reinterpret_cast as a form of static_assert (I don't know if anyone actually does that.) Jon
Re: bootstrap comparision failure with --enable-targets=all on i486-linux-gnu
this is now PR 33368, only seen when building with BOOT_CFLAGS="-O2" CFLAGS="-g -O2", an oversight on my side. Seems to be introduced by r128190. Matthias Matthias Klose writes: > seen with r128264, was sucessful on 20070906 > > Matthias > > make[5]: Leaving directory > `/scratch/packages/gcc/snap/gcc-snapshot-20070907/build' > Comparing stages 2 and 3 > warning: ./cc1-checksum.o differs > warning: ./cc1plus-checksum.o differs > Bootstrap comparison failure! > ./cfgloopmanip.o differs > make[4]: *** [compare] Error 1 > make[4]: Leaving directory > `/scratch/packages/gcc/snap/gcc-snapshot-20070907/build' > make[3]: *** [stage3-bubble] Error 2 > make[3]: Leaving directory > `/scratch/packages/gcc/snap/gcc-snapshot-20070907/build' > make[2]: *** [bootstrap-lean] Error 2
Re: bootstrap comparision failure with --enable-targets=all on i486-linux-gnu
On 9/9/07, Matthias Klose <[EMAIL PROTECTED]> wrote: > this is now PR 33368, only seen when building with BOOT_CFLAGS="-O2" > CFLAGS="-g -O2", an oversight on my side. > > Seems to be introduced by r128190. CFLAGS="-g -O2' pulls in all of the nasty dependence on a working host compiler. Which is? If it is 4.1 I would suggest to only use -O at most (no strict aliasing, no VRP and thus less integer overflow issues). Richard.
Re: bootstrap comparision failure with --enable-targets=all on i486-linux-gnu
Richard Guenther writes: > On 9/9/07, Matthias Klose <[EMAIL PROTECTED]> wrote: > > this is now PR 33368, only seen when building with BOOT_CFLAGS="-O2" > > CFLAGS="-g -O2", an oversight on my side. > > > > Seems to be introduced by r128190. > > CFLAGS="-g -O2' pulls in all of the nasty dependence on a working host > compiler. Which is? Seen with both 4.1 and 4.2, recent versions derived from the branches. Matthias
Re: Which RTL pass should handle REG_EQUAL notes?
Uros Bizjak wrote: Hello! I would like to bring a strange optimization problem to the attention of RTL expert. The problem is outlined in PR rtl-optimization/33353, the core of the problem is that passes that follow RTL fwprop1 pass simply don't process REG_EQUAL notes that mark constant resul However, it looks that GCC doesn't know what to do with the constants. The problem is that there is no (set (reg) (const_vector)) insn. RTL passes know how to do many substitutions, but only if the resulting RTL matches. fwprop, combine, CSE could probably do something interesting with an insn matching such a pattern Paolo
Re: [RFC] Marking C++ new operator as malloc?
Gabriel Dos Reis wrote: Joe Buck <[EMAIL PROTECTED]> writes: | On Sat, Sep 08, 2007 at 04:33:50PM -0500, Gabriel Dos Reis wrote: | > "Richard Guenther" <[EMAIL PROTECTED]> writes: | > | > | On 9/8/07, Chris Lattner <[EMAIL PROTECTED]> wrote: | > | > I understand, but allowing users to override new means that the actual | > | > implementation may not honor the aliasing guarantees of attribute | > | > malloc. | > | | > | Well, you can argue that all hell breaks lose if you do so. A sane ::new | > | is required for almost everything :) | > | > I suspect the question is how to you distinguish a sane new from an an | > insane one. | | Does it matter? No, it does not. The reason is 3.7.3.1/2 [...] If the request succeeds, the value returned shall be a nonnull pointer value (4.10) p0 different from any previously returned value p1, unless that value p1 was subsequently passed to an operator delete. That's not sufficient. First, merely requiring pointers to be different isn't the same as requiring them not to alias, which requires the blocks of memory they point to not to overlap. Second, the standard only requires the pointers returned by new to be different from each other, not from any other pointer in the program. Probably the most common use of a custom new is to allocate memory from a user-controlled pool instead of the standard free store. Somewhere in the program there will be a pointer to the complete pool, which aliases every pointer returned by that version of new. Any such pool-based new doesn't meet the requirements of the malloc attribute.
Re: [RFC] Marking C++ new operator as malloc?
On 9/9/07, Ross Smith <[EMAIL PROTECTED]> wrote: > Gabriel Dos Reis wrote: > > Joe Buck <[EMAIL PROTECTED]> writes: > > > > | On Sat, Sep 08, 2007 at 04:33:50PM -0500, Gabriel Dos Reis wrote: > > | > "Richard Guenther" <[EMAIL PROTECTED]> writes: > > | > > > | > | On 9/8/07, Chris Lattner <[EMAIL PROTECTED]> wrote: > > | > | > I understand, but allowing users to override new means that the > > actual > > | > | > implementation may not honor the aliasing guarantees of attribute > > | > | > malloc. > > | > | > > | > | Well, you can argue that all hell breaks lose if you do so. A sane > > ::new > > | > | is required for almost everything :) > > | > > > | > I suspect the question is how to you distinguish a sane new from an an > > | > insane one. > > | > > | Does it matter? > > > > No, it does not. > > > > The reason is 3.7.3.1/2 > > > > [...] If the request succeeds, the value returned shall be a nonnull > > pointer value (4.10) p0 different from any previously returned value > > p1, unless that value p1 was subsequently passed to an operator delete. > > That's not sufficient. First, merely requiring pointers to be different > isn't the same as requiring them not to alias, which requires the blocks > of memory they point to not to overlap. Second, the standard only > requires the pointers returned by new to be different from each other, > not from any other pointer in the program. > > Probably the most common use of a custom new is to allocate memory from > a user-controlled pool instead of the standard free store. Somewhere in > the program there will be a pointer to the complete pool, which aliases > every pointer returned by that version of new. Any such pool-based new > doesn't meet the requirements of the malloc attribute. That doesn't matter. What matters is object lifetime, which is properly preserved by a conforming pool allocator. Richard.
Re: GCC 4.3.0 Status Report (2007-09-04)
Martin Jambor wrote: > Well, there's mine :-) Specifically, its the "Switch initializations > conversion:" http://gcc.gnu.org/ml/gcc-patches/2007-09/msg00215.html Do you have an FSF copyright assignment on file? This patch is big enough that we would not be able to include it without that. > Jakub Jelinek had a few comments and I changed the patch according to > them. After that, nothing much happened. If any maintainer likes the > patch, please commit it as I do not have write access to svn. OTOH, if > there are any further concerns, please let me know. I see one technical change that should be made. In particular, please change: > +/* We never create arrays larger than the following constant (given in number > + of elements). */ > +#define MAX_ARRAY_RANGE 0x2000 > + > +/* We never create arrays if the number of branches is not at least the > range > + divided by the following constant. */ > +#define MAX_RANGE_BRANCH_RATIO 8 to use the --param mechanism. Our policy is to have *no* magic numbers for these kinds of things. It's easy enough to allow users to use --param to set the values, and that makes it easy for people (often the compiler developers themselves) to experiment with the values to help fine-tune the defaults. Other than that, the patch looks pretty good to me. However, I'd like a middle-end maintainer to review the patch. Ian, Diego, Roger, would one of you please take a look? Is there any reason to think this patch might generate worse code on some processors or in some modes? For example, while this patch seems it's definitely a code-size win for dense switch statements, do we need some kind of cost model to tell us whether it's a code-size win with less dense switch statements? Do we want want separate params when we're operating under -Os from when we're operating under -O2? Thanks, -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Re: GCC 4.3.0 Status Report (2007-09-04)
Rask Ingemann Lambertsen wrote: > On Tue, Sep 04, 2007 at 07:40:19PM -0700, Mark Mitchell wrote: >> Are there Stage 1 or Stage 2 patches in need of review? I'll do my best >> to either (a) convince someone to review them, or (b) review them myself. > > http://gcc.gnu.org/ml/gcc-patches/2007-08/msg02217.html This patch is OK. There may be machine descriptions that, for whatever reason, only do something clever with "a + b < b"; they will now lose. But, those machine descriptions were odd anyhow; logically, they should handle both "a + b < a" and "a + b < b" the same way. So, your patch seems like a good improvement; as you say, it gives the back end fewer cases to optimize. Thanks, -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Another BOOTSTRAP failure on sparc-sun-solaris2.10, stage2 miscompiled
Rats, I'm getting another bootstap failure on sparc-sun-solaris2.10. This time it happens in stage2 building libgcc. What happens is that when it runs configure for stage2 libgcc, I get: checking for suffix of object files... configure: error: cannot compute suffix of object files: cannot compile See `config.log' for more details. whereupon in config.log I see: configure: failed program was: | /* confdefs.h. */ | | #define PACKAGE_NAME "GNU C Runtime Library" | #define PACKAGE_TARNAME "libgcc" | #define PACKAGE_VERSION "1.0" | #define PACKAGE_STRING "GNU C Runtime Library 1.0" | #define PACKAGE_BUGREPORT "" | /* end confdefs.h. */ | | int | main () | { | | ; | return 0; | } The stage2 gcc cannot compile this simple program. The stage1 compiler can, so looks like stage2 was miscompiled. Running it under gdb doesn't yield any useful info. This is fairly recent as I got a successful testresult here: http://gcc.gnu.org/ml/gcc-testresults/2007-09/msg00402.html The top of the gcc/ChangeLog from the working checkout was: 2007-09-07 Sterling Augustine <[EMAIL PROTECTED]> * config/xtensa/lib2funcs.S (__xtensa_sync_caches): Use an ISYNC even if there is no i-cache. Is anyone else having a similar problem? Thanks, --Kaveh -- Kaveh R. Ghazi [EMAIL PROTECTED]
Re: Another BOOTSTRAP failure on sparc-sun-solaris2.10, stage2 miscompiled
> Kaveh R GHAZI writes: Kaveh> Rats, I'm getting another bootstap failure on sparc-sun-solaris2.10. Kaveh> This time it happens in stage2 building libgcc. What happens is that Kaveh> when it runs configure for stage2 libgcc, I get: Kaveh> checking for suffix of object files... Kaveh> configure: error: cannot compute suffix of object files: cannot compile Kaveh> See `config.log' for more details. Kaveh> whereupon in config.log I see: Kaveh> configure: failed program was: Kaveh> | /* confdefs.h. */ Kaveh> | Kaveh> | #define PACKAGE_NAME "GNU C Runtime Library" Kaveh> | #define PACKAGE_TARNAME "libgcc" Kaveh> | #define PACKAGE_VERSION "1.0" Kaveh> | #define PACKAGE_STRING "GNU C Runtime Library 1.0" Kaveh> | #define PACKAGE_BUGREPORT "" Kaveh> | /* end confdefs.h. */ Kaveh> | Kaveh> | int Kaveh> | main () Kaveh> | { Kaveh> | Kaveh> | ; Kaveh> | return 0; Kaveh> | } Kaveh> The stage2 gcc cannot compile this simple program. The stage1 Kaveh> compiler can, so looks like stage2 was miscompiled. Running it under Kaveh> gdb doesn't yield any useful info. I am seeing the same failure on AIX. The SEGV on AIX is in postreload.c and if I recompile that file without optimization, the config test succeeds. David
Re: Another BOOTSTRAP failure on sparc-sun-solaris2.10, stage2 miscompiled
On Sun, 9 Sep 2007, David Edelsohn wrote: > Kaveh> The stage2 gcc cannot compile this simple program. The stage1 > Kaveh> compiler can, so looks like stage2 was miscompiled. Running it under > Kaveh> gdb doesn't yield any useful info. > > I am seeing the same failure on AIX. The SEGV on AIX is in > postreload.c and if I recompile that file without optimization, the config > test succeeds. > David Ditto. Program received signal SIGSEGV, Segmentation fault. 0x002cf780 in reload_combine_note_store (dst=0xff0b90e0, set=, data=0x0) at ../../egcc-SVN20070909/gcc/postreload.c:1018 1018 reg_state[i].store_ruid = reload_combine_ruid; (gdb) Any luck figuring out which patch broke it? --Kaveh -- Kaveh R. Ghazi [EMAIL PROTECTED]
Re: [RFC] Marking C++ new operator as malloc?
On Mon, Sep 10, 2007 at 05:33:24AM +1200, Ross Smith wrote: > > [...] If the request succeeds, the value returned shall be a nonnull > > pointer value (4.10) p0 different from any previously returned value > > p1, unless that value p1 was subsequently passed to an operator delete. > > That's not sufficient. First, merely requiring pointers to be different > isn't the same as requiring them not to alias, which requires the blocks > of memory they point to not to overlap. That might be grounds for a defect report; clearly the blocks handed out must not overlap, or conforming programs will fail.
Re: [RFC] Marking C++ new operator as malloc?
Richard Guenther wrote: >> Probably the most common use of a custom new is to allocate memory from >> a user-controlled pool instead of the standard free store. Somewhere in >> the program there will be a pointer to the complete pool, which aliases >> every pointer returned by that version of new. Any such pool-based new >> doesn't meet the requirements of the malloc attribute. > > That doesn't matter. What matters is object lifetime, which is properly > preserved by a conforming pool allocator. We have some terminology issues here. The definition of the malloc attribute is: > The `malloc' attribute is used to tell the compiler that a function > may be treated as if any non-`NULL' pointer it returns cannot > alias any other pointer valid when the function returns. This > will often improve optimization. The term "cannot alias" is not fully defined. It could mean "cannot have the same value as any other pointer of the same type". It could mean "cannot have the same value as any other pointer, when both pointers are cast to `void *'". It could mean, a la "restrict", that "no store through an expression based on this pointer can modify the value read from via any expression based on any other pointer". In the case of "malloc", and assuming that all of the machinery for malloc is hidden away in some piece of the program we're not talking about, all three definitions apply. Each pointer returned by malloc is an island unto itself; there's no conforming way to get there except by using the pointer just returned. For, operator new, the same is true -- but we're more often able to see the machinery for the allocator. For example: char pool[N]; size_t next; /* Never mind that the return memory isn't properly aligned here; fixing the implementation is left to the reader. */ void *operator new(size_t s) { void *p = pool + next; next += s; return p; } bool f() { char *c = new char; return (c == pool); } Now, I don't think we should allow the compiler to optimize the return statement in "f" to "return false"? If operator new has attribute malloc, then it may in fact do so -- even though the value returned might be "pool" itself. The same issue occurs if you call malloc from within the file that defines malloc; the malloc attribute is saying something about what you can do *if you cannot see the pool out of which the allocation is occurring*. For malloc, which is fully squirreled away in libc somewhere, this is probably safe in practice -- until LTO. For operator new, it's a little dicier, since people do tend more often to replace it in their own programs, and to put those replacements in inline functions in header files where the compiler is liable to see more about what's going on. This seems like a useful optimization to me, and I understand that it will work 99.99% of the time, and it's in the spirit of the standard -- but how do we actually make it safe? If the attribute only applied to other values returned from the same function, then it would be safe -- but less useful. Can we do better? -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Re: Another BOOTSTRAP failure on sparc-sun-solaris2.10, stage2 miscompiled
> Kaveh R GHAZI writes: Kaveh> Program received signal SIGSEGV, Segmentation fault. Kaveh> 0x002cf780 in reload_combine_note_store (dst=0xff0b90e0, set= optimized out>, data=0x0) Kaveh> at ../../egcc-SVN20070909/gcc/postreload.c:1018 Kaveh> 1018 reg_state[i].store_ruid = reload_combine_ruid; Kaveh> (gdb) That is the exact same failure and line for AIX. Apparently all Big Endian targets are affected. Kaveh> Any luck figuring out which patch broke it? Not yet. Candidates include: r128239 (honza's simple dce/addressing passes) and then r128272 (the iv-opt patch), and Richi's sccvn patch. David
Re: [RFC] Marking C++ new operator as malloc?
On Sun, Sep 09, 2007 at 12:24:13PM -0700, Mark Mitchell wrote: > The term "cannot alias" is not fully defined. It could mean "cannot > have the same value as any other pointer of the same type". It could > mean "cannot have the same value as any other pointer, when both > pointers are cast to `void *'". It could mean, a la "restrict", that > "no store through an expression based on this pointer can modify the > value read from via any expression based on any other pointer". > > In the case of "malloc", and assuming that all of the machinery for > malloc is hidden away in some piece of the program we're not talking > about, all three definitions apply. Each pointer returned by malloc is > an island unto itself; there's no conforming way to get there except by > using the pointer just returned. The key point is that the mechanism is hidden away. This might become more of an issue with LTO, so the question is how to make such guarantees make sense to an optimizer that can see the full program. > For, operator new, the same is true -- but we're more often able to see > the machinery for the allocator. For example: > > char pool[N]; > size_t next; > > /* Never mind that the return memory isn't properly aligned here; >fixing the implementation is left to the reader. */ > void *operator new(size_t s) { >void *p = pool + next; >next += s; >return p; > } > > bool f() { > char *c = new char; > return (c == pool); > } > > Now, I don't think we should allow the compiler to optimize the return > statement in "f" to "return false"? If operator new has attribute > malloc, then it may in fact do so -- even though the value returned > might be "pool" itself. The issue seems to be that the mechanism is exposed. The operator new pointers don't alias each other (when used to store objects that fit within the size argument), but they do have a relationship with "pool". It seems that there needs to be some sort of protection boundary. If there's no LTO, then it would suffice to treat the file implementing operator new as a black-box module, perhaps exporting a "first_allocation" function to do the c == pool check. > This seems like a useful optimization to me, and I understand that it > will work 99.99% of the time, and it's in the spirit of the standard -- > but how do we actually make it safe? If the attribute only applied to > other values returned from the same function, then it would be safe -- > but less useful. Can we do better? Maybe "pool", if exported, would have to be marked as aliasing the "new" calls, possibly with some new attribute "malloc_implementation" or something like that. Working out the details would be tricky: calling a malloc-attributed function might change storage marked "malloc_implementation", and a return value might alias an implementation value, but two calls would not alias each other.
Re: GCC 4.3.0 Status Report (2007-09-04)
Richard Guenther wrote: > There is > > http://gcc.gnu.org/ml/gcc-patches/2007-08/msg01978.html > > for example, which is not suitable for stage3. This is an optimization pass which leads to dramatically better code on at least one SPEC benchmark. Ian, Roger, Diego, would one of you care to review this? Thanks, -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Re: GCC 4.3.0 Status Report (2007-09-04)
Jan Hubicka wrote: > I am still planning to do some retuning of inliner (our inline limits > wasn't revisited for inclusion of SSA optimizers). Assuming that the tuning is essentially twiddling constants, I'm not overly worried. If you're planning to adjust the algorithms substantially, then I'd be more concerned. Let me know. Thanks! -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Re: GCC 4.3.0 Status Report (2007-09-04)
Jagasia, Harsha wrote: > I still plan to submit a patch for the x86 target cost model tuning. Assuming that this isn't too dramatic, I'll leave approval of that during Stage 3 to the x86 back-end maintainers. Thanks, -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Re: [RFC] Marking C++ new operator as malloc?
On 9/9/07, Mark Mitchell <[EMAIL PROTECTED]> wrote: > Richard Guenther wrote: > > >> Probably the most common use of a custom new is to allocate memory from > >> a user-controlled pool instead of the standard free store. Somewhere in > >> the program there will be a pointer to the complete pool, which aliases > >> every pointer returned by that version of new. Any such pool-based new > >> doesn't meet the requirements of the malloc attribute. > > > > That doesn't matter. What matters is object lifetime, which is properly > > preserved by a conforming pool allocator. > > We have some terminology issues here. The definition of the malloc > attribute is: > > > The `malloc' attribute is used to tell the compiler that a function > > may be treated as if any non-`NULL' pointer it returns cannot > > alias any other pointer valid when the function returns. This > > will often improve optimization. > > The term "cannot alias" is not fully defined. It could mean "cannot > have the same value as any other pointer of the same type". It could > mean "cannot have the same value as any other pointer, when both > pointers are cast to `void *'". It could mean, a la "restrict", that > "no store through an expression based on this pointer can modify the > value read from via any expression based on any other pointer". It actually means that all accesses based on the returned pointer do not alias accesses based on other pointers that are not derived. In particular, int *p; int * __attribute__((malloc)) my_malloc() { return p; } void foo(void) { int *q = my_malloc(); *p = 1; *q = 0; return *p; } will be optimized to return 1 if my_malloc is not inlined and 0 otherwise. > In the case of "malloc", and assuming that all of the machinery for > malloc is hidden away in some piece of the program we're not talking > about, all three definitions apply. Each pointer returned by malloc is > an island unto itself; there's no conforming way to get there except by > using the pointer just returned. > > For, operator new, the same is true -- but we're more often able to see > the machinery for the allocator. For example: > > char pool[N]; > size_t next; > > /* Never mind that the return memory isn't properly aligned here; >fixing the implementation is left to the reader. */ > void *operator new(size_t s) { >void *p = pool + next; >next += s; >return p; > } > > bool f() { > char *c = new char; > return (c == pool); > } > > Now, I don't think we should allow the compiler to optimize the return > statement in "f" to "return false"? If operator new has attribute > malloc, then it may in fact do so -- even though the value returned > might be "pool" itself. Yes, at least the first case would give different results based on inlining decisions. But only for undefined cases I believe. > The same issue occurs if you call malloc from within the file that > defines malloc; the malloc attribute is saying something about what you > can do *if you cannot see the pool out of which the allocation is > occurring*. For malloc, which is fully squirreled away in libc > somewhere, this is probably safe in practice -- until LTO. Which brings back the fact that you cannot implement malloc in C (you certainly remember the discussions about C++ placement new handling wrt aliasing). To re-use the machinery we invented there we would need to place a CHANGE_DYNAMIC_TYPE_EXPR for the pointer assignment resulting from inlining a function with attribute malloc set. As you say, unless we are inlining such functions we are safe in practice. > For operator > new, it's a little dicier, since people do tend more often to replace it > in their own programs, and to put those replacements in inline functions > in header files where the compiler is liable to see more about what's > going on. > > This seems like a useful optimization to me, and I understand that it > will work 99.99% of the time, and it's in the spirit of the standard -- > but how do we actually make it safe? If the attribute only applied to > other values returned from the same function, then it would be safe -- > but less useful. Can we do better? See above - inlining an allocator function produces the need to change the dynamic type of the pointed-to memory as we are basically exposing a "placement new" operation to the optimizers. Richard.
Re: [RFC] Marking C++ new operator as malloc?
Joe Buck wrote: >> In the case of "malloc", and assuming that all of the machinery for >> malloc is hidden away in some piece of the program we're not talking >> about, all three definitions apply. Each pointer returned by malloc is >> an island unto itself; there's no conforming way to get there except by >> using the pointer just returned. > > The key point is that the mechanism is hidden away. This might become > more of an issue with LTO, so the question is how to make such guarantees > make sense to an optimizer that can see the full program. Correct. The "malloc" attribute is only applicable to "malloc" because we can't see how "malloc" is implemented. >> This seems like a useful optimization to me, and I understand that it >> will work 99.99% of the time, and it's in the spirit of the standard -- >> but how do we actually make it safe? If the attribute only applied to >> other values returned from the same function, then it would be safe -- >> but less useful. Can we do better? > > Maybe "pool", if exported, would have to be marked as aliasing the "new" > calls, possibly with some new attribute "malloc_implementation" or > something like that. It's worse than that: char *pool; void set_pool(char *p) { pool = p; } void *operator new(size_t s) { // return stuff from pool. } bool f() { char *p = new char[1024]; set_pool (p); char *i = new char; return (p == i); } In other words, pointers from any part of the program can potentially be "laundered" through set_pool and return via the new operator. I don't see any way to make this fully safe, in general, without the limitation I imposed: the no-aliasing guarantee only applies to the values returned from the function called. For a particular implementation of "operator new" (such as the one in libstdc++), you can of course make it safe in the same way as "malloc"; hide the implementation somewhere the rest of the program can't see it (modulo LTO). But, to declare it with the "malloc" attribute in the headers seems dangerous, since we have no way of knowing if the user replaced it, off in some file somewhere we don't know about, but in such a way that pointers in our source code are being laundered back to us. Perhaps we could have an header, which you can include if you aren't overriding the operator... -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Re: [RFC] Marking C++ new operator as malloc?
On 9/9/07, Mark Mitchell <[EMAIL PROTECTED]> wrote: > Joe Buck wrote: > > >> In the case of "malloc", and assuming that all of the machinery for > >> malloc is hidden away in some piece of the program we're not talking > >> about, all three definitions apply. Each pointer returned by malloc is > >> an island unto itself; there's no conforming way to get there except by > >> using the pointer just returned. > > > > The key point is that the mechanism is hidden away. This might become > > more of an issue with LTO, so the question is how to make such guarantees > > make sense to an optimizer that can see the full program. > > Correct. The "malloc" attribute is only applicable to "malloc" because > we can't see how "malloc" is implemented. > > >> This seems like a useful optimization to me, and I understand that it > >> will work 99.99% of the time, and it's in the spirit of the standard -- > >> but how do we actually make it safe? If the attribute only applied to > >> other values returned from the same function, then it would be safe -- > >> but less useful. Can we do better? > > > > Maybe "pool", if exported, would have to be marked as aliasing the "new" > > calls, possibly with some new attribute "malloc_implementation" or > > something like that. > > It's worse than that: > > char *pool; > void set_pool(char *p) { pool = p; } > void *operator new(size_t s) { // return stuff from pool. } > > bool f() { > char *p = new char[1024]; > set_pool (p); > char *i = new char; > return (p == i); > } > > In other words, pointers from any part of the program can potentially be > "laundered" through set_pool and return via the new operator. I don't > see any way to make this fully safe, in general, without the limitation > I imposed: the no-aliasing guarantee only applies to the values returned > from the function called. But in this case an access to *i through *p is invalid. [I suppose both new calls are actually different implementations here] Each new call starts lifetime of a new object, the previous object lifetime is terminated. Even comparing both pointers here for this reason would lead to undefined behavior. I know it's easy to play games to trick optimizers into doing something, but creating a not undefined testcase that goes wrong is hard ;) At least iff you remember to transform 'malloc' attributes to a dynamic type change if you inline a malloc. Richard.
Re: [RFC] Marking C++ new operator as malloc?
On 9/9/07, Richard Guenther <[EMAIL PROTECTED]> wrote: > > Which brings back the fact that you cannot implement malloc in C > (you certainly remember the discussions about C++ placement new > handling wrt aliasing). To re-use the machinery we invented there > we would need to place a CHANGE_DYNAMIC_TYPE_EXPR for > the pointer assignment resulting from inlining a function with > attribute malloc set. As you say, unless we are inlining such functions > we are safe in practice. Actually this looks nice in general. We could implement placement new in C this way: extern inline T * __attribute__((malloc)) placement_new (void *p) { return p; } if we can somehow encode the target type here. Note that only type-based aliasing is a problem with this discussion - PTA will be obviously fine if new is inlined as it will see that both pointers are related and we loose the 'malloc' attribution on the target pointer during inlining. Richard.
Re: [RFC] Marking C++ new operator as malloc?
Richard Guenther wrote: >> char *pool; >> void set_pool(char *p) { pool = p; } >> void *operator new(size_t s) { // return stuff from pool. } >> >> bool f() { >> char *p = new char[1024]; >> set_pool (p); >> char *i = new char; >> return (p == i); >> } >> >> In other words, pointers from any part of the program can potentially be >> "laundered" through set_pool and return via the new operator. I don't >> see any way to make this fully safe, in general, without the limitation >> I imposed: the no-aliasing guarantee only applies to the values returned >> from the function called. > > But in this case an access to *i through *p is invalid. [I suppose both > new calls are actually different implementations here] Each new > call starts lifetime of a new object, the previous object lifetime is > terminated. Even comparing both pointers here for this reason > would lead to undefined behavior. I don't think there's necessarily agreement about that; you're into what-is-an-object land here... In any case, using new to allocate from a pool doesn't invalidate the pointer to the pool itself. Even if you think reads/writes through *p are undefined, do you think that comparing addresses is undefined? If so, how can you still talk about "pool" at all, even in the implementation of "new" and "delete" themselves, after the first allocation? If comparing addresses is allowed, it's weird to think that: if (p == i) *p = '\0'; is invalid, while: if (p == i) *i = '\0'; is valid, but I suppose it's possible. Do we have any way to guarantee that aliasing information will not be used when analyzing pointer comparisons, but only when analyzing stores through pointers? -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Re: Some thoughts about steerring commitee work
Vladimir, On Fri, 15 Jun 2007, Vladimir N. Makarov wrote: > Sorry, it is even make me a bit scary becuase I don't know when the SC > decides that we need more maintainers and what maintainers. When should > we propose. After that I am just starting to think who usually propose > them. I know this thread is a bit old, but this part I wanted to respond nevertheless (and had kept in my TODO folder therefore). The SC does not fill the role of the project manager of a regular software development project, and as such the SC rarely (if at all) sits down and decides that we need more maintainers and what maintainers, not the least because, after all, this is a volunteer project. Maintainers are usually proposed when one of us notices good and ongoing contributions by someone, or when someone else (sometimes a maintainer of the respective part, sometimes even not a maintainer at all) suggests someone else, or someone raises the question him- or herself. And when there is a new piece contributed we usually try to find a maintainer from the beginning, the original contributor(s) being primary candidates. In other words, if you anyone in mind, please do not hesitate to contact a SC member of your choice and he will take it from there! Gerald PS: I know that we do have a problem with the role of GWP and how these are being lived and filled (or not). This is a tough nut that does not have an easy solution, I'm afraid.
Re: [RFC] Marking C++ new operator as malloc?
On 9/9/07, Mark Mitchell <[EMAIL PROTECTED]> wrote: > Richard Guenther wrote: > > >> char *pool; > >> void set_pool(char *p) { pool = p; } > >> void *operator new(size_t s) { // return stuff from pool. } > >> > >> bool f() { > >> char *p = new char[1024]; > >> set_pool (p); > >> char *i = new char; > >> return (p == i); > >> } > >> > >> In other words, pointers from any part of the program can potentially be > >> "laundered" through set_pool and return via the new operator. I don't > >> see any way to make this fully safe, in general, without the limitation > >> I imposed: the no-aliasing guarantee only applies to the values returned > >> from the function called. > > > > But in this case an access to *i through *p is invalid. [I suppose both > > new calls are actually different implementations here] Each new > > call starts lifetime of a new object, the previous object lifetime is > > terminated. Even comparing both pointers here for this reason > > would lead to undefined behavior. > > I don't think there's necessarily agreement about that; you're into > what-is-an-object land here... > > In any case, using new to allocate from a pool doesn't invalidate the > pointer to the pool itself. Even if you think reads/writes through *p > are undefined, do you think that comparing addresses is undefined? If > so, how can you still talk about "pool" at all, even in the > implementation of "new" and "delete" themselves, after the first > allocation? > > If comparing addresses is allowed, it's weird to think that: > > if (p == i) > *p = '\0'; > > is invalid, while: > > if (p == i) > *i = '\0'; > > is valid, but I suppose it's possible. > > Do we have any way to guarantee that aliasing information will not be > used when analyzing pointer comparisons, but only when analyzing stores > through pointers? I don't know of any place we would use such information. At least int *p = new int; int *q = new int; if (p == q) cannot be simplified as both pointers may be NULL? Richard.
Re: [RFC] Marking C++ new operator as malloc?
Richard Guenther wrote: > I don't know of any place we would use such information. At least > > int *p = new int; > int *q = new int; > if (p == q) > > cannot be simplified as both pointers may be NULL? They cannot be NULL; new-expressions throw an exception if the allocation fails. (Of course, they could be NULL if you called the "nothrow" variant, or another "operator new" declared "throw()".) We should optimize away things like: int *p = new int; if (!p) cerr << "Could not allocate memory\n"; -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Re: [RFC] Marking C++ new operator as malloc?
On 9/9/07, Mark Mitchell <[EMAIL PROTECTED]> wrote: > Richard Guenther wrote: > > > I don't know of any place we would use such information. At least > > > > int *p = new int; > > int *q = new int; > > if (p == q) > > > > cannot be simplified as both pointers may be NULL? > > They cannot be NULL; new-expressions throw an exception if the > allocation fails. (Of course, they could be NULL if you called the > "nothrow" variant, or another "operator new" declared "throw()".) > > We should optimize away things like: > > int *p = new int; > if (!p) > cerr << "Could not allocate memory\n"; We don't I believe. We'd optimize int *p = new int; *p; if (!p) cerr << "Could not allocate memory\n"; though ;) Well, at least malloc is allowed to return NULL, so unless we want to force all malloc attributed functions in C++ to throw exceptions we cannot assume they return non-NULL (just on the basis they have malloc attribute, that is). Richard.
Re: [RFC] Marking C++ new operator as malloc?
On 9/9/07, Richard Guenther <[EMAIL PROTECTED]> wrote: > On 9/9/07, Mark Mitchell <[EMAIL PROTECTED]> wrote: > > Richard Guenther wrote: > > > > > I don't know of any place we would use such information. At least > > > > > > int *p = new int; > > > int *q = new int; > > > if (p == q) > > > > > > cannot be simplified as both pointers may be NULL? A better one: int *p = new int; foo(p); int *q = new int; if foo deletes p then q may be equal to p. But alias analysis still (validly!) says they don't alias. Richard.
Re: [RFC] Marking C++ new operator as malloc?
Richard Guenther wrote: >> We should optimize away things like: >> >> int *p = new int; >> if (!p) >> cerr << "Could not allocate memory\n"; > > We don't I believe. That's a missed-optimization, and independent of any attributes on "operator new". It's a property of the new *expression*, not of the implementation of new. If the compiler treats: int *p = new int; any differently from: int &r = *new int; then we're missing an optimization opportunity. > though ;) Well, at least malloc is allowed to return NULL, so unless > we want to force all malloc attributed functions in C++ to throw exceptions > we cannot assume they return non-NULL (just on the basis they have > malloc attribute, that is). Sure, we can have the attribute in C++ mean the same thing it does in C, even if that's not the strongest declaration we can make. That's OK. But, I don't think that even the C meaning is safe in C++ for use with the library declaration of . I'm also somewhat skeptical of the idea that we will never do any optimization on pointer comparisons. What design principle in the compiler is going to keep us from some day introducing the obvious idea that "if modifying *p cannot affect the value of *q, and p and q are of the same type, then p != q"? I think that (a) either we have to weaken the meaning of the attribute in some way, or (b) we let users use this attribute optionally, for their implementations of operator new when they "know" it's OK to do so, but do not actually put it in the standard headers. I'm not arguing that the attribute is meaningless in C++, or does not apply to the libstdc++ implementation; I'm just arguing that putting it into is not safe. -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Re: [RFC] Marking C++ new operator as malloc?
On 9/9/07, Mark Mitchell <[EMAIL PROTECTED]> wrote: > > But, I don't think that even the C meaning is safe in C++ for use with > the library declaration of . I'm also somewhat skeptical of the > idea that we will never do any optimization on pointer comparisons. > What design principle in the compiler is going to keep us from some day > introducing the obvious idea that "if modifying *p cannot affect the > value of *q, and p and q are of the same type, then p != q"? But that reasoning is not valid. Consider void foo(int *q, double *p) { if (q != p) abort (); } int main() { int i; foo (&i, &i); } which would abort. Now, instead void foo(int *q, double *p) { *q; *p; if (q != p) abort (); } we can optimize the comparison to alwas true as in the case of p == q the program invokes undefined behavior. The essence is that we usually cannot tell anything about pointer values and pointed-to types unless we see accesses through them. > I think that (a) either we have to weaken the meaning of the attribute > in some way, or (b) we let users use this attribute optionally, for > their implementations of operator new when they "know" it's OK to do so, > but do not actually put it in the standard headers. > I'm not arguing that the attribute is meaningless in C++, or does not > apply to the libstdc++ implementation; I'm just arguing that putting it > into is not safe. Today we should be safe I believe. Even if we inline new (we'd lose knowledge about the call in this case -- which we of course may fix in future). It would be nice to have some testcases in the testsuite with the ideas that pop up around these discussions though :) Richard.
Re: [RFC] Marking C++ new operator as malloc?
Richard Guenther wrote: > A better one: > > int *p = new int; > foo(p); > int *q = new int; > > if foo deletes p then q may be equal to p. But alias analysis still > (validly!) says they don't alias. Yes, I agree that this is safe. (Either "p" is still valid and therefore different from "q", or it has been deleted and you may no longer talk about it.) That's the case I mentioned of assuming that distinct calls to "operator new" result in different values. But, that's not as strong as assuming that "p" is distinct from all other pointers in the program, which is what the "malloc" attribute says. And, even here there's a corner case: char *pool; void *operator new(size_t) { // return memory from pool } bool f() { char *p = new char; pool = p; char *q = new char; return p == q; } Here, we have the situation that two subsequent calls to the same "operator new" returned the same pointer. Why isn't that valid? For a more real-world example, use array-new for the first call. I don't think the GCC lists are actually the place to fix these kinds of problems. These are fundamental problems with the C++ standard. It simply is not sufficiently clear about all of these memory model issues to allow us (as compiler vendors) to reason about them in the ways that we "know" make sense. I think the optimization we want to do here (i.e., assume that pointers returned by operator new are all distinct, and distinct from all other pointers we can see) is only safe for particular implementations of operator new. So, I don't think we can put any attribute to that affect in our standard headers. You need a command-line switch, macro, etc., for the user to use to say that they are using an implementation that meets the requirements. -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Re: GCC 4.3.0 Status Report (2007-09-04)
This is an optimization pass which leads to dramatically better code on at least one SPEC benchmark. Ian, Roger, Diego, would one of you care to review this? My concern is that as formulated, conditional store elimination is not always a win. Transforming if (cond) *p = x; into tmp = *p; if (cond) tmp = x; *p = tmp; on it's own, effectively transforms a conditional write to memory into an unconditional write to memory. On many platforms, even x86, this a pessimization. For example, the "Intel Architecture Optimization Manual", available at ftp://download.intel.com/design/PentiumII/manuals/24281603.PDF in section 3.5.5 "Write Allocation Effects", actually recommends the inverse transformation. On page 3-21 they show how the "Sieve of Erastothenes" benchmark can be sped up on Pentium class processors by transforming the line array[j] = 0; into the equivalent if (array[j] != 0) array[j] = 0; i.e. by introducing conditional stores. The significant observation with Michael Matz's extremely impressive 26% improvement on 456.hmmer is the interaction between this transformation with other passes, that allow the conditional store to be hoisted out of a critical loop. By reading the value into a "tmp" before the loop, conditionally storing to the register tmp in the loop, then unconditionally writing the result back afterwards, we dramatically reduce the number of memory writes, rather than increase them as when this transformation is applied in isolation. I think the correct fix is not to apply this transformation everywhere, but to correctly identify those loop cases where it helps and perform the loop transformation there. i.e. conditional induction variable identification, hoisting and sinking needs to be improved instead of pessimizing code to a simpler form that allows our existing flawed passes to trigger. I do very much like the loop-restricted version of this transformation, and it's impressive impact of HMMR (whose author Sean Eddy is a good friend). Perhaps Mark might give revised versions of this patch special dispensation to be applied in stage 3. I'd not expect any correctness issues/bugs, just performance trade-offs that need to be investigated. Perhaps we should even apply this patch as is during stage 2, and allow the potential non-loop performance degradations to be addressed as follow-up patches and therefore regression fixes suitable for stage 3? Congratulations again to Michael for this impressive performance improvement. Roger -- Roger Sayle, Ph.D. OpenEye Scientific Software, Suite #D, 9 Bisbee Court, Santa Fe, New Mexico, 87508.
Re: [RFC] Marking C++ new operator as malloc?
Richard Guenther wrote: > On 9/9/07, Mark Mitchell <[EMAIL PROTECTED]> wrote: >> But, I don't think that even the C meaning is safe in C++ for use with >> the library declaration of . I'm also somewhat skeptical of the >> idea that we will never do any optimization on pointer comparisons. >> What design principle in the compiler is going to keep us from some day >> introducing the obvious idea that "if modifying *p cannot affect the >> value of *q, and p and q are of the same type, then p != q"? > > But that reasoning is not valid. Consider > > void foo(int *q, double *p) > { > if (q != p) > abort (); > } > int main() > { >int i; >foo (&i, &i); > } That doesn't type-check; did you want to have a cast somewhere? Note that my statement above depends on the pointers having the same type. What is an example program in that meets the requirements I gave above -- i.e., allows the compiler to prove that two same-typed pointers do not alias (whether by the compiler's cleverness, use of "restrict", or whatever), but where the compiler must still assume that the values of the pointers might be the same? -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Re: GCC 4.3.0 Status Report (2007-09-04)
On 9/9/07, Roger Sayle <[EMAIL PROTECTED]> wrote: > > > This is an optimization pass which leads to dramatically better code on > > > at least one SPEC benchmark. Ian, Roger, Diego, would one of you care > > to review this? Btw, diego already approved the patch. > My concern is that as formulated, conditional store elimination is not > always a win. > > Transforming > > if (cond) > *p = x; > > into > > tmp = *p; > if (cond) > tmp = x; > *p = tmp; > > on it's own, effectively transforms a conditional write to memory into an > unconditional write to memory. The pass currently only does the transformation if there is a preceding load already. Because I raised this same issue ;) > On many platforms, even x86, this a pessimization. For example, the "Intel > Architecture Optimization Manual", available at > ftp://download.intel.com/design/PentiumII/manuals/24281603.PDF in section > 3.5.5 "Write Allocation Effects", actually recommends the inverse > transformation. On page 3-21 they show how the "Sieve of Erastothenes" > benchmark can be sped up on Pentium class processors by transforming the > line > > array[j] = 0; > > into the equivalent > > if (array[j] != 0) > array[j] = 0; > > i.e. by introducing conditional stores. I suppose this is no longer true on modern processors? I think the pass may undo this case. But I'm also not sure we should worry about this. > The significant observation with Michael Matz's extremely impressive 26% > improvement on 456.hmmer is the interaction between this transformation with > other passes, that allow the conditional store to be hoisted out of a > critical loop. By reading the value into a "tmp" before the loop, > conditionally storing to the register tmp in the loop, then unconditionally > writing the result back afterwards, we dramatically reduce the number of > memory writes, rather than increase them as when this transformation is > applied in isolation. > > > I think the correct fix is not to apply this transformation everywhere, but > to correctly identify those loop cases where it helps and perform the loop > transformation there. i.e. conditional induction variable identification, > hoisting and sinking needs to be improved instead of pessimizing code to a > simpler form that allows our existing flawed passes to trigger. > > > I do very much like the loop-restricted version of this transformation, and > it's impressive impact of HMMR (whose author Sean Eddy is a good friend). > Perhaps Mark might give revised versions of this patch special dispensation > to be applied in stage 3. I'd not expect any correctness issues/bugs, just > performance trade-offs that need to be investigated. Perhaps we should even > apply this patch as is during stage 2, and allow the potential non-loop > performance degradations to be addressed as follow-up patches and therefore > regression fixes suitable for stage 3? I think it should be straight forward to apply this transformation in loops only - requiring analysis that the resulting loads and stores are loop invariant would of course require more work. Given the above restriction we apply already, do you hold your objections or would you consider the "simple" loop improvement? Thanks, Richard.
Re: [RFC] Marking C++ new operator as malloc?
Mark Mitchell <[EMAIL PROTECTED]> writes: [...] | This seems like a useful optimization to me, and I understand that it | will work 99.99% of the time Except for people writing allocators :-) -- Gaby
Re: [RFC] Marking C++ new operator as malloc?
"Richard Guenther" <[EMAIL PROTECTED]> writes: [...] | > It's worse than that: | > | > char *pool; | > void set_pool(char *p) { pool = p; } | > void *operator new(size_t s) { // return stuff from pool. } | > | > bool f() { | > char *p = new char[1024]; | > set_pool (p); | > char *i = new char; | > return (p == i); | > } | > | > In other words, pointers from any part of the program can potentially be | > "laundered" through set_pool and return via the new operator. I don't | > see any way to make this fully safe, in general, without the limitation | > I imposed: the no-aliasing guarantee only applies to the values returned | > from the function called. | | But in this case an access to *i through *p is invalid. [I suppose both | new calls are actually different implementations here] Each new | call starts lifetime of a new object, the previous object lifetime is | terminated. Even comparing both pointers here for this reason | would lead to undefined behavior. I don't follow your reasoning here. 'char*' and 'void*' are special. -- Gaby
Re: [RFC] Marking C++ new operator as malloc?
"Richard Guenther" <[EMAIL PROTECTED]> writes: [...] | I don't know of any place we would use such information. At least | | int *p = new int; | int *q = new int; | if (p == q) | | cannot be simplified as both pointers may be NULL? The above does not use the no-throw operator new, so neither can be null -- except if the user used command-line -fno-exceptions. -- Gaby
Re: GCC 4.3.0 Status Report (2007-09-04)
Richard Guenther wrote: > On 9/9/07, Roger Sayle <[EMAIL PROTECTED]> wrote: >>> This is an optimization pass which leads to dramatically better code on >>> at least one SPEC benchmark. Ian, Roger, Diego, would one of you care >>> to review this? > > Btw, diego already approved the patch. I apologize for muddying the waters, then. Roger, thank you for reviewing. I'll leave Richard G., Roger, and Diego to work out what best to do; please let me know if I can help. Thanks, -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Re: [RFC] Marking C++ new operator as malloc?
On 9/9/07, Mark Mitchell <[EMAIL PROTECTED]> wrote: > Richard Guenther wrote: > > On 9/9/07, Mark Mitchell <[EMAIL PROTECTED]> wrote: > >> But, I don't think that even the C meaning is safe in C++ for use with > >> the library declaration of . I'm also somewhat skeptical of the > >> idea that we will never do any optimization on pointer comparisons. > >> What design principle in the compiler is going to keep us from some day > >> introducing the obvious idea that "if modifying *p cannot affect the > >> value of *q, and p and q are of the same type, then p != q"? > > > > But that reasoning is not valid. Consider > > > > void foo(int *q, double *p) > > { > > if (q != p) > > abort (); > > } > > int main() > > { > >int i; > >foo (&i, &i); > > } > > That doesn't type-check; did you want to have a cast somewhere? Note > that my statement above depends on the pointers having the same type. > > What is an example program in that meets the requirements I gave above > -- i.e., allows the compiler to prove that two same-typed pointers do > not alias (whether by the compiler's cleverness, use of "restrict", or > whatever), but where the compiler must still assume that the values of > the pointers might be the same? I see I misinterpreted your sentence. I don't think a testcase that holds all your requirements can be constructed as they contradict each other. Can you give one? Richard.
Re: Bootstrap failure (on FreeBSD)
On Sun, 9 Sep 2007, Jan Hubicka wrote: >> [bootstrap/33352] invalid rtl sharing -- bootstrap failure compiling >> libgomp/team.c on i386 > I can definitly take alook on it, however i386-linux bootstrap fine for > me. Can I have testcase? After a couple of days of failure (at least four nightly builds) some 24 hours ago the problem magically went away with one of the latest update. My last nightly build and a manual build today both succeeded now, so it seems this was addressed by one of the other fixes. I guess this means we can close PR/33352. Since it has been fixed, do you have an idea whether it might be a duplicate of some other report you have fixed? Gerald
Re: Another BOOTSTRAP failure on sparc-sun-solaris2.10, stage2 miscompiled
I succeed past this failure if I revert Zdenek's iv-opts patch (r128272). David
Re: [RFC] Marking C++ new operator as malloc?
Richard Guenther wrote: >> What is an example program in that meets the requirements I gave above >> -- i.e., allows the compiler to prove that two same-typed pointers do >> not alias (whether by the compiler's cleverness, use of "restrict", or >> whatever), but where the compiler must still assume that the values of >> the pointers might be the same? > > I see I misinterpreted your sentence. I don't think a testcase that > holds all your requirements can be constructed as they > contradict each other. Can you give one? No -- I don't think any such test case should exist. But, IIUC, one of your proposals could lead to the existence of such a test case. In particular, I understood you to be suggesting that we might be able to make the "malloc" attribute work for any implementation of "operator new" by saying that while the compiler could assume that "*p" and "*q" did not alias, the compiler was none-the-less not allowed to assume that "p != q". My point was that this seems like a very strange requirement to impose on the compiler, and that the compiler -- now, or in future -- is very likely to make exactly that deduction, since it is logically true. More broadly, my point was that a universe in which "*p does not alias *q" fails to imply "p != q", for "p" and "q" pointers of the same type, is a weird place to be. -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Re: Another BOOTSTRAP failure on sparc-sun-solaris2.10, stage2 miscompiled
> I succeed past this failure if I revert Zdenek's iv-opts patch (r128272). Same here. The failure also occurs on all hppa targets. Dave -- J. David Anglin [EMAIL PROTECTED] National Research Council of Canada (613) 990-0752 (FAX: 952-6602)
Re: GCC 4.3.0 Status Report (2007-09-04)
> Jan Hubicka wrote: > > > I am still planning to do some retuning of inliner (our inline limits > > wasn't revisited for inclusion of SSA optimizers). > > Assuming that the tuning is essentially twiddling constants, I'm not > overly worried. If you're planning to adjust the algorithms > substantially, then I'd be more concerned. Let me know. Thanks, the plan is to essentially twiddle the constants (reduce limits since we now see more realistic program estimates). There is similar situation with the currently discussed SSE conversion codegen - I've comitted the basic codegen changes today, but we need to run some benchmarks to figure out setting for generic model. I hope this would be acceptable too... CPU2006 takes a lot of time :( Honza
GCC 4.2.2 RC1
GCC 4.2.2 RC1 is now available from: ftp://gcc.gnu.org/pub/gcc/snapshots/4.2.2-RC-20070909 If you want to help test this release candidate, please download files from the directory given above, rather than checking out from SVN, so that we can catch any packaging problems. If you find problems, please file them in the GCC bug-tracker. See: http://gcc.gnu.org/bugs.html for instructions regarding fixing bugs. You may CC: me on the bug report, but please do not send mail directly to me about problems. If all goes to plan, I will make the final GCC 4.2.2 release in about a week. -- Mark Mitchell CodeSourcery [EMAIL PROTECTED] (650) 331-3385 x713
Re: [RFC] Marking C++ new operator as malloc?
On 9/10/07, Mark Mitchell <[EMAIL PROTECTED]> wrote: > Richard Guenther wrote: > > >> What is an example program in that meets the requirements I gave above > >> -- i.e., allows the compiler to prove that two same-typed pointers do > >> not alias (whether by the compiler's cleverness, use of "restrict", or > >> whatever), but where the compiler must still assume that the values of > >> the pointers might be the same? > > > > I see I misinterpreted your sentence. I don't think a testcase that > > holds all your requirements can be constructed as they > > contradict each other. Can you give one? > > No -- I don't think any such test case should exist. But, IIUC, one of > your proposals could lead to the existence of such a test case. In > particular, I understood you to be suggesting that we might be able to > make the "malloc" attribute work for any implementation of "operator > new" by saying that while the compiler could assume that "*p" and "*q" > did not alias, the compiler was none-the-less not allowed to assume that > "p != q". > > My point was that this seems like a very strange requirement to impose > on the compiler, and that the compiler -- now, or in future -- is very > likely to make exactly that deduction, since it is logically true. More > broadly, my point was that a universe in which "*p does not alias *q" > fails to imply "p != q", for "p" and "q" pointers of the same type, is a > weird place to be. Well, we have that now: int *q = new int; delete q; int *p = new int; delete p; if (q != p) cout << "different"; we cannot optimize the test to be always true. The point is that alias analysis tells us something about accesses to *q and *p, but neither on lifetime of *q and *p nor lifetime of q and p (and thus their value). The only value analysis valid on pointers is non-NULLness which we can derive from accesses to the pointed-to memory location (ok, assuming the OS really traps on accesses to address zero, which is not true in general). I don't think my proposal opens up more "problems" in this area. Richard.