[llvm] [BasicAA] Consider 'nneg' flag when comparing CastedValues (PR #94129)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 2 02:26:15 PDT 2024
================
@@ -268,43 +268,59 @@ struct CastedValue {
unsigned ZExtBits = 0;
unsigned SExtBits = 0;
unsigned TruncBits = 0;
+ bool IsNonNegative = false;
explicit CastedValue(const Value *V) : V(V) {}
explicit CastedValue(const Value *V, unsigned ZExtBits, unsigned SExtBits,
- unsigned TruncBits)
- : V(V), ZExtBits(ZExtBits), SExtBits(SExtBits), TruncBits(TruncBits) {}
+ unsigned TruncBits, bool IsNonNegative)
+ : V(V), ZExtBits(ZExtBits), SExtBits(SExtBits), TruncBits(TruncBits),
+ IsNonNegative(IsNonNegative) {}
unsigned getBitWidth() const {
return V->getType()->getPrimitiveSizeInBits() - TruncBits + ZExtBits +
SExtBits;
}
- CastedValue withValue(const Value *NewV) const {
- return CastedValue(NewV, ZExtBits, SExtBits, TruncBits);
+ CastedValue withValue(const Value *NewV, bool PreserveNonNeg) const {
+ return CastedValue(NewV, ZExtBits, SExtBits, TruncBits,
+ IsNonNegative && PreserveNonNeg);
}
/// Replace V with zext(NewV)
- CastedValue withZExtOfValue(const Value *NewV) const {
+ CastedValue withZExtOfValue(const Value *NewV, bool ZExtNonNegative) const {
unsigned ExtendBy = V->getType()->getPrimitiveSizeInBits() -
NewV->getType()->getPrimitiveSizeInBits();
if (ExtendBy <= TruncBits)
- return CastedValue(NewV, ZExtBits, SExtBits, TruncBits - ExtendBy);
+ // zext<nneg>(trunc(zext(NewV))) == zext<nneg>(trunc(NewV))
+ // The nneg can be preserved on the outer zext here
+ return CastedValue(NewV, ZExtBits, SExtBits, TruncBits - ExtendBy,
+ IsNonNegative);
// zext(sext(zext(NewV))) == zext(zext(zext(NewV)))
ExtendBy -= TruncBits;
- return CastedValue(NewV, ZExtBits + SExtBits + ExtendBy, 0, 0);
+ // zext<nneg>(zext(NewV)) == zext(NewV)
+ // zext(zext<nneg>(NewV)) == zext<nneg>(NewV)
+ // The nneg can be preserved from the inner zext here but must be dropped
+ // from the outer.
+ return CastedValue(NewV, ZExtBits + SExtBits + ExtendBy, 0, 0,
+ ZExtNonNegative);
}
/// Replace V with sext(NewV)
CastedValue withSExtOfValue(const Value *NewV) const {
unsigned ExtendBy = V->getType()->getPrimitiveSizeInBits() -
NewV->getType()->getPrimitiveSizeInBits();
if (ExtendBy <= TruncBits)
- return CastedValue(NewV, ZExtBits, SExtBits, TruncBits - ExtendBy);
+ // zext<nneg>(trunc(sext(NewV))) == zext<nneg>(trunc(NewV))
+ // The nneg can be preserved on the outer zext here
+ return CastedValue(NewV, ZExtBits, SExtBits, TruncBits - ExtendBy,
+ IsNonNegative);
// zext(sext(sext(NewV)))
ExtendBy -= TruncBits;
- return CastedValue(NewV, ZExtBits, SExtBits + ExtendBy, 0);
+ // zext<nneg>(sext(sext(NewV))) = zext<nneg>(sext(NewV))
+ // The nneg can be preserved on the outer zext here
----------------
nikic wrote:
I wonder whether it would make sense to have an invariant that if `IsNonNegative` then `SExtBits == 0`. If the value is non-negative, then it doesn't really make sense to separately track ZExtBits and SExtBits and we could canonicalize both to ZExtBits.
```
if (IsNonNegative)
return CastedValue(NewV, ZExtBits + ExtendBy, 0, IsNonNegative);
```
https://github.com/llvm/llvm-project/pull/94129
More information about the llvm-commits
mailing list