Index: llvm/include/llvm/Transforms/IPO/Attributor.h =================================================================== --- llvm/include/llvm/Transforms/IPO/Attributor.h +++ llvm/include/llvm/Transforms/IPO/Attributor.h @@ -3362,9 +3362,10 @@ struct PotentialValuesState : AbstractState { using SetTy = DenseSet; - PotentialValuesState() : IsValidState(true) {} + PotentialValuesState() : IsValidState(true), UndefIsContained(false) {} - PotentialValuesState(bool IsValid) : IsValidState(IsValid) {} + PotentialValuesState(bool IsValid) + : IsValidState(IsValid), UndefIsContained(false) {} /// See AbstractState::isValidState(...) bool isValidState() const { return IsValidState.isValidState(); } @@ -3393,11 +3394,19 @@ return Set; } + /// Returns whether this state contains an undef value or not. + bool undefIsContained() const { + assert(isValidState() && "This flag shoud not be used when it is invalid!"); + return UndefIsContained; + } + bool operator==(const PotentialValuesState &RHS) const { if (isValidState() != RHS.isValidState()) return false; if (!isValidState() && !RHS.isValidState()) return true; + if (undefIsContained() != RHS.undefIsContained()) + return false; return Set == RHS.getAssumedSet(); } @@ -3425,6 +3434,9 @@ /// Union assumed set with assumed set of the passed state \p PVS. void unionAssumed(const PotentialValuesState &PVS) { unionWith(PVS); } + /// Union assumed set with an undef value. + void unionAssumedWithUndef() { unionWithUndef(); } + /// "Clamp" this state with \p PVS. PotentialValuesState operator^=(const PotentialValuesState &PVS) { unionAssumed(PVS); @@ -3444,6 +3456,10 @@ indicatePessimisticFixpoint(); } + /// If this state contains both undef and not undef, we can reduce + /// undef to the not undef value. + void reduceUndefValue() { UndefIsContained = UndefIsContained & Set.empty(); } + /// Insert an element into this set. void insert(const MemberTy &C) { if (!isValidState()) @@ -3464,9 +3480,17 @@ } for (const MemberTy &C : R.Set) Set.insert(C); + UndefIsContained |= R.undefIsContained(); + reduceUndefValue(); checkAndInvalidate(); } + /// Take union with an undef value. + void unionWithUndef() { + UndefIsContained = true; + reduceUndefValue(); + } + /// Take intersection with R. void intersectWith(const PotentialValuesState &R) { /// If R is a full set, do nothing. @@ -3483,6 +3507,8 @@ IntersectSet.insert(C); } Set = IntersectSet; + UndefIsContained &= R.undefIsContained(); + reduceUndefValue(); } /// A helper state which indicate whether this state is valid or not. @@ -3490,6 +3516,9 @@ /// Container for potential values SetTy Set; + + /// Flag for undef value + bool UndefIsContained; }; using PotentialConstantIntValuesState = PotentialValuesState; @@ -3536,8 +3565,12 @@ if (getAssumedSet().size() == 1) return cast(ConstantInt::get(getAssociatedValue().getType(), *(getAssumedSet().begin()))); - if (getAssumedSet().size() == 0) + if (getAssumedSet().size() == 0) { + if (undefIsContained()) + return cast( + ConstantInt::get(getAssociatedValue().getType(), 0)); return llvm::None; + } return nullptr; } Index: llvm/lib/Transforms/IPO/Attributor.cpp =================================================================== --- llvm/lib/Transforms/IPO/Attributor.cpp +++ llvm/lib/Transforms/IPO/Attributor.cpp @@ -2084,9 +2084,12 @@ OS << "set-state(< {"; if (!S.isValidState()) OS << "full-set"; - else + else { for (auto &it : S.getAssumedSet()) OS << it << ", "; + if (S.undefIsContained()) + OS << "undef "; + } OS << "} >)"; return OS; Index: llvm/lib/Transforms/IPO/AttributorAttributes.cpp =================================================================== --- llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -7255,10 +7255,7 @@ } if (isa(&V)) { - // Collapse the undef state to 0. - unionAssumed( - APInt(/* numBits */ getAssociatedType()->getIntegerBitWidth(), - /* val */ 0)); + unionAssumedWithUndef(); indicateOptimisticFixpoint(); return; }