Index: include/llvm/IR/Constant.h =================================================================== --- include/llvm/IR/Constant.h +++ include/llvm/IR/Constant.h @@ -122,6 +122,32 @@ /// the same value, return that value. Otherwise return 0. Constant *getSplatValue() const; + /// A byte pattern. + /// + /// Can be "any" pattern if the value was padding or known to be undef. + /// Can be "none" pattern if a sequence doesn't exist. + class BytePattern { + uint8_t Val; + enum class ValueType : uint8_t { Specific, Any, None } Type; + BytePattern(ValueType Type) : Type(Type) {} + + public: + BytePattern(uint8_t Value) : Val(Value), Type(ValueType::Specific) {} + static BytePattern Any() { return BytePattern(ValueType::Any); } + static BytePattern None() { return BytePattern(ValueType::None); } + bool isAny() const { return Type == ValueType::Any; } + bool isNone() const { return Type == ValueType::None; } + bool isValued() const { return Type == ValueType::Specific; } + uint8_t getValue() const { + assert(isValued()); + return Val; + } + BytePattern merge(const BytePattern Other) const; + }; + + /// If a constant is recursively a repeated byte pattern, return that value. + BytePattern isRepeatedBytePattern() const; + /// If C is a constant integer then return its value, otherwise C must be a /// vector of constant integers, all equal, and the common value is returned. const APInt &getUniqueInteger() const; Index: lib/IR/Constants.cpp =================================================================== --- lib/IR/Constants.cpp +++ lib/IR/Constants.cpp @@ -1372,6 +1372,79 @@ return cast(C)->getValue(); } +Constant::BytePattern +Constant::BytePattern::merge(const BytePattern Other) const { + if (isNone() || Other.isNone()) + return None(); + if (isAny()) + return Other; + if (Other.isAny()) + return *this; + if (getValue() == Other.getValue()) + return *this; + return None(); +} + +Constant::BytePattern Constant::isRepeatedBytePattern() const { + if (isa(this) || isa(this)) + return BytePattern(0x00); + if (isa(this)) + return BytePattern::Any(); + + if (isa(this)) { + auto *Int = cast(this); + if (Int->getBitWidth() % 8 != 0) + return BytePattern::None(); + const APInt &Value = Int->getValue(); + if (Value.isSplat(8)) + return BytePattern(Value.getLoBits(8).getLimitedValue()); + return BytePattern::None(); + } + + if (isa(this)) { + auto *FP = cast(this); + APInt Bits = FP->getValueAPF().bitcastToAPInt(); + if (Bits.getBitWidth() % 8 != 0) + return BytePattern::None(); + if (!Bits.isSplat(8)) + return BytePattern::None(); + return BytePattern(Bits.getLimitedValue() & 0xFF); + } + + if (isa(this)) { + Constant *Splat = cast(this)->getSplatValue(); + if (Splat) + return Splat->isRepeatedBytePattern(); + return BytePattern::None(); + } + + if (isa(this) || isa(this)) { + BytePattern Pattern(BytePattern::Any()); + for (unsigned I = 0, E = getNumOperands(); I != E; ++I) { + Constant *Elt = cast(this->getOperand(I)); + Pattern = Pattern.merge(Elt->isRepeatedBytePattern()); + if (Pattern.isNone()) + return Pattern; + } + return Pattern; + } + + if (const ConstantDataSequential *CDS = + dyn_cast(this)) { + BytePattern Pattern(BytePattern::Any()); + for (unsigned I = 0, E = CDS->getNumElements(); I != E; ++I) { + Constant *Elt = CDS->getElementAsConstant(I); + Pattern = Pattern.merge(Elt->isRepeatedBytePattern()); + if (Pattern.isNone()) + return Pattern; + } + return Pattern; + } + + // BlockAddress, ConstantExpr, and everything else is scary. + return BytePattern::None(); +} + //---- ConstantPointerNull::get() implementation. //