[llvm] [Aarch64] Add missing earlyclobber to sqrshr and uqrshl instructions. (PR #77782)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 11 07:18:06 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-arm

Author: None (AlfieRichardsArm)

<details>
<summary>Changes</summary>

This avoids possible undefined behavior using the same register for Rm and Rda.

Additionally adds a check in MC to produce an error upon parsing this case.

---
Full diff: https://github.com/llvm/llvm-project/pull/77782.diff


4 Files Affected:

- (modified) llvm/lib/Target/ARM/ARMInstrMVE.td (+1-1) 
- (modified) llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (+8) 
- (added) llvm/test/CodeGen/AArch64/sqrshr-uqrshl-unpredictable.ll (+21) 
- (added) llvm/test/MC/AArch64/mve-sqrshr-uqrshl-earlyclobber.s (+6) 


``````````diff
diff --git a/llvm/lib/Target/ARM/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td
index fa25c571a9bd5e..12c3968b9cecea 100644
--- a/llvm/lib/Target/ARM/ARMInstrMVE.td
+++ b/llvm/lib/Target/ARM/ARMInstrMVE.td
@@ -478,7 +478,7 @@ def MVE_URSHR : MVE_ScalarShiftSRegImm<"urshr", 0b01>;
 
 class MVE_ScalarShiftSRegReg<string iname, bits<2> op5_4>
   : MVE_ScalarShiftSingleReg<iname, (ins rGPR:$RdaSrc, rGPR:$Rm),
-                     "$RdaSrc, $Rm", "$RdaDest = $RdaSrc",
+                     "$RdaSrc, $Rm", "@earlyclobber $RdaDest,$RdaDest = $RdaSrc",
                      [(set rGPR:$RdaDest,
                          (i32 (!cast<Intrinsic>("int_arm_mve_" # iname)
                                    (i32 rGPR:$RdaSrc), (i32 rGPR:$Rm))))]> {
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index 18dccb26b87769..7414b5307f704c 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -8308,6 +8308,14 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
       return Error (Operands[3]->getStartLoc(), "Q-register indexes must be 2 and 0 or 3 and 1");
     break;
   }
+  case ARM::MVE_SQRSHR:
+  case ARM::MVE_UQRSHL: {
+    if (Operands[2]->getReg() == Operands[3]->getReg()) {
+      return Error (Operands[2]->getStartLoc(),
+                    "Rda register and Rm register can't be identical");
+    }
+    break;
+  }
   case ARM::UMAAL:
   case ARM::UMLAL:
   case ARM::UMULL:
diff --git a/llvm/test/CodeGen/AArch64/sqrshr-uqrshl-unpredictable.ll b/llvm/test/CodeGen/AArch64/sqrshr-uqrshl-unpredictable.ll
new file mode 100644
index 00000000000000..d393a474dfa63a
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/sqrshr-uqrshl-unpredictable.ll
@@ -0,0 +1,21 @@
+; RUN: llc -mtriple armv8.1m.main -mattr=+mve %s -o - | FileCheck %s
+
+; Check that we don't create an unpredictable sqrshr or uqrshl instruction,
+; e.g. sqrshr r0, r0
+
+declare i32 @llvm.arm.mve.sqrshr(i32, i32) #1
+declare i32 @llvm.arm.mve.uqrshl(i32, i32) #1
+
+define i32 @sqrshr() #0 {
+; CHECK-LABEL: sqrshr
+; CHECK-NOT: sqrshr  r[[REG:[0-9]+]], r[[REG]]
+  %1 = tail call i32 @llvm.arm.mve.sqrshr(i32 1, i32 1)
+  ret i32 %1
+}
+
+define i32 @uqrshl() #0 {
+; CHECK-LABEL: uqrshl
+; CHECK-NOT: uqrshl  r[[REG:[0-9]+]], r[[REG]]
+  %1 = tail call i32 @llvm.arm.mve.uqrshl(i32 1, i32 1)
+  ret i32 %1
+}
diff --git a/llvm/test/MC/AArch64/mve-sqrshr-uqrshl-earlyclobber.s b/llvm/test/MC/AArch64/mve-sqrshr-uqrshl-earlyclobber.s
new file mode 100644
index 00000000000000..3b78b826538f77
--- /dev/null
+++ b/llvm/test/MC/AArch64/mve-sqrshr-uqrshl-earlyclobber.s
@@ -0,0 +1,6 @@
+@ RUN: not llvm-mc -triple armv8.1m.main -mattr=+mve < %s 2>&1 | FileCheck %s
+
+  sqrshr    r1, r1
+@ CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Rda register and Rm register can't be identical
+  uqrshl   r1, r1
+@ CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Rda register and Rm register can't be identical

``````````

</details>


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


More information about the llvm-commits mailing list