summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Bitcode
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Bitcode')
-rw-r--r--llvm/lib/Bitcode/Reader/BitcodeReader.cpp133
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriter.cpp14
-rw-r--r--llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp15
3 files changed, 79 insertions, 83 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 4b1ccf85231..69fb4ece9f3 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -7,13 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Bitcode/BitstreamReader.h"
#include "llvm/Bitcode/LLVMBitCodes.h"
+#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/AutoUpgrade.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfo.h"
@@ -25,9 +25,9 @@
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/IR/OperandTraits.h"
#include "llvm/IR/Operator.h"
-#include "llvm/IR/FunctionInfo.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/DataStream.h"
#include "llvm/Support/ManagedStatic.h"
@@ -413,11 +413,11 @@ private:
/// Class to manage reading and parsing function summary index bitcode
/// files/sections.
-class FunctionIndexBitcodeReader {
+class ModuleSummaryIndexBitcodeReader {
DiagnosticHandlerFunction DiagnosticHandler;
/// Eventually points to the module index built during parsing.
- FunctionInfoIndex *TheIndex = nullptr;
+ ModuleSummaryIndex *TheIndex = nullptr;
std::unique_ptr<MemoryBuffer> Buffer;
std::unique_ptr<BitstreamReader> StreamFile;
@@ -427,7 +427,7 @@ class FunctionIndexBitcodeReader {
///
/// If false, the summary section is fully parsed into the index during
/// the initial parse. Otherwise, if true, the caller is expected to
- /// invoke \a readFunctionSummary for each summary needed, and the summary
+ /// invoke \a readGlobalValueSummary for each summary needed, and the summary
/// section is thus parsed lazily.
bool IsLazy = false;
@@ -452,7 +452,7 @@ class FunctionIndexBitcodeReader {
// ValueSymbolTable. It is used after the VST is parsed to convert
// call graph edges read from the function summary from referencing
// callees by their ValueId to using the GUID instead, which is how
- // they are recorded in the function index being built.
+ // they are recorded in the summary index being built.
DenseMap<unsigned, uint64_t> ValueIdToCallGraphGUIDMap;
/// Map to save the association between summary offset in the VST to the
@@ -474,14 +474,13 @@ public:
std::error_code error(BitcodeError E);
std::error_code error(const Twine &Message);
- FunctionIndexBitcodeReader(MemoryBuffer *Buffer,
- DiagnosticHandlerFunction DiagnosticHandler,
- bool IsLazy = false,
- bool CheckGlobalValSummaryPresenceOnly = false);
- FunctionIndexBitcodeReader(DiagnosticHandlerFunction DiagnosticHandler,
- bool IsLazy = false,
- bool CheckGlobalValSummaryPresenceOnly = false);
- ~FunctionIndexBitcodeReader() { freeState(); }
+ ModuleSummaryIndexBitcodeReader(
+ MemoryBuffer *Buffer, DiagnosticHandlerFunction DiagnosticHandler,
+ bool IsLazy = false, bool CheckGlobalValSummaryPresenceOnly = false);
+ ModuleSummaryIndexBitcodeReader(
+ DiagnosticHandlerFunction DiagnosticHandler, bool IsLazy = false,
+ bool CheckGlobalValSummaryPresenceOnly = false);
+ ~ModuleSummaryIndexBitcodeReader() { freeState(); }
void freeState();
@@ -493,12 +492,12 @@ public:
/// \brief Main interface to parsing a bitcode buffer.
/// \returns true if an error occurred.
std::error_code parseSummaryIndexInto(std::unique_ptr<DataStreamer> Streamer,
- FunctionInfoIndex *I);
+ ModuleSummaryIndex *I);
/// \brief Interface for parsing a summary lazily.
- std::error_code parseFunctionSummary(std::unique_ptr<DataStreamer> Streamer,
- FunctionInfoIndex *I,
- size_t FunctionSummaryOffset);
+ std::error_code
+ parseGlobalValueSummary(std::unique_ptr<DataStreamer> Streamer,
+ ModuleSummaryIndex *I, size_t SummaryOffset);
private:
std::error_code parseModule();
@@ -5414,44 +5413,44 @@ BitcodeReader::initLazyStream(std::unique_ptr<DataStreamer> Streamer) {
return std::error_code();
}
-std::error_code FunctionIndexBitcodeReader::error(BitcodeError E,
- const Twine &Message) {
+std::error_code ModuleSummaryIndexBitcodeReader::error(BitcodeError E,
+ const Twine &Message) {
return ::error(DiagnosticHandler, make_error_code(E), Message);
}
-std::error_code FunctionIndexBitcodeReader::error(const Twine &Message) {
+std::error_code ModuleSummaryIndexBitcodeReader::error(const Twine &Message) {
return ::error(DiagnosticHandler,
make_error_code(BitcodeError::CorruptedBitcode), Message);
}
-std::error_code FunctionIndexBitcodeReader::error(BitcodeError E) {
+std::error_code ModuleSummaryIndexBitcodeReader::error(BitcodeError E) {
return ::error(DiagnosticHandler, make_error_code(E));
}
-FunctionIndexBitcodeReader::FunctionIndexBitcodeReader(
+ModuleSummaryIndexBitcodeReader::ModuleSummaryIndexBitcodeReader(
MemoryBuffer *Buffer, DiagnosticHandlerFunction DiagnosticHandler,
bool IsLazy, bool CheckGlobalValSummaryPresenceOnly)
: DiagnosticHandler(DiagnosticHandler), Buffer(Buffer), IsLazy(IsLazy),
CheckGlobalValSummaryPresenceOnly(CheckGlobalValSummaryPresenceOnly) {}
-FunctionIndexBitcodeReader::FunctionIndexBitcodeReader(
+ModuleSummaryIndexBitcodeReader::ModuleSummaryIndexBitcodeReader(
DiagnosticHandlerFunction DiagnosticHandler, bool IsLazy,
bool CheckGlobalValSummaryPresenceOnly)
: DiagnosticHandler(DiagnosticHandler), Buffer(nullptr), IsLazy(IsLazy),
CheckGlobalValSummaryPresenceOnly(CheckGlobalValSummaryPresenceOnly) {}
-void FunctionIndexBitcodeReader::freeState() { Buffer = nullptr; }
+void ModuleSummaryIndexBitcodeReader::freeState() { Buffer = nullptr; }
-void FunctionIndexBitcodeReader::releaseBuffer() { Buffer.release(); }
+void ModuleSummaryIndexBitcodeReader::releaseBuffer() { Buffer.release(); }
-uint64_t FunctionIndexBitcodeReader::getGUIDFromValueId(unsigned ValueId) {
+uint64_t ModuleSummaryIndexBitcodeReader::getGUIDFromValueId(unsigned ValueId) {
auto VGI = ValueIdToCallGraphGUIDMap.find(ValueId);
assert(VGI != ValueIdToCallGraphGUIDMap.end());
return VGI->second;
}
GlobalValueInfo *
-FunctionIndexBitcodeReader::getInfoFromSummaryOffset(uint64_t Offset) {
+ModuleSummaryIndexBitcodeReader::getInfoFromSummaryOffset(uint64_t Offset) {
auto I = SummaryOffsetToInfoMap.find(Offset);
assert(I != SummaryOffsetToInfoMap.end());
return I->second;
@@ -5463,7 +5462,7 @@ FunctionIndexBitcodeReader::getInfoFromSummaryOffset(uint64_t Offset) {
// from global value name to GlobalValueInfo. The global value info contains
// the function block's bitcode offset (if applicable), or the offset into the
// summary section for the combined index.
-std::error_code FunctionIndexBitcodeReader::parseValueSymbolTable(
+std::error_code ModuleSummaryIndexBitcodeReader::parseValueSymbolTable(
uint64_t Offset,
DenseMap<unsigned, GlobalValue::LinkageTypes> &ValueIdToLinkageMap) {
assert(Offset > 0 && "Expected non-zero VST offset");
@@ -5564,7 +5563,7 @@ std::error_code FunctionIndexBitcodeReader::parseValueSymbolTable(
// either the parsed summary information (when parsing summaries
// eagerly), or just to the summary record's offset
// if parsing lazily (IsLazy).
-std::error_code FunctionIndexBitcodeReader::parseModule() {
+std::error_code ModuleSummaryIndexBitcodeReader::parseModule() {
if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
return error("Invalid record");
@@ -5701,7 +5700,7 @@ std::error_code FunctionIndexBitcodeReader::parseModule() {
// Eagerly parse the entire summary block. This populates the GlobalValueSummary
// objects in the index.
-std::error_code FunctionIndexBitcodeReader::parseEntireSummary() {
+std::error_code ModuleSummaryIndexBitcodeReader::parseEntireSummary() {
if (Stream.EnterSubBlock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID))
return error("Invalid record");
@@ -5883,7 +5882,7 @@ std::error_code FunctionIndexBitcodeReader::parseEntireSummary() {
// Parse the module string table block into the Index.
// This populates the ModulePathStringTable map in the index.
-std::error_code FunctionIndexBitcodeReader::parseModuleStringTable() {
+std::error_code ModuleSummaryIndexBitcodeReader::parseModuleStringTable() {
if (Stream.EnterSubBlock(bitc::MODULE_STRTAB_BLOCK_ID))
return error("Invalid record");
@@ -5924,8 +5923,8 @@ std::error_code FunctionIndexBitcodeReader::parseModuleStringTable() {
}
// Parse the function info index from the bitcode streamer into the given index.
-std::error_code FunctionIndexBitcodeReader::parseSummaryIndexInto(
- std::unique_ptr<DataStreamer> Streamer, FunctionInfoIndex *I) {
+std::error_code ModuleSummaryIndexBitcodeReader::parseSummaryIndexInto(
+ std::unique_ptr<DataStreamer> Streamer, ModuleSummaryIndex *I) {
TheIndex = I;
if (std::error_code EC = initStream(std::move(Streamer)))
@@ -5959,14 +5958,14 @@ std::error_code FunctionIndexBitcodeReader::parseSummaryIndexInto(
}
}
-// Parse the function information at the given offset in the buffer into
-// the index. Used to support lazy parsing of function summaries from the
+// Parse the summary information at the given offset in the buffer into
+// the index. Used to support lazy parsing of summaries from the
// combined index during importing.
// TODO: This function is not yet complete as it won't have a consumer
// until ThinLTO function importing is added.
-std::error_code FunctionIndexBitcodeReader::parseFunctionSummary(
- std::unique_ptr<DataStreamer> Streamer, FunctionInfoIndex *I,
- size_t FunctionSummaryOffset) {
+std::error_code ModuleSummaryIndexBitcodeReader::parseGlobalValueSummary(
+ std::unique_ptr<DataStreamer> Streamer, ModuleSummaryIndex *I,
+ size_t SummaryOffset) {
TheIndex = I;
if (std::error_code EC = initStream(std::move(Streamer)))
@@ -5976,7 +5975,7 @@ std::error_code FunctionIndexBitcodeReader::parseFunctionSummary(
if (!hasValidBitcodeHeader(Stream))
return error("Invalid bitcode signature");
- Stream.JumpToBit(FunctionSummaryOffset);
+ Stream.JumpToBit(SummaryOffset);
BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
@@ -6002,14 +6001,14 @@ std::error_code FunctionIndexBitcodeReader::parseFunctionSummary(
return std::error_code();
}
-std::error_code
-FunctionIndexBitcodeReader::initStream(std::unique_ptr<DataStreamer> Streamer) {
+std::error_code ModuleSummaryIndexBitcodeReader::initStream(
+ std::unique_ptr<DataStreamer> Streamer) {
if (Streamer)
return initLazyStream(std::move(Streamer));
return initStreamFromBuffer();
}
-std::error_code FunctionIndexBitcodeReader::initStreamFromBuffer() {
+std::error_code ModuleSummaryIndexBitcodeReader::initStreamFromBuffer() {
const unsigned char *BufPtr = (const unsigned char *)Buffer->getBufferStart();
const unsigned char *BufEnd = BufPtr + Buffer->getBufferSize();
@@ -6028,7 +6027,7 @@ std::error_code FunctionIndexBitcodeReader::initStreamFromBuffer() {
return std::error_code();
}
-std::error_code FunctionIndexBitcodeReader::initLazyStream(
+std::error_code ModuleSummaryIndexBitcodeReader::initLazyStream(
std::unique_ptr<DataStreamer> Streamer) {
// Check and strip off the bitcode wrapper; BitstreamReader expects never to
// see it.
@@ -6187,14 +6186,14 @@ std::string llvm::getBitcodeProducerString(MemoryBufferRef Buffer,
// the index. Otherwise skip the function summary section, and only create
// an index object with a map from function name to function summary offset.
// The index is used to perform lazy function summary reading later.
-ErrorOr<std::unique_ptr<FunctionInfoIndex>>
-llvm::getFunctionInfoIndex(MemoryBufferRef Buffer,
- DiagnosticHandlerFunction DiagnosticHandler,
- bool IsLazy) {
+ErrorOr<std::unique_ptr<ModuleSummaryIndex>>
+llvm::getModuleSummaryIndex(MemoryBufferRef Buffer,
+ DiagnosticHandlerFunction DiagnosticHandler,
+ bool IsLazy) {
std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);
- FunctionIndexBitcodeReader R(Buf.get(), DiagnosticHandler, IsLazy);
+ ModuleSummaryIndexBitcodeReader R(Buf.get(), DiagnosticHandler, IsLazy);
- auto Index = llvm::make_unique<FunctionInfoIndex>();
+ auto Index = llvm::make_unique<ModuleSummaryIndex>();
auto cleanupOnError = [&](std::error_code EC) {
R.releaseBuffer(); // Never take ownership on error.
@@ -6204,7 +6203,7 @@ llvm::getFunctionInfoIndex(MemoryBufferRef Buffer,
if (std::error_code EC = R.parseSummaryIndexInto(nullptr, Index.get()))
return cleanupOnError(EC);
- Buf.release(); // The FunctionIndexBitcodeReader owns it now.
+ Buf.release(); // The ModuleSummaryIndexBitcodeReader owns it now.
return std::move(Index);
}
@@ -6212,7 +6211,7 @@ llvm::getFunctionInfoIndex(MemoryBufferRef Buffer,
bool llvm::hasGlobalValueSummary(MemoryBufferRef Buffer,
DiagnosticHandlerFunction DiagnosticHandler) {
std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);
- FunctionIndexBitcodeReader R(Buf.get(), DiagnosticHandler, false, true);
+ ModuleSummaryIndexBitcodeReader R(Buf.get(), DiagnosticHandler, false, true);
auto cleanupOnError = [&](std::error_code EC) {
R.releaseBuffer(); // Never take ownership on error.
@@ -6222,38 +6221,38 @@ bool llvm::hasGlobalValueSummary(MemoryBufferRef Buffer,
if (std::error_code EC = R.parseSummaryIndexInto(nullptr, nullptr))
return cleanupOnError(EC);
- Buf.release(); // The FunctionIndexBitcodeReader owns it now.
+ Buf.release(); // The ModuleSummaryIndexBitcodeReader owns it now.
return R.foundGlobalValSummary();
}
-// This method supports lazy reading of function summary data from the combined
+// This method supports lazy reading of summary data from the combined
// index during ThinLTO function importing. When reading the combined index
-// file, getFunctionInfoIndex is first invoked with IsLazy=true.
-// Then this method is called for each function considered for importing,
-// to parse the summary information for the given function name into
+// file, getModuleSummaryIndex is first invoked with IsLazy=true.
+// Then this method is called for each value considered for importing,
+// to parse the summary information for the given value name into
// the index.
-std::error_code llvm::readFunctionSummary(
+std::error_code llvm::readGlobalValueSummary(
MemoryBufferRef Buffer, DiagnosticHandlerFunction DiagnosticHandler,
- StringRef FunctionName, std::unique_ptr<FunctionInfoIndex> Index) {
+ StringRef ValueName, std::unique_ptr<ModuleSummaryIndex> Index) {
std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false);
- FunctionIndexBitcodeReader R(Buf.get(), DiagnosticHandler);
+ ModuleSummaryIndexBitcodeReader R(Buf.get(), DiagnosticHandler);
auto cleanupOnError = [&](std::error_code EC) {
R.releaseBuffer(); // Never take ownership on error.
return EC;
};
- // Lookup the given function name in the FunctionMap, which may
- // contain a list of function infos in the case of a COMDAT. Walk through
- // and parse each function summary info at the function summary offset
+ // Lookup the given value name in the GlobalValueMap, which may
+ // contain a list of global value infos in the case of a COMDAT. Walk through
+ // and parse each summary info at the summary offset
// recorded when parsing the value symbol table.
- for (const auto &FI : Index->getGlobalValueInfoList(FunctionName)) {
- size_t FunctionSummaryOffset = FI->bitcodeIndex();
+ for (const auto &FI : Index->getGlobalValueInfoList(ValueName)) {
+ size_t SummaryOffset = FI->bitcodeIndex();
if (std::error_code EC =
- R.parseFunctionSummary(nullptr, Index.get(), FunctionSummaryOffset))
+ R.parseGlobalValueSummary(nullptr, Index.get(), SummaryOffset))
return cleanupOnError(EC);
}
- Buf.release(); // The FunctionIndexBitcodeReader owns it now.
+ Buf.release(); // The ModuleSummaryIndexBitcodeReader owns it now.
return std::error_code();
}
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
index 2e13958fdb1..de5aa73bd6d 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -2245,7 +2245,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
}
/// Emit names for globals/functions etc. The VSTOffsetPlaceholder,
-/// BitcodeStartBit and FunctionIndex are only passed for the module-level
+/// BitcodeStartBit and ModuleSummaryIndex are only passed for the module-level
/// VST, where we are including a function bitcode index and need to
/// backpatch the VST forward declaration record.
static void WriteValueSymbolTable(
@@ -2347,7 +2347,6 @@ static void WriteValueSymbolTable(
// Save the word offset of the function (from the start of the
// actual bitcode written to the stream).
- assert(FunctionIndex->count(F) == 1);
uint64_t BitcodeIndex =
(*FunctionIndex)[F]->bitcodeIndex() - BitcodeStartBit;
assert((BitcodeIndex & 31) == 0 && "function block not 32-bit aligned");
@@ -2380,7 +2379,7 @@ static void WriteValueSymbolTable(
/// Emit function names and summary offsets for the combined index
/// used by ThinLTO.
static void
-WriteCombinedValueSymbolTable(const FunctionInfoIndex &Index,
+WriteCombinedValueSymbolTable(const ModuleSummaryIndex &Index,
BitstreamWriter &Stream,
std::map<uint64_t, unsigned> &GUIDToValueIdMap,
uint64_t VSTOffsetPlaceholder) {
@@ -2810,7 +2809,7 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) {
/// Write the module path strings, currently only used when generating
/// a combined index file.
-static void WriteModStrings(const FunctionInfoIndex &I,
+static void WriteModStrings(const ModuleSummaryIndex &I,
BitstreamWriter &Stream) {
Stream.EnterSubblock(bitc::MODULE_STRTAB_BLOCK_ID, 3);
@@ -3011,10 +3010,9 @@ static void WritePerModuleGlobalValueSummary(
Stream.ExitBlock();
}
-/// Emit the combined function summary section into the combined index
-/// file.
+/// Emit the combined summary section into the combined index file.
static void WriteCombinedGlobalValueSummary(
- const FunctionInfoIndex &I, BitstreamWriter &Stream,
+ const ModuleSummaryIndex &I, BitstreamWriter &Stream,
std::map<uint64_t, unsigned> &GUIDToValueIdMap, unsigned GlobalValueId) {
Stream.EnterSubblock(bitc::GLOBALVAL_SUMMARY_BLOCK_ID, 3);
@@ -3354,7 +3352,7 @@ void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out,
// Write the specified module summary index to the given raw output stream,
// where it will be written in a new bitcode block. This is used when
// writing the combined index file for ThinLTO.
-void llvm::WriteIndexToFile(const FunctionInfoIndex &Index, raw_ostream &Out) {
+void llvm::WriteIndexToFile(const ModuleSummaryIndex &Index, raw_ostream &Out) {
SmallVector<char, 0> Buffer;
Buffer.reserve(256 * 1024);
diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp
index 24de99a34d3..85b9bd83c13 100644
--- a/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp
+++ b/llvm/lib/Bitcode/Writer/BitcodeWriterPass.cpp
@@ -19,7 +19,7 @@
using namespace llvm;
PreservedAnalyses BitcodeWriterPass::run(Module &M) {
- WriteBitcodeToFile(&M, OS, ShouldPreserveUseListOrder, EmitFunctionSummary);
+ WriteBitcodeToFile(&M, OS, ShouldPreserveUseListOrder, EmitSummaryIndex);
return PreservedAnalyses::all();
}
@@ -27,21 +27,20 @@ namespace {
class WriteBitcodePass : public ModulePass {
raw_ostream &OS; // raw_ostream to print on
bool ShouldPreserveUseListOrder;
- bool EmitFunctionSummary;
+ bool EmitSummaryIndex;
public:
static char ID; // Pass identification, replacement for typeid
explicit WriteBitcodePass(raw_ostream &o, bool ShouldPreserveUseListOrder,
- bool EmitFunctionSummary)
+ bool EmitSummaryIndex)
: ModulePass(ID), OS(o),
ShouldPreserveUseListOrder(ShouldPreserveUseListOrder),
- EmitFunctionSummary(EmitFunctionSummary) {}
+ EmitSummaryIndex(EmitSummaryIndex) {}
const char *getPassName() const override { return "Bitcode Writer"; }
bool runOnModule(Module &M) override {
- WriteBitcodeToFile(&M, OS, ShouldPreserveUseListOrder,
- EmitFunctionSummary);
+ WriteBitcodeToFile(&M, OS, ShouldPreserveUseListOrder, EmitSummaryIndex);
return false;
}
};
@@ -51,7 +50,7 @@ char WriteBitcodePass::ID = 0;
ModulePass *llvm::createBitcodeWriterPass(raw_ostream &Str,
bool ShouldPreserveUseListOrder,
- bool EmitFunctionSummary) {
+ bool EmitSummaryIndex) {
return new WriteBitcodePass(Str, ShouldPreserveUseListOrder,
- EmitFunctionSummary);
+ EmitSummaryIndex);
}
OpenPOWER on IntegriCloud