[llvm] 6414ae6 - [RISCV] Do not commute with shift if we might break a qc.shladd pattern (#155367)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 27 04:30:43 PDT 2025
Author: Sudharsan Veeravalli
Date: 2025-08-27T17:00:40+05:30
New Revision: 6414ae686b369db59d47d80f6d5a8965af33894e
URL: https://github.com/llvm/llvm-project/commit/6414ae686b369db59d47d80f6d5a8965af33894e
DIFF: https://github.com/llvm/llvm-project/commit/6414ae686b369db59d47d80f6d5a8965af33894e.diff
LOG: [RISCV] Do not commute with shift if we might break a qc.shladd pattern (#155367)
Similar to what we do if might break a `sh{1,2,3}add` pattern.
Added:
Modified:
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/test/CodeGen/RISCV/xqciac.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 6aa86741dcc1d..6adce8877ef50 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -21127,9 +21127,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 6fdc63fddbc30..934deb5a0c327 100644
--- a/llvm/test/CodeGen/RISCV/xqciac.ll
+++ b/llvm/test/CodeGen/RISCV/xqciac.ll
@@ -490,3 +490,112 @@ 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 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 a0, a0, 1
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a0, 4
+; 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 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 a0, a0, 1
+; RV32IZBAMXQCIAC-NEXT: qc.shladd a0, a0, a0, 10
+; 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
+}
More information about the llvm-commits
mailing list