[llvm] [RISCV] Enable early if-conversion (PR #92959)
Mikhail Gudim via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 25 15:02:44 PDT 2024
https://github.com/mgudim updated https://github.com/llvm/llvm-project/pull/92959
>From 27d71e42bc99d4db304359302960c502b45f5931 Mon Sep 17 00:00:00 2001
From: Mikhail Gudim <mgudim at gmail.com>
Date: Tue, 21 May 2024 15:26:47 -0400
Subject: [PATCH 1/4] [RISCV] Enable early if-conversion.
Implements the necessary target methods (insertSelect, canInsertSelect)
and adds early if-conversion to the RISCV pipeline. Doing if-conversion
increases the number of executed instructions, so it only makes sense if
there is enough ILP.
---
llvm/lib/CodeGen/EarlyIfConversion.cpp | 2 +-
llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 121 +++++++++++++++++++
llvm/lib/Target/RISCV/RISCVInstrInfo.h | 14 +++
llvm/lib/Target/RISCV/RISCVSubtarget.cpp | 13 ++
llvm/lib/Target/RISCV/RISCVSubtarget.h | 2 +
llvm/lib/Target/RISCV/RISCVTargetMachine.cpp | 8 ++
6 files changed, 159 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/EarlyIfConversion.cpp b/llvm/lib/CodeGen/EarlyIfConversion.cpp
index 2a7bee1618deb..2f8729fcbb945 100644
--- a/llvm/lib/CodeGen/EarlyIfConversion.cpp
+++ b/llvm/lib/CodeGen/EarlyIfConversion.cpp
@@ -879,7 +879,7 @@ bool EarlyIfConverter::shouldConvertIf() {
// from a loop-invariant address predictable; we were unable to prove that it
// doesn't alias any of the memory-writes in the loop, but it is likely to
// read to same value multiple times.
- if (CurrentLoop && any_of(IfConv.Cond, [&](MachineOperand &MO) {
+ if (CurrentLoop && all_of(IfConv.Cond, [&](MachineOperand &MO) {
if (!MO.isReg() || !MO.isUse())
return false;
Register Reg = MO.getReg();
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 444b9076005c2..fcf8ab5838143 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -1446,6 +1446,127 @@ RISCVInstrInfo::optimizeSelect(MachineInstr &MI,
return NewMI;
}
+int RISCVInstrInfo::getICmpCost(unsigned CC,
+ const TargetSchedModel &SchedModel) const {
+ switch (CC) {
+ default:
+ llvm_unreachable("Unknown condition code!");
+ case RISCVCC::COND_LT:
+ return SchedModel.computeInstrLatency(RISCV::SLT);
+ case RISCVCC::COND_LTU:
+ return SchedModel.computeInstrLatency(RISCV::SLTU);
+ case RISCVCC::COND_EQ:
+ return SchedModel.computeInstrLatency(RISCV::XOR) +
+ SchedModel.computeInstrLatency(RISCV::SLTIU);
+ case RISCVCC::COND_NE:
+ return SchedModel.computeInstrLatency(RISCV::XOR) +
+ SchedModel.computeInstrLatency(RISCV::SLTU);
+ case RISCVCC::COND_GE:
+ return SchedModel.computeInstrLatency(RISCV::XORI) +
+ SchedModel.computeInstrLatency(RISCV::SLT);
+ case RISCVCC::COND_GEU:
+ return SchedModel.computeInstrLatency(RISCV::XORI) +
+ SchedModel.computeInstrLatency(RISCV::SLTU);
+ }
+}
+
+void RISCVInstrInfo::insertICmp(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ const DebugLoc &DL, Register DstReg,
+ ArrayRef<MachineOperand> Cond) const {
+ MachineRegisterInfo &MRI = MI->getParent()->getParent()->getRegInfo();
+ unsigned CC = Cond[0].getImm();
+ Register LHSReg = Cond[1].getReg();
+ Register RHSReg = Cond[2].getReg();
+
+ switch (CC) {
+ default:
+ llvm_unreachable("Unknown condition code!");
+ case RISCVCC::COND_LT:
+ case RISCVCC::COND_LTU: {
+ BuildMI(MBB, MI, DL, get(CC == RISCVCC::COND_LT ? RISCV::SLT : RISCV::SLTU),
+ DstReg)
+ .addReg(LHSReg)
+ .addReg(RHSReg);
+ return;
+ }
+ case RISCVCC::COND_EQ:
+ case RISCVCC::COND_NE: {
+ Register XorReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ BuildMI(MBB, MI, DL, get(RISCV::XOR), XorReg).addReg(LHSReg).addReg(RHSReg);
+ if (CC == RISCVCC::COND_EQ) {
+ BuildMI(MBB, MI, DL, get(RISCV::SLTIU), DstReg).addReg(XorReg).addImm(1);
+ return;
+ } else {
+ BuildMI(MBB, MI, DL, get(RISCV::SLTU), DstReg)
+ .addReg(RISCV::X0)
+ .addReg(XorReg);
+ return;
+ }
+ }
+ case RISCVCC::COND_GE:
+ case RISCVCC::COND_GEU: {
+ Register NotCCReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ BuildMI(MBB, MI, DL, get(CC == RISCVCC::COND_GE ? RISCV::SLT : RISCV::SLTU),
+ NotCCReg)
+ .addReg(LHSReg)
+ .addReg(RHSReg);
+ BuildMI(MBB, MI, DL, get(RISCV::XORI), DstReg).addReg(NotCCReg).addImm(1);
+ return;
+ }
+ }
+}
+
+void RISCVInstrInfo::insertSelect(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ const DebugLoc &DL, Register DstReg,
+ ArrayRef<MachineOperand> Cond,
+ Register TrueReg, Register FalseReg) const {
+ MachineFunction &MF = *MI->getParent()->getParent();
+ const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>();
+ MachineRegisterInfo &MRI = MF.getRegInfo();
+
+ Register CCReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ insertICmp(MBB, MI, DL, CCReg, Cond);
+ unsigned CondZeroEqzOpc =
+ ST.hasVendorXVentanaCondOps() ? RISCV::VT_MASKC : RISCV::CZERO_EQZ;
+ unsigned CondZeroNezOpc =
+ ST.hasVendorXVentanaCondOps() ? RISCV::VT_MASKCN : RISCV::CZERO_NEZ;
+ Register TrueValOrZeroReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ Register FalseValOrZeroReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ BuildMI(MBB, MI, DL, get(CondZeroEqzOpc), TrueValOrZeroReg)
+ .addReg(TrueReg)
+ .addReg(CCReg);
+ BuildMI(MBB, MI, DL, get(CondZeroNezOpc), FalseValOrZeroReg)
+ .addReg(FalseReg)
+ .addReg(CCReg);
+ BuildMI(MBB, MI, DL, get(RISCV::OR), DstReg)
+ .addReg(TrueValOrZeroReg)
+ .addReg(FalseValOrZeroReg);
+ return;
+}
+
+bool RISCVInstrInfo::canInsertSelect(const MachineBasicBlock &MBB,
+ ArrayRef<MachineOperand> Cond,
+ Register DstReg, Register TrueReg,
+ Register FalseReg, int &CondCycles,
+ int &TrueCycles, int &FalseCycles) const {
+ TargetSchedModel SchedModel;
+ SchedModel.init(&STI);
+
+ CondCycles = getICmpCost(Cond[0].getImm(), SchedModel);
+ TrueCycles = SchedModel.computeInstrLatency(RISCV::OR) +
+ SchedModel.computeInstrLatency(STI.hasVendorXVentanaCondOps()
+ ? RISCV::VT_MASKC
+ : RISCV::CZERO_EQZ);
+ FalseCycles = SchedModel.computeInstrLatency(RISCV::OR) +
+ SchedModel.computeInstrLatency(STI.hasVendorXVentanaCondOps()
+ ? RISCV::VT_MASKCN
+ : RISCV::CZERO_NEZ);
+
+ return true;
+}
+
unsigned RISCVInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
if (MI.isMetaInstruction())
return 0;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
index e069717aaef23..92c01f5e8d098 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -149,6 +149,20 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
SmallPtrSetImpl<MachineInstr *> &SeenMIs,
bool) const override;
+ int getICmpCost(unsigned CC, const TargetSchedModel &SchedModel) const;
+ void insertICmp(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+ const DebugLoc &DL, Register DstReg,
+ ArrayRef<MachineOperand> Cond) const;
+
+ bool canInsertSelect(const MachineBasicBlock &, ArrayRef<MachineOperand> Cond,
+ Register, Register, Register, int &, int &,
+ int &) const override;
+
+ void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+ const DebugLoc &DL, Register DstReg,
+ ArrayRef<MachineOperand> Cond, Register TrueReg,
+ Register FalseReg) const override;
+
bool isAsCheapAsAMove(const MachineInstr &MI) const override;
std::optional<DestSourcePair>
diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
index d3236bb07d56d..61d2d49efec4f 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
@@ -65,6 +65,11 @@ static cl::opt<unsigned> RISCVMinimumJumpTableEntries(
"riscv-min-jump-table-entries", cl::Hidden,
cl::desc("Set minimum number of entries to use a jump table on RISCV"));
+static cl::opt<bool>
+ RISCVDisableEarlyIfcvt("riscv-disable-early-ifcvt", cl::Hidden,
+ cl::desc("Disable early if-conversion"),
+ cl::init(true), cl::Hidden);
+
void RISCVSubtarget::anchor() {}
RISCVSubtarget &
@@ -203,3 +208,11 @@ unsigned RISCVSubtarget::getMinimumJumpTableEntries() const {
? RISCVMinimumJumpTableEntries
: TuneInfo->MinimumJumpTableEntries;
}
+
+bool RISCVSubtarget::enableEarlyIfConversion() const {
+ TargetSchedModel SchedModel;
+ SchedModel.init(this);
+ return !RISCVDisableEarlyIfcvt &&
+ (hasStdExtZicond() || hasVendorXVentanaCondOps()) &&
+ SchedModel.hasInstrSchedModelOrItineraries();
+}
diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h
index c880c9e921e0e..fe8143942e938 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -303,6 +303,8 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
unsigned getMinimumJumpTableEntries() const;
bool supportsInitUndef() const override { return hasVInstructions(); }
+
+ bool enableEarlyIfConversion() const override;
};
} // End llvm namespace
diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
index 5aab138dae408..a205738eeebd9 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -349,6 +349,7 @@ class RISCVPassConfig : public TargetPassConfig {
bool addPreISel() override;
void addCodeGenPrepare() override;
bool addInstSelector() override;
+ bool addILPOpts() override;
bool addIRTranslator() override;
void addPreLegalizeMachineIR() override;
bool addLegalizeMachineIR() override;
@@ -450,6 +451,13 @@ bool RISCVPassConfig::addInstSelector() {
return false;
}
+bool RISCVPassConfig::addILPOpts() {
+ if (getOptLevel() != CodeGenOptLevel::None) {
+ addPass(&EarlyIfConverterID);
+ }
+ return true;
+}
+
bool RISCVPassConfig::addIRTranslator() {
addPass(new IRTranslator(getOptLevel()));
return false;
>From e36fe83556fd4b49e1d0393e2f4a699103b4aff3 Mon Sep 17 00:00:00 2001
From: Mikhail Gudim <mgudim at gmail.com>
Date: Tue, 21 May 2024 17:04:02 -0400
Subject: [PATCH 2/4] Swap TrueReg and FalseReg to avoid negation in
insertSelect
---
llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 18 ++++++++++++------
llvm/lib/Target/RISCV/RISCVInstrInfo.h | 4 ++--
2 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index fcf8ab5838143..1fe135360af1e 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -1473,11 +1473,9 @@ int RISCVInstrInfo::getICmpCost(unsigned CC,
void RISCVInstrInfo::insertICmp(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const DebugLoc &DL, Register DstReg,
- ArrayRef<MachineOperand> Cond) const {
+ unsigned CC, Register LHSReg,
+ Register RHSReg) const {
MachineRegisterInfo &MRI = MI->getParent()->getParent()->getRegInfo();
- unsigned CC = Cond[0].getImm();
- Register LHSReg = Cond[1].getReg();
- Register RHSReg = Cond[2].getReg();
switch (CC) {
default:
@@ -1525,9 +1523,17 @@ void RISCVInstrInfo::insertSelect(MachineBasicBlock &MBB,
MachineFunction &MF = *MI->getParent()->getParent();
const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>();
MachineRegisterInfo &MRI = MF.getRegInfo();
-
Register CCReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
- insertICmp(MBB, MI, DL, CCReg, Cond);
+
+ unsigned CC = Cond[0].getImm();
+ Register LHSReg = Cond[1].getReg();
+ Register RHSReg = Cond[2].getReg();
+ if (CC == RISCVCC::COND_GE || CC == RISCVCC::COND_GEU) {
+ CC = (CC == RISCVCC::COND_GE) ? RISCV::SLT : RISCV::SLTU;
+ std::swap(TrueReg, FalseReg);
+ }
+
+ insertICmp(MBB, MI, DL, CCReg, CC, LHSReg, RHSReg);
unsigned CondZeroEqzOpc =
ST.hasVendorXVentanaCondOps() ? RISCV::VT_MASKC : RISCV::CZERO_EQZ;
unsigned CondZeroNezOpc =
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
index 92c01f5e8d098..faedce462f8d5 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -151,8 +151,8 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
int getICmpCost(unsigned CC, const TargetSchedModel &SchedModel) const;
void insertICmp(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
- const DebugLoc &DL, Register DstReg,
- ArrayRef<MachineOperand> Cond) const;
+ const DebugLoc &DL, Register DstReg, unsigned CC,
+ Register LHSReg, Register RHSReg) const;
bool canInsertSelect(const MachineBasicBlock &, ArrayRef<MachineOperand> Cond,
Register, Register, Register, int &, int &,
>From a93059ceb5724aa2ad3ac199771d06a44493cfa5 Mon Sep 17 00:00:00 2001
From: Mikhail Gudim <mgudim at gmail.com>
Date: Wed, 29 May 2024 17:52:03 -0400
Subject: [PATCH 3/4] Some bug fixes and added test.
---
llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 79 +++-
llvm/lib/Target/RISCV/RISCVInstrInfo.h | 2 -
llvm/lib/Target/RISCV/RISCVSubtarget.cpp | 10 +-
llvm/test/CodeGen/RISCV/early-ifcvt.mir | 553 +++++++++++++++++++++++
4 files changed, 631 insertions(+), 13 deletions(-)
create mode 100644 llvm/test/CodeGen/RISCV/early-ifcvt.mir
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 1fe135360af1e..0ed63b88da39e 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -1522,33 +1522,60 @@ void RISCVInstrInfo::insertSelect(MachineBasicBlock &MBB,
Register TrueReg, Register FalseReg) const {
MachineFunction &MF = *MI->getParent()->getParent();
const RISCVSubtarget &ST = MF.getSubtarget<RISCVSubtarget>();
+ const TargetRegisterInfo &TRI = *ST.getRegisterInfo();
MachineRegisterInfo &MRI = MF.getRegInfo();
Register CCReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
unsigned CC = Cond[0].getImm();
Register LHSReg = Cond[1].getReg();
Register RHSReg = Cond[2].getReg();
- if (CC == RISCVCC::COND_GE || CC == RISCVCC::COND_GEU) {
- CC = (CC == RISCVCC::COND_GE) ? RISCV::SLT : RISCV::SLTU;
- std::swap(TrueReg, FalseReg);
- }
- insertICmp(MBB, MI, DL, CCReg, CC, LHSReg, RHSReg);
unsigned CondZeroEqzOpc =
ST.hasVendorXVentanaCondOps() ? RISCV::VT_MASKC : RISCV::CZERO_EQZ;
unsigned CondZeroNezOpc =
ST.hasVendorXVentanaCondOps() ? RISCV::VT_MASKCN : RISCV::CZERO_NEZ;
+
+ const TargetRegisterClass *DstRC = MRI.getRegClass(DstReg);
+ const TargetRegisterClass *CommonRC =
+ TRI.getCommonSubClass(DstRC, &RISCV::GPRRegClass);
+ bool NeedsRCCopies = (CommonRC != DstRC) && (CommonRC != &RISCV::GPRRegClass);
+
+ Register CondZeroEqzReg = TrueReg;
+ Register CondZeroNezReg = FalseReg;
+ if (NeedsRCCopies) {
+ CondZeroEqzReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ BuildMI(MBB, MI, DL, get(TargetOpcode::COPY), CondZeroEqzReg)
+ .addReg(TrueReg);
+ CondZeroNezReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ BuildMI(MBB, MI, DL, get(TargetOpcode::COPY), CondZeroNezReg)
+ .addReg(FalseReg);
+ }
+ if (CC == RISCVCC::COND_GE || CC == RISCVCC::COND_GEU) {
+ CC = (CC == RISCVCC::COND_GE) ? RISCVCC::COND_LT : RISCVCC::COND_LTU;
+ std::swap(CondZeroEqzReg, CondZeroNezReg);
+ }
+ insertICmp(MBB, MI, DL, CCReg, CC, LHSReg, RHSReg);
+
Register TrueValOrZeroReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
Register FalseValOrZeroReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
BuildMI(MBB, MI, DL, get(CondZeroEqzOpc), TrueValOrZeroReg)
- .addReg(TrueReg)
+ .addReg(CondZeroEqzReg)
.addReg(CCReg);
BuildMI(MBB, MI, DL, get(CondZeroNezOpc), FalseValOrZeroReg)
- .addReg(FalseReg)
+ .addReg(CondZeroNezReg)
.addReg(CCReg);
- BuildMI(MBB, MI, DL, get(RISCV::OR), DstReg)
+
+ Register SelectOutReg = DstReg;
+ if (NeedsRCCopies) {
+ SelectOutReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ }
+ BuildMI(MBB, MI, DL, get(RISCV::OR), SelectOutReg)
.addReg(TrueValOrZeroReg)
.addReg(FalseValOrZeroReg);
+ if (NeedsRCCopies) {
+ BuildMI(MBB, MI, DL, get(TargetOpcode::COPY), DstReg).addReg(SelectOutReg);
+ }
+
return;
}
@@ -1557,9 +1584,21 @@ bool RISCVInstrInfo::canInsertSelect(const MachineBasicBlock &MBB,
Register DstReg, Register TrueReg,
Register FalseReg, int &CondCycles,
int &TrueCycles, int &FalseCycles) const {
+ const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
+ const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
+ const TargetRegisterClass *TrueRC = MRI.getRegClass(TrueReg);
+ const TargetRegisterClass *DstRC = MRI.getRegClass(DstReg);
+ const TargetRegisterClass *CommonRC =
+ TRI.getCommonSubClass(DstRC, &RISCV::GPRRegClass);
+ bool NeedsRCCopies = (CommonRC != DstRC) && (CommonRC != &RISCV::GPRRegClass);
+
TargetSchedModel SchedModel;
SchedModel.init(&STI);
+ // this is used for testing only.
+ if (!SchedModel.hasInstrSchedModelOrItineraries())
+ return true;
+
CondCycles = getICmpCost(Cond[0].getImm(), SchedModel);
TrueCycles = SchedModel.computeInstrLatency(RISCV::OR) +
SchedModel.computeInstrLatency(STI.hasVendorXVentanaCondOps()
@@ -1570,6 +1609,30 @@ bool RISCVInstrInfo::canInsertSelect(const MachineBasicBlock &MBB,
? RISCV::VT_MASKCN
: RISCV::CZERO_NEZ);
+ if (NeedsRCCopies) {
+ unsigned CopyIntoGPROpc = 0;
+ if (TrueRC == &RISCV::FPR32RegClass) {
+ CopyIntoGPROpc = RISCV::FMV_X_W;
+ } else if (TrueRC == &RISCV::FPR64RegClass) {
+ CopyIntoGPROpc = RISCV::FMV_X_D;
+ } else {
+ llvm_unreachable("Unknown register class");
+ }
+ int CopyIntoGPRCycles = SchedModel.computeInstrLatency(CopyIntoGPROpc);
+
+ unsigned CopyFromGPROpc = 0;
+ if (DstRC == &RISCV::FPR32RegClass) {
+ CopyIntoGPROpc = RISCV::FMV_W_X;
+ } else if (DstRC == &RISCV::FPR64RegClass) {
+ CopyIntoGPROpc = RISCV::FMV_D_X;
+ } else {
+ llvm_unreachable("Unknown register class");
+ }
+ int CopyFromGPRCycles = SchedModel.computeInstrLatency(CopyFromGPROpc);
+
+ TrueCycles += (CopyIntoGPRCycles + CopyFromGPRCycles);
+ FalseCycles += (CopyIntoGPRCycles + CopyFromGPRCycles);
+ }
return true;
}
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
index faedce462f8d5..a331f1e2af9db 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -153,11 +153,9 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
void insertICmp(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
const DebugLoc &DL, Register DstReg, unsigned CC,
Register LHSReg, Register RHSReg) const;
-
bool canInsertSelect(const MachineBasicBlock &, ArrayRef<MachineOperand> Cond,
Register, Register, Register, int &, int &,
int &) const override;
-
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
const DebugLoc &DL, Register DstReg,
ArrayRef<MachineOperand> Cond, Register TrueReg,
diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
index 61d2d49efec4f..0b0347003f0d4 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.cpp
@@ -70,6 +70,9 @@ static cl::opt<bool>
cl::desc("Disable early if-conversion"),
cl::init(true), cl::Hidden);
+static cl::opt<bool> RISCVForceEalyIfcvt("riscv-force-early-ifcvt", cl::Hidden,
+ cl::desc("Force early if-conversion"),
+ cl::init(false), cl::Hidden);
void RISCVSubtarget::anchor() {}
RISCVSubtarget &
@@ -212,7 +215,8 @@ unsigned RISCVSubtarget::getMinimumJumpTableEntries() const {
bool RISCVSubtarget::enableEarlyIfConversion() const {
TargetSchedModel SchedModel;
SchedModel.init(this);
- return !RISCVDisableEarlyIfcvt &&
- (hasStdExtZicond() || hasVendorXVentanaCondOps()) &&
- SchedModel.hasInstrSchedModelOrItineraries();
+ return RISCVForceEalyIfcvt ||
+ (!RISCVDisableEarlyIfcvt &&
+ (hasStdExtZicond() || hasVendorXVentanaCondOps()) &&
+ SchedModel.hasInstrSchedModelOrItineraries());
}
diff --git a/llvm/test/CodeGen/RISCV/early-ifcvt.mir b/llvm/test/CodeGen/RISCV/early-ifcvt.mir
new file mode 100644
index 0000000000000..f4acd2e3a38ec
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/early-ifcvt.mir
@@ -0,0 +1,553 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -mtriple=riscv64 -mcpu=veyron-v1 -riscv-disable-early-ifcvt=false -riscv-force-early-ifcvt=true -stress-early-ifcvt=true \
+# RUN: -run-pass=early-ifcvt -simplify-mir -o - %s | FileCheck %s
+
+---
+name: blt
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: blt
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: liveins: $x10, $x11, $x12
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:gpr = COPY $x10
+ ; CHECK-NEXT: %n:gpr = COPY $x11
+ ; CHECK-NEXT: %k:gpr = COPY $x12
+ ; CHECK-NEXT: %zero:gpr = COPY $x0
+ ; CHECK-NEXT: PseudoBR %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.1, %bb.5
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %i:gpr = PHI %zero, %bb.0, %i_inc, %bb.1
+ ; CHECK-NEXT: %x_i_addr:gpr = ADD %x, %i
+ ; CHECK-NEXT: %x_i:gpr = LD %x_i_addr, 0
+ ; CHECK-NEXT: %add1:gpr = ADDI %x_i, 1
+ ; CHECK-NEXT: %add2:gpr = ADDI %x_i, 2
+ ; CHECK-NEXT: [[SLT:%[0-9]+]]:gpr = SLT %x_i, %k
+ ; CHECK-NEXT: [[VT_MASKC:%[0-9]+]]:gpr = VT_MASKC %add1, [[SLT]]
+ ; CHECK-NEXT: [[VT_MASKCN:%[0-9]+]]:gpr = VT_MASKCN %add2, [[SLT]]
+ ; CHECK-NEXT: %res:gpr = OR [[VT_MASKC]], [[VT_MASKCN]]
+ ; CHECK-NEXT: SD %res, %x_i, 0
+ ; CHECK-NEXT: %i_inc:gpr = ADDI %i, 1
+ ; CHECK-NEXT: BEQ %i_inc, %n, %bb.5
+ ; CHECK-NEXT: PseudoBR %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.5:
+ ; CHECK-NEXT: PseudoRET
+ bb.0:
+ successors: %bb.1
+ liveins: $x10, $x11, $x12
+
+ %x:gpr = COPY $x10
+ %n:gpr = COPY $x11
+ %k:gpr = COPY $x12
+ %zero:gpr = COPY $x0
+ PseudoBR %bb.1
+
+ bb.1:
+ successors: %bb.2, %bb.3
+
+ %i:gpr = PHI %zero, %bb.0, %i_inc, %bb.4
+ %x_i_addr:gpr = ADD %x, %i
+ %x_i:gpr = LD %x_i_addr, 0
+ BLT %x_i, %k, %bb.2
+ PseudoBR %bb.3
+
+ bb.2:
+ successors: %bb.4
+
+ %add1:gpr = ADDI %x_i, 1
+ PseudoBR %bb.4
+
+ bb.3:
+ successors: %bb.4
+
+ %add2:gpr = ADDI %x_i, 2
+ PseudoBR %bb.4
+
+ bb.4:
+ successors: %bb.1, %bb.5
+
+ %res:gpr = PHI %add1, %bb.2, %add2, %bb.3
+ SD %res, %x_i, 0
+ %i_inc:gpr = ADDI %i, 1
+ BEQ %i_inc, %n, %bb.5
+ PseudoBR %bb.1
+
+ bb.5:
+ PseudoRET
+...
+
+---
+name: bltu
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: bltu
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: liveins: $x10, $x11, $x12
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:gpr = COPY $x10
+ ; CHECK-NEXT: %n:gpr = COPY $x11
+ ; CHECK-NEXT: %k:gpr = COPY $x12
+ ; CHECK-NEXT: %zero:gpr = COPY $x0
+ ; CHECK-NEXT: PseudoBR %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.1, %bb.5
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %i:gpr = PHI %zero, %bb.0, %i_inc, %bb.1
+ ; CHECK-NEXT: %x_i_addr:gpr = ADD %x, %i
+ ; CHECK-NEXT: %x_i:gpr = LD %x_i_addr, 0
+ ; CHECK-NEXT: %add1:gpr = ADDI %x_i, 1
+ ; CHECK-NEXT: %add2:gpr = ADDI %x_i, 2
+ ; CHECK-NEXT: [[SLTU:%[0-9]+]]:gpr = SLTU %x_i, %k
+ ; CHECK-NEXT: [[VT_MASKC:%[0-9]+]]:gpr = VT_MASKC %add1, [[SLTU]]
+ ; CHECK-NEXT: [[VT_MASKCN:%[0-9]+]]:gpr = VT_MASKCN %add2, [[SLTU]]
+ ; CHECK-NEXT: %res:gpr = OR [[VT_MASKC]], [[VT_MASKCN]]
+ ; CHECK-NEXT: SD %res, %x_i, 0
+ ; CHECK-NEXT: %i_inc:gpr = ADDI %i, 1
+ ; CHECK-NEXT: BEQ %i_inc, %n, %bb.5
+ ; CHECK-NEXT: PseudoBR %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.5:
+ ; CHECK-NEXT: PseudoRET
+ bb.0:
+ successors: %bb.1
+ liveins: $x10, $x11, $x12
+
+ %x:gpr = COPY $x10
+ %n:gpr = COPY $x11
+ %k:gpr = COPY $x12
+ %zero:gpr = COPY $x0
+ PseudoBR %bb.1
+
+ bb.1:
+ successors: %bb.2, %bb.3
+
+ %i:gpr = PHI %zero, %bb.0, %i_inc, %bb.4
+ %x_i_addr:gpr = ADD %x, %i
+ %x_i:gpr = LD %x_i_addr, 0
+ BLTU %x_i, %k, %bb.2
+ PseudoBR %bb.3
+
+ bb.2:
+ successors: %bb.4
+
+ %add1:gpr = ADDI %x_i, 1
+ PseudoBR %bb.4
+
+ bb.3:
+ successors: %bb.4
+
+ %add2:gpr = ADDI %x_i, 2
+ PseudoBR %bb.4
+
+ bb.4:
+ successors: %bb.1, %bb.5
+
+ %res:gpr = PHI %add1, %bb.2, %add2, %bb.3
+ SD %res, %x_i, 0
+ %i_inc:gpr = ADDI %i, 1
+ BEQ %i_inc, %n, %bb.5
+ PseudoBR %bb.1
+
+ bb.5:
+ PseudoRET
+...
+
+---
+name: beq
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: beq
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: liveins: $x10, $x11, $x12
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:gpr = COPY $x10
+ ; CHECK-NEXT: %n:gpr = COPY $x11
+ ; CHECK-NEXT: %k:gpr = COPY $x12
+ ; CHECK-NEXT: %zero:gpr = COPY $x0
+ ; CHECK-NEXT: PseudoBR %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.1, %bb.5
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %i:gpr = PHI %zero, %bb.0, %i_inc, %bb.1
+ ; CHECK-NEXT: %x_i_addr:gpr = ADD %x, %i
+ ; CHECK-NEXT: %x_i:gpr = LD %x_i_addr, 0
+ ; CHECK-NEXT: %add1:gpr = ADDI %x_i, 1
+ ; CHECK-NEXT: %add2:gpr = ADDI %x_i, 2
+ ; CHECK-NEXT: [[XOR:%[0-9]+]]:gpr = XOR %x_i, %k
+ ; CHECK-NEXT: [[SLTIU:%[0-9]+]]:gpr = SLTIU [[XOR]], 1
+ ; CHECK-NEXT: [[VT_MASKC:%[0-9]+]]:gpr = VT_MASKC %add1, [[SLTIU]]
+ ; CHECK-NEXT: [[VT_MASKCN:%[0-9]+]]:gpr = VT_MASKCN %add2, [[SLTIU]]
+ ; CHECK-NEXT: %res:gpr = OR [[VT_MASKC]], [[VT_MASKCN]]
+ ; CHECK-NEXT: SD %res, %x_i, 0
+ ; CHECK-NEXT: %i_inc:gpr = ADDI %i, 1
+ ; CHECK-NEXT: BEQ %i_inc, %n, %bb.5
+ ; CHECK-NEXT: PseudoBR %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.5:
+ ; CHECK-NEXT: PseudoRET
+ bb.0:
+ successors: %bb.1
+ liveins: $x10, $x11, $x12
+
+ %x:gpr = COPY $x10
+ %n:gpr = COPY $x11
+ %k:gpr = COPY $x12
+ %zero:gpr = COPY $x0
+ PseudoBR %bb.1
+
+ bb.1:
+ successors: %bb.2, %bb.3
+
+ %i:gpr = PHI %zero, %bb.0, %i_inc, %bb.4
+ %x_i_addr:gpr = ADD %x, %i
+ %x_i:gpr = LD %x_i_addr, 0
+ BEQ %x_i, %k, %bb.2
+ PseudoBR %bb.3
+
+ bb.2:
+ successors: %bb.4
+
+ %add1:gpr = ADDI %x_i, 1
+ PseudoBR %bb.4
+
+ bb.3:
+ successors: %bb.4
+
+ %add2:gpr = ADDI %x_i, 2
+ PseudoBR %bb.4
+
+ bb.4:
+ successors: %bb.1, %bb.5
+
+ %res:gpr = PHI %add1, %bb.2, %add2, %bb.3
+ SD %res, %x_i, 0
+ %i_inc:gpr = ADDI %i, 1
+ BEQ %i_inc, %n, %bb.5
+ PseudoBR %bb.1
+
+ bb.5:
+ PseudoRET
+...
+
+---
+name: bne
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: bne
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: liveins: $x10, $x11, $x12
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:gpr = COPY $x10
+ ; CHECK-NEXT: %n:gpr = COPY $x11
+ ; CHECK-NEXT: %k:gpr = COPY $x12
+ ; CHECK-NEXT: %zero:gpr = COPY $x0
+ ; CHECK-NEXT: PseudoBR %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.1, %bb.5
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %i:gpr = PHI %zero, %bb.0, %i_inc, %bb.1
+ ; CHECK-NEXT: %x_i_addr:gpr = ADD %x, %i
+ ; CHECK-NEXT: %x_i:gpr = LD %x_i_addr, 0
+ ; CHECK-NEXT: %add1:gpr = ADDI %x_i, 1
+ ; CHECK-NEXT: %add2:gpr = ADDI %x_i, 2
+ ; CHECK-NEXT: [[XOR:%[0-9]+]]:gpr = XOR %x_i, %k
+ ; CHECK-NEXT: [[SLTU:%[0-9]+]]:gpr = SLTU $x0, [[XOR]]
+ ; CHECK-NEXT: [[VT_MASKC:%[0-9]+]]:gpr = VT_MASKC %add1, [[SLTU]]
+ ; CHECK-NEXT: [[VT_MASKCN:%[0-9]+]]:gpr = VT_MASKCN %add2, [[SLTU]]
+ ; CHECK-NEXT: %res:gpr = OR [[VT_MASKC]], [[VT_MASKCN]]
+ ; CHECK-NEXT: SD %res, %x_i, 0
+ ; CHECK-NEXT: %i_inc:gpr = ADDI %i, 1
+ ; CHECK-NEXT: BEQ %i_inc, %n, %bb.5
+ ; CHECK-NEXT: PseudoBR %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.5:
+ ; CHECK-NEXT: PseudoRET
+ bb.0:
+ successors: %bb.1
+ liveins: $x10, $x11, $x12
+
+ %x:gpr = COPY $x10
+ %n:gpr = COPY $x11
+ %k:gpr = COPY $x12
+ %zero:gpr = COPY $x0
+ PseudoBR %bb.1
+
+ bb.1:
+ successors: %bb.2, %bb.3
+
+ %i:gpr = PHI %zero, %bb.0, %i_inc, %bb.4
+ %x_i_addr:gpr = ADD %x, %i
+ %x_i:gpr = LD %x_i_addr, 0
+ BNE %x_i, %k, %bb.2
+ PseudoBR %bb.3
+
+ bb.2:
+ successors: %bb.4
+
+ %add1:gpr = ADDI %x_i, 1
+ PseudoBR %bb.4
+
+ bb.3:
+ successors: %bb.4
+
+ %add2:gpr = ADDI %x_i, 2
+ PseudoBR %bb.4
+
+ bb.4:
+ successors: %bb.1, %bb.5
+
+ %res:gpr = PHI %add1, %bb.2, %add2, %bb.3
+ SD %res, %x_i, 0
+ %i_inc:gpr = ADDI %i, 1
+ BEQ %i_inc, %n, %bb.5
+ PseudoBR %bb.1
+
+ bb.5:
+ PseudoRET
+...
+
+---
+name: bge
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: bge
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: liveins: $x10, $x11, $x12
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:gpr = COPY $x10
+ ; CHECK-NEXT: %n:gpr = COPY $x11
+ ; CHECK-NEXT: %k:gpr = COPY $x12
+ ; CHECK-NEXT: %zero:gpr = COPY $x0
+ ; CHECK-NEXT: PseudoBR %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.1, %bb.5
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %i:gpr = PHI %zero, %bb.0, %i_inc, %bb.1
+ ; CHECK-NEXT: %x_i_addr:gpr = ADD %x, %i
+ ; CHECK-NEXT: %x_i:gpr = LD %x_i_addr, 0
+ ; CHECK-NEXT: %add1:gpr = ADDI %x_i, 1
+ ; CHECK-NEXT: %add2:gpr = ADDI %x_i, 2
+ ; CHECK-NEXT: [[SLT:%[0-9]+]]:gpr = SLT %x_i, %k
+ ; CHECK-NEXT: [[VT_MASKC:%[0-9]+]]:gpr = VT_MASKC %add2, [[SLT]]
+ ; CHECK-NEXT: [[VT_MASKCN:%[0-9]+]]:gpr = VT_MASKCN %add1, [[SLT]]
+ ; CHECK-NEXT: %res:gpr = OR [[VT_MASKC]], [[VT_MASKCN]]
+ ; CHECK-NEXT: SD %res, %x_i, 0
+ ; CHECK-NEXT: %i_inc:gpr = ADDI %i, 1
+ ; CHECK-NEXT: BEQ %i_inc, %n, %bb.5
+ ; CHECK-NEXT: PseudoBR %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.5:
+ ; CHECK-NEXT: PseudoRET
+ bb.0:
+ successors: %bb.1
+ liveins: $x10, $x11, $x12
+
+ %x:gpr = COPY $x10
+ %n:gpr = COPY $x11
+ %k:gpr = COPY $x12
+ %zero:gpr = COPY $x0
+ PseudoBR %bb.1
+
+ bb.1:
+ successors: %bb.2, %bb.3
+
+ %i:gpr = PHI %zero, %bb.0, %i_inc, %bb.4
+ %x_i_addr:gpr = ADD %x, %i
+ %x_i:gpr = LD %x_i_addr, 0
+ BGE %x_i, %k, %bb.2
+ PseudoBR %bb.3
+
+ bb.2:
+ successors: %bb.4
+
+ %add1:gpr = ADDI %x_i, 1
+ PseudoBR %bb.4
+
+ bb.3:
+ successors: %bb.4
+
+ %add2:gpr = ADDI %x_i, 2
+ PseudoBR %bb.4
+
+ bb.4:
+ successors: %bb.1, %bb.5
+
+ %res:gpr = PHI %add1, %bb.2, %add2, %bb.3
+ SD %res, %x_i, 0
+ %i_inc:gpr = ADDI %i, 1
+ BEQ %i_inc, %n, %bb.5
+ PseudoBR %bb.1
+
+ bb.5:
+ PseudoRET
+...
+
+---
+name: bgeu
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: bgeu
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: liveins: $x10, $x11, $x12
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:gpr = COPY $x10
+ ; CHECK-NEXT: %n:gpr = COPY $x11
+ ; CHECK-NEXT: %k:gpr = COPY $x12
+ ; CHECK-NEXT: %zero:gpr = COPY $x0
+ ; CHECK-NEXT: PseudoBR %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.1, %bb.5
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %i:gpr = PHI %zero, %bb.0, %i_inc, %bb.1
+ ; CHECK-NEXT: %x_i_addr:gpr = ADD %x, %i
+ ; CHECK-NEXT: %x_i:gpr = LD %x_i_addr, 0
+ ; CHECK-NEXT: %add1:gpr = ADDI %x_i, 1
+ ; CHECK-NEXT: %add2:gpr = ADDI %x_i, 2
+ ; CHECK-NEXT: [[SLTU:%[0-9]+]]:gpr = SLTU %x_i, %k
+ ; CHECK-NEXT: [[VT_MASKC:%[0-9]+]]:gpr = VT_MASKC %add2, [[SLTU]]
+ ; CHECK-NEXT: [[VT_MASKCN:%[0-9]+]]:gpr = VT_MASKCN %add1, [[SLTU]]
+ ; CHECK-NEXT: %res:gpr = OR [[VT_MASKC]], [[VT_MASKCN]]
+ ; CHECK-NEXT: SD %res, %x_i, 0
+ ; CHECK-NEXT: %i_inc:gpr = ADDI %i, 1
+ ; CHECK-NEXT: BEQ %i_inc, %n, %bb.5
+ ; CHECK-NEXT: PseudoBR %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.5:
+ ; CHECK-NEXT: PseudoRET
+ bb.0:
+ successors: %bb.1
+ liveins: $x10, $x11, $x12
+
+ %x:gpr = COPY $x10
+ %n:gpr = COPY $x11
+ %k:gpr = COPY $x12
+ %zero:gpr = COPY $x0
+ PseudoBR %bb.1
+
+ bb.1:
+ successors: %bb.2, %bb.3
+
+ %i:gpr = PHI %zero, %bb.0, %i_inc, %bb.4
+ %x_i_addr:gpr = ADD %x, %i
+ %x_i:gpr = LD %x_i_addr, 0
+ BGEU %x_i, %k, %bb.2
+ PseudoBR %bb.3
+
+ bb.2:
+ successors: %bb.4
+
+ %add1:gpr = ADDI %x_i, 1
+ PseudoBR %bb.4
+
+ bb.3:
+ successors: %bb.4
+
+ %add2:gpr = ADDI %x_i, 2
+ PseudoBR %bb.4
+
+ bb.4:
+ successors: %bb.1, %bb.5
+
+ %res:gpr = PHI %add1, %bb.2, %add2, %bb.3
+ SD %res, %x_i, 0
+ %i_inc:gpr = ADDI %i, 1
+ BEQ %i_inc, %n, %bb.5
+ PseudoBR %bb.1
+
+ bb.5:
+ PseudoRET
+...
+
+---
+name: needs_rc_copy_fpr64
+tracksRegLiveness: true
+body: |
+ ; CHECK-LABEL: name: needs_rc_copy_fpr64
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: liveins: $x10, $x11, $x12
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %x:gpr = COPY $x10
+ ; CHECK-NEXT: %n:gpr = COPY $x11
+ ; CHECK-NEXT: %k:gpr = COPY $x12
+ ; CHECK-NEXT: %zero:gpr = COPY $x0
+ ; CHECK-NEXT: PseudoBR %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.1, %bb.5
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %i:gpr = PHI %zero, %bb.0, %i_inc, %bb.1
+ ; CHECK-NEXT: %x_i_addr:gpr = ADD %x, %i
+ ; CHECK-NEXT: %x_i:gpr = LD %x_i_addr, 0
+ ; CHECK-NEXT: %add1:gpr = ADDI %x_i, 1
+ ; CHECK-NEXT: %itofp1:fpr64 = nofpexcept FCVT_D_W %add1, 0
+ ; CHECK-NEXT: %add2:gpr = ADDI %x_i, 2
+ ; CHECK-NEXT: %itofp2:fpr64 = nofpexcept FCVT_D_W %add2, 0
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY %itofp1
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY %itofp2
+ ; CHECK-NEXT: [[SLT:%[0-9]+]]:gpr = SLT %x_i, %k
+ ; CHECK-NEXT: [[VT_MASKC:%[0-9]+]]:gpr = VT_MASKC [[COPY]], [[SLT]]
+ ; CHECK-NEXT: [[VT_MASKCN:%[0-9]+]]:gpr = VT_MASKCN [[COPY1]], [[SLT]]
+ ; CHECK-NEXT: [[OR:%[0-9]+]]:gpr = OR [[VT_MASKC]], [[VT_MASKCN]]
+ ; CHECK-NEXT: %res:fpr64 = COPY [[OR]]
+ ; CHECK-NEXT: %fptoi:gpr = nofpexcept FCVT_W_D %res, 1
+ ; CHECK-NEXT: SD %fptoi, %x_i, 0
+ ; CHECK-NEXT: %i_inc:gpr = ADDI %i, 1
+ ; CHECK-NEXT: BEQ %i_inc, %n, %bb.5
+ ; CHECK-NEXT: PseudoBR %bb.1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.5:
+ ; CHECK-NEXT: PseudoRET
+ bb.0:
+ successors: %bb.1
+ liveins: $x10, $x11, $x12
+
+ %x:gpr = COPY $x10
+ %n:gpr = COPY $x11
+ %k:gpr = COPY $x12
+ %zero:gpr = COPY $x0
+ PseudoBR %bb.1
+
+ bb.1:
+ successors: %bb.2, %bb.3
+
+ %i:gpr = PHI %zero, %bb.0, %i_inc, %bb.4
+ %x_i_addr:gpr = ADD %x, %i
+ %x_i:gpr = LD %x_i_addr, 0
+ BLT %x_i, %k, %bb.2
+ PseudoBR %bb.3
+
+ bb.2:
+ successors: %bb.4
+
+ %add1:gpr = ADDI %x_i, 1
+ %itofp1:fpr64 = nofpexcept FCVT_D_W %add1, 0
+ PseudoBR %bb.4
+
+ bb.3:
+ successors: %bb.4
+
+ %add2:gpr = ADDI %x_i, 2
+ %itofp2:fpr64 = nofpexcept FCVT_D_W %add2, 0
+ PseudoBR %bb.4
+
+ bb.4:
+ successors: %bb.1, %bb.5
+
+ %res:fpr64 = PHI %itofp1, %bb.2, %itofp2, %bb.3
+ %fptoi:gpr = nofpexcept FCVT_W_D %res, 1
+ SD %fptoi, %x_i, 0
+ %i_inc:gpr = ADDI %i, 1
+ BEQ %i_inc, %n, %bb.5
+ PseudoBR %bb.1
+
+ bb.5:
+ PseudoRET
+...
>From 356a6c790f364b23bd1d1ceb64b64683021c505a Mon Sep 17 00:00:00 2001
From: Mikhail Gudim <mgudim at gmail.com>
Date: Tue, 25 Jun 2024 18:01:52 -0400
Subject: [PATCH 4/4] Simplified insertICmp for the cases of seqz and snez.
---
llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 0ed63b88da39e..748fc34cfe353 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -1490,8 +1490,11 @@ void RISCVInstrInfo::insertICmp(MachineBasicBlock &MBB,
}
case RISCVCC::COND_EQ:
case RISCVCC::COND_NE: {
- Register XorReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
- BuildMI(MBB, MI, DL, get(RISCV::XOR), XorReg).addReg(LHSReg).addReg(RHSReg);
+ Register XorReg = LHSReg;
+ if (RHSReg != RISCV::X0) {
+ XorReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+ BuildMI(MBB, MI, DL, get(RISCV::XOR), XorReg).addReg(LHSReg).addReg(RHSReg);
+ }
if (CC == RISCVCC::COND_EQ) {
BuildMI(MBB, MI, DL, get(RISCV::SLTIU), DstReg).addReg(XorReg).addImm(1);
return;
More information about the llvm-commits
mailing list