Allow mem2reg to replace an Alloca used as a nocapture and inaccessiblememonly/readnone function call operand with undef
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Unit Tests
Time | Test | |
---|---|---|
20 ms | MLIR.Dialect/Affine::Unknown Unit Message ("") |
Event Timeline
Allow mem2reg to replace an Alloca used as a nocapture and inaccessiblememonly/readnone function call operand with undef
This is not sound. Take the following example
int foo(int *a) { return a & 31; // or "worse": if(a&32) return 1; else return 0; } int is_stack_aligned() { int stack; return foo(&stack); }
Replacing stack with undef will introduce poison or UB where there was none before.
It also breaks if you have something like:
int is_same(int *a, short *b) { return a == b; } int return_true() { int Stack; return is_same(&Stack, (short*)&Stack); }
That said, I think what we can do is "privatize" the pointer under more strict requirements than you have here. I was hoping to do that in AAPrivatizablePtrImpl at some point but I now think the requirements we have there are still a little too weak. I'll have to think about this one a bit. (Btw. you should really consider implementing some of these in the Attributor instead. It should be way more powerful there.)
Hmm, yeah, undef is probably too strong. Ok, how about I replace the argument with a fresh alloca? It should still permit load/store optimizations on the original alloca, while still providing some alloca that isn't accessed.
I'm not familiar with the attributor, is that the component that infers function attributes? Isn't that somewhat orthogonal since it tags function attributes for subsequent optimizations like this one?
I'm unsure about the scope of this. It seems to match a particular pattern and it is unclear this is the right place to do so. Have you considered doing this as part of AAPrivatizablePtr (or a new AbstractAttribute) in the Attributor?
llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp | ||
---|---|---|
317 | This comment will be outdated. | |
llvm/test/Transforms/Mem2Reg/fnattr.ll | ||
2 | If it is OK with you, please run update_test_checks.py --function-signature --scrub-attributes on this file to create the check lines. I personally find it way easier to read as almost complete check lines. | |
112 | We should do something with the return value of is_same, either here or in is_same. Dead code for testing is not always future proof. Similarly in other test cases. |
No, I'm not familiar with the attributor, but I thought that was the component that infers function attributes? I admit I'm a bit hesitant to revise and reimplement this in a different framework. The original reason I ended up implementing this here is that in some benchmark code, I noticed the optimization sequence of global variable localization and memory to register conversion was being inhibited by these attributed functions, when compared against a baseline without attributed functions.
llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp | ||
---|---|---|
317 | I'll elaborate more here, but this function must still remove all non load/store instructions using this alloca, because the rest of the memtoreg pass assumes it. The only change is that a promotable alloca passed as a non-capturing and non-read function call argument is changed to use a separate fresh alloca, instead of the original one. | |
llvm/test/Transforms/Mem2Reg/fnattr.ll | ||
2 | Ok, done. | |
112 | Done. |
This comment will be outdated.