[PATCH] D80272: [mlir] Support big-endian systems in DenseElementsAttr (multiple word)

Haruki Imai via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 10 19:25:41 PDT 2020


imaihal updated this revision to Diff 270022.
imaihal edited the summary of this revision.
imaihal added a comment.

Reflect reviewer's comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D80272/new/

https://reviews.llvm.org/D80272

Files:
  mlir/lib/IR/Attributes.cpp


Index: mlir/lib/IR/Attributes.cpp
===================================================================
--- mlir/lib/IR/Attributes.cpp
+++ mlir/lib/IR/Attributes.cpp
@@ -17,6 +17,7 @@
 #include "llvm/ADT/Sequence.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/Endian.h"
+#include <tuple>
 
 using namespace mlir;
 using namespace mlir::detail;
@@ -555,25 +556,66 @@
 
 /// Get start position of actual data in `value`. Actual data is
 /// stored in last `bitWidth`/CHAR_BIT bytes in big endian.
-static char *getAPIntDataPos(APInt &value, size_t bitWidth) {
+static char *getAPIntDataPos(APInt &value, size_t bitWidth, size_t wordNum) {
   char *dataPos =
       const_cast<char *>(reinterpret_cast<const char *>(value.getRawData()));
-  if (llvm::support::endian::system_endianness() ==
-      llvm::support::endianness::big)
-    dataPos = dataPos + 8 - llvm::divideCeil(bitWidth, CHAR_BIT);
+  unsigned apintBytesPerWord = APInt::APINT_BITS_PER_WORD / CHAR_BIT;
+
+  dataPos = dataPos + apintBytesPerWord * wordNum -
+            llvm::divideCeil(bitWidth, CHAR_BIT);
   return dataPos;
 }
 
+/// Get parameters for copying APInt in big-endian. `numFilledWords` is the
+/// number of words which filled with 8 bytes(64 bits). `resBits` is the rest of
+/// bit. `filledWordsElements` is the elements of `numFiiledWords`
+static std::tuple<unsigned, unsigned, unsigned>
+getAPIntCopyParam(size_t bitWidth) {
+  unsigned numFilledWords = bitWidth / APInt::APINT_BITS_PER_WORD;
+  unsigned resBits = bitWidth - numFilledWords * APInt::APINT_BITS_PER_WORD;
+  unsigned filledWordsElements =
+      numFilledWords * APInt::APINT_BITS_PER_WORD / CHAR_BIT;
+  return std::forward_as_tuple(numFilledWords, resBits, filledWordsElements);
+}
+
 /// Read APInt `value` from appropriate position.
 static void readAPInt(APInt &value, size_t bitWidth, char *outData) {
-  char *dataPos = getAPIntDataPos(value, bitWidth);
-  std::copy_n(dataPos, llvm::divideCeil(bitWidth, CHAR_BIT), outData);
+  char *dataPos =
+      const_cast<char *>(reinterpret_cast<const char *>(value.getRawData()));
+  if (llvm::support::endian::system_endianness() ==
+      llvm::support::endianness::big) {
+    unsigned numFilledWords, resBits, filledWordsElements;
+    std::tie(numFilledWords, resBits, filledWordsElements) =
+        getAPIntCopyParam(bitWidth);
+    // Read words filled with 8 bytes data
+    std::copy_n(dataPos, filledWordsElements, outData);
+    // Then, read the rest bits from apropriate position in big endian
+    dataPos = getAPIntDataPos(value, resBits, numFilledWords + 1);
+    std::copy_n(dataPos, llvm::divideCeil(resBits, CHAR_BIT),
+                outData + filledWordsElements);
+  } else {
+    std::copy_n(dataPos, llvm::divideCeil(bitWidth, CHAR_BIT), outData);
+  }
 }
 
 /// Write `inData` to appropriate position of APInt `value`.
 static void writeAPInt(const char *inData, size_t bitWidth, APInt &value) {
-  char *dataPos = getAPIntDataPos(value, bitWidth);
-  std::copy_n(inData, llvm::divideCeil(bitWidth, CHAR_BIT), dataPos);
+  char *dataPos =
+      const_cast<char *>(reinterpret_cast<const char *>(value.getRawData()));
+  if (llvm::support::endian::system_endianness() ==
+      llvm::support::endianness::big) {
+    unsigned numFilledWords, resBits, filledWordsElements;
+    std::tie(numFilledWords, resBits, filledWordsElements) =
+        getAPIntCopyParam(bitWidth);
+    // Write words filled with 8 bytes data
+    std::copy_n(inData, filledWordsElements, dataPos);
+    // Then, write the rest bits from apropriate position in big endian
+    dataPos = getAPIntDataPos(value, resBits, numFilledWords + 1);
+    std::copy_n(inData + filledWordsElements,
+                llvm::divideCeil(resBits, CHAR_BIT), dataPos);
+  } else {
+    std::copy_n(inData, llvm::divideCeil(bitWidth, CHAR_BIT), dataPos);
+  }
 }
 
 /// Writes value to the bit position `bitPos` in array `rawData`.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D80272.270022.patch
Type: text/x-patch
Size: 3921 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200611/cdcd0af5/attachment.bin>


More information about the llvm-commits mailing list