I don't know the overall impact of this change, or if it goes far enough, but based on:
https://bugs.llvm.org/show_bug.cgi?id=43501
...we can't declare the GEP 'inbounds' in general. But we can salvage that information if we have known dereferenceable bytes on the source pointer.
Details
- Reviewers
nlopes efriedma regehr jdoerfert lebedev.ri - Commits
- rGc38881a6b7f9: [InstCombine] don't assume 'inbounds' for bitcast pointer to GEP transform…
rL373847: [InstCombine] don't assume 'inbounds' for bitcast pointer to GEP transform…
rC373847: [InstCombine] don't assume 'inbounds' for bitcast pointer to GEP transform…
Diff Detail
Event Timeline
Patch updated:
Use 'dereferenceable' knowledge to deduce 'inbounds'. This removes the 3 diffs from the previous revision that had an argument with dereferenceable bytes.
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | ||
---|---|---|
2344–2345 | Why beyond? You check >=. | |
2351 | @jdoerfert @uenoku @sstefan1 |
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | ||
---|---|---|
2344–2345 | Yes, inaccurate comment. I'll fix it... | |
2351 | Right...so I proposed this change based on the comments in PR43501, but it raises a question: |
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | ||
---|---|---|
2351 | Once attributor is enabled and can do this, if it will run frequent-enough in the pipeline, But currently it does not, so let's keep this for now. |
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | ||
---|---|---|
2348 | /// Note that this may not reflect the size of memory allocated for an /// instance of the type or the number of bytes that are written when an /// instance of the type is stored to memory. The DataLayout class provides /// additional query functions to provide this information. /// unsigned getPrimitiveSizeInBits() const LLVM_READONLY; We are sure this is what we want? |
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | ||
---|---|---|
2351 | Why all this logic? bitcast -> gep inbounds 0, 0 should be fine as long as the pointer is null or points into (or to the end of) an allocated object. @lebedev.ri |
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | ||
---|---|---|
2351 |
We don't know that the input is inbounds, see https://bugs.llvm.org/show_bug.cgi?id=43501 |
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | ||
---|---|---|
2348 | Actually, what @jdoerfert was saying is that we don't care what the size of the type is. |
llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp | ||
---|---|---|
2348 | That is what I should have said at least ;) |
Patch updated:
Loosen the dereferenceable constraint - any deref will do. Add a test to show that.
You accidentally or intentionally did the right thing when it comes to deref_or_null.
That is,
define float @matching_scalar_smallest_deref_or_null(<4 x float>* dereferenceable_or_null(1) %p) { ; CHECK-LABEL: @matching_scalar_smallest_deref_or_null( ; CHECK-NEXT: [[BC:%.*]] = getelementptr inbounds <4 x float>, <4 x float>* [[P:%.*]], i64 0, i64 0 ; CHECK-NEXT: [[R:%.*]] = load float, float* [[BC]], align 16 ; CHECK-NEXT: ret float [[R]] ; %bc = bitcast <4 x float>* %p to float* %r = load float, float* %bc, align 16 ret float %r }
should also work fine.
Thanks, I'll add that test too. It was intentional to allow that possibility based on the previous comments, but admittedly, I'm not very familiar with 'inbounds' semantics/usage. The LangRef says:
"The only in bounds address for a null pointer in the default address-space is the null pointer itself."
So what does that mean for a null pointer *not* in the default address-space?
Why beyond? You check >=.