1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00

[ADT] Remove APInt/APSInt toString() std::string variants

<string> is currently the highest impact header in a clang+llvm build:

https://commondatastorage.googleapis.com/chromium-browser-clang/llvm-include-analysis.html

One of the most common places this is being included is the APInt.h header, which needs it for an old toString() implementation that returns std::string - an inefficient method compared to the SmallString versions that it actually wraps.

This patch replaces these APInt/APSInt methods with a pair of llvm::toString() helpers inside StringExtras.h, adjusts users accordingly and removes the <string> from APInt.h - I was hoping that more of these users could be converted to use the SmallString methods, but it appears that most end up creating a std::string anyhow. I avoided trying to use the raw_ostream << operators as well as I didn't want to lose having the integer radix explicit in the code.

Differential Revision: https://reviews.llvm.org/D103888
This commit is contained in:
Simon Pilgrim 2021-06-11 13:19:00 +01:00
parent 13db9330f8
commit 165132af1b
13 changed files with 70 additions and 31 deletions

View File

@ -20,7 +20,6 @@
#include <cassert> #include <cassert>
#include <climits> #include <climits>
#include <cstring> #include <cstring>
#include <string>
namespace llvm { namespace llvm {
class FoldingSetNodeID; class FoldingSetNodeID;
@ -1753,13 +1752,6 @@ public:
toString(Str, Radix, true, false); toString(Str, Radix, true, false);
} }
/// Return the APInt as a std::string.
///
/// Note that this is an inefficient method. It is better to pass in a
/// SmallVector/SmallString to the methods above to avoid thrashing the heap
/// for the string.
std::string toString(unsigned Radix, bool Signed) const;
/// \returns a byte-swapped representation of this APInt Value. /// \returns a byte-swapped representation of this APInt Value.
APInt byteSwap() const; APInt byteSwap() const;

View File

@ -82,11 +82,6 @@ public:
void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { void toString(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
APInt::toString(Str, Radix, isSigned()); APInt::toString(Str, Radix, isSigned());
} }
/// Converts an APInt to a std::string. This is an inefficient
/// method; you should prefer passing in a SmallString instead.
std::string toString(unsigned Radix) const {
return APInt::toString(Radix, isSigned());
}
using APInt::toString; using APInt::toString;
/// Get the correctly-extended \c int64_t value. /// Get the correctly-extended \c int64_t value.

View File

@ -13,6 +13,7 @@
#ifndef LLVM_ADT_STRINGEXTRAS_H #ifndef LLVM_ADT_STRINGEXTRAS_H
#define LLVM_ADT_STRINGEXTRAS_H #define LLVM_ADT_STRINGEXTRAS_H
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
@ -296,6 +297,17 @@ inline std::string itostr(int64_t X) {
return utostr(static_cast<uint64_t>(X)); return utostr(static_cast<uint64_t>(X));
} }
inline std::string toString(const APInt &I, unsigned Radix, bool Signed,
bool formatAsCLiteral = false) {
SmallString<40> S;
I.toString(S, Radix, Signed, formatAsCLiteral);
return std::string(S.str());
}
inline std::string toString(const APSInt &I, unsigned Radix) {
return toString(I, Radix, I.isSigned());
}
/// StrInStrNoCase - Portable version of strcasestr. Locates the first /// StrInStrNoCase - Portable version of strcasestr. Locates the first
/// occurrence of string 's1' in string 's2', ignoring case. Returns /// occurrence of string 's1' in string 's2', ignoring case. Returns
/// the offset of s2 in s1 or npos if s2 cannot be found. /// the offset of s2 in s1 or npos if s2 cannot be found.

View File

@ -88,10 +88,10 @@ LLVM_ATTRIBUTE_UNUSED static void
dumpResult(const MachineInstr &MI, const KnownBits &Known, unsigned Depth) { dumpResult(const MachineInstr &MI, const KnownBits &Known, unsigned Depth) {
dbgs() << "[" << Depth << "] Compute known bits: " << MI << "[" << Depth dbgs() << "[" << Depth << "] Compute known bits: " << MI << "[" << Depth
<< "] Computed for: " << MI << "[" << Depth << "] Known: 0x" << "] Computed for: " << MI << "[" << Depth << "] Known: 0x"
<< (Known.Zero | Known.One).toString(16, false) << "\n" << toString(Known.Zero | Known.One, 16, false) << "\n"
<< "[" << Depth << "] Zero: 0x" << Known.Zero.toString(16, false) << "[" << Depth << "] Zero: 0x" << toString(Known.Zero, 16, false)
<< "\n" << "\n"
<< "[" << Depth << "] One: 0x" << Known.One.toString(16, false) << "[" << Depth << "] One: 0x" << toString(Known.One, 16, false)
<< "\n"; << "\n";
} }

