I'd like some short description in LangRef we can point to when questions come up, rather than the complicated discussion in https://bugs.llvm.org/show_bug.cgi?id=34548 .
|240 ms||linux > Clang.Driver::riscv-cpus.c|
Script: -- : 'RUN: at line 3'; /mnt/disks/ssd0/agent/llvm-project/build/bin/clang -target riscv32 -### -c /mnt/disks/ssd0/agent/llvm-project/clang/test/Driver/riscv-cpus.c 2>&1 -mcpu=rocket-rv32 | /mnt/disks/ssd0/agent/llvm-project/build/bin/FileCheck -check-prefix=MCPU-ROCKET32 /mnt/disks/ssd0/agent/llvm-project/clang/test/Driver/riscv-cpus.c
The contents below talk about loads that produce pointers as well - maybe the title should be more comprehensive?
Let's talk about inttoptr in this paragraph first, and talk about load pointers as separate paragraph(s). I believe inttoptr already has quite a few things to talk about.
I think it is important to mention that, with this inttoptr semantics, inttoptr isn't a scalar operation anymore. It cannot be freely hoisted or sunk across pointer escaping instructions, but it is currently done by LLVM.
Another possible semantics that would be good to mention here too is to make inttoptr i simply based on i.
FYI: Alive2 uses this semantics, and it returns poison when a pointer-byte is read as a non-pointer type (and vice versa). The main blocker is a load type canonicalization in InstCombine, which changes load pointer to load i64.
My meta-comment about this patch is that I'm not sure LangRef is the right place for this content. I see LangRef as the stuff that is set in stone, not necessarily for ongoing discussions.
However, since LangRef doesn't get these bits right, it might be ok to have a warning section about stuff that is disputed/under discussion so that readers know that part is not set in stone.
my understanding is that for C we need to allow a pointer to be at the end of the object (not past, just at the end; you can't dereference it still). This is, for example, because of loops that increment pointers and check them against the end ptr.
That end pointer can have the same underlying machine value as the beginning of another object, thus making inttoptr complicated.
We support this semantics of control-flow contributing to the aliasing of an inttoptr result. To fold inttoptr(ptrtoint(ptr)) -> ptr one needs to prove that ptr is dereferenceable though.
My meta-comment about this patch is that I'm not sure LangRef is the right place for this content. I see LangRef as the stuff that is set in stone, not necessarily for ongoing discussions. However, since LangRef doesn't get these bits right, it might be ok to have a warning section about stuff that is disputed/under discussion so that readers know that part is not set in stone.
Given the feedback, I'm going to cut the bits describing the potential solutions, to try to keep it more readable.
Well, for pointers we know are dereferenced, we could mark up the GEPs more aggressively. But yes, that's where this sort of model breaks down.
I guess if you have load(inttoptr(ptrtoint(ptr))), you can optimize that to load(ptr) if ptr is dereferenceable: the load would be UB if it wasn't equivalent. I don't think it helps more generally, though.