Re: Conditional sibcalls?
Hi, Sorry, mistyped. Please read `jne` instead of `je` in handwritten "optimized" assembler. --- With best regards, Konstantin On Thu, Feb 21, 2013 at 3:57 PM, Konstantin Vladimirov wrote: > Hi, > > Discovered this optimization possibilty on private backend, but can > easily reproduce on x86 > > Consider code, say test.c: > > static __attribute__((noinline)) unsigned int* > proxy1( unsigned int* codeBuffer, unsigned int oper, unsigned int a, unsigned > in > { > return codeBuffer; > } > > static __attribute__((noinline)) unsigned int* > proxy2( unsigned int* codeBuffer, unsigned int oper, unsigned int a, unsigned > in > { > return codeBuffer; > } > > __attribute__((noinline)) unsigned int* > myFunc( unsigned int* codeBuffer, unsigned int oper) > { > if( (oper & 0xF) == 14) > { > return proxy1( codeBuffer, oper, 0x22, 0x2102400b); > } > else > { > return proxy2( codeBuffer, oper, 0x22, 0x1102400b); > } > } > > With ~/x86-toolchain-4.7.2/bin/gcc -O2 -fomit-frame-pointer -S test.c, > gcc yields: > > myFunc: > .LFB2: > .cfi_startproc > andl $15, %esi > cmpl $14, %esi > je .L6 > jmp proxy2.isra.1 > .p2align 4,,10 > .p2align 3 > .L6: > jmp proxy1.isra.0 > > Which can be simplified to: > > myFunc: > .LFB2: > .cfi_startproc > andl $15, %esi > cmpl $14, %esi > je proxy2.isra.1 // <--- conditional sibling call here > .p2align 4,,10 > .p2align 3 > jmp proxy1.isra.0 > > I want to somehow introduce conditional sibling calls in my backend. > What approach would you advise as the best? > > Target GCC is 4.7.2 (with some patches from 4.7.3 trunk). > > --- > With best regards, Konstantin
Re: Conditional sibcalls?
On Thu, Feb 21, 2013 at 03:58:56PM +0400, Konstantin Vladimirov wrote: > Hi, > > Sorry, mistyped. Please read `jne` instead of `je` in handwritten > "optimized" assembler. > > --- > With best regards, Konstantin > > On Thu, Feb 21, 2013 at 3:57 PM, Konstantin Vladimirov > wrote: > > Hi, > > > > Discovered this optimization possibilty on private backend, but can > > easily reproduce on x86 > > > > Consider code, say test.c: > > > > static __attribute__((noinline)) unsigned int* > > proxy1( unsigned int* codeBuffer, unsigned int oper, unsigned int a, > > unsigned in > > { > > return codeBuffer; > > } > > > > static __attribute__((noinline)) unsigned int* > > proxy2( unsigned int* codeBuffer, unsigned int oper, unsigned int a, > > unsigned in > > { > > return codeBuffer; > > } > > > > __attribute__((noinline)) unsigned int* > > myFunc( unsigned int* codeBuffer, unsigned int oper) > > { > > if( (oper & 0xF) == 14) > > { > > return proxy1( codeBuffer, oper, 0x22, 0x2102400b); > > } > > else > > { > > return proxy2( codeBuffer, oper, 0x22, 0x1102400b); > > } > > } This cannot be done in general as proxy1 could be self-modifying code. I considered writing post optimizer of binaries but I do not know how detect self-modifying behaviour so what I can do is limited.
[RFC] IL verification reorg
I'm trying to make IL verifying more streamlined - it's often that passes have some random (or no) verification in their TODO which makes pinning down issues to specific passes hard. Thus I propose to unify the various TODO_verify_* flags into a single one, TODO_verify_il, and based on what IL properties are currently active perform checking. That still leaves the possibility to have no checking (with no TODO_verify_il). Do people think that the fine-grained verification control is actually useful or do you agree with me that it leads to sloppiness? Verification would be as outlined in the patch below - I didn't yet adjust users of the then obsoleted TODO flags (another possibility were to unconditionally verify - in the old days all verification was controlled by --enable-checking options). Thoughts? Thanks, Richard. Index: gcc/passes.c === *** gcc/passes.c(revision 196201) --- gcc/passes.c(working copy) *** execute_function_todo (void *data) *** 1957,1976 return; #if defined ENABLE_CHECKING ! if (flags & TODO_verify_ssa ! || (current_loops && loops_state_satisfies_p (LOOP_CLOSED_SSA))) { ! verify_gimple_in_cfg (cfun); ! verify_ssa (true); } - else if (flags & TODO_verify_stmts) - verify_gimple_in_cfg (cfun); - if (flags & TODO_verify_flow) - verify_flow_info (); - if (current_loops && loops_state_satisfies_p (LOOP_CLOSED_SSA)) - verify_loop_closed_ssa (false); - if (flags & TODO_verify_rtl_sharing) - verify_rtl_sharing (); #endif cfun->last_verified = flags & TODO_verify_all; --- 1955,1982 return; #if defined ENABLE_CHECKING ! if (flags & TODO_verify_il) { ! if (cfun->curr_properties & PROP_cfg) ! verify_flow_info (); ! if (cfun->curr_properties & PROP_loops) ! verify_loop_structure (); ! if (cfun->curr_properties & PROP_gimple_any) ! { ! if (cfun->curr_properties & PROP_cfg) ! verify_gimple_in_cfg (cfun); ! else ! verify_gimple_in_seq (gimple_body (cfun->decl)); ! } ! if (cfun->curr_properties & PROP_ssa) ! { ! verify_ssa (); ! if (current_loops && loops_state_satisfies_p (LOOP_CLOSED_SSA)) ! verify_loop_closed_ssa (false); ! } ! if (cfun->curr_properties & PROP_rtl) ! verify_rtl_sharing (); } #endif cfun->last_verified = flags & TODO_verify_all;
Re: Conditional sibcalls?
On Thu, Feb 21, 2013 at 03:57:05PM +0400, Konstantin Vladimirov wrote: > Hi, > > Discovered this optimization possibilty on private backend, but can > easily reproduce on x86 > > Consider code, say test.c: > > static __attribute__((noinline)) unsigned int* > proxy1( unsigned int* codeBuffer, unsigned int oper, unsigned int a, unsigned > in > { > return codeBuffer; > } > > static __attribute__((noinline)) unsigned int* > proxy2( unsigned int* codeBuffer, unsigned int oper, unsigned int a, unsigned > in > { > return codeBuffer; > } > > __attribute__((noinline)) unsigned int* > myFunc( unsigned int* codeBuffer, unsigned int oper) > { > if( (oper & 0xF) == 14) > { > return proxy1( codeBuffer, oper, 0x22, 0x2102400b); > } > else > { > return proxy2( codeBuffer, oper, 0x22, 0x1102400b); > } > } > > With ~/x86-toolchain-4.7.2/bin/gcc -O2 -fomit-frame-pointer -S test.c, > gcc yields: > > myFunc: > .LFB2: > .cfi_startproc > andl $15, %esi > cmpl $14, %esi > je .L6 > jmp proxy2.isra.1 > .p2align 4,,10 > .p2align 3 > .L6: > jmp proxy1.isra.0 > > Which can be simplified to: > > myFunc: > .LFB2: > .cfi_startproc > andl $15, %esi > cmpl $14, %esi > je proxy2.isra.1 // <--- conditional sibling call here > .p2align 4,,10 > .p2align 3 > jmp proxy1.isra.0 Apart from the je/jne thinko you mentioned, the .p2align directives are completely useless in this case. Regards, Gabriel
Re: Conditional sibcalls?
On Thu, Feb 21, 2013 at 04:37:48PM +0400, Konstantin Vladimirov wrote: > Hi, > > Can you please make more clear why possible self-modifying code in > proxy2 blocks optimization of caller function? We just sending control > from caller to proxy1 or proxy2 and saying goodbye. Am I missed > something? It is on only at caller function. It could be at unrelated part like here. bar(){ *((char*)proxy1)=42; } foo(unsigned int* codeBuffer, unsigned int oper){ if (oper) bar(); myFunc(codeBuffer,oper); } With static it at least possible to check if address of function is used in compilation unit which cannot be done at general. > > --- > With best regards, Konstantin > > On Thu, Feb 21, 2013 at 4:25 PM, Ondřej Bílka wrote: > > On Thu, Feb 21, 2013 at 03:58:56PM +0400, Konstantin Vladimirov wrote: > >> Hi, > >> > >> Sorry, mistyped. Please read `jne` instead of `je` in handwritten > >> "optimized" assembler. > >> > >> --- > >> With best regards, Konstantin > >> > >> On Thu, Feb 21, 2013 at 3:57 PM, Konstantin Vladimirov > >> wrote: > >> > Hi, > >> > > >> > Discovered this optimization possibilty on private backend, but can > >> > easily reproduce on x86 > >> > > >> > Consider code, say test.c: > >> > > >> > static __attribute__((noinline)) unsigned int* > >> > proxy1( unsigned int* codeBuffer, unsigned int oper, unsigned int a, > >> > unsigned in > >> > { > >> > return codeBuffer; > >> > } > >> > > >> > static __attribute__((noinline)) unsigned int* > >> > proxy2( unsigned int* codeBuffer, unsigned int oper, unsigned int a, > >> > unsigned in > >> > { > >> > return codeBuffer; > >> > } > >> > > >> > __attribute__((noinline)) unsigned int* > >> > myFunc( unsigned int* codeBuffer, unsigned int oper) > >> > { > >> > if( (oper & 0xF) == 14) > >> > { > >> > return proxy1( codeBuffer, oper, 0x22, 0x2102400b); > >> > } > >> > else > >> > { > >> > return proxy2( codeBuffer, oper, 0x22, 0x1102400b); > >> > } > >> > } > > > > This cannot be done in general as proxy1 could be self-modifying code. > > > > I considered writing post optimizer of binaries but I do not know how > > detect self-modifying behaviour so what I can do is limited.
Re: [RFC] IL verification reorg
On 02/21/13 05:37, Richard Biener wrote: I'm trying to make IL verifying more streamlined - it's often that passes have some random (or no) verification in their TODO which makes pinning down issues to specific passes hard. Thus I propose to unify the various TODO_verify_* flags into a single one, TODO_verify_il, and based on what IL properties are currently active perform checking. That still leaves the possibility to have no checking (with no TODO_verify_il). Do people think that the fine-grained verification control is actually useful or do you agree with me that it leads to sloppiness? Verification would be as outlined in the patch below - I didn't yet adjust users of the then obsoleted TODO flags (another possibility were to unconditionally verify - in the old days all verification was controlled by --enable-checking options). Ideally if there's a property that's supposed to hold at this time, it should be checked in a development compiler. Thus dropping the passes ability to control things in a fine grained manner and checking everything implied by the PROPs seems reasonable to me. jeff
Re: How does _ZNSs4_Rep20_S_empty_rep_storageE (not) become a unique global symbol?
Hi, On Wed, 20 Feb 2013, Michael Matz wrote: > I.e. it looks like as if a following reference once the link editor saw > the definition of the symbol resets it's unique status. I can make both > symbols wrong/non-unique by placing wlocale-inst.o last in the linker > cmdline. Actually this bug seems to still exist in latest binutils trunk, so I just reported http://sourceware.org/bugzilla/show_bug.cgi?id=15167 I can't explain why it doesn't show up on RHEL (and neither in the next service pack of SLE11, which uses binutils 2.23, but as 2.21.1 and trunk is broken it's reasonable to assume that also 2.23 is broken), perhaps it uses a good linking order for libstdc++ by pure luck, or there are other circumstances that hide the problem, not just only linking order. Ciao, Michael.
Re: [RFC] IL verification reorg
Hi, On Thu, 21 Feb 2013, Richard Biener wrote: > Do people think that the fine-grained verification control > is actually useful or do you agree with me that it leads to > sloppiness? I agree with you ... > --- 1955,1982 > return; > > #if defined ENABLE_CHECKING > ! if (flags & TODO_verify_il) > { > ! if (cfun->curr_properties & PROP_cfg) > ! verify_flow_info (); > ! if (cfun->curr_properties & PROP_loops) > ! verify_loop_structure (); > ! if (cfun->curr_properties & PROP_gimple_any) > ! { > ! if (cfun->curr_properties & PROP_cfg) > ! verify_gimple_in_cfg (cfun); > ! else > ! verify_gimple_in_seq (gimple_body (cfun->decl)); > ! } > ! if (cfun->curr_properties & PROP_ssa) > ! { > ! verify_ssa (); > ! if (current_loops && loops_state_satisfies_p (LOOP_CLOSED_SSA)) > ! verify_loop_closed_ssa (false); > ! } > ! if (cfun->curr_properties & PROP_rtl) > ! verify_rtl_sharing (); ... but I think the checking should be bottom up. First test gimple, then the cfg, then ssa, then loops, then loop-closedness. Ciao, Michael.
Re: [RFC] IL verification reorg
Hi, On Thu, Feb 21, 2013 at 01:37:28PM +0100, Richard Biener wrote: > > I'm trying to make IL verifying more streamlined - it's often > that passes have some random (or no) verification in their TODO > which makes pinning down issues to specific passes hard. > > Thus I propose to unify the various TODO_verify_* flags into > a single one, TODO_verify_il, and based on what IL properties > are currently active perform checking. That still leaves the > possibility to have no checking (with no TODO_verify_il). > > Do people think that the fine-grained verification control > is actually useful or do you agree with me that it leads to > sloppiness? I do not think it is useful and I agree that checking everything that is supposed to hold at the given time is a good idea. Possibly, if you are touching this are anyway, could we (if requested) dump before verifying so that if verification fails, the last function in a dump is actually the one with the problem? Of course, all other TODOs would need to be processed before dumping... but of course that is just a thought. Thanks, Martin
Re: [RFC] IL verification reorg
On Thu, 21 Feb 2013, Martin Jambor wrote: > Hi, > > On Thu, Feb 21, 2013 at 01:37:28PM +0100, Richard Biener wrote: > > > > I'm trying to make IL verifying more streamlined - it's often > > that passes have some random (or no) verification in their TODO > > which makes pinning down issues to specific passes hard. > > > > Thus I propose to unify the various TODO_verify_* flags into > > a single one, TODO_verify_il, and based on what IL properties > > are currently active perform checking. That still leaves the > > possibility to have no checking (with no TODO_verify_il). > > > > Do people think that the fine-grained verification control > > is actually useful or do you agree with me that it leads to > > sloppiness? > > I do not think it is useful and I agree that checking everything that > is supposed to hold at the given time is a good idea. > > Possibly, if you are touching this are anyway, could we (if requested) > dump before verifying so that if verification fails, the last function > in a dump is actually the one with the problem? Of course, all other > TODOs would need to be processed before dumping... but of course that > is just a thought. Yeah, I put that on my TODO. (it might be that the dumping itself ICEs then, of course ...) Richard.
Re: [RFC] IL verification reorg
On Thu, Feb 21, 2013 at 7:37 AM, Richard Biener wrote: > > I'm trying to make IL verifying more streamlined - it's often > that passes have some random (or no) verification in their TODO > which makes pinning down issues to specific passes hard. > > Thus I propose to unify the various TODO_verify_* flags into > a single one, TODO_verify_il, and based on what IL properties > are currently active perform checking. That still leaves the > possibility to have no checking (with no TODO_verify_il). Agreed. > Do people think that the fine-grained verification control > is actually useful or do you agree with me that it leads to > sloppiness? It leads to sloppiness. We should not allow fine grained checking. At most, we could throttle IL checking automatically depending on the chosen --enable-checking value at config time. For --enable-checking=release we could leave only the quickest and more fundamental checks. > > Verification would be as outlined in the patch below - I didn't > yet adjust users of the then obsoleted TODO flags (another > possibility were to unconditionally verify - in the old days > all verification was controlled by --enable-checking options). > > Thoughts? > > Thanks, > Richard. > > Index: gcc/passes.c > === > *** gcc/passes.c(revision 196201) > --- gcc/passes.c(working copy) > *** execute_function_todo (void *data) > *** 1957,1976 > return; > > #if defined ENABLE_CHECKING > ! if (flags & TODO_verify_ssa > ! || (current_loops && loops_state_satisfies_p (LOOP_CLOSED_SSA))) > { > ! verify_gimple_in_cfg (cfun); > ! verify_ssa (true); > } > - else if (flags & TODO_verify_stmts) > - verify_gimple_in_cfg (cfun); > - if (flags & TODO_verify_flow) > - verify_flow_info (); > - if (current_loops && loops_state_satisfies_p (LOOP_CLOSED_SSA)) > - verify_loop_closed_ssa (false); > - if (flags & TODO_verify_rtl_sharing) > - verify_rtl_sharing (); > #endif > > cfun->last_verified = flags & TODO_verify_all; > --- 1955,1982 > return; > > #if defined ENABLE_CHECKING > ! if (flags & TODO_verify_il) > { > ! if (cfun->curr_properties & PROP_cfg) > ! verify_flow_info (); > ! if (cfun->curr_properties & PROP_loops) > ! verify_loop_structure (); > ! if (cfun->curr_properties & PROP_gimple_any) > ! { > ! if (cfun->curr_properties & PROP_cfg) > ! verify_gimple_in_cfg (cfun); > ! else > ! verify_gimple_in_seq (gimple_body (cfun->decl)); > ! } > ! if (cfun->curr_properties & PROP_ssa) > ! { > ! verify_ssa (); > ! if (current_loops && loops_state_satisfies_p (LOOP_CLOSED_SSA)) > ! verify_loop_closed_ssa (false); > ! } > ! if (cfun->curr_properties & PROP_rtl) > ! verify_rtl_sharing (); I agree with Micha. Do the checks bottom up? IL -> CFG -> SSA -> LOOP. Diego.
TREE_ADDRESSABLE types cause ICE in declare_return_variable
Hi, the gdc D compiler currently doesn't implement "non-POD" types. As in C++ those types can have copy constructors or destructors and should be kept in memory. Right now I just set TREE_ADDRESSABLE on the RECORD_TYPE tree and it's mostly working. Some test cases fail though if optimization / inlining is enabled: D code like this: -- Appender appender() { return Appender(""); } void main() { Appender w = appender(); auto x = &w; } -- where Appender is a non-POD type causes an assertion failure in declare_return_variable: "gcc_assert (!TREE_ADDRESSABLE (callee_type));" There's a comment saying "All types requiring non-trivial constructors should have been handled." but where and how? The problem only occurs if the address of w is taken, as this will mark w as addressable. Then gimple_call_return_slot_opt_p test in expand_call_inline fails and return_slot is not set. If the address of w is not taken the return_slot is used and everything works fine. -fdump-tree-original dump: -- ;; Function appender (_D6format8appenderFZS6format8Appender) ;; enabled by -tree-original { struct Appender __ctmp5; return = *format.Appender.this (&((void) (__ctmp5 = {});, __ctmp5), {.length=0, .ptr=""}); } ;; Function main (_Dmain) ;; enabled by -tree-original { struct Appender * x; struct Appender w; (void) (w = format.appender ()); (void) (x = &w); return = 0; } -- Thanks, Johannes
Re: TREE_ADDRESSABLE types cause ICE in declare_return_variable
On Thu, Feb 21, 2013 at 7:58 AM, Johannes Pfau wrote: > > the gdc D compiler currently doesn't implement "non-POD" types. As in C++ > those > types can have copy constructors or destructors and should be kept in memory. > Right now I just set TREE_ADDRESSABLE on the RECORD_TYPE tree and it's mostly > working. Some test cases fail though if optimization / inlining is enabled: > > D code like this: > -- > Appender appender() { return Appender(""); } > > void main() { > Appender w = appender(); > auto x = &w; > } > -- > where Appender is a non-POD type causes an assertion failure in > declare_return_variable: "gcc_assert (!TREE_ADDRESSABLE (callee_type));" > > There's a comment saying "All types requiring non-trivial constructors should > have been handled." but where and how? The problem only occurs if the address > of > w is taken, as this will mark w as addressable. Then > gimple_call_return_slot_opt_p test in expand_call_inline fails and return_slot > is not set. If the address of w is not taken the return_slot is used and > everything works fine. I don't know exactly what is going wrong. But I can tell you that if a function returns a TREE_ADDRESSABLE type, that should be handled by passing in an invisible first parameter that is a pointer to the area on the stack where the function should write the return value. Ian
Re: TREE_ADDRESSABLE types cause ICE in declare_return_variable
> I don't know exactly what is going wrong. But I can tell you that if > a function returns a TREE_ADDRESSABLE type, that should be handled by > passing in an invisible first parameter that is a pointer to the area > on the stack where the function should write the return value. Yes, TREE_ADDRESSABLE types cannot be returned by value. Either you return them via the invisible parameter manually or you set DECL_BY_REFERENCE on the RESULT_DECL and the middle-end should do it for you. The C++ and Ada FEs use the latter mechanism. -- Eric Botcazou
Not exception-safe default move constructors (demonstrated on std::pair)
Hi! (reposting to gcc@, probably gcc-bugs@ was the wrong list, sorry) I'm not really sure which (g++ or libstdc++) problem this really is, so posting into both lists. The problem is described here: http://cpp-next.com/archive/2009/10/exceptionally-moving/ - You have two classes: A, which has a proper move constructor which doesn't throw B, which which only has copy constructor which may throw - You have an std::pair - You move a pair std::pair pair1; try { std::pair pair2(std::move(a)); } What happens: - A part is moved with move constructor. This is obviously destructive to pair1. - B part is copied as it doesn't have move constuctor. - Now, that copy constructor throws (which is pretty expectable is it likely allocates resources). After this, as A part was already moved, we're left with corrupted pair1 (with empty A part). The same problem applies to most containers, but, for example, in std::vector it is solved gracefully: --- bits/vector.tcc from gcc-4.8: pointer __tmp = _M_allocate_and_copy(__n, _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_start), _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_finish)); --- so move semantics are only used IF the type has non-throwing(noexcept) move constructor. However, with pair this does not apply: --- bits/stl_pair.h from gcc-4.8: struct pair { ... constexpr pair(pair&&) = default; --- Either the default constructor generated by gcc is unsafe, or there should be custom, safe move constuctor with corresponding enable_if. I lean towards the former, as safe default move constuctors should be always generated probably, and specific ones may be really hard to implement for more complex types (tuples). I've written a small program which demonstrates the problem: https://gist.github.com/AMDmi3/5005557 tested it on FreeBSD with gcc-4.8 and on Debian with gcc-4.7, and it showed problem on both. Is this really a gcc problem? Should I file a bug? -- Dmitry Marakasov . 55B5 0596 FF1E 8D84 5F56 9510 D35A 80DD F9D2 F77D amd...@amdmi3.ru ..: jabber: amd...@jabber.ruhttp://www.amdmi3.ru
Inconsistency between code and document on nop_expr
Hi, GCCINT says that nop_expr is used to represent conversions that do not require any code generation, while function tree_strip_nop_conversions calls tree_nop_conversion, which returns false even for NOP_EXPR node like "(unsigned int)a", where a has type int. Did I miss something? Thanks -- Best Regards.
Re: Inconsistency between code and document on nop_expr
On Thu, Feb 21, 2013 at 7:16 PM, Bin.Cheng wrote: > Hi, > GCCINT says that nop_expr is used to represent conversions that do not > require any code generation, while function tree_strip_nop_conversions > calls tree_nop_conversion, which returns false even for NOP_EXPR node > like "(unsigned int)a", where a has type int. Are you sure a has the type of int? The code does: if ((INTEGRAL_TYPE_P (outer_type) || POINTER_TYPE_P (outer_type) || TREE_CODE (outer_type) == OFFSET_TYPE) && (INTEGRAL_TYPE_P (inner_type) || POINTER_TYPE_P (inner_type) || TREE_CODE (inner_type) == OFFSET_TYPE)) return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type); Which will return true for the case you mentioned. Also NOP_EXPR and CONVERT_EXPR are handled almost the same through out the whole compiler. Thanks, Andrew pinski > > Did I miss something? Thanks > > -- > Best Regards.
Re: Inconsistency between code and document on nop_expr
On Fri, Feb 22, 2013 at 12:14 PM, Andrew Pinski wrote: > On Thu, Feb 21, 2013 at 7:16 PM, Bin.Cheng wrote: >> Hi, >> GCCINT says that nop_expr is used to represent conversions that do not >> require any code generation, while function tree_strip_nop_conversions >> calls tree_nop_conversion, which returns false even for NOP_EXPR node >> like "(unsigned int)a", where a has type int. > > Are you sure a has the type of int? > > The code does: > if ((INTEGRAL_TYPE_P (outer_type) >|| POINTER_TYPE_P (outer_type) >|| TREE_CODE (outer_type) == OFFSET_TYPE) > && (INTEGRAL_TYPE_P (inner_type) > || POINTER_TYPE_P (inner_type) > || TREE_CODE (inner_type) == OFFSET_TYPE)) > return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type); > > Which will return true for the case you mentioned. Also NOP_EXPR and > CONVERT_EXPR are handled almost the same through out the whole > compiler. > Oh, sorry about the mistake, a has type of signed short. Maybe we can improve tree_nop_conversion with this case. Thanks for your help. -- Best Regards.
Re: Inconsistency between code and document on nop_expr
On Thu, Feb 21, 2013 at 8:31 PM, Bin.Cheng wrote: > On Fri, Feb 22, 2013 at 12:14 PM, Andrew Pinski wrote: >> On Thu, Feb 21, 2013 at 7:16 PM, Bin.Cheng wrote: >>> Hi, >>> GCCINT says that nop_expr is used to represent conversions that do not >>> require any code generation, while function tree_strip_nop_conversions >>> calls tree_nop_conversion, which returns false even for NOP_EXPR node >>> like "(unsigned int)a", where a has type int. >> >> Are you sure a has the type of int? >> >> The code does: >> if ((INTEGRAL_TYPE_P (outer_type) >>|| POINTER_TYPE_P (outer_type) >>|| TREE_CODE (outer_type) == OFFSET_TYPE) >> && (INTEGRAL_TYPE_P (inner_type) >> || POINTER_TYPE_P (inner_type) >> || TREE_CODE (inner_type) == OFFSET_TYPE)) >> return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type); >> >> Which will return true for the case you mentioned. Also NOP_EXPR and >> CONVERT_EXPR are handled almost the same through out the whole >> compiler. >> > Oh, sorry about the mistake, a has type of signed short. Maybe we can > improve tree_nop_conversion with this case. No because it is not a true nop conversion. The whole NOP_EXPR vs CONVERT_EXPR has been going on for a while now. I was trying to make the point to the middle-end NOP_EXPR and CONVERT_EXPR are exactly the same and the documentation about NOP_EXPR being a conversion which makes no code is incorrect. Thanks, Andrew Pinski
Re: Inconsistency between code and document on nop_expr
On Fri, Feb 22, 2013 at 12:33 PM, Andrew Pinski wrote: > On Thu, Feb 21, 2013 at 8:31 PM, Bin.Cheng wrote: >> On Fri, Feb 22, 2013 at 12:14 PM, Andrew Pinski wrote: >>> On Thu, Feb 21, 2013 at 7:16 PM, Bin.Cheng wrote: Hi, GCCINT says that nop_expr is used to represent conversions that do not require any code generation, while function tree_strip_nop_conversions calls tree_nop_conversion, which returns false even for NOP_EXPR node like "(unsigned int)a", where a has type int. >>> >>> Are you sure a has the type of int? >>> >>> The code does: >>> if ((INTEGRAL_TYPE_P (outer_type) >>>|| POINTER_TYPE_P (outer_type) >>>|| TREE_CODE (outer_type) == OFFSET_TYPE) >>> && (INTEGRAL_TYPE_P (inner_type) >>> || POINTER_TYPE_P (inner_type) >>> || TREE_CODE (inner_type) == OFFSET_TYPE)) >>> return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type); >>> >>> Which will return true for the case you mentioned. Also NOP_EXPR and >>> CONVERT_EXPR are handled almost the same through out the whole >>> compiler. >>> >> Oh, sorry about the mistake, a has type of signed short. Maybe we can >> improve tree_nop_conversion with this case. > > No because it is not a true nop conversion. The whole NOP_EXPR vs > CONVERT_EXPR has been going on for a while now. I was trying to make > the point to the middle-end NOP_EXPR and CONVERT_EXPR are exactly the > same and the documentation about NOP_EXPR being a conversion which > makes no code is incorrect. > Thanks for your explanation. -- Best Regards.