public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Confusion with labels as values
@ 2019-06-19 13:05 Florian Rommel
  2019-06-19 15:39 ` Jeff Law
  0 siblings, 1 reply; 5+ messages in thread
From: Florian Rommel @ 2019-06-19 13:05 UTC (permalink / raw)
  To: gcc

[-- Attachment #1: Type: text/plain, Size: 1861 bytes --]

Hi,

Recently I wanted to take and print the address of a label.  When
compiling with -O2, I noticed that the address equals the function body
start address if the label is not used as a goto target.

Here is an example:

#include <stdio.h>
int main(void) {
    printf("main:   %p\n", main);
    printf("label1: %p\n", &&label1);
    label1:
    puts("---");
    return 0;
}

compile with:
$ gcc -O2 -o example1 example1.c

or more specifically:
$ gcc -O1 -fschedule-insns2 -o example1 example1.c

Output:
  main:   0x562ed396216e
  label1: 0x562ed396216e
  ---


(or compile with -S to see that the label is moved to the start of the
function)

That is not completely surprising because labels as values are not
really valid outside of the originating function [1].

However when I assign the two addresses to automatic variables (which
should be okay) and compare them, they are different (despite having
the same value; the substraction result is 0).  Passing them to an
external function yields equality again (if the function is not
inlined).

#include <stdio.h>
void compare(size_t x, size_t y) {
    printf("x == y : %d\n", x == y);
}
int main(void) {
    size_t m = (size_t)main;
    size_t l = (size_t)&&label1;
    printf("m: %p\n", m);
    printf("l: %p\n", l);
    printf("m == l : %d\n", m == l);
    printf("m - l  :% d\n", m - l);
    compare(m, l);
    label1:
    puts("---");
    return 0;
}

Output:
  m: 0x559a775cd16e
  l: 0x559a775cd16e
  m - l  : 0
  m == l : 0
  x == y : 1
  ---


The reasons for this behavior probably lies in constant
folding/propagation.

I'm not sure whether this is technically a bug (Labels as Values /
Computed Gotos are not Standard C anyway).  But this is at least
confusing.  Maybe the label should not be moved in the first place?

Regards,
Flo


[1] https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html

[-- Attachment #2: example2.c --]
[-- Type: text/x-csrc, Size: 477 bytes --]

// Compile with:
// $ gcc -O2 -o example2 example2.c
// or
// $ gcc -O1 -fschedule-insns2 -o example2 example2.c

#include <stdio.h>

void compare(size_t x, size_t y) {
    printf("x == y : %d\n", x == y);
}

int main(void) {
    size_t m = (size_t)main;
    size_t l = (size_t)&&label1;
    printf("m: %p\n", m);
    printf("l: %p\n", l);
    printf("m == l : %d\n", m == l);
    printf("m - l  :% d\n", m - l);
    compare(m, l);
    label1:
    puts("---");
    return 0;
}

[-- Attachment #3: example1.c --]
[-- Type: text/x-csrc, Size: 268 bytes --]

// Compile with:
// $ gcc -O2 -o example1 example1.c
// or
// $ gcc -O1 -fschedule-insns2 -o example1 example1.c

#include <stdio.h>

int main(void) {
    printf("main:   %p\n", main);
    printf("label1: %p\n", &&label1);
    label1:
    puts("---");
    return 0;
}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Confusion with labels as values
  2019-06-19 13:05 Confusion with labels as values Florian Rommel
@ 2019-06-19 15:39 ` Jeff Law
  2019-06-19 17:09   ` Segher Boessenkool
  0 siblings, 1 reply; 5+ messages in thread
From: Jeff Law @ 2019-06-19 15:39 UTC (permalink / raw)
  To: Florian Rommel, gcc

On 6/19/19 7:04 AM, Florian Rommel wrote:
> Hi,
> 
> Recently I wanted to take and print the address of a label.  When
> compiling with -O2, I noticed that the address equals the function body
> start address if the label is not used as a goto target.
> 
> Here is an example:
> 
> #include <stdio.h>
> int main(void) {
>     printf("main:   %p\n", main);
>     printf("label1: %p\n", &&label1);
>     label1:
>     puts("---");
>     return 0;
> }
> 
> compile with:
> $ gcc -O2 -o example1 example1.c
> 
> or more specifically:
> $ gcc -O1 -fschedule-insns2 -o example1 example1.c
> 
> Output:
>   main:   0x562ed396216e
>   label1: 0x562ed396216e
>   ---
> 
> 
> (or compile with -S to see that the label is moved to the start of the
> function)
> 
> That is not completely surprising because labels as values are not
> really valid outside of the originating function [1].
> 
> However when I assign the two addresses to automatic variables (which
> should be okay) and compare them, they are different (despite having
> the same value; the substraction result is 0).  Passing them to an
> external function yields equality again (if the function is not
> inlined).
> 
> #include <stdio.h>
> void compare(size_t x, size_t y) {
>     printf("x == y : %d\n", x == y);
> }
> int main(void) {
>     size_t m = (size_t)main;
>     size_t l = (size_t)&&label1;
>     printf("m: %p\n", m);
>     printf("l: %p\n", l);
>     printf("m == l : %d\n", m == l);
>     printf("m - l  :% d\n", m - l);
>     compare(m, l);
>     label1:
>     puts("---");
>     return 0;
> }
> 
> Output:
>   m: 0x559a775cd16e
>   l: 0x559a775cd16e
>   m - l  : 0
>   m == l : 0
>   x == y : 1
>   ---
> 
> 
> The reasons for this behavior probably lies in constant
> folding/propagation.
> 
> I'm not sure whether this is technically a bug (Labels as Values /
> Computed Gotos are not Standard C anyway).  But this is at least
> confusing.  Maybe the label should not be moved in the first place?
A label used as a value, but which is not a jump target will have an
indeterminate value -- it'll end up somewhere in its containing
function,  that's all we guarantee in that case.

jeff

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Confusion with labels as values
  2019-06-19 15:39 ` Jeff Law
