[llvm] [WebAssembly] Fold unsigned offset (PR #145829)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 26 09:05:24 PDT 2025


https://github.com/badumbatish updated https://github.com/llvm/llvm-project/pull/145829

>From e1cd7019bde37cb3d6ad3540f4357717a0077c0b Mon Sep 17 00:00:00 2001
From: badumbatish <jjasmine at igalia.com>
Date: Wed, 25 Jun 2025 14:29:56 -0700
Subject: [PATCH 1/2] Precommit test for folding a load of unsigned offset

---
 .../CodeGen/WebAssembly/fold-load-unsigned.ll | 21 +++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 llvm/test/CodeGen/WebAssembly/fold-load-unsigned.ll

diff --git a/llvm/test/CodeGen/WebAssembly/fold-load-unsigned.ll b/llvm/test/CodeGen/WebAssembly/fold-load-unsigned.ll
new file mode 100644
index 0000000000000..18aadb6c0de80
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/fold-load-unsigned.ll
@@ -0,0 +1,21 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -O3 -wasm-keep-registers | FileCheck %s
+target triple = "wasm64"
+
+ at data = hidden local_unnamed_addr global [12 x i8] c"Hello world\00", align 1
+
+define hidden signext i8 @fold_load_unsigned(i32 noundef %idx) local_unnamed_addr {
+; CHECK-LABEL: fold_load_unsigned:
+; CHECK:         .functype fold_load_unsigned (i32) -> (i32)
+; CHECK-NEXT:  # %bb.0: # %entry
+; CHECK-NEXT:    local.get $push4=, 0
+; CHECK-NEXT:    i64.extend_i32_s $push0=, $pop4
+; CHECK-NEXT:    i64.const $push1=, data
+; CHECK-NEXT:    i64.add $push2=, $pop0, $pop1
+; CHECK-NEXT:    i32.load $push3=, 0($pop2):p2align=0
+; CHECK-NEXT:    # fallthrough-return
+entry:
+  %arrayidx = getelementptr inbounds nuw [12 x i8], ptr @data, i32 0, i32 %idx
+  %0 = load i8, ptr %arrayidx, align 1
+  ret i8 %0
+}

>From 9db18a17c7c7841ea320383966b0b92a0fa2de10 Mon Sep 17 00:00:00 2001
From: badumbatish <jjasmine at igalia.com>
Date: Wed, 25 Jun 2025 18:58:55 -0700
Subject: [PATCH 2/2] Attempt to fold no unsigned wrap offset load

---
 .../WebAssembly/WebAssemblyISelLowering.cpp   | 47 +++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index ec77154d17caa..f099df8b815de 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -19,11 +19,14 @@
 #include "WebAssemblyTargetMachine.h"
 #include "WebAssemblyUtilities.h"
 #include "llvm/CodeGen/CallingConvLower.h"
+#include "llvm/CodeGen/ISDOpcodes.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/CodeGen/MachineMemOperand.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/SDPatternMatch.h"
 #include "llvm/CodeGen/SelectionDAG.h"
 #include "llvm/CodeGen/SelectionDAGNodes.h"
 #include "llvm/IR/DiagnosticInfo.h"
@@ -32,10 +35,13 @@
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/IntrinsicsWebAssembly.h"
+#include "llvm/Support/Casting.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/KnownBits.h"
 #include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetOptions.h"
+#include <iostream>
 using namespace llvm;
 
 #define DEBUG_TYPE "wasm-lower"
@@ -178,6 +184,9 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
       for (auto T : {MVT::i32, MVT::i64})
         setOperationAction(Op, T, Custom);
 
+  // Folding adds with global addresses into load offset
+  setTargetDAGCombine(ISD::LOAD);
+
   // SIMD-specific configuration
   if (Subtarget->hasSIMD128()) {
 
@@ -3212,6 +3221,42 @@ static SDValue performTruncateCombine(SDNode *N,
   return truncateVectorWithNARROW(OutVT, In, DL, DAG);
 }
 
+static SDValue performLoadCombine(SDNode *N, SelectionDAG &DAG) {
+  using namespace SDPatternMatch;
+
+  SDLoc DL(N);
+  SDValue Add = N->getOperand(1);
+  SDValue Offset = Add.getOperand(0), Global = Add.getOperand(1);
+
+  // INFO: we're folding this
+  //     t4: i64 = sign_extend t2
+  //     t5: i64 = add nuw t4, GlobalAddress:i64<ptr @data> 0
+  //     t8: i8,ch = load<(load (s8) from %ir.arrayidx)> t0, t5, undef:i64
+  // into this:
+  //     t4: i64 = sign_extend t2
+  //     t8: i8,ch = load<(load (s8) from %ir.arrayidx)> t0,
+  //     GlobalAddress:i64<ptr @data>, t4
+
+  if (Add->getFlags().hasNoUnsignedWrap()) {
+    if (isa<GlobalAddressSDNode>(Global)) {
+      auto *LD = dyn_cast<LoadSDNode>(N);
+      // SDValue SelectionDAG::getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType
+      // ExtType,
+      //                               EVT VT, const SDLoc &dl, SDValue Chain,
+      //                               SDValue Ptr, SDValue Offset, EVT MemVT,
+      //                               MachineMemOperand *MMO) {
+
+      // INFO: Use the above signature for now, the previous getLoad signatuer
+      // automatically creates undef
+      return DAG.getLoad(ISD::MemIndexedMode::PRE_INC,
+                         ISD::LoadExtType::NON_EXTLOAD, LD->getValueType(0), DL,
+                         LD->getChain(), Global, Offset, LD->getValueType(0),
+                         LD->getMemOperand());
+    }
+  }
+  return SDValue();
+}
+
 static SDValue performBitcastCombine(SDNode *N,
                                      TargetLowering::DAGCombinerInfo &DCI) {
   auto &DAG = DCI.DAG;
@@ -3408,6 +3453,8 @@ WebAssemblyTargetLowering::PerformDAGCombine(SDNode *N,
   switch (N->getOpcode()) {
   default:
     return SDValue();
+  case ISD::LOAD:
+    return performLoadCombine(N, DCI.DAG);
   case ISD::BITCAST:
     return performBitcastCombine(N, DCI);
   case ISD::SETCC:



More information about the llvm-commits mailing list