View File

@ -1930,7 +1930,7 @@ const MCExpr *TargetLoweringObjectFileCOFF::lowerRelativeReference(
static std::string APIntToHexString(const APInt &AI) { static std::string APIntToHexString(const APInt &AI) {
unsigned Width = (AI.getBitWidth() / 8) * 2; unsigned Width = (AI.getBitWidth() / 8) * 2;
std::string HexString = AI.toString(16, /*Signed=*/false); std::string HexString = toString(AI, 16, /*Signed=*/false);
llvm::transform(HexString, HexString.begin(), tolower); llvm::transform(HexString, HexString.begin(), tolower);
unsigned Size = HexString.size(); unsigned Size = HexString.size();
assert(Width >= Size && "hex string is too large!"); assert(Width >= Size && "hex string is too large!");

View File

@ -2281,14 +2281,6 @@ void APInt::toString(SmallVectorImpl<char> &Str, unsigned Radix,
std::reverse(Str.begin()+StartDig, Str.end()); std::reverse(Str.begin()+StartDig, Str.end());
} }
/// Returns the APInt as a std::string. Note that this is an inefficient method.
/// It is better to pass in a SmallVector/SmallString to the methods above.
std::string APInt::toString(unsigned Radix = 10, bool Signed = true) const {
SmallString<40> S;
toString(S, Radix, Signed, /* formatAsCLiteral = */false);
return std::string(S.str());
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void APInt::dump() const { LLVM_DUMP_METHOD void APInt::dump() const {
SmallString<40> S, U; SmallString<40> S, U;

View File

@ -2167,7 +2167,7 @@ static void addConstantComments(const MachineInstr *MI,
const MachineOperand &DstOp = MI->getOperand(0); const MachineOperand &DstOp = MI->getOperand(0);
CS << X86ATTInstPrinter::getRegisterName(DstOp.getReg()) << " = "; CS << X86ATTInstPrinter::getRegisterName(DstOp.getReg()) << " = ";
if (auto *CF = dyn_cast<ConstantFP>(C)) { if (auto *CF = dyn_cast<ConstantFP>(C)) {
CS << "0x" << CF->getValueAPF().bitcastToAPInt().toString(16, false); CS << "0x" << toString(CF->getValueAPF().bitcastToAPInt(), 16, false);
OutStreamer.AddComment(CS.str()); OutStreamer.AddComment(CS.str());
} }
} }

View File

@ -585,7 +585,7 @@ struct OpenMPOpt {
return ORA << "OpenMP ICV " << ore::NV("OpenMPICV", ICVInfo.Name) return ORA << "OpenMP ICV " << ore::NV("OpenMPICV", ICVInfo.Name)
<< " Value: " << " Value: "
<< (ICVInfo.InitValue << (ICVInfo.InitValue
? ICVInfo.InitValue->getValue().toString(10, true) ? toString(ICVInfo.InitValue->getValue(), 10, true)
: "IMPLEMENTATION_DEFINED"); : "IMPLEMENTATION_DEFINED");
}; };

View File

@ -255,7 +255,7 @@ template <> struct ScalarTraits<exegesis::RegisterValue> {
raw_ostream &Out) { raw_ostream &Out) {
YamlContext &Context = getTypedContext(Ctx); YamlContext &Context = getTypedContext(Ctx);
Out << Context.getRegName(RV.Register) << "=0x" Out << Context.getRegName(RV.Register) << "=0x"
<< RV.Value.toString(kRadix, kSigned); << toString(RV.Value, kRadix, kSigned);
} }
static StringRef input(StringRef String, void *Ctx, static StringRef input(StringRef String, void *Ctx,

View File

@ -559,7 +559,7 @@ Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
P.format(" `{0}`", Constant.Name); P.format(" `{0}`", Constant.Name);
AutoIndent Indent(P, 7); AutoIndent Indent(P, 7);
P.formatLine("type = {0}, value = {1}", typeIndex(Constant.Type), P.formatLine("type = {0}, value = {1}", typeIndex(Constant.Type),
Constant.Value.toString(10)); toString(Constant.Value, 10));
return Error::success(); return Error::success();
} }

View File

@ -557,7 +557,7 @@ Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR, Error MinimalTypeDumpVisitor::visitKnownMember(CVMemberRecord &CVR,
EnumeratorRecord &Enum) { EnumeratorRecord &Enum) {
P.format(" [{0} = {1}]", Enum.Name, P.format(" [{0} = {1}]", Enum.Name,
Enum.Value.toString(10, Enum.Value.isSigned())); toString(Enum.Value, 10, Enum.Value.isSigned()));
return Error::success(); return Error::success();
} }

View File

@ -1461,7 +1461,10 @@ TEST(APIntTest, mul_clear) {
APInt ValC(65, 0); APInt ValC(65, 0);
ValC = ValA * ValB; ValC = ValA * ValB;
ValA *= ValB; ValA *= ValB;
EXPECT_EQ(ValA.toString(10, false), ValC.toString(10, false)); SmallString<16> StrA, StrC;
ValA.toString(StrA, 10, false);
ValC.toString(StrC, 10, false);
EXPECT_EQ(std::string(StrA), std::string(StrC));
} }
TEST(APIntTest, Rotate) { TEST(APIntTest, Rotate) {

View File

@ -229,3 +229,48 @@ TEST(StringExtrasTest, ListSeparator) {
S = LS2; S = LS2;
EXPECT_EQ(S, " "); EXPECT_EQ(S, " ");
} }
TEST(StringExtrasTest, toStringAPInt) {
bool isSigned;
EXPECT_EQ(toString(APInt(8, 0), 2, true, true), "0b0");
EXPECT_EQ(toString(APInt(8, 0), 8, true, true), "00");
EXPECT_EQ(toString(APInt(8, 0), 10, true, true), "0");
EXPECT_EQ(toString(APInt(8, 0), 16, true, true), "0x0");
EXPECT_EQ(toString(APInt(8, 0), 36, true, false), "0");
isSigned = false;
EXPECT_EQ(toString(APInt(8, 255, isSigned), 2, isSigned, true), "0b11111111");
EXPECT_EQ(toString(APInt(8, 255, isSigned), 8, isSigned, true), "0377");
EXPECT_EQ(toString(APInt(8, 255, isSigned), 10, isSigned, true), "255");
EXPECT_EQ(toString(APInt(8, 255, isSigned), 16, isSigned, true), "0xFF");
EXPECT_EQ(toString(APInt(8, 255, isSigned), 36, isSigned, false), "73");
isSigned = true;
EXPECT_EQ(toString(APInt(8, 255, isSigned), 2, isSigned, true), "-0b1");
EXPECT_EQ(toString(APInt(8, 255, isSigned), 8, isSigned, true), "-01");
EXPECT_EQ(toString(APInt(8, 255, isSigned), 10, isSigned, true), "-1");
EXPECT_EQ(toString(APInt(8, 255, isSigned), 16, isSigned, true), "-0x1");
EXPECT_EQ(toString(APInt(8, 255, isSigned), 36, isSigned, false), "-1");
}
TEST(StringExtrasTest, toStringAPSInt) {
bool isUnsigned;
EXPECT_EQ(toString(APSInt(APInt(8, 0), false), 2), "0");
EXPECT_EQ(toString(APSInt(APInt(8, 0), false), 8), "0");
EXPECT_EQ(toString(APSInt(APInt(8, 0), false), 10), "0");
EXPECT_EQ(toString(APSInt(APInt(8, 0), false), 16), "0");
isUnsigned = true;
EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 2), "11111111");
EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 8), "377");
EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 10), "255");
EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 16), "FF");
isUnsigned = false;
EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 2), "-1");
EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 8), "-1");
EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 10), "-1");
EXPECT_EQ(toString(APSInt(APInt(8, 255), isUnsigned), 16), "-1");
}