@ 2019-06-19 17:09   ` Segher Boessenkool
  2019-06-19 17:38     ` Jeff Law
  0 siblings, 1 reply; 5+ messages in thread
From: Segher Boessenkool @ 2019-06-19 17:09 UTC (permalink / raw)
  To: Jeff Law; +Cc: Florian Rommel, gcc

On Wed, Jun 19, 2019 at 09:39:01AM -0600, Jeff Law wrote:
> A label used as a value, but which is not a jump target will have an
> indeterminate value -- it'll end up somewhere in its containing
> function,  that's all we guarantee in that case.

In gimple it was fine and expected, and expand *did* make a code_label,
it was just immediately optimised away:

===
;; Generating RTL for gimple basic block 3

;; label1:

(code_label/s 14 13 15 2 ("label1") [0 uses])

(note 15 14 0 NOTE_INSN_BASIC_BLOCK)
===

and then we get

===
Merging block 3 into block 2...
Merged blocks 2 and 3.
Merged 2 and 3 without moving.
===

leaving

===
(note/s 14 13 16 2 ("label1") NOTE_INSN_DELETED_LABEL 2)
===

Do we want this to work as expected?


Segher

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Confusion with labels as values
  2019-06-19 17:09   ` Segher Boessenkool
@ 2019-06-19 17:38     ` Jeff Law
  2019-06-20  7:29       ` Segher Boessenkool
  0 siblings, 1 reply; 5+ messages in thread
From: Jeff Law @ 2019-06-19 17:38 UTC (permalink / raw)
  To: Segher Boessenkool; +Cc: Florian Rommel, gcc

On 6/19/19 11:09 AM, Segher Boessenkool wrote:
> On Wed, Jun 19, 2019 at 09:39:01AM -0600, Jeff Law wrote:
>> A label used as a value, but which is not a jump target will have an
>> indeterminate value -- it'll end up somewhere in its containing
>> function,  that's all we guarantee in that case.
> 
> In gimple it was fine and expected, and expand *did* make a code_label,
> it was just immediately optimised away:
Yea, because it wasn't used as a jump target.  That's why it gets turned
into a NOTE_INSN_DELETED_LABEL rather than just deleted.

Jeff

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Confusion with labels as values
  2019-06-19 17:38     ` Jeff Law
@ 2019-06-20  7:29       ` Segher Boessenkool
  0 siblings, 0 replies; 5+ messages in thread
From: Segher Boessenkool @ 2019-06-20  7:29 UTC (permalink / raw)
  To: Jeff Law; +Cc: Florian Rommel, gcc

On Wed, Jun 19, 2019 at 11:37:52AM -0600, Jeff Law wrote:
> On 6/19/19 11:09 AM, Segher Boessenkool wrote:
> > On Wed, Jun 19, 2019 at 09:39:01AM -0600, Jeff Law wrote:
> >> A label used as a value, but which is not a jump target will have an
> >> indeterminate value -- it'll end up somewhere in its containing
> >> function,  that's all we guarantee in that case.
> > 
> > In gimple it was fine and expected, and expand *did* make a code_label,
> > it was just immediately optimised away:
> Yea, because it wasn't used as a jump target.  That's why it gets turned
> into a NOTE_INSN_DELETED_LABEL rather than just deleted.

My point was, we could change that.  But the more I look at it the worse
plan that looks -- it's not as simple as it appears, and for what?  :-)


Segher

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-06-20  7:29 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-19 13:05 Confusion with labels as values Florian Rommel
2019-06-19 15:39 ` Jeff Law
2019-06-19 17:09   ` Segher Boessenkool
2019-06-19 17:38     ` Jeff Law
2019-06-20  7:29       ` Segher Boessenkool

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).