▲ | ncruces 2 days ago | ||||||||||||||||
Hi Andy. Did you read the linked thread? I was not the one making this claim: > However, I believe that currently, there is no well-defined way to actually achieve this on the LLVM IR level. Using plain loads for this is UB (even if it may usually work out in practice, and I'm sure plenty of C code just does that). My claim is that the below snippet is implemention defined (not UB):
Further, that this is actually defined by the implementation to do the correct thing, by any good faith reading of the standard:> The mapping functions for converting a pointer to an integer or an integer to a pointer are intended to be consistent with the addressing structure of the execution environment. I further suggested laundering the pointer with something like the below, but was told it would amount to nothing, again the blame being put on LLVM:
I honestly don't know if LLVM or clang should be to blame. I was told LLVM IR and took it in good faith. | |||||||||||||||||
▲ | AndyKelley 2 days ago | parent [-] | ||||||||||||||||
No, I hadn't read the linked thread until you prodded me. Now I have and I understand the situation entirely. I'll give a brief overview; feel free to ask any followup questions. A straightforward implementation of memchr, i.e. finding the index of a particular byte inside an array of bytes, looks like this:
This is trivial to lower to well-defined LLVM IR.But it's desirable to use tricks to make the function really fast, such as assuming that you can read up to the page boundary with SIMD instructions[1]. This is generally true on real world hardware, but this is incompatible with the pointer provenance memory model, which is load-bearing for important optimizations that C, C++, Rust, and Zig all rely on. So if you want to do such tricks you have to do it in a black box that is exempt from the memory model rules. The Zig code I link to here is unsound because it does not do this. An optimization pass, whether it be implemented in Zig pipeline or LLVM pipeline, would be able to prove that it writes outside a pointer provenance, mark that particular control flow unreachable, and thereby cause undefined behavior if it happens. This is not really LLVM's fault. This is a language shortcoming in C, C++, Rust, Zig, and probably many others. It's a fundamental conflict between the utility of pointer provenance rules, and the utility of ignoring that crap and just doing what you know the machine allows you to do. [1]: https://github.com/ziglang/zig/blob/0.14.1/lib/std/mem.zig#L... | |||||||||||||||||
|