[flang-commits] [flang] [llvm] [flang-rt] Copy out only the modified suffix of an argument temporary (PR #222101)
Eugene Epshteyn via flang-commits
flang-commits at lists.llvm.org
Fri Sep 11 07:19:26 PDT 2026
================
@@ -271,6 +271,165 @@ RT_API_ATTRS void ShallowCopy(const Descriptor &to, const Descriptor &from) {
ShallowCopy(to, from, to.IsContiguous(), from.IsContiguous());
}
+// Compares one element bitwise. As in the ShallowCopy* helpers above, the
+// compile-time element size lets the compiler inline the comparison.
+template <typename P>
+static inline RT_API_ATTRS bool ElementIsModified(
+ const char *toAt, const char *fromAt, std::size_t elementBytes) {
+ constexpr std::size_t typeElementBytes{sizeof(P)};
+ if constexpr (typeElementBytes != 1) {
+ return runtime::memcmp(toAt, fromAt, typeElementBytes) != 0;
+ } else {
+ return runtime::memcmp(toAt, fromAt, elementBytes) != 0;
+ }
+}
+
+template <typename P>
+static inline RT_API_ATTRS void CopyElement(
+ char *toAt, const char *fromAt, std::size_t elementBytes) {
+ constexpr std::size_t typeElementBytes{sizeof(P)};
+ if constexpr (typeElementBytes != 1) {
+ runtime::memcpy(toAt, fromAt, typeElementBytes);
+ } else {
+ runtime::memcpy(toAt, fromAt, elementBytes);
+ }
+}
+
+// Scans for the first bitwise difference; when one is found, copies that
+// element and everything after it, reusing the scan's position (fused, one
+// pass). Elements before the first difference are bitwise-identical and are
+// not stored to, so an unmodified copy-out performs no stores at all, and a
+// copy-out never traverses the data more than once nor stores more elements
+// than the unconditional copy would.
+template <typename P, int RANK = -1>
+static RT_API_ATTRS void ShallowCopyModifiedSuffixInner(const Descriptor &to,
+ const Descriptor &from, bool toIsContiguous, bool fromIsContiguous) {
+ std::size_t elementBytes{to.ElementBytes()};
+ std::size_t n{to.Elements()};
+ if (toIsContiguous) {
+ char *toAt{to.OffsetElement()};
+ if (fromIsContiguous) {
+ const char *fromAt{from.OffsetElement()};
+ for (; n > 0; --n, toAt += elementBytes, fromAt += elementBytes) {
----------------
eugeneepshteyn wrote:
That was benchmarked to be faster for unmodified data, but slower for modified data. The issue is that memcmp loses the position of the first element, so need to memcpy the whole buffer. We really need optimized memcmp equivalent that returns the location of the first non-equal element.
We could possibly chunk the buffer into larger chunks for comparison and use memcmp on each chunk.
https://github.com/llvm/llvm-project/pull/222101
More information about the flang-commits
mailing list