[llvm] [AMDGPU] Fix negative immediate offset for unbuffered smem loads (PR #79553)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 29 04:42:36 PST 2024


================
@@ -2096,21 +2099,53 @@ bool AMDGPUDAGToDAGISel::SelectSMRDBaseOffset(SDValue Addr, SDValue &SBase,
   }
   if (!N0 || !N1)
     return false;
+
+  bool Selected = false;
   if (SelectSMRDOffset(N1, SOffset, Offset, Imm32Only, IsBuffer)) {
     SBase = N0;
-    return true;
-  }
-  if (SelectSMRDOffset(N0, SOffset, Offset, Imm32Only, IsBuffer)) {
+    Selected = true;
+  } else if (SelectSMRDOffset(N0, SOffset, Offset, Imm32Only, IsBuffer)) {
     SBase = N1;
+    Selected = true;
+  }
+
+  if (Selected) {
+    // For unbuffered smem loads, it is illegal and undefined for the Immediate
+    // Offset to be negative if the resulting (Offset + (M0 or SOffset or zero)
+    // is negative. Handle the case where the Immediate Offset is negative and
+    // there is no SOffset.
+    //
+    // FIXME: Also handle M0 or SOffset case?
+    if (Offset && !HasSOffset && !IsBuffer && !IsPrefetch &&
+        Subtarget->hasSignedSMRDImmOffset()) {
+      if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(*Offset)) {
+        if (C->getSExtValue() < 0) {
+          SDLoc SL(SBase);
+          *Offset = CurDAG->getTargetConstant(std::abs(C->getSExtValue()), SL,
+                                              MVT::i32);
+          const SDValue Ops[] = {SBase, *Offset};
+          if (Subtarget->hasScalarAddSub64())
+            SBase = SDValue(
+                CurDAG->getMachineNode(AMDGPU::S_SUB_U64, SL, MVT::i64, Ops),
+                0);
+          else
+            SBase = SDValue(CurDAG->getMachineNode(AMDGPU::S_SUB_U64_PSEUDO, SL,
+                                                   MVT::i64, Ops),
+                            0);
----------------
arsenm wrote:

This can be ternary to select the opcode only

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


More information about the llvm-commits mailing list