[llvm] [RISCV] Do not commute with shift if we might break a qc.shladd pattern (PR #155367)

Sudharsan Veeravalli via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 27 03:08:56 PDT 2025


https://github.com/svs-quic updated https://github.com/llvm/llvm-project/pull/155367

>From 822e13cf4150c0a18e44bdfffd9a435b69407b4f Mon Sep 17 00:00:00 2001
From: Sudharsan Veeravalli <quic_svs at quicinc.com>
Date: Wed, 27 Aug 2025 08:46:44 +0530
Subject: [PATCH 1/2] Pre commit test

---
 llvm/test/CodeGen/RISCV/xqciac.ll | 117 ++++++++++++++++++++++++++++++
 1 file changed, 117 insertions(+)

diff --git a/llvm/test/CodeGen/RISCV/xqciac.ll b/llvm/test/CodeGen/RISCV/xqciac.ll
index 6fdc63fddbc30..ffba5f7febfb7 100644
--- a/llvm/test/CodeGen/RISCV/xqciac.ll
+++ b/llvm/test/CodeGen/RISCV/xqciac.ll
@@ -490,3 +490,120 @@ define i32 @testmuliaddnegimm(i32 %a) {
   %add = add i32 %mul, 3
   ret i32 %add
 }
+
+define i32 @add_shl_OneUse_1(i32 %x) {
+; RV32IM-LABEL: add_shl_OneUse_1:
+; RV32IM:       # %bb.0:
+; RV32IM-NEXT:    ori a1, a0, 1
+; RV32IM-NEXT:    slli a0, a0, 4
+; RV32IM-NEXT:    ori a0, a0, 16
+; RV32IM-NEXT:    add a0, a0, a1
+; RV32IM-NEXT:    ret
+;
+; RV32IMXQCIAC-LABEL: add_shl_OneUse_1:
+; RV32IMXQCIAC:       # %bb.0:
+; RV32IMXQCIAC-NEXT:    ori a1, a0, 1
+; RV32IMXQCIAC-NEXT:    slli a0, a0, 4
+; RV32IMXQCIAC-NEXT:    ori a0, a0, 16
+; RV32IMXQCIAC-NEXT:    add a0, a0, a1
+; RV32IMXQCIAC-NEXT:    ret
+;
+; RV32IZBAMXQCIAC-LABEL: add_shl_OneUse_1:
+; RV32IZBAMXQCIAC:       # %bb.0:
+; RV32IZBAMXQCIAC-NEXT:    ori a1, a0, 1
+; RV32IZBAMXQCIAC-NEXT:    slli a0, a0, 4
+; RV32IZBAMXQCIAC-NEXT:    ori a0, a0, 16
+; RV32IZBAMXQCIAC-NEXT:    add a0, a0, a1
+; RV32IZBAMXQCIAC-NEXT:    ret
+  %or = or i32 %x, 1
+  %mul = shl i32 %or, 4
+  %add = add i32 %mul, %or
+  ret i32 %add
+}
+
+define i32 @add_shl_OneUse_2(i32 %x) {
+; RV32IM-LABEL: add_shl_OneUse_2:
+; RV32IM:       # %bb.0:
+; RV32IM-NEXT:    ori a1, a0, 1
+; RV32IM-NEXT:    slli a0, a0, 10
+; RV32IM-NEXT:    ori a0, a0, 1024
+; RV32IM-NEXT:    add a0, a0, a1
+; RV32IM-NEXT:    ret
+;
+; RV32IMXQCIAC-LABEL: add_shl_OneUse_2:
+; RV32IMXQCIAC:       # %bb.0:
+; RV32IMXQCIAC-NEXT:    ori a1, a0, 1
+; RV32IMXQCIAC-NEXT:    slli a0, a0, 10
+; RV32IMXQCIAC-NEXT:    ori a0, a0, 1024
+; RV32IMXQCIAC-NEXT:    add a0, a0, a1
+; RV32IMXQCIAC-NEXT:    ret
+;
+; RV32IZBAMXQCIAC-LABEL: add_shl_OneUse_2:
+; RV32IZBAMXQCIAC:       # %bb.0:
+; RV32IZBAMXQCIAC-NEXT:    ori a1, a0, 1
+; RV32IZBAMXQCIAC-NEXT:    slli a0, a0, 10
+; RV32IZBAMXQCIAC-NEXT:    ori a0, a0, 1024
+; RV32IZBAMXQCIAC-NEXT:    add a0, a0, a1
+; RV32IZBAMXQCIAC-NEXT:    ret
+  %or = or i32 %x, 1
+  %mul = shl i32 %or, 10
+  %add = add i32 %mul, %or
+  ret i32 %add
+}
+
+; For shifts greater than 10 the ori immediate cannot fit within 12 bits so
+; we don't commute with shift and generate qc.shaldd
+define i32 @add_shl_OneUse_3(i32 %x) {
+; RV32IM-LABEL: add_shl_OneUse_3:
+; RV32IM:       # %bb.0:
+; RV32IM-NEXT:    ori a0, a0, 1
+; RV32IM-NEXT:    slli a1, a0, 11
+; RV32IM-NEXT:    add a0, a1, a0
+; RV32IM-NEXT:    ret
+;
+; RV32IMXQCIAC-LABEL: add_shl_OneUse_3:
+; RV32IMXQCIAC:       # %bb.0:
+; RV32IMXQCIAC-NEXT:    ori a0, a0, 1
+; RV32IMXQCIAC-NEXT:    qc.shladd a0, a0, a0, 11
+; RV32IMXQCIAC-NEXT:    ret
+;
+; RV32IZBAMXQCIAC-LABEL: add_shl_OneUse_3:
+; RV32IZBAMXQCIAC:       # %bb.0:
+; RV32IZBAMXQCIAC-NEXT:    ori a0, a0, 1
+; RV32IZBAMXQCIAC-NEXT:    qc.shladd a0, a0, a0, 11
+; RV32IZBAMXQCIAC-NEXT:    ret
+  %or = or i32 %x, 1
+  %mul = shl i32 %or, 11
+  %add = add i32 %mul, %or
+  ret i32 %add
+}
+
+; The shift left gets converted early and as a result we cannot
+; generate the qc.shladd.
+; FIXME: Should we handle this case and generate qc.shladd if possible?
+define i32 @add_shl_moreOneUse_4(i32 %x) {
+; RV32IM-LABEL: add_shl_moreOneUse_4:
+; RV32IM:       # %bb.0:
+; RV32IM-NEXT:    ori a0, a0, 7
+; RV32IM-NEXT:    lui a1, 524288
+; RV32IM-NEXT:    add a0, a0, a1
+; RV32IM-NEXT:    ret
+;
+; RV32IMXQCIAC-LABEL: add_shl_moreOneUse_4:
+; RV32IMXQCIAC:       # %bb.0:
+; RV32IMXQCIAC-NEXT:    ori a0, a0, 7
+; RV32IMXQCIAC-NEXT:    lui a1, 524288
+; RV32IMXQCIAC-NEXT:    add a0, a0, a1
+; RV32IMXQCIAC-NEXT:    ret
+;
+; RV32IZBAMXQCIAC-LABEL: add_shl_moreOneUse_4:
+; RV32IZBAMXQCIAC:       # %bb.0:
+; RV32IZBAMXQCIAC-NEXT:    ori a0, a0, 7
+; RV32IZBAMXQCIAC-NEXT:    lui a1, 524288
+; RV32IZBAMXQCIAC-NEXT:    add a0, a0, a1
+; RV32IZBAMXQCIAC-NEXT:    ret
+  %or = or i32 %x, 7
+  %mul = shl i32 %or, 31
+  %add = add i32 %mul, %or
+  ret i32 %add
+}

>From bcf3bf3f740089a85a840d5a85c867d7b2f9937b Mon Sep 17 00:00:00 2001
From: Sudharsan Veeravalli <quic_svs at quicinc.com>
Date: Wed, 27 Aug 2025 08:48:04 +0530
Subject: [PATCH 2/2] Don't commute with shift

---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 11 +++++++---
 llvm/test/CodeGen/RISCV/xqciac.ll           | 24 +++++++--------------
 2 files changed, 16 insertions(+), 19 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index b84bd1ce0ac50..f636d3006584b 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -21120,9 +21120,14 @@ bool RISCVTargetLowering::isDesirableToCommuteWithShift(
     auto *C1 = dyn_cast<ConstantSDNode>(N0->getOperand(1));
     auto *C2 = dyn_cast<ConstantSDNode>(N->getOperand(1));
 
-    // Bail if we might break a sh{1,2,3}add pattern.
-    if ((Subtarget.hasStdExtZba() || Subtarget.hasVendorXAndesPerf()) && C2 &&
-        C2->getZExtValue() >= 1 && C2->getZExtValue() <= 3 && N->hasOneUse() &&
+    bool IsShXAdd =
+        (Subtarget.hasStdExtZba() || Subtarget.hasVendorXAndesPerf()) && C2 &&
+        C2->getZExtValue() >= 1 && C2->getZExtValue() <= 3;
+    bool IsQCShlAdd = Subtarget.hasVendorXqciac() && C2 &&
+                      C2->getZExtValue() >= 4 && C2->getZExtValue() <= 31;
+
+    // Bail if we might break a sh{1,2,3}add/qc.shladd pattern.
+    if ((IsShXAdd || IsQCShlAdd) && N->hasOneUse() &&
         N->user_begin()->getOpcode() == ISD::ADD &&
         !isUsedByLdSt(*N->user_begin(), nullptr) &&
         !isa<ConstantSDNode>(N->user_begin()->getOperand(1)))
diff --git a/llvm/test/CodeGen/RISCV/xqciac.ll b/llvm/test/CodeGen/RISCV/xqciac.ll
index ffba5f7febfb7..934deb5a0c327 100644
--- a/llvm/test/CodeGen/RISCV/xqciac.ll
+++ b/llvm/test/CodeGen/RISCV/xqciac.ll
@@ -502,18 +502,14 @@ define i32 @add_shl_OneUse_1(i32 %x) {
 ;
 ; RV32IMXQCIAC-LABEL: add_shl_OneUse_1:
 ; RV32IMXQCIAC:       # %bb.0:
-; RV32IMXQCIAC-NEXT:    ori a1, a0, 1
-; RV32IMXQCIAC-NEXT:    slli a0, a0, 4
-; RV32IMXQCIAC-NEXT:    ori a0, a0, 16
-; RV32IMXQCIAC-NEXT:    add a0, a0, a1
+; RV32IMXQCIAC-NEXT:    ori a0, a0, 1
+; RV32IMXQCIAC-NEXT:    qc.shladd a0, a0, a0, 4
 ; RV32IMXQCIAC-NEXT:    ret
 ;
 ; RV32IZBAMXQCIAC-LABEL: add_shl_OneUse_1:
 ; RV32IZBAMXQCIAC:       # %bb.0:
-; RV32IZBAMXQCIAC-NEXT:    ori a1, a0, 1
-; RV32IZBAMXQCIAC-NEXT:    slli a0, a0, 4
-; RV32IZBAMXQCIAC-NEXT:    ori a0, a0, 16
-; RV32IZBAMXQCIAC-NEXT:    add a0, a0, a1
+; RV32IZBAMXQCIAC-NEXT:    ori a0, a0, 1
+; RV32IZBAMXQCIAC-NEXT:    qc.shladd a0, a0, a0, 4
 ; RV32IZBAMXQCIAC-NEXT:    ret
   %or = or i32 %x, 1
   %mul = shl i32 %or, 4
@@ -532,18 +528,14 @@ define i32 @add_shl_OneUse_2(i32 %x) {
 ;
 ; RV32IMXQCIAC-LABEL: add_shl_OneUse_2:
 ; RV32IMXQCIAC:       # %bb.0:
-; RV32IMXQCIAC-NEXT:    ori a1, a0, 1
-; RV32IMXQCIAC-NEXT:    slli a0, a0, 10
-; RV32IMXQCIAC-NEXT:    ori a0, a0, 1024
-; RV32IMXQCIAC-NEXT:    add a0, a0, a1
+; RV32IMXQCIAC-NEXT:    ori a0, a0, 1
+; RV32IMXQCIAC-NEXT:    qc.shladd a0, a0, a0, 10
 ; RV32IMXQCIAC-NEXT:    ret
 ;
 ; RV32IZBAMXQCIAC-LABEL: add_shl_OneUse_2:
 ; RV32IZBAMXQCIAC:       # %bb.0:
-; RV32IZBAMXQCIAC-NEXT:    ori a1, a0, 1
-; RV32IZBAMXQCIAC-NEXT:    slli a0, a0, 10
-; RV32IZBAMXQCIAC-NEXT:    ori a0, a0, 1024
-; RV32IZBAMXQCIAC-NEXT:    add a0, a0, a1
+; RV32IZBAMXQCIAC-NEXT:    ori a0, a0, 1
+; RV32IZBAMXQCIAC-NEXT:    qc.shladd a0, a0, a0, 10
 ; RV32IZBAMXQCIAC-NEXT:    ret
   %or = or i32 %x, 1
   %mul = shl i32 %or, 10



More information about the llvm-commits mailing list