[llvm] 4458ba8 - [RISCV][GISel] Select G_SELECT (G_ICMP, A, B) (#68247)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 23 07:07:20 PDT 2023
Author: Michael Maitland
Date: 2023-10-23T10:07:15-04:00
New Revision: 4458ba8cef1c3dcc3c9006f5292e3a276007b33f
URL: https://github.com/llvm/llvm-project/commit/4458ba8cef1c3dcc3c9006f5292e3a276007b33f
DIFF: https://github.com/llvm/llvm-project/commit/4458ba8cef1c3dcc3c9006f5292e3a276007b33f.diff
LOG: [RISCV][GISel] Select G_SELECT (G_ICMP, A, B) (#68247)
If MI is a G_SELECT(G_ICMP(tst, A, B), C, D) then we can use (A, B, tst)
as the (LHS, RHS, CC) of the Select_GPR_Using_CC_GPR.
Added:
Modified:
llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/select-rv32.mir
llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/select-rv64.mir
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index ab2125a3615f385..a7f18c04a190790 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -26,6 +26,7 @@
#define DEBUG_TYPE "riscv-isel"
using namespace llvm;
+using namespace MIPatternMatch;
#define GET_GLOBALISEL_PREDICATE_BITSET
#include "RISCVGenGlobalISel.inc"
@@ -83,6 +84,13 @@ class RISCVInstructionSelector : public InstructionSelector {
void renderImm(MachineInstrBuilder &MIB, const MachineInstr &MI,
int OpIdx) const;
+ /// Sets CC, LHS, and RHS so that they form an equivelent G_ICMP (ICMPCC, LHS,
+ /// RHS) to that of MI, but whose condition code matches one of the
+ /// comparisons supported directly by branches in the RISC-V ISA.
+ void getICMPOperandsForBranch(MachineInstr &MI, MachineIRBuilder &MIB,
+ MachineRegisterInfo &MRI, RISCVCC::CondCode &CC,
+ Register &LHS, Register &RHS) const;
+
const RISCVSubtarget &STI;
const RISCVInstrInfo &TII;
const RISCVRegisterInfo &TRI;
@@ -498,21 +506,111 @@ bool RISCVInstructionSelector::selectSExtInreg(MachineInstr &MI,
return true;
}
+/// Returns the RISCVCC::CondCode that corresponds to the CmpInst::Predicate CC.
+/// CC Must be an ICMP Predicate.
+static RISCVCC::CondCode getRISCVCCFromICMP(CmpInst::Predicate CC) {
+ switch (CC) {
+ default:
+ llvm_unreachable("Expected ICMP CmpInst::Predicate.");
+ case CmpInst::Predicate::ICMP_EQ:
+ return RISCVCC::COND_EQ;
+ case CmpInst::Predicate::ICMP_NE:
+ return RISCVCC::COND_NE;
+ case CmpInst::Predicate::ICMP_ULT:
+ return RISCVCC::COND_LTU;
+ case CmpInst::Predicate::ICMP_SLT:
+ return RISCVCC::COND_LT;
+ case CmpInst::Predicate::ICMP_UGE:
+ return RISCVCC::COND_GEU;
+ case CmpInst::Predicate::ICMP_SGE:
+ return RISCVCC::COND_GE;
+ }
+}
+
+void RISCVInstructionSelector::getICMPOperandsForBranch(
+ MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI,
+ RISCVCC::CondCode &CC, Register &LHS, Register &RHS) const {
+ assert(MI.getOpcode() == TargetOpcode::G_ICMP);
+ CmpInst::Predicate ICMPCC =
+ static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
+ LHS = MI.getOperand(2).getReg();
+ RHS = MI.getOperand(3).getReg();
+
+ // Adjust comparisons to use comparison with 0 if possible.
+ if (auto Constant = getIConstantVRegSExtVal(RHS, MRI, true)) {
+ switch (ICMPCC) {
+ case CmpInst::Predicate::ICMP_SGT:
+ // Convert X > -1 to X >= 0
+ if (*Constant == -1) {
+ MachineInstr *Zero = MIB.buildConstant(MRI.getType(RHS), 0);
+ selectConstant(*Zero, MIB, MRI);
+ CC = RISCVCC::COND_GE;
+ RHS = Zero->getOperand(0).getReg();
+ return;
+ }
+ break;
+ case CmpInst::Predicate::ICMP_SLT:
+ // Convert X < 1 to 0 >= X
+ if (*Constant == 1) {
+ MachineInstr *Zero = MIB.buildConstant(MRI.getType(RHS), 0);
+ selectConstant(*Zero, MIB, MRI);
+ CC = RISCVCC::COND_GE;
+ RHS = LHS;
+ LHS = Zero->getOperand(0).getReg();
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ switch (ICMPCC) {
+ default:
+ llvm_unreachable("Expected ICMP CmpInst::Predicate.");
+ case CmpInst::Predicate::ICMP_EQ:
+ case CmpInst::Predicate::ICMP_NE:
+ case CmpInst::Predicate::ICMP_ULT:
+ case CmpInst::Predicate::ICMP_SLT:
+ case CmpInst::Predicate::ICMP_UGE:
+ case CmpInst::Predicate::ICMP_SGE:
+ // These CCs are supported directly by RISC-V branches.
+ CC = getRISCVCCFromICMP(ICMPCC);
+ return;
+ case CmpInst::Predicate::ICMP_SGT:
+ case CmpInst::Predicate::ICMP_SLE:
+ case CmpInst::Predicate::ICMP_UGT:
+ case CmpInst::Predicate::ICMP_ULE:
+ // These CCs are not supported directly by RISC-V branches, but changing the
+ // direction of the CC and swapping LHS and RHS are.
+ CC = getRISCVCCFromICMP(CmpInst::getSwappedPredicate(ICMPCC));
+ std::swap(LHS, RHS);
+ return;
+ }
+}
+
bool RISCVInstructionSelector::selectSelect(MachineInstr &MI,
MachineIRBuilder &MIB,
MachineRegisterInfo &MRI) const {
- // TODO: Currently we check that the conditional code passed to G_SELECT is
- // not equal to zero; however, in the future, we might want to try and check
- // if the conditional code comes from a G_ICMP. If it does, we can directly
- // use G_ICMP to get the first three input operands of the
- // Select_GPR_Using_CC_GPR. This might be done here, or in the appropriate
- // combiner.
assert(MI.getOpcode() == TargetOpcode::G_SELECT);
+
+ // If MI is a G_SELECT(G_ICMP(tst, A, B), C, D) then we can use (A, B, tst)
+ // as the (LHS, RHS, CC) of the Select_GPR_Using_CC_GPR.
+ Register MIOp1Reg = MI.getOperand(1).getReg();
+ bool Op1IsICMP = mi_match(MIOp1Reg, MRI, m_GICmp(m_Pred(), m_Reg(), m_Reg()));
+ RISCVCC::CondCode CC;
+ Register LHS, RHS;
+ if (Op1IsICMP)
+ getICMPOperandsForBranch(*MRI.getVRegDef(MIOp1Reg), MIB, MRI, CC, LHS, RHS);
+
+ Register Op1 = Op1IsICMP ? LHS : MI.getOperand(1).getReg();
+ Register Op2 = Op1IsICMP ? RHS : RISCV::X0;
+ unsigned Op3 = Op1IsICMP ? CC : RISCVCC::COND_NE;
MachineInstr *Result = MIB.buildInstr(RISCV::Select_GPR_Using_CC_GPR)
.addDef(MI.getOperand(0).getReg())
- .addReg(MI.getOperand(1).getReg())
- .addReg(RISCV::X0)
- .addImm(RISCVCC::COND_NE)
+ .addReg(Op1)
+ .addReg(Op2)
+ .addImm(Op3)
.addReg(MI.getOperand(2).getReg())
.addReg(MI.getOperand(3).getReg());
MI.eraseFromParent();
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/select-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/select-rv32.mir
index 828835dac8f80ca..b9bd9b980e2e475 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/select-rv32.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/select-rv32.mir
@@ -53,3 +53,125 @@ body: |
PseudoRET implicit $x10
...
+---
+name: select_icmp_ult
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10, $x11, $x12, $x13, $x14
+
+ ; CHECK-LABEL: name: select_icmp_ult
+ ; CHECK: liveins: $x10, $x11, $x12, $x13, $x14
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x12
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr = COPY $x13
+ ; CHECK-NEXT: [[Select_GPR_Using_CC_GPR:%[0-9]+]]:gpr = Select_GPR_Using_CC_GPR [[COPY2]], [[COPY3]], 4, [[COPY]], [[COPY1]]
+ ; CHECK-NEXT: $x10 = COPY [[Select_GPR_Using_CC_GPR]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:gprb(s32) = COPY $x10
+ %1:gprb(s32) = COPY $x11
+ %2:gprb(s32) = COPY $x12
+ %3:gprb(s32) = COPY $x13
+ %4:gprb(s32) = COPY $x14
+ %5:gprb(s32) = G_ICMP intpred(ult), %2, %3
+ %6:gprb(s32) = G_SELECT %5, %0, %1
+ $x10 = COPY %6(s32)
+ PseudoRET implicit $x10
+
+...
+---
+name: select_icmp_ugt
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10, $x11, $x12, $x13, $x14
+
+ ; CHECK-LABEL: name: select_icmp_ugt
+ ; CHECK: liveins: $x10, $x11, $x12, $x13, $x14
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x12
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr = COPY $x13
+ ; CHECK-NEXT: [[Select_GPR_Using_CC_GPR:%[0-9]+]]:gpr = Select_GPR_Using_CC_GPR [[COPY3]], [[COPY2]], 4, [[COPY]], [[COPY1]]
+ ; CHECK-NEXT: $x10 = COPY [[Select_GPR_Using_CC_GPR]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:gprb(s32) = COPY $x10
+ %1:gprb(s32) = COPY $x11
+ %2:gprb(s32) = COPY $x12
+ %3:gprb(s32) = COPY $x13
+ %4:gprb(s32) = COPY $x14
+ %5:gprb(s32) = G_ICMP intpred(ugt), %2, %3
+ %6:gprb(s32) = G_SELECT %5, %0, %1
+ $x10 = COPY %6(s32)
+ PseudoRET implicit $x10
+
+...
+---
+name: select_icmp_sgtneg1
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10, $x11, $x12, $x13, $x14
+
+ ; CHECK-LABEL: name: select_icmp_sgtneg1
+ ; CHECK: liveins: $x10, $x11, $x12, $x13, $x14
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x12
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr = COPY $x0
+ ; CHECK-NEXT: [[Select_GPR_Using_CC_GPR:%[0-9]+]]:gpr = Select_GPR_Using_CC_GPR [[COPY2]], [[COPY3]], 3, [[COPY]], [[COPY1]]
+ ; CHECK-NEXT: $x10 = COPY [[Select_GPR_Using_CC_GPR]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:gprb(s32) = COPY $x10
+ %1:gprb(s32) = COPY $x11
+ %2:gprb(s32) = COPY $x12
+ %3:gprb(s32) = COPY $x13
+ %4:gprb(s32) = COPY $x14
+ %5:gprb(s32) = G_CONSTANT i32 -1
+ %6:gprb(s32) = G_ICMP intpred(sgt), %2, %5
+ %7:gprb(s32) = G_SELECT %6, %0, %1
+ $x10 = COPY %7(s32)
+ PseudoRET implicit $x10
+
+...
+---
+name: select_icmp_slt1
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10, $x11, $x12, $x13, $x14
+
+ ; CHECK-LABEL: name: select_icmp_slt1
+ ; CHECK: liveins: $x10, $x11, $x12, $x13, $x14
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x12
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr = COPY $x0
+ ; CHECK-NEXT: [[Select_GPR_Using_CC_GPR:%[0-9]+]]:gpr = Select_GPR_Using_CC_GPR [[COPY3]], [[COPY2]], 3, [[COPY]], [[COPY1]]
+ ; CHECK-NEXT: $x10 = COPY [[Select_GPR_Using_CC_GPR]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:gprb(s32) = COPY $x10
+ %1:gprb(s32) = COPY $x11
+ %2:gprb(s32) = COPY $x12
+ %3:gprb(s32) = COPY $x13
+ %4:gprb(s32) = COPY $x14
+ %5:gprb(s32) = G_CONSTANT i32 1
+ %6:gprb(s32) = G_ICMP intpred(slt), %2, %5
+ %7:gprb(s32) = G_SELECT %6, %0, %1
+ $x10 = COPY %7(s32)
+ PseudoRET implicit $x10
+
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/select-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/select-rv64.mir
index caa42f01c40cad1..6eee273d320be94 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/select-rv64.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/select-rv64.mir
@@ -53,3 +53,125 @@ body: |
PseudoRET implicit $x10
...
+---
+name: select_icmp_ult
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10, $x11, $x12, $x13, $x14
+
+ ; CHECK-LABEL: name: select_icmp_ult
+ ; CHECK: liveins: $x10, $x11, $x12, $x13, $x14
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x12
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr = COPY $x13
+ ; CHECK-NEXT: [[Select_GPR_Using_CC_GPR:%[0-9]+]]:gpr = Select_GPR_Using_CC_GPR [[COPY2]], [[COPY3]], 4, [[COPY]], [[COPY1]]
+ ; CHECK-NEXT: $x10 = COPY [[Select_GPR_Using_CC_GPR]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:gprb(s64) = COPY $x10
+ %1:gprb(s64) = COPY $x11
+ %2:gprb(s64) = COPY $x12
+ %3:gprb(s64) = COPY $x13
+ %4:gprb(s64) = COPY $x14
+ %5:gprb(s64) = G_ICMP intpred(ult), %2, %3
+ %6:gprb(s64) = G_SELECT %5, %0, %1
+ $x10 = COPY %6(s64)
+ PseudoRET implicit $x10
+
+...
+---
+name: select_icmp_ugt
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10, $x11, $x12, $x13, $x14
+
+ ; CHECK-LABEL: name: select_icmp_ugt
+ ; CHECK: liveins: $x10, $x11, $x12, $x13, $x14
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x12
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr = COPY $x13
+ ; CHECK-NEXT: [[Select_GPR_Using_CC_GPR:%[0-9]+]]:gpr = Select_GPR_Using_CC_GPR [[COPY3]], [[COPY2]], 4, [[COPY]], [[COPY1]]
+ ; CHECK-NEXT: $x10 = COPY [[Select_GPR_Using_CC_GPR]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:gprb(s64) = COPY $x10
+ %1:gprb(s64) = COPY $x11
+ %2:gprb(s64) = COPY $x12
+ %3:gprb(s64) = COPY $x13
+ %4:gprb(s64) = COPY $x14
+ %5:gprb(s64) = G_ICMP intpred(ugt), %2, %3
+ %6:gprb(s64) = G_SELECT %5, %0, %1
+ $x10 = COPY %6(s64)
+ PseudoRET implicit $x10
+
+...
+---
+name: select_icmp_sgtneg1
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10, $x11, $x12, $x13, $x14
+
+ ; CHECK-LABEL: name: select_icmp_sgtneg1
+ ; CHECK: liveins: $x10, $x11, $x12, $x13, $x14
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x12
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr = COPY $x0
+ ; CHECK-NEXT: [[Select_GPR_Using_CC_GPR:%[0-9]+]]:gpr = Select_GPR_Using_CC_GPR [[COPY2]], [[COPY3]], 3, [[COPY]], [[COPY1]]
+ ; CHECK-NEXT: $x10 = COPY [[Select_GPR_Using_CC_GPR]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:gprb(s64) = COPY $x10
+ %1:gprb(s64) = COPY $x11
+ %2:gprb(s64) = COPY $x12
+ %3:gprb(s64) = COPY $x13
+ %4:gprb(s64) = COPY $x14
+ %5:gprb(s64) = G_CONSTANT i64 -1
+ %6:gprb(s64) = G_ICMP intpred(sgt), %2, %5
+ %7:gprb(s64) = G_SELECT %6, %0, %1
+ $x10 = COPY %7(s64)
+ PseudoRET implicit $x10
+
+...
+---
+name: select_icmp_slt1
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10, $x11, $x12, $x13, $x14
+
+ ; CHECK-LABEL: name: select_icmp_slt1
+ ; CHECK: liveins: $x10, $x11, $x12, $x13, $x14
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:gpr = COPY $x12
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:gpr = COPY $x0
+ ; CHECK-NEXT: [[Select_GPR_Using_CC_GPR:%[0-9]+]]:gpr = Select_GPR_Using_CC_GPR [[COPY3]], [[COPY2]], 3, [[COPY]], [[COPY1]]
+ ; CHECK-NEXT: $x10 = COPY [[Select_GPR_Using_CC_GPR]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:gprb(s64) = COPY $x10
+ %1:gprb(s64) = COPY $x11
+ %2:gprb(s64) = COPY $x12
+ %3:gprb(s64) = COPY $x13
+ %4:gprb(s64) = COPY $x14
+ %5:gprb(s64) = G_CONSTANT i64 1
+ %6:gprb(s64) = G_ICMP intpred(slt), %2, %5
+ %7:gprb(s64) = G_SELECT %6, %0, %1
+ $x10 = COPY %7(s64)
+ PseudoRET implicit $x10
+
+...
More information about the llvm-commits
mailing list