From 2f0582fcc73f231d60e8e10c1af5ad5a1891457c Mon Sep 17 00:00:00 2001 From: JF Bastien Date: Fri, 21 Sep 2018 13:54:09 +0000 Subject: [PATCH] NFC: deduplicate isRepeatedBytePattern from clang to LLVM's isBytewiseValue Summary: This code was in CGDecl.cpp and really belongs in LLVM. It happened to have isBytewiseValue which served a very similar purpose but wasn't as powerful as clang's version. Remove the clang version, and augment isBytewiseValue to be as powerful so that clang does the same thing it used to. LLVM part of this patch: D51751 Subscribers: dexonsmith, cfe-commits Differential Revision: https://reviews.llvm.org/D51752 llvm-svn: 342734 --- clang/lib/CodeGen/CGDecl.cpp | 114 ++++------------------------------- 1 file changed, 13 insertions(+), 101 deletions(-) diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 5c47212f1b52..44ee6b3b3a64 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -30,6 +30,7 @@ #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "clang/Frontend/CodeGenOptions.h" +#include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Intrinsics.h" @@ -948,111 +949,17 @@ static bool shouldUseBZeroPlusStoresToInitialize(llvm::Constant *Init, canEmitInitWithFewStoresAfterBZero(Init, StoreBudget); } -/// 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 (isNone() || Other.isNone()) - return None(); - if (isAny()) - return Other; - if (Other.isAny()) - return *this; - if (getValue() == Other.getValue()) - return *this; - return None(); - } -}; - -/// Figures out whether the constant can be initialized with memset. -static BytePattern constantIsRepeatedBytePattern(llvm::Constant *C) { - if (isa(C) || isa(C)) - return BytePattern(0x00); - if (isa(C)) - return BytePattern::Any(); - - if (isa(C)) { - auto *Int = cast(C); - if (Int->getBitWidth() % 8 != 0) - return BytePattern::None(); - const llvm::APInt &Value = Int->getValue(); - if (Value.isSplat(8)) - return BytePattern(Value.getLoBits(8).getLimitedValue()); - return BytePattern::None(); - } - - if (isa(C)) { - auto *FP = cast(C); - llvm::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(C)) { - llvm::Constant *Splat = cast(C)->getSplatValue(); - if (Splat) - return constantIsRepeatedBytePattern(Splat); - return BytePattern::None(); - } - - if (isa(C) || isa(C)) { - BytePattern Pattern(BytePattern::Any()); - for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I) { - llvm::Constant *Elt = cast(C->getOperand(I)); - Pattern = Pattern.merge(constantIsRepeatedBytePattern(Elt)); - if (Pattern.isNone()) - return Pattern; - } - return Pattern; - } - - if (llvm::ConstantDataSequential *CDS = - dyn_cast(C)) { - BytePattern Pattern(BytePattern::Any()); - for (unsigned I = 0, E = CDS->getNumElements(); I != E; ++I) { - llvm::Constant *Elt = CDS->getElementAsConstant(I); - Pattern = Pattern.merge(constantIsRepeatedBytePattern(Elt)); - if (Pattern.isNone()) - return Pattern; - } - return Pattern; - } - - // BlockAddress, ConstantExpr, and everything else is scary. - return BytePattern::None(); -} - /// Decide whether we should use memset to initialize a local variable instead /// of using a memcpy from a constant global. Assumes we've already decided to /// not user bzero. /// FIXME We could be more clever, as we are for bzero above, and generate /// memset followed by stores. It's unclear that's worth the effort. -static BytePattern shouldUseMemSetToInitialize(llvm::Constant *Init, - uint64_t GlobalSize) { +static llvm::Value *shouldUseMemSetToInitialize(llvm::Constant *Init, + uint64_t GlobalSize) { uint64_t SizeLimit = 32; if (GlobalSize <= SizeLimit) - return BytePattern::None(); - return constantIsRepeatedBytePattern(Init); + return nullptr; + return llvm::isBytewiseValue(Init); } static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D, @@ -1081,9 +988,14 @@ static void emitStoresForConstant(CodeGenModule &CGM, const VarDecl &D, return; } - BytePattern Pattern = shouldUseMemSetToInitialize(constant, ConstantSize); - if (!Pattern.isNone()) { - uint8_t Value = Pattern.isAny() ? 0x00 : Pattern.getValue(); + llvm::Value *Pattern = shouldUseMemSetToInitialize(constant, ConstantSize); + if (Pattern) { + uint64_t Value = 0x00; + if (!isa(Pattern)) { + const llvm::APInt &AP = cast(Pattern)->getValue(); + assert(AP.getBitWidth() <= 8); + Value = AP.getLimitedValue(); + } Builder.CreateMemSet(Loc, llvm::ConstantInt::get(Int8Ty, Value), SizeVal, isVolatile); return;