[llvm] [RISCV][GISel] Select G_SELECT (G_ICMP, A, B) (PR #68247)
Michael Maitland via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 5 07:26:08 PDT 2023
https://github.com/michaelmaitland updated https://github.com/llvm/llvm-project/pull/68247
>From d0fd82338e42d1a1d47da4e6289f22cf07e9aba6 Mon Sep 17 00:00:00 2001
From: Nitin John Raj <nitin.raj at sifive.com>
Date: Wed, 27 Sep 2023 15:13:26 -0700
Subject: [PATCH 1/8] [RISCV][GISel] Select G_SELECT
---
.../RISCV/GISel/RISCVInstructionSelector.cpp | 29 ++++++++++
.../instruction-select/select-rv32.mir | 55 +++++++++++++++++++
.../instruction-select/select-rv64.mir | 55 +++++++++++++++++++
3 files changed, 139 insertions(+)
create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/select-rv32.mir
create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/select-rv64.mir
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 4f97a0d84f686f9..4f18b2bb576fead 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -44,11 +44,17 @@ class RISCVInstructionSelector : public InstructionSelector {
const TargetRegisterClass *
getRegClassForTypeOnBank(LLT Ty, const RegisterBank &RB) const;
+ // tblgen-erated 'select' implementation, used as the initial selector for
+ // the patterns that don't require complex C++.
bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
+
+ // Custom selection methods
bool selectCopy(MachineInstr &MI, MachineRegisterInfo &MRI) const;
bool selectConstant(MachineInstr &MI, MachineIRBuilder &MIB,
MachineRegisterInfo &MRI) const;
bool selectSExtInreg(MachineInstr &MI, MachineIRBuilder &MIB) const;
+ bool selectSelect(MachineInstr &MI, MachineIRBuilder &MIB,
+ MachineRegisterInfo &MRI) const;
bool earlySelectShift(unsigned Opc, MachineInstr &I, MachineIRBuilder &MIB,
const MachineRegisterInfo &MRI);
@@ -239,6 +245,8 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
}
case TargetOpcode::G_SEXT_INREG:
return selectSExtInreg(MI, MIB);
+ case TargetOpcode::G_SELECT:
+ return selectSelect(MI, MIB, MRI);
default:
return false;
}
@@ -376,6 +384,27 @@ bool RISCVInstructionSelector::selectSExtInreg(MachineInstr &MI,
return true;
}
+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);
+ 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(MI.getOperand(2).getReg())
+ .addReg(MI.getOperand(3).getReg());
+ MI.eraseFromParent();
+ return constrainSelectedInstRegOperands(*Result, TII, TRI, RBI);
+}
+
namespace llvm {
InstructionSelector *
createRISCVInstructionSelector(const RISCVTargetMachine &TM,
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/select-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/select-rv32.mir
new file mode 100644
index 000000000000000..828835dac8f80ca
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/select-rv32.mir
@@ -0,0 +1,55 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=riscv32 -run-pass=instruction-select --simplify-mir \
+# RUN: -verify-machineinstrs %s -o - | FileCheck %s
+---
+name: select_s32
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10, $x11, $x12
+
+ ; CHECK-LABEL: name: select_s32
+ ; CHECK: liveins: $x10, $x11, $x12
+ ; 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: [[Select_GPR_Using_CC_GPR:%[0-9]+]]:gpr = Select_GPR_Using_CC_GPR [[COPY]], $x0, 1, [[COPY1]], [[COPY2]]
+ ; 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) = G_SELECT %0, %1, %2
+ $x10 = COPY %3(s32)
+ PseudoRET implicit $x10
+
+...
+---
+name: select_p0
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10, $x11, $x12
+
+ ; CHECK-LABEL: name: select_p0
+ ; CHECK: liveins: $x10, $x11, $x12
+ ; 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: [[Select_GPR_Using_CC_GPR:%[0-9]+]]:gpr = Select_GPR_Using_CC_GPR [[COPY]], $x0, 1, [[COPY1]], [[COPY2]]
+ ; CHECK-NEXT: $x10 = COPY [[Select_GPR_Using_CC_GPR]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:gprb(s32) = COPY $x10
+ %1:gprb(p0) = COPY $x11
+ %2:gprb(p0) = COPY $x12
+ %3:gprb(p0) = G_SELECT %0, %1, %2
+ $x10 = COPY %3(p0)
+ 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
new file mode 100644
index 000000000000000..caa42f01c40cad1
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/select-rv64.mir
@@ -0,0 +1,55 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=riscv64 -run-pass=instruction-select %s -o - \
+# RUN: | FileCheck %s
+---
+name: select_s64
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10, $x11, $x12
+
+ ; CHECK-LABEL: name: select_s64
+ ; CHECK: liveins: $x10, $x11, $x12
+ ; 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: [[Select_GPR_Using_CC_GPR:%[0-9]+]]:gpr = Select_GPR_Using_CC_GPR [[COPY]], $x0, 1, [[COPY1]], [[COPY2]]
+ ; 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) = G_SELECT %0, %1, %2
+ $x10 = COPY %3(s64)
+ PseudoRET implicit $x10
+
+...
+---
+name: select_p0
+legalized: true
+regBankSelected: true
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x10, $x11, $x12
+
+ ; CHECK-LABEL: name: select_p0
+ ; CHECK: liveins: $x10, $x11, $x12
+ ; 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: [[Select_GPR_Using_CC_GPR:%[0-9]+]]:gpr = Select_GPR_Using_CC_GPR [[COPY]], $x0, 1, [[COPY1]], [[COPY2]]
+ ; CHECK-NEXT: $x10 = COPY [[Select_GPR_Using_CC_GPR]]
+ ; CHECK-NEXT: PseudoRET implicit $x10
+ %0:gprb(s64) = COPY $x10
+ %1:gprb(p0) = COPY $x11
+ %2:gprb(p0) = COPY $x12
+ %3:gprb(p0) = G_SELECT %0, %1, %2
+ $x10 = COPY %3(p0)
+ PseudoRET implicit $x10
+
+...
>From 321f3e891b76356e807d9abe9c23048a5e9ba9da Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Tue, 3 Oct 2023 15:29:47 -0700
Subject: [PATCH 2/8] [RISCV][GISel] Select G_SELECT (G_ICMP, A, B)
---
.../RISCV/GISel/RISCVInstructionSelector.cpp | 128 ++++++++++++++++--
.../instruction-select/select-rv32.mir | 122 +++++++++++++++++
.../instruction-select/select-rv64.mir | 122 +++++++++++++++++
3 files changed, 359 insertions(+), 13 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 4f18b2bb576fead..93fdba869257d83 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -65,6 +65,11 @@ class RISCVInstructionSelector : public InstructionSelector {
void renderNegImm(MachineInstrBuilder &MIB, const MachineInstr &MI,
int OpIdx) const;
+ /// Returns a G_ICMP that is equivalent to MI, whose condition code matches
+ /// one of the comparisons supported directly by branches in the RISC-V ISA.
+ MachineInstr *createICMPForBranch(MachineInstr *MI, MachineIRBuilder &MIB,
+ MachineRegisterInfo &MRI) const;
+
const RISCVSubtarget &STI;
const RISCVInstrInfo &TII;
const RISCVRegisterInfo &TRI;
@@ -384,23 +389,120 @@ 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;
+ }
+}
+
+MachineInstr *RISCVInstructionSelector::createICMPForBranch(
+ MachineInstr *MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI) const {
+ assert(MI->getOpcode() == TargetOpcode::G_ICMP);
+ CmpInst::Predicate CC =
+ static_cast<CmpInst::Predicate>(MI->getOperand(1).getPredicate());
+ MachineOperand &LHS = MI->getOperand(2);
+ MachineOperand &RHS = MI->getOperand(3);
+
+ // Adjust comparisons to use comparison with 0 if possible.
+ MachineInstr *MaybeConstant = MRI.getVRegDef(RHS.getReg());
+ if (MaybeConstant && MaybeConstant->getOpcode() == TargetOpcode::G_CONSTANT) {
+ switch (CC) {
+ case CmpInst::Predicate::ICMP_SGT:
+ // Convert X > -1 to X >= 0
+ if (MaybeConstant->getOperand(1).getCImm()->getSExtValue() == -1) {
+ MachineInstr *Zero = MIB.buildConstant(
+ MRI.getType(MaybeConstant->getOperand(0).getReg()), 0);
+ selectConstant(*Zero, MIB, MRI);
+ return MIB.buildICmp(CmpInst::Predicate::ICMP_SGE, MI->getOperand(0),
+ LHS, Zero->getOperand(0));
+ }
+ break;
+ case CmpInst::Predicate::ICMP_SLT:
+ // Convert X < 1 to 0 >= X
+ if (MaybeConstant->getOperand(1).getCImm()->getSExtValue() == 1) {
+ MachineInstr *Zero= MIB.buildConstant(
+ MRI.getType(MaybeConstant->getOperand(0).getReg()), 0);
+ selectConstant(*Zero, MIB, MRI);
+ return MIB.buildICmp(CmpInst::Predicate::ICMP_SGE, MI->getOperand(0),
+ Zero->getOperand(0), LHS);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ switch (CC) {
+ 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.
+ return MI;
+ 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.
+ return MIB.buildICmp(CmpInst::getSwappedPredicate(CC), MI->getOperand(0),
+ RHS, LHS);
+ }
+}
+
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);
- 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(MI.getOperand(2).getReg())
- .addReg(MI.getOperand(3).getReg());
+ MachineInstr *Result;
+ MachineInstr *MaybeICMP = MRI.getVRegDef(MI.getOperand(1).getReg());
+ if (MaybeICMP && MaybeICMP->getOpcode() == TargetOpcode::G_ICMP) {
+ // 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.
+ MachineInstr *ICMPForBranch = createICMPForBranch(MaybeICMP, MIB, MRI);
+ CmpInst::Predicate CC = static_cast<CmpInst::Predicate>(
+ ICMPForBranch->getOperand(1).getPredicate());
+ Result = MIB.buildInstr(RISCV::Select_GPR_Using_CC_GPR)
+ .addDef(MI.getOperand(0).getReg());
+ Result->addOperand(ICMPForBranch->getOperand(2));
+ Result->addOperand(ICMPForBranch->getOperand(3));
+ Result->addOperand(
+ MachineOperand::CreateImm(getRISCVCCFromICMP(CC)));
+ Result->addOperand(MI.getOperand(2));
+ Result->addOperand(MI.getOperand(3));
+
+ // Delete ICMPForBranch since we know it has no users. Let the original
+ // G_ICMP be selected normally in case it has other users.
+ if (ICMPForBranch != MaybeICMP)
+ ICMPForBranch->eraseFromParent();
+ } else {
+ 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(MI.getOperand(2).getReg())
+ .addReg(MI.getOperand(3).getReg());
+ }
MI.eraseFromParent();
return constrainSelectedInstRegOperands(*Result, TII, TRI, RBI);
}
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
+
+...
>From 247d694d9d4fa7102be6b2a6ef82f6bab9c07962 Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Wed, 4 Oct 2023 13:02:54 -0700
Subject: [PATCH 3/8] fixup! [RISCV][GISel] Select G_SELECT (G_ICMP, A, B)
Don't create new G_ICMP
---
.../RISCV/GISel/RISCVInstructionSelector.cpp | 66 +++++++++----------
1 file changed, 33 insertions(+), 33 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 93fdba869257d83..2815ae518926bb9 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -65,10 +65,13 @@ class RISCVInstructionSelector : public InstructionSelector {
void renderNegImm(MachineInstrBuilder &MIB, const MachineInstr &MI,
int OpIdx) const;
- /// Returns a G_ICMP that is equivalent to MI, whose condition code matches
- /// one of the comparisons supported directly by branches in the RISC-V ISA.
- MachineInstr *createICMPForBranch(MachineInstr *MI, MachineIRBuilder &MIB,
- MachineRegisterInfo &MRI) const;
+ /// Sets CC, LHS, and RHS so that they form an equivelent G_ICMP (CC, 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 setICMPOperandsForBranch(MachineInstr &MI, MachineIRBuilder &MIB,
+ MachineRegisterInfo &MRI,
+ CmpInst::Predicate &CC, MachineOperand &LHS,
+ MachineOperand &RHS) const;
const RISCVSubtarget &STI;
const RISCVInstrInfo &TII;
@@ -410,13 +413,13 @@ static RISCVCC::CondCode getRISCVCCFromICMP(CmpInst::Predicate CC) {
}
}
-MachineInstr *RISCVInstructionSelector::createICMPForBranch(
- MachineInstr *MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI) const {
- assert(MI->getOpcode() == TargetOpcode::G_ICMP);
- CmpInst::Predicate CC =
- static_cast<CmpInst::Predicate>(MI->getOperand(1).getPredicate());
- MachineOperand &LHS = MI->getOperand(2);
- MachineOperand &RHS = MI->getOperand(3);
+void RISCVInstructionSelector::setICMPOperandsForBranch(
+ MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI,
+ CmpInst::Predicate &CC, MachineOperand &LHS, MachineOperand &RHS) const {
+ assert(MI.getOpcode() == TargetOpcode::G_ICMP);
+ CC = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
+ LHS = MI.getOperand(2);
+ RHS = MI.getOperand(3);
// Adjust comparisons to use comparison with 0 if possible.
MachineInstr *MaybeConstant = MRI.getVRegDef(RHS.getReg());
@@ -428,20 +431,21 @@ MachineInstr *RISCVInstructionSelector::createICMPForBranch(
MachineInstr *Zero = MIB.buildConstant(
MRI.getType(MaybeConstant->getOperand(0).getReg()), 0);
selectConstant(*Zero, MIB, MRI);
- return MIB.buildICmp(CmpInst::Predicate::ICMP_SGE, MI->getOperand(0),
- LHS, Zero->getOperand(0));
+ CC = CmpInst::Predicate::ICMP_SGE;
+ RHS = MachineOperand::CreateReg(Zero->getOperand(0).getReg(), false);
}
- break;
+ return;
case CmpInst::Predicate::ICMP_SLT:
// Convert X < 1 to 0 >= X
if (MaybeConstant->getOperand(1).getCImm()->getSExtValue() == 1) {
- MachineInstr *Zero= MIB.buildConstant(
+ MachineInstr *Zero = MIB.buildConstant(
MRI.getType(MaybeConstant->getOperand(0).getReg()), 0);
selectConstant(*Zero, MIB, MRI);
- return MIB.buildICmp(CmpInst::Predicate::ICMP_SGE, MI->getOperand(0),
- Zero->getOperand(0), LHS);
+ CC = CmpInst::Predicate::ICMP_SGE;
+ RHS = LHS;
+ LHS = MachineOperand::CreateReg(Zero->getOperand(0).getReg(), false);
}
- break;
+ return;
default:
break;
}
@@ -457,15 +461,16 @@ MachineInstr *RISCVInstructionSelector::createICMPForBranch(
case CmpInst::Predicate::ICMP_UGE:
case CmpInst::Predicate::ICMP_SGE:
// These CCs are supported directly by RISC-V branches.
- return MI;
+ 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.
- return MIB.buildICmp(CmpInst::getSwappedPredicate(CC), MI->getOperand(0),
- RHS, LHS);
+ CC = CmpInst::getSwappedPredicate(CC);
+ std::swap(LHS, RHS);
+ return;
}
}
@@ -478,22 +483,17 @@ bool RISCVInstructionSelector::selectSelect(MachineInstr &MI,
if (MaybeICMP && MaybeICMP->getOpcode() == TargetOpcode::G_ICMP) {
// 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.
- MachineInstr *ICMPForBranch = createICMPForBranch(MaybeICMP, MIB, MRI);
- CmpInst::Predicate CC = static_cast<CmpInst::Predicate>(
- ICMPForBranch->getOperand(1).getPredicate());
+ CmpInst::Predicate CC;
+ MachineOperand LHS = MaybeICMP->getOperand(2);
+ MachineOperand RHS = MaybeICMP->getOperand(3);
+ setICMPOperandsForBranch(*MaybeICMP, MIB, MRI, CC, LHS, RHS);
Result = MIB.buildInstr(RISCV::Select_GPR_Using_CC_GPR)
.addDef(MI.getOperand(0).getReg());
- Result->addOperand(ICMPForBranch->getOperand(2));
- Result->addOperand(ICMPForBranch->getOperand(3));
- Result->addOperand(
- MachineOperand::CreateImm(getRISCVCCFromICMP(CC)));
+ Result->addOperand(LHS);
+ Result->addOperand(RHS);
+ Result->addOperand(MachineOperand::CreateImm(getRISCVCCFromICMP(CC)));
Result->addOperand(MI.getOperand(2));
Result->addOperand(MI.getOperand(3));
-
- // Delete ICMPForBranch since we know it has no users. Let the original
- // G_ICMP be selected normally in case it has other users.
- if (ICMPForBranch != MaybeICMP)
- ICMPForBranch->eraseFromParent();
} else {
Result = MIB.buildInstr(RISCV::Select_GPR_Using_CC_GPR)
.addDef(MI.getOperand(0).getReg())
>From ca40a4788229647576846eacf711c0ff9e1ef24f Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Wed, 4 Oct 2023 14:24:37 -0700
Subject: [PATCH 4/8] fixup! [RISCV][GISel] Select G_SELECT (G_ICMP, A, B)
Refactor NFC
---
.../RISCV/GISel/RISCVInstructionSelector.cpp | 80 +++++++++----------
1 file changed, 38 insertions(+), 42 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 2815ae518926bb9..4a4d4a497ddd9f8 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -65,13 +65,12 @@ class RISCVInstructionSelector : public InstructionSelector {
void renderNegImm(MachineInstrBuilder &MIB, const MachineInstr &MI,
int OpIdx) const;
- /// Sets CC, LHS, and RHS so that they form an equivelent G_ICMP (CC, LHS,
+ /// 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 setICMPOperandsForBranch(MachineInstr &MI, MachineIRBuilder &MIB,
- MachineRegisterInfo &MRI,
- CmpInst::Predicate &CC, MachineOperand &LHS,
- MachineOperand &RHS) const;
+ void getICMPOperandsForBranch(MachineInstr &MI, MachineIRBuilder &MIB,
+ MachineRegisterInfo &MRI, RISCVCC::CondCode &CC,
+ Register &LHS, Register &RHS) const;
const RISCVSubtarget &STI;
const RISCVInstrInfo &TII;
@@ -413,26 +412,27 @@ static RISCVCC::CondCode getRISCVCCFromICMP(CmpInst::Predicate CC) {
}
}
-void RISCVInstructionSelector::setICMPOperandsForBranch(
+void RISCVInstructionSelector::getICMPOperandsForBranch(
MachineInstr &MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI,
- CmpInst::Predicate &CC, MachineOperand &LHS, MachineOperand &RHS) const {
+ RISCVCC::CondCode &CC, Register &LHS, Register &RHS) const {
assert(MI.getOpcode() == TargetOpcode::G_ICMP);
- CC = static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
- LHS = MI.getOperand(2);
- RHS = MI.getOperand(3);
+ 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.
- MachineInstr *MaybeConstant = MRI.getVRegDef(RHS.getReg());
+ MachineInstr *MaybeConstant = MRI.getVRegDef(RHS);
if (MaybeConstant && MaybeConstant->getOpcode() == TargetOpcode::G_CONSTANT) {
- switch (CC) {
+ switch (ICMPCC) {
case CmpInst::Predicate::ICMP_SGT:
// Convert X > -1 to X >= 0
if (MaybeConstant->getOperand(1).getCImm()->getSExtValue() == -1) {
MachineInstr *Zero = MIB.buildConstant(
MRI.getType(MaybeConstant->getOperand(0).getReg()), 0);
selectConstant(*Zero, MIB, MRI);
- CC = CmpInst::Predicate::ICMP_SGE;
- RHS = MachineOperand::CreateReg(Zero->getOperand(0).getReg(), false);
+ CC = getRISCVCCFromICMP(CmpInst::Predicate::ICMP_SGE);
+ RHS = Zero->getOperand(0).getReg();
}
return;
case CmpInst::Predicate::ICMP_SLT:
@@ -441,9 +441,9 @@ void RISCVInstructionSelector::setICMPOperandsForBranch(
MachineInstr *Zero = MIB.buildConstant(
MRI.getType(MaybeConstant->getOperand(0).getReg()), 0);
selectConstant(*Zero, MIB, MRI);
- CC = CmpInst::Predicate::ICMP_SGE;
+ CC = getRISCVCCFromICMP(CmpInst::Predicate::ICMP_SGE);
RHS = LHS;
- LHS = MachineOperand::CreateReg(Zero->getOperand(0).getReg(), false);
+ LHS = Zero->getOperand(0).getReg();
}
return;
default:
@@ -451,7 +451,7 @@ void RISCVInstructionSelector::setICMPOperandsForBranch(
}
}
- switch (CC) {
+ switch (ICMPCC) {
default:
llvm_unreachable("Expected ICMP CmpInst::Predicate.");
case CmpInst::Predicate::ICMP_EQ:
@@ -461,6 +461,7 @@ void RISCVInstructionSelector::setICMPOperandsForBranch(
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:
@@ -468,7 +469,7 @@ void RISCVInstructionSelector::setICMPOperandsForBranch(
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 = CmpInst::getSwappedPredicate(CC);
+ CC = getRISCVCCFromICMP(CmpInst::getSwappedPredicate(ICMPCC));
std::swap(LHS, RHS);
return;
}
@@ -478,31 +479,26 @@ bool RISCVInstructionSelector::selectSelect(MachineInstr &MI,
MachineIRBuilder &MIB,
MachineRegisterInfo &MRI) const {
assert(MI.getOpcode() == TargetOpcode::G_SELECT);
- MachineInstr *Result;
+
+ // 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.
MachineInstr *MaybeICMP = MRI.getVRegDef(MI.getOperand(1).getReg());
- if (MaybeICMP && MaybeICMP->getOpcode() == TargetOpcode::G_ICMP) {
- // 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.
- CmpInst::Predicate CC;
- MachineOperand LHS = MaybeICMP->getOperand(2);
- MachineOperand RHS = MaybeICMP->getOperand(3);
- setICMPOperandsForBranch(*MaybeICMP, MIB, MRI, CC, LHS, RHS);
- Result = MIB.buildInstr(RISCV::Select_GPR_Using_CC_GPR)
- .addDef(MI.getOperand(0).getReg());
- Result->addOperand(LHS);
- Result->addOperand(RHS);
- Result->addOperand(MachineOperand::CreateImm(getRISCVCCFromICMP(CC)));
- Result->addOperand(MI.getOperand(2));
- Result->addOperand(MI.getOperand(3));
- } else {
- 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(MI.getOperand(2).getReg())
- .addReg(MI.getOperand(3).getReg());
- }
+ bool Op1IsICMP = MaybeICMP && MaybeICMP->getOpcode() == TargetOpcode::G_ICMP;
+ RISCVCC::CondCode CC;
+ Register LHS, RHS;
+ if (Op1IsICMP)
+ getICMPOperandsForBranch(*MaybeICMP, 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(Op1)
+ .addReg(Op2)
+ .addImm(Op3)
+ .addReg(MI.getOperand(2).getReg())
+ .addReg(MI.getOperand(3).getReg());
MI.eraseFromParent();
return constrainSelectedInstRegOperands(*Result, TII, TRI, RBI);
}
>From d576073f8654fb4561487acf00ab1a5243fa3f9f Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Wed, 4 Oct 2023 14:47:02 -0700
Subject: [PATCH 5/8] fixup! [RISCV][GISel] Select G_SELECT (G_ICMP, A, B)
simplify cond code and fix returns
---
.../Target/RISCV/GISel/RISCVInstructionSelector.cpp | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 4a4d4a497ddd9f8..de83ff16711ebd3 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -431,21 +431,23 @@ void RISCVInstructionSelector::getICMPOperandsForBranch(
MachineInstr *Zero = MIB.buildConstant(
MRI.getType(MaybeConstant->getOperand(0).getReg()), 0);
selectConstant(*Zero, MIB, MRI);
- CC = getRISCVCCFromICMP(CmpInst::Predicate::ICMP_SGE);
+ CC = RISCVCC::COND_GE;
RHS = Zero->getOperand(0).getReg();
+ return;
}
- return;
+ break;
case CmpInst::Predicate::ICMP_SLT:
// Convert X < 1 to 0 >= X
if (MaybeConstant->getOperand(1).getCImm()->getSExtValue() == 1) {
MachineInstr *Zero = MIB.buildConstant(
MRI.getType(MaybeConstant->getOperand(0).getReg()), 0);
selectConstant(*Zero, MIB, MRI);
- CC = getRISCVCCFromICMP(CmpInst::Predicate::ICMP_SGE);
+ CC = RISCVCC::COND_GE;
RHS = LHS;
LHS = Zero->getOperand(0).getReg();
+ return;
}
- return;
+ break;
default:
break;
}
>From 3380e12773c8c90b45638b360c29192b847efa52 Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Wed, 4 Oct 2023 15:33:26 -0700
Subject: [PATCH 6/8] Use match to simplify checks
---
.../RISCV/GISel/RISCVInstructionSelector.cpp | 21 +++++++++----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index de83ff16711ebd3..6ba7b0c1e928bc3 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -17,6 +17,7 @@
#include "RISCVTargetMachine.h"
#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
+#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/IR/IntrinsicsRISCV.h"
#include "llvm/Support/Debug.h"
@@ -24,6 +25,7 @@
#define DEBUG_TYPE "riscv-isel"
using namespace llvm;
+using namespace MIPatternMatch;
#define GET_GLOBALISEL_PREDICATE_BITSET
#include "RISCVGenGlobalISel.inc"
@@ -422,14 +424,12 @@ void RISCVInstructionSelector::getICMPOperandsForBranch(
RHS = MI.getOperand(3).getReg();
// Adjust comparisons to use comparison with 0 if possible.
- MachineInstr *MaybeConstant = MRI.getVRegDef(RHS);
- if (MaybeConstant && MaybeConstant->getOpcode() == TargetOpcode::G_CONSTANT) {
+ if (auto Constant = matchConstant<int64_t>(RHS, MRI)) {
switch (ICMPCC) {
case CmpInst::Predicate::ICMP_SGT:
// Convert X > -1 to X >= 0
- if (MaybeConstant->getOperand(1).getCImm()->getSExtValue() == -1) {
- MachineInstr *Zero = MIB.buildConstant(
- MRI.getType(MaybeConstant->getOperand(0).getReg()), 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();
@@ -438,9 +438,8 @@ void RISCVInstructionSelector::getICMPOperandsForBranch(
break;
case CmpInst::Predicate::ICMP_SLT:
// Convert X < 1 to 0 >= X
- if (MaybeConstant->getOperand(1).getCImm()->getSExtValue() == 1) {
- MachineInstr *Zero = MIB.buildConstant(
- MRI.getType(MaybeConstant->getOperand(0).getReg()), 0);
+ if (*Constant == 1) {
+ MachineInstr *Zero = MIB.buildConstant(MRI.getType(RHS), 0);
selectConstant(*Zero, MIB, MRI);
CC = RISCVCC::COND_GE;
RHS = LHS;
@@ -484,12 +483,12 @@ bool RISCVInstructionSelector::selectSelect(MachineInstr &MI,
// 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.
- MachineInstr *MaybeICMP = MRI.getVRegDef(MI.getOperand(1).getReg());
- bool Op1IsICMP = MaybeICMP && MaybeICMP->getOpcode() == TargetOpcode::G_ICMP;
+ 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(*MaybeICMP, MIB, MRI, CC, LHS, RHS);
+ getICMPOperandsForBranch(*MRI.getVRegDef(MIOp1Reg), MIB, MRI, CC, LHS, RHS);
Register Op1 = Op1IsICMP ? LHS : MI.getOperand(1).getReg();
Register Op2 = Op1IsICMP ? RHS : RISCV::X0;
>From 225e64f879e1fe4a7881a2af01867891a92f07ca Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Wed, 4 Oct 2023 15:42:34 -0700
Subject: [PATCH 7/8] Use mICst
---
llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 6ba7b0c1e928bc3..0df7eb320658e64 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -424,11 +424,12 @@ void RISCVInstructionSelector::getICMPOperandsForBranch(
RHS = MI.getOperand(3).getReg();
// Adjust comparisons to use comparison with 0 if possible.
- if (auto Constant = matchConstant<int64_t>(RHS, MRI)) {
+ int64_t Constant;
+ if (mi_match(RHS, MRI, m_ICst(Constant))) {
switch (ICMPCC) {
case CmpInst::Predicate::ICMP_SGT:
// Convert X > -1 to X >= 0
- if (*Constant == -1) {
+ if (Constant == -1) {
MachineInstr *Zero = MIB.buildConstant(MRI.getType(RHS), 0);
selectConstant(*Zero, MIB, MRI);
CC = RISCVCC::COND_GE;
@@ -438,7 +439,7 @@ void RISCVInstructionSelector::getICMPOperandsForBranch(
break;
case CmpInst::Predicate::ICMP_SLT:
// Convert X < 1 to 0 >= X
- if (*Constant == 1) {
+ if (Constant == 1) {
MachineInstr *Zero = MIB.buildConstant(MRI.getType(RHS), 0);
selectConstant(*Zero, MIB, MRI);
CC = RISCVCC::COND_GE;
>From 35cfe9c39f5769ce2221ec09969ebb77ed9b98ba Mon Sep 17 00:00:00 2001
From: Michael Maitland <michaeltmaitland at gmail.com>
Date: Thu, 5 Oct 2023 07:24:37 -0700
Subject: [PATCH 8/8] Use getIConstantVRegSExtVal
---
llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
index 0df7eb320658e64..969c26bcb8a44b9 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
@@ -424,12 +424,11 @@ void RISCVInstructionSelector::getICMPOperandsForBranch(
RHS = MI.getOperand(3).getReg();
// Adjust comparisons to use comparison with 0 if possible.
- int64_t Constant;
- if (mi_match(RHS, MRI, m_ICst(Constant))) {
+ if (auto Constant = getIConstantVRegSExtVal(RHS, MRI)) {
switch (ICMPCC) {
case CmpInst::Predicate::ICMP_SGT:
// Convert X > -1 to X >= 0
- if (Constant == -1) {
+ if (*Constant == -1) {
MachineInstr *Zero = MIB.buildConstant(MRI.getType(RHS), 0);
selectConstant(*Zero, MIB, MRI);
CC = RISCVCC::COND_GE;
@@ -439,7 +438,7 @@ void RISCVInstructionSelector::getICMPOperandsForBranch(
break;
case CmpInst::Predicate::ICMP_SLT:
// Convert X < 1 to 0 >= X
- if (Constant == 1) {
+ if (*Constant == 1) {
MachineInstr *Zero = MIB.buildConstant(MRI.getType(RHS), 0);
selectConstant(*Zero, MIB, MRI);
CC = RISCVCC::COND_GE;
More information about the llvm-commits
mailing list