Remix.run Logo
ncruces 4 days ago

Why? What specific optimization do you have in mind that prevents me from doing an aligned 16/32/64-byte vector load that covers the address pointed to by a valid char*?

gpderetta 4 days ago | parent | next [-]

Casting a char pointer to a vector pointer and doing vector loads doesn't violate provenance, although it might violate TBAA.

Regarding provenance, consider this:

  void bar();
  int foo() {
    int * ptr = malloc(sizeof(int));
    *ptr = 10;
    bar();
    int result = *ptr;
    free(ptr);
    return result;
  }
If the compiler can track the lifetime of the dynamically allocated int, it can remove the allocation and covert this function to simply

  int foo() { 
      bar();
      return 10;
  }
It can't if arbitrary code (for example inside bar()) can forge pointers to that memory location. The code can seem silly, but you could end up with something similar after inlining.
rurban 3 days ago | parent | next [-]

Then show me the compiler which tells the user that it removed this dead code. There is even an assignment removed, which violates all expectations

torstenvl 4 days ago | parent | prev [-]

> It can't if arbitrary code (for example inside bar()) can forge pointers to that memory location.

Yes. It absolutely can. What are you even talking about?

C is not the Windows Start Menu. This habit of thinking it needs to do what it thinks I might expect instead of what I told it is deeply psychotic.

gpderetta 4 days ago | parent [-]

I litterally have no idea what are you trying to say. Do you mean that bar should be allowed to access *ptr with impunity or not?

torstenvl 4 days ago | parent [-]

I'm not trying to say anything. I said and meant exactly what I said. No more, no less. Your logic is obviously flawed. There is nothing preventing that optimization in the presence of a forged pointer in bar().

gpderetta 4 days ago | parent [-]

Either there is no provenance, forging is allowed and the optimization is disallowed; or there is provenance and forging the pointer and attempting to inspect (or modify) the value of *ptr in bar() is UB.

ncruces 4 days ago | parent | next [-]

You never converted ptr to an integer. If you did, if the pointer escapes, yes, I claim that then the allocation can't be optimized away. Why is that so bad?

torstenvl 4 days ago | parent | prev [-]

Attempting to inspect or modify the value of *ptr in bar() through a forged pointer was always UB. You are saying absolutely nothing meaningful.

ncruces 4 days ago | parent | prev [-]

Can't reply to the sibling comment, for some reason.

If you don't know the extents of the object pointed to by the char*, using an aligned vector load can reach outside the bounds of the object. Keeping provenance makes that undefined behavior.

Using integer arithmetic, and pointer-to-integer/integer-to-pointer conversions would make this implementation defined, and well defined in all of the hardware platforms where an aligned vector load can never possibly fail.

So you can't do some optimizations to functions where this happens? Great. Do it. What else?

As for why you'd want to do this. C makes strings null-terminated, and you can't know their extents without strlen first. So how do you implement strlen? Similarly your example. Seems great until you're the one implementing malloc.

But I'm sure "let's create undefined behavior for a libc implemented in C" is a fine goal.

gpderetta 4 days ago | parent [-]

[when there is no reply button, you need to click on the date (i.e. N minutes ago) to get the reply box]

I think your example would fall foul of reading beyond the end of an object in addition to pointer provenance. In your case the oob read is harmless as you do not expect any meaningful values for the extra bytes, but generally the compiler would not be able to give any guarantees about the content of the additional memory (or that the memory exists in the first place).

This specific use case could be addressed by the standard, but vectors are already out of the standard, so in practice you use whatever extension you have to use and abide to whatever additional rule the compiler requires (of course this is often underspecified). For example, on GCC simd primitives already have carve-outs for TBAA.

FWIW, a libc implementation in practice already must rely on compiler specific, beyond the standard behaviour anyway.

tialaramex 4 days ago | parent [-]

> [when there is no reply button, you need to click on the date (i.e. N minutes ago) to get the reply box]

As an off-topic aside here that might help anybody who is wondering: HN deliberately doesn't provide "Reply" for very recent comments to try to dissuade you from having the sort of urgent back-and-forth you might reasonably do in a real time chat system, and less reasonably attempt (and likely regret) on platforms like Twitter.

A brief window to think about the thing you just read might cause you to write something more thoughtful, and even to realise that it wasn't saying what you had thought in the first place.

My favourite example was an example where somebody said a feature means "less typing" and another comment insisted it did not, and I was outraged until I realised all that's happening is that one person thinks "Typing" means "You know, pressing keys on your keyboard" and the other person thinks "Typing" means "You know, why an integer is different from a float in C" and so they're actually not even disagreeing the conflict is purely syntax!

gpderetta 4 days ago | parent [-]

Allegedly. Instead I like to think it is a reality check to remind me I'm wasting too much time on HN and should I do something productive :D