[llvm] [LoopIdiom] Update MemorySSA when optimizing CRC with lookup table (PR #213054)

Sean Clarke via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 30 08:54:41 PDT 2026


https://github.com/xarkenz created https://github.com/llvm/llvm-project/pull/213054

Although the lookup table optimization of CRC loops inserts a `load` instruction, MemorySSA is not properly updated, and is oblivious to the new memory access. Insert a memory use immediately after creating the `load` instruction, and verify MemorySSA at the end of the optimization if applicable.

>From e6955fd4dae2bddfcd90e0e5c1b1e4454bdd4418 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Thu, 30 Jul 2026 10:32:51 -0500
Subject: [PATCH 1/2] Add baseline test

---
 .../cyclic-redundancy-check-memoryssa.ll      | 29 +++++++++++++++++++
 1 file changed, 29 insertions(+)
 create mode 100644 llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check-memoryssa.ll

diff --git a/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check-memoryssa.ll b/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check-memoryssa.ll
new file mode 100644
index 0000000000000..d54f96accd37c
--- /dev/null
+++ b/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check-memoryssa.ll
@@ -0,0 +1,29 @@
+; RUN: opt -passes='loop-mssa(loop-idiom),print<memoryssa>' -disable-output %s 2>&1 | FileCheck %s
+
+define i16 @crc16.le.tc8(i8 %msg, i16 %checksum) {
+; CHECK-LABEL: MemorySSA for function: crc16.le.tc8
+; CHECK:         %tbl.ptradd = getelementptr inbounds i16, ptr @.crctable, i64 %indexer.ext
+; CHECK-NEXT:    %tbl.ld = load i16, ptr %tbl.ptradd, align 2
+;
+entry:
+  br label %loop
+
+loop:                                             ; preds = %loop, %entry
+  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
+  %crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ]
+  %data = phi i8 [ %msg, %entry ], [ %data.next, %loop ]
+  %crc.cast = trunc i16 %crc to i8
+  %xor.crc.data = xor i8 %crc.cast, %data
+  %and.crc.data = and i8 %xor.crc.data, 1
+  %data.next = lshr i8 %data, 1
+  %check.sb = icmp eq i8 %and.crc.data, 0
+  %crc.shift = lshr i16 %crc, 1
+  %crc.xor = xor i16 %crc.shift, -24575
+  %crc.next = select i1 %check.sb, i16 %crc.shift, i16 %crc.xor
+  %iv.next = add nuw nsw i32 %iv, 1
+  %exit.cond = icmp samesign ult i32 %iv, 7
+  br i1 %exit.cond, label %loop, label %exit
+
+exit:                                             ; preds = %loop
+  ret i16 %crc.next
+}

>From 699ea1ef5bd85d1a3ccd59db4db558a05ce383f4 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Thu, 30 Jul 2026 10:50:24 -0500
Subject: [PATCH 2/2] Update MemorySSA when optimizing CRC with table

---
 llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp    | 12 +++++++++++-
 .../LoopIdiom/cyclic-redundancy-check-memoryssa.ll   |  1 +
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index 7dc303149aaa6..f6bdc65bb3bb3 100644
--- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -1870,7 +1870,15 @@ void LoopIdiomRecognize::optimizeCRCLoopUsingTableLookup(
     // CRCTableLd = CRCTable[(iv'th byte of data) ^ (top|bottom) byte of CRC].
     Value *CRCTableGEP =
         Builder.CreateInBoundsGEP(CRCTy, GV, Indexer, "tbl.ptradd");
-    Value *CRCTableLd = Builder.CreateLoad(CRCTy, CRCTableGEP, "tbl.ld");
+    Instruction *CRCTableLd = Builder.CreateLoad(CRCTy, CRCTableGEP, "tbl.ld");
+
+    // Update MemorySSA since we just created a new load instruction.
+    if (MSSAU) {
+      auto *NewMemAcc = MSSAU->createMemoryAccessInBB(
+          CRCTableLd, /*Definition=*/nullptr, CRCTableLd->getParent(),
+          MemorySSA::Beginning);
+      MSSAU->insertUse(cast<MemoryUse>(NewMemAcc), /*RenameUses=*/true);
+    }
 
     // CRCNext = (CRC (<<|>>) 8) ^ CRCTableLd, or simply CRCTableLd in case of
     // CRC-8.
@@ -1893,6 +1901,8 @@ void LoopIdiomRecognize::optimizeCRCLoopUsingTableLookup(
     for (PHINode *PN : Cleanup)
       RecursivelyDeleteDeadPHINode(PN);
     SE->forgetLoop(CurLoop);
+    if (MSSAU && VerifyMemorySSA)
+      MSSAU->getMemorySSA()->verifyMemorySSA();
   }
 }
 
diff --git a/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check-memoryssa.ll b/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check-memoryssa.ll
index d54f96accd37c..a4beaad330dfc 100644
--- a/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check-memoryssa.ll
+++ b/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check-memoryssa.ll
@@ -3,6 +3,7 @@
 define i16 @crc16.le.tc8(i8 %msg, i16 %checksum) {
 ; CHECK-LABEL: MemorySSA for function: crc16.le.tc8
 ; CHECK:         %tbl.ptradd = getelementptr inbounds i16, ptr @.crctable, i64 %indexer.ext
+; CHECK-NEXT:  ; MemoryUse({{.*}})
 ; CHECK-NEXT:    %tbl.ld = load i16, ptr %tbl.ptradd, align 2
 ;
 entry:



More information about the llvm-commits mailing list