[llvm] [SPIRV] Sign-extend operands of sign-sensitive ops on sub-pow2 widths (PR #203661)

Faijul Amin via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 11 10:45:27 PDT 2026


================
@@ -564,6 +565,83 @@ generateAssignInstrs(MachineFunction &MF, SPIRVGlobalRegistry *GR,
     }
     for (MachineInstr *MI : TruncToRemove)
       MI->eraseFromParent();
+
+    // The widening loop below only retypes registers, so sign-sensitive ops
+    // (G_ASHR, G_SDIV, G_SREM, signed G_ICMP) on sub-pow2 widths see the sign
+    // bit at the wrong position. Emit G_SEXT_INREG; the legalizer lowers it.
+    // TODO: handle vector operands.
+    auto IsSignSensitive = [](const MachineInstr &MI) {
+      switch (MI.getOpcode()) {
+      case TargetOpcode::G_ASHR:
+      case TargetOpcode::G_SDIV:
+      case TargetOpcode::G_SREM:
+        return true;
+      case TargetOpcode::G_ICMP:
+        return CmpInst::isSigned(
+            static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate()));
+      default:
+        return false;
+      }
+    };
+
+    // Per-Reg original width: once we retype a Reg to its widened width,
+    // a later visit can no longer infer the narrow width from MRI. Record
+    // it on first visit so subsequent visits still know to sign-extend.
+    DenseMap<Register, unsigned> OrigWidth;
+    // Per-MI cache so the same vreg used as both operands of a single MI
+    // (e.g. G_ICMP slt %x, %x) gets one shared sext, not two — and so the
+    // second operand isn't left referring to the un-extended Reg after the
+    // first call retypes it.
+    DenseMap<Register, Register> SExtedThisMI;
----------------
mdfaijul wrote:

Yes, it was an overkill. Removed this cache. Reused sign-extended vreg in the refactored code.

https://github.com/llvm/llvm-project/pull/203661


More information about the llvm-commits mailing list