[llvm] [SPIR-V] Allow NoUnsignedWrap decoration on OpShiftLeftLogical (PR #206155)

Arseniy Obolenskiy via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 29 05:16:43 PDT 2026


https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/206155

>From d1fafe5f83cd22febf214687d81ef4ef2af219c1 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Fri, 26 Jun 2026 21:03:34 +0200
Subject: [PATCH 1/2] [SPIR-V] Allow NoUnsignedWrap decoration on
 OpShiftLeftLogical

Align the list of supported ops with spirv-val (shl is missing)
---
 llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp                   | 2 ++
 .../SPIRV/extensions/SPV_KHR_no_integer_wrap_decoration.ll | 7 +++++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp
index 1a65e9635d855..386da52e009d7 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp
@@ -196,6 +196,8 @@ bool SPIRVInstrInfo::canUseNUW(const MachineInstr &MI) const {
   case SPIRV::OpISubV:
   case SPIRV::OpIMulS:
   case SPIRV::OpIMulV:
+  case SPIRV::OpShiftLeftLogicalS:
+  case SPIRV::OpShiftLeftLogicalV:
     return true;
   default:
     return false;
diff --git a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_no_integer_wrap_decoration.ll b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_no_integer_wrap_decoration.ll
index 216ca54a8abc9..5e4df6968865d 100644
--- a/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_no_integer_wrap_decoration.ll
+++ b/llvm/test/CodeGen/SPIRV/extensions/SPV_KHR_no_integer_wrap_decoration.ll
@@ -11,6 +11,7 @@
 ; CHECK-DAG: OpDecorate %[[#D:]] NoSignedWrap
 ; CHECK-DAG: OpDecorate %[[#E:]] NoUnsignedWrap
 ; CHECK-DAG: OpDecorate %[[#E]] NoSignedWrap
+; CHECK-DAG: OpDecorate %[[#F:]] NoUnsignedWrap
 
 ; CHECK-NOT: DAG-FENCE
 
@@ -23,7 +24,8 @@ define i32 @no_wrap_test(i32 %a, i32 %b) {
     %c = mul nuw i32 %a, %b
     %d = mul nsw i32 %a, %b
     %e = add nuw nsw i32 %c, %d
-    ret i32 %e
+    %f = shl nuw i32 %e, %b
+    ret i32 %f
 }
 
 ; CHECK:      OpFunction %[[#I32]] None %[[#FN]]
@@ -33,5 +35,6 @@ define i32 @no_wrap_test(i32 %a, i32 %b) {
 ; CHECK:      %[[#C]] = OpIMul %[[#I32]] %[[#A]] %[[#B]]
 ; CHECK:      %[[#D]] = OpIMul %[[#I32]] %[[#A]] %[[#B]]
 ; CHECK:      %[[#E]] = OpIAdd %[[#I32]] %[[#C]] %[[#D]]
-; CHECK:      OpReturnValue %[[#E]]
+; CHECK:      %[[#F]] = OpShiftLeftLogical %[[#I32]] %[[#E]] %[[#B]]
+; CHECK:      OpReturnValue %[[#F]]
 ; CHECK-NEXT: OpFunctionEnd

>From 00538e07e139237d61f277061a7aa0f568f944da Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Mon, 29 Jun 2026 14:16:33 +0200
Subject: [PATCH 2/2] Address review comments

---
 llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp      | 18 +-----------
 llvm/lib/Target/SPIRV/SPIRVInstrInfo.h        |  3 +-
 llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 29 ++++++++++---------
 3 files changed, 17 insertions(+), 33 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp
index 386da52e009d7..ab4719099339a 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.cpp
@@ -171,7 +171,7 @@ bool SPIRVInstrInfo::canUseFastMathFlags(const MachineInstr &MI,
   }
 }
 
-bool SPIRVInstrInfo::canUseNSW(const MachineInstr &MI) const {
+bool SPIRVInstrInfo::canUseIntegerWrapDecoration(const MachineInstr &MI) const {
   switch (MI.getOpcode()) {
   case SPIRV::OpIAddS:
   case SPIRV::OpIAddV:
@@ -188,22 +188,6 @@ bool SPIRVInstrInfo::canUseNSW(const MachineInstr &MI) const {
   }
 }
 
-bool SPIRVInstrInfo::canUseNUW(const MachineInstr &MI) const {
-  switch (MI.getOpcode()) {
-  case SPIRV::OpIAddS:
-  case SPIRV::OpIAddV:
-  case SPIRV::OpISubS:
-  case SPIRV::OpISubV:
-  case SPIRV::OpIMulS:
-  case SPIRV::OpIMulV:
-  case SPIRV::OpShiftLeftLogicalS:
-  case SPIRV::OpShiftLeftLogicalV:
-    return true;
-  default:
-    return false;
-  }
-}
-
 // Analyze the branching code at the end of MBB, returning
 // true if it cannot be understood (e.g. it's a switch dispatch or isn't
 // implemented for a target).  Upon success, this returns false and returns
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.h b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.h
index 5d629283c5da7..87d389e3f58ec 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstrInfo.h
+++ b/llvm/lib/Target/SPIRV/SPIRVInstrInfo.h
@@ -38,8 +38,7 @@ class SPIRVInstrInfo : public SPIRVGenInstrInfo {
   bool isAliasingInstr(const MachineInstr &MI) const;
   bool canUseFastMathFlags(const MachineInstr &MI,
                            bool KHRFloatControls2) const;
-  bool canUseNSW(const MachineInstr &MI) const;
-  bool canUseNUW(const MachineInstr &MI) const;
+  bool canUseIntegerWrapDecoration(const MachineInstr &MI) const;
 
   bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
                      MachineBasicBlock *&FBB,
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index aed16fd785af8..2e87a0195a314 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -2773,20 +2773,21 @@ static void handleMIFlagDecoration(
     MachineInstr &I, const SPIRVSubtarget &ST, const SPIRVInstrInfo &TII,
     SPIRV::RequirementHandler &Reqs, const SPIRVGlobalRegistry *GR,
     SPIRV::FPFastMathDefaultInfoVector &FPFastMathDefaultInfoVec) {
-  if (I.getFlag(MachineInstr::MIFlag::NoSWrap) && TII.canUseNSW(I) &&
-      getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
-                                     SPIRV::Decoration::NoSignedWrap, ST, Reqs)
-          .IsSatisfiable) {
-    buildOpDecorate(I.getOperand(0).getReg(), I, TII,
-                    SPIRV::Decoration::NoSignedWrap, {});
-  }
-  if (I.getFlag(MachineInstr::MIFlag::NoUWrap) && TII.canUseNUW(I) &&
-      getSymbolicOperandRequirements(SPIRV::OperandCategory::DecorationOperand,
-                                     SPIRV::Decoration::NoUnsignedWrap, ST,
-                                     Reqs)
-          .IsSatisfiable) {
-    buildOpDecorate(I.getOperand(0).getReg(), I, TII,
-                    SPIRV::Decoration::NoUnsignedWrap, {});
+  if (TII.canUseIntegerWrapDecoration(I)) {
+    if (I.getFlag(MachineInstr::MIFlag::NoSWrap) &&
+        getSymbolicOperandRequirements(
+            SPIRV::OperandCategory::DecorationOperand,
+            SPIRV::Decoration::NoSignedWrap, ST, Reqs)
+            .IsSatisfiable)
+      buildOpDecorate(I.getOperand(0).getReg(), I, TII,
+                      SPIRV::Decoration::NoSignedWrap, {});
+    if (I.getFlag(MachineInstr::MIFlag::NoUWrap) &&
+        getSymbolicOperandRequirements(
+            SPIRV::OperandCategory::DecorationOperand,
+            SPIRV::Decoration::NoUnsignedWrap, ST, Reqs)
+            .IsSatisfiable)
+      buildOpDecorate(I.getOperand(0).getReg(), I, TII,
+                      SPIRV::Decoration::NoUnsignedWrap, {});
   }
   // In Kernel environments, FPFastMathMode on OpExtInst is valid per core
   // spec. For other instruction types, SPV_KHR_float_controls2 is required.



More information about the llvm-commits mailing list