[llvm] [RISCV] Enable early if-conversion (PR #92959)

Mikhail Gudim via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 27 11:46:35 PDT 2024


https://github.com/mgudim updated https://github.com/llvm/llvm-project/pull/92959

>From 350505ffd00eaf3e3fb3d5e00b9875a0361f0242 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/5] [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 347c1bc3c278f..b1ee2e86cb174 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -301,6 +301,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 87ae2ee0d3791..7b284d69ac637 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -353,6 +353,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;
@@ -456,6 +457,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 fd3f3f94a8a1812071567052f9826d426829dc0c 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/5] 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 b3dc357f1a5a21e4a25bacbe7f2e95e083cc0aa8 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/5] 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 c03161dd576082b373690e6e3c6e99baa97e1557 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/5] Simplified insertICmp for the cases of seqz and snez.
 Updated cost estimate for these cases. Made `getICmpCost` and `insertICmp`
 accept `Cond` to make their signatures more like `insertSelect`.

---
 llvm/lib/Target/RISCV/RISCVInstrInfo.cpp | 29 +++++++++++++++---------
 llvm/lib/Target/RISCV/RISCVInstrInfo.h   |  7 +++---
 2 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 0ed63b88da39e..b2ed87e7d8a97 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -1446,8 +1446,10 @@ RISCVInstrInfo::optimizeSelect(MachineInstr &MI,
   return NewMI;
 }
 
-int RISCVInstrInfo::getICmpCost(unsigned CC,
+int RISCVInstrInfo::getICmpCost(ArrayRef<MachineOperand> Cond,
                                 const TargetSchedModel &SchedModel) const {
+  unsigned CC = Cond[0].getImm();
+  bool IsEQZOrNEZ = (Cond[2].getReg() == RISCV::X0);
   switch (CC) {
   default:
     llvm_unreachable("Unknown condition code!");
@@ -1456,10 +1458,10 @@ int RISCVInstrInfo::getICmpCost(unsigned CC,
   case RISCVCC::COND_LTU:
     return SchedModel.computeInstrLatency(RISCV::SLTU);
   case RISCVCC::COND_EQ:
-    return SchedModel.computeInstrLatency(RISCV::XOR) +
+    return (IsEQZOrNEZ ? SchedModel.computeInstrLatency(RISCV::XOR) : 0) +
            SchedModel.computeInstrLatency(RISCV::SLTIU);
   case RISCVCC::COND_NE:
-    return SchedModel.computeInstrLatency(RISCV::XOR) +
+    return (IsEQZOrNEZ ? SchedModel.computeInstrLatency(RISCV::XOR) : 0) +
            SchedModel.computeInstrLatency(RISCV::SLTU);
   case RISCVCC::COND_GE:
     return SchedModel.computeInstrLatency(RISCV::XORI) +
@@ -1473,10 +1475,12 @@ int RISCVInstrInfo::getICmpCost(unsigned CC,
 void RISCVInstrInfo::insertICmp(MachineBasicBlock &MBB,
                                 MachineBasicBlock::iterator MI,
                                 const DebugLoc &DL, Register DstReg,
-                                unsigned CC, Register LHSReg,
-                                Register RHSReg) const {
+                                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!");
@@ -1490,8 +1494,13 @@ 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;
@@ -1527,8 +1536,6 @@ void RISCVInstrInfo::insertSelect(MachineBasicBlock &MBB,
   Register CCReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
 
   unsigned CC = Cond[0].getImm();
-  Register LHSReg = Cond[1].getReg();
-  Register RHSReg = Cond[2].getReg();
 
   unsigned CondZeroEqzOpc =
       ST.hasVendorXVentanaCondOps() ? RISCV::VT_MASKC : RISCV::CZERO_EQZ;
@@ -1554,7 +1561,7 @@ void RISCVInstrInfo::insertSelect(MachineBasicBlock &MBB,
     CC = (CC == RISCVCC::COND_GE) ? RISCVCC::COND_LT : RISCVCC::COND_LTU;
     std::swap(CondZeroEqzReg, CondZeroNezReg);
   }
-  insertICmp(MBB, MI, DL, CCReg, CC, LHSReg, RHSReg);
+  insertICmp(MBB, MI, DL, CCReg, Cond);
 
   Register TrueValOrZeroReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
   Register FalseValOrZeroReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
@@ -1599,7 +1606,7 @@ bool RISCVInstrInfo::canInsertSelect(const MachineBasicBlock &MBB,
   if (!SchedModel.hasInstrSchedModelOrItineraries())
     return true;
 
-  CondCycles = getICmpCost(Cond[0].getImm(), SchedModel);
+  CondCycles = getICmpCost(Cond, SchedModel);
   TrueCycles = SchedModel.computeInstrLatency(RISCV::OR) +
                SchedModel.computeInstrLatency(STI.hasVendorXVentanaCondOps()
                                                   ? RISCV::VT_MASKC
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
index a331f1e2af9db..8fc916e5d960c 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -149,10 +149,11 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
                                SmallPtrSetImpl<MachineInstr *> &SeenMIs,
                                bool) const override;
 
-  int getICmpCost(unsigned CC, const TargetSchedModel &SchedModel) const;
+  int getICmpCost(ArrayRef<MachineOperand> Cond,
+                  const TargetSchedModel &SchedModel) const;
   void insertICmp(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
-                  const DebugLoc &DL, Register DstReg, unsigned CC,
-                  Register LHSReg, Register RHSReg) const;
+                  const DebugLoc &DL, Register DstReg,
+                  ArrayRef<MachineOperand> Cond) const;
   bool canInsertSelect(const MachineBasicBlock &, ArrayRef<MachineOperand> Cond,
                        Register, Register, Register, int &, int &,
                        int &) const override;

>From 3936f91a59000709420c3bf197002292e2eb58b9 Mon Sep 17 00:00:00 2001
From: Mikhail Gudim <mgudim at gmail.com>
Date: Thu, 27 Jun 2024 14:45:35 -0400
Subject: [PATCH 5/5] Updated tests.

---
 llvm/test/CodeGen/RISCV/early-ifcvt.mir | 637 ++++++++++++------------
 1 file changed, 316 insertions(+), 321 deletions(-)

diff --git a/llvm/test/CodeGen/RISCV/early-ifcvt.mir b/llvm/test/CodeGen/RISCV/early-ifcvt.mir
index f4acd2e3a38ec..cca12583065a2 100644
--- a/llvm/test/CodeGen/RISCV/early-ifcvt.mir
+++ b/llvm/test/CodeGen/RISCV/early-ifcvt.mir
@@ -3,550 +3,545 @@
 # RUN: -run-pass=early-ifcvt -simplify-mir  -o - %s | FileCheck %s
 
 ---
-name: blt
+name:            ifcvt_lt
 tracksRegLiveness: true
-body: |
-  ; CHECK-LABEL: name: blt
+body:             |
+  ; CHECK-LABEL: name: ifcvt_lt
   ; CHECK: bb.0:
-  ; CHECK-NEXT:   liveins: $x10, $x11, $x12
+  ; CHECK-NEXT:   liveins: $x10, $x11
   ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT:   %x:gpr = COPY $x10
+  ; CHECK-NEXT:   %base_addr:gpr = COPY $x10
   ; CHECK-NEXT:   %n:gpr = COPY $x11
-  ; CHECK-NEXT:   %k:gpr = COPY $x12
-  ; CHECK-NEXT:   %zero:gpr = COPY $x0
+  ; CHECK-NEXT:   %i_0: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:   %offset:gpr = PHI %i_inc, %bb.1, %i_0, %bb.0
+  ; CHECK-NEXT:   %addr:gpr = ADD %base_addr, %offset
+  ; CHECK-NEXT:   %x:gpr = LW %addr, 0
+  ; CHECK-NEXT:   %const_5:gpr = ADDI $x0, 5
+  ; CHECK-NEXT:   %const_t:gpr = ADDI $x0, 1
+  ; CHECK-NEXT:   %const_f:gpr = ADDI $x0, 2
+  ; CHECK-NEXT:   [[SLT:%[0-9]+]]:gpr = SLT %x, %const_5
+  ; CHECK-NEXT:   [[VT_MASKC:%[0-9]+]]:gpr = VT_MASKC %const_t, [[SLT]]
+  ; CHECK-NEXT:   [[VT_MASKCN:%[0-9]+]]:gpr = VT_MASKCN %const_f, [[SLT]]
+  ; CHECK-NEXT:   %val:gpr = OR [[VT_MASKC]], [[VT_MASKCN]]
+  ; CHECK-NEXT:   SW %val, %addr, 0
+  ; CHECK-NEXT:   %i_inc:gpr = ADDI %offset, 4
+  ; CHECK-NEXT:   BLT %i_inc, %n, %bb.1
+  ; CHECK-NEXT:   PseudoBR %bb.5
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT: bb.5:
   ; CHECK-NEXT:   PseudoRET
   bb.0:
     successors: %bb.1
-    liveins: $x10, $x11, $x12
+    liveins: $x10, $x11
 
-    %x:gpr = COPY $x10
+    %base_addr:gpr = COPY $x10
     %n:gpr = COPY $x11
-    %k:gpr = COPY $x12
-    %zero:gpr = COPY $x0
+    %i_0: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
+    %offset:gpr = PHI %i_inc, %bb.4, %i_0, %bb.0
+    %addr:gpr = ADD %base_addr, %offset
+    %x:gpr = LW %addr, 0
+    %const_5:gpr = ADDI $x0, 5
+    BLT %x, %const_5, %bb.2
     PseudoBR %bb.3
 
   bb.2:
-    successors: %bb.4
-
-    %add1:gpr = ADDI %x_i, 1
+    %const_t:gpr = ADDI $x0, 1
     PseudoBR %bb.4
 
   bb.3:
-    successors: %bb.4
-
-    %add2:gpr = ADDI %x_i, 2
+    %const_f:gpr = ADDI $x0, 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
+    %val:gpr = PHI %const_t, %bb.2, %const_f, %bb.3
+    SW %val, %addr, 0
+    %i_inc:gpr = ADDI %offset, 4
+    BLT %i_inc, %n, %bb.1
+    PseudoBR %bb.5
 
   bb.5:
     PseudoRET
 ...
 
 ---
-name: bltu
+name:            ifcvt_ltu
 tracksRegLiveness: true
-body: |
-  ; CHECK-LABEL: name: bltu
+body:             |
+  ; CHECK-LABEL: name: ifcvt_ltu
   ; CHECK: bb.0:
-  ; CHECK-NEXT:   liveins: $x10, $x11, $x12
+  ; CHECK-NEXT:   liveins: $x10, $x11
   ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT:   %x:gpr = COPY $x10
+  ; CHECK-NEXT:   %base_addr:gpr = COPY $x10
   ; CHECK-NEXT:   %n:gpr = COPY $x11
-  ; CHECK-NEXT:   %k:gpr = COPY $x12
-  ; CHECK-NEXT:   %zero:gpr = COPY $x0
+  ; CHECK-NEXT:   %i_0: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:   %offset:gpr = PHI %i_inc, %bb.1, %i_0, %bb.0
+  ; CHECK-NEXT:   %addr:gpr = ADD %base_addr, %offset
+  ; CHECK-NEXT:   %x:gpr = LW %addr, 0
+  ; CHECK-NEXT:   %const_5:gpr = ADDI $x0, 5
+  ; CHECK-NEXT:   %const_t:gpr = ADDI $x0, 1
+  ; CHECK-NEXT:   %const_f:gpr = ADDI $x0, 2
+  ; CHECK-NEXT:   [[SLTU:%[0-9]+]]:gpr = SLTU %x, %const_5
+  ; CHECK-NEXT:   [[VT_MASKC:%[0-9]+]]:gpr = VT_MASKC %const_t, [[SLTU]]
+  ; CHECK-NEXT:   [[VT_MASKCN:%[0-9]+]]:gpr = VT_MASKCN %const_f, [[SLTU]]
+  ; CHECK-NEXT:   %val:gpr = OR [[VT_MASKC]], [[VT_MASKCN]]
+  ; CHECK-NEXT:   SW %val, %addr, 0
+  ; CHECK-NEXT:   %i_inc:gpr = ADDI %offset, 4
+  ; CHECK-NEXT:   BLT %i_inc, %n, %bb.1
+  ; CHECK-NEXT:   PseudoBR %bb.5
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT: bb.5:
   ; CHECK-NEXT:   PseudoRET
   bb.0:
     successors: %bb.1
-    liveins: $x10, $x11, $x12
+    liveins: $x10, $x11
 
-    %x:gpr = COPY $x10
+    %base_addr:gpr = COPY $x10
     %n:gpr = COPY $x11
-    %k:gpr = COPY $x12
-    %zero:gpr = COPY $x0
+    %i_0: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
+    %offset:gpr = PHI %i_inc, %bb.4, %i_0, %bb.0
+    %addr:gpr = ADD %base_addr, %offset
+    %x:gpr = LW %addr, 0
+    %const_5:gpr = ADDI $x0, 5
+    BLTU %x, %const_5, %bb.2
     PseudoBR %bb.3
 
   bb.2:
-    successors: %bb.4
-
-    %add1:gpr = ADDI %x_i, 1
+    %const_t:gpr = ADDI $x0, 1
     PseudoBR %bb.4
 
   bb.3:
-    successors: %bb.4
-
-    %add2:gpr = ADDI %x_i, 2
+    %const_f:gpr = ADDI $x0, 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
+    %val:gpr = PHI %const_t, %bb.2, %const_f, %bb.3
+    SW %val, %addr, 0
+    %i_inc:gpr = ADDI %offset, 4
+    BLT %i_inc, %n, %bb.1
+    PseudoBR %bb.5
 
   bb.5:
     PseudoRET
 ...
 
 ---
-name: beq
+name:            ifcvt_ge
 tracksRegLiveness: true
-body: |
-  ; CHECK-LABEL: name: beq
+body:             |
+  ; CHECK-LABEL: name: ifcvt_ge
   ; CHECK: bb.0:
-  ; CHECK-NEXT:   liveins: $x10, $x11, $x12
+  ; CHECK-NEXT:   liveins: $x10, $x11
   ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT:   %x:gpr = COPY $x10
+  ; CHECK-NEXT:   %base_addr:gpr = COPY $x10
   ; CHECK-NEXT:   %n:gpr = COPY $x11
-  ; CHECK-NEXT:   %k:gpr = COPY $x12
-  ; CHECK-NEXT:   %zero:gpr = COPY $x0
+  ; CHECK-NEXT:   %i_0: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:   %offset:gpr = PHI %i_inc, %bb.1, %i_0, %bb.0
+  ; CHECK-NEXT:   %addr:gpr = ADD %base_addr, %offset
+  ; CHECK-NEXT:   %x:gpr = LW %addr, 0
+  ; CHECK-NEXT:   %const_5:gpr = ADDI $x0, 5
+  ; CHECK-NEXT:   %const_t:gpr = ADDI $x0, 1
+  ; CHECK-NEXT:   %const_f:gpr = ADDI $x0, 2
+  ; CHECK-NEXT:   [[SLT:%[0-9]+]]:gpr = SLT %x, %const_5
+  ; CHECK-NEXT:   [[XORI:%[0-9]+]]:gpr = XORI [[SLT]], 1
+  ; CHECK-NEXT:   [[VT_MASKC:%[0-9]+]]:gpr = VT_MASKC %const_f, [[XORI]]
+  ; CHECK-NEXT:   [[VT_MASKCN:%[0-9]+]]:gpr = VT_MASKCN %const_t, [[XORI]]
+  ; CHECK-NEXT:   %val:gpr = OR [[VT_MASKC]], [[VT_MASKCN]]
+  ; CHECK-NEXT:   SW %val, %addr, 0
+  ; CHECK-NEXT:   %i_inc:gpr = ADDI %offset, 4
+  ; CHECK-NEXT:   BLT %i_inc, %n, %bb.1
+  ; CHECK-NEXT:   PseudoBR %bb.5
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT: bb.5:
   ; CHECK-NEXT:   PseudoRET
   bb.0:
     successors: %bb.1
-    liveins: $x10, $x11, $x12
+    liveins: $x10, $x11
 
-    %x:gpr = COPY $x10
+    %base_addr:gpr = COPY $x10
     %n:gpr = COPY $x11
-    %k:gpr = COPY $x12
-    %zero:gpr = COPY $x0
+    %i_0: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
+    %offset:gpr = PHI %i_inc, %bb.4, %i_0, %bb.0
+    %addr:gpr = ADD %base_addr, %offset
+    %x:gpr = LW %addr, 0
+    %const_5:gpr = ADDI $x0, 5
+    BGE %x, %const_5, %bb.2
     PseudoBR %bb.3
 
   bb.2:
-    successors: %bb.4
-
-    %add1:gpr = ADDI %x_i, 1
+    %const_t:gpr = ADDI $x0, 1
     PseudoBR %bb.4
 
   bb.3:
-    successors: %bb.4
-
-    %add2:gpr = ADDI %x_i, 2
+    %const_f:gpr = ADDI $x0, 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
+    %val:gpr = PHI %const_t, %bb.2, %const_f, %bb.3
+    SW %val, %addr, 0
+    %i_inc:gpr = ADDI %offset, 4
+    BLT %i_inc, %n, %bb.1
+    PseudoBR %bb.5
 
   bb.5:
     PseudoRET
 ...
 
 ---
-name: bne
+name:            ifcvt_geu
 tracksRegLiveness: true
-body: |
-  ; CHECK-LABEL: name: bne
+body:             |
+  ; CHECK-LABEL: name: ifcvt_geu
   ; CHECK: bb.0:
-  ; CHECK-NEXT:   liveins: $x10, $x11, $x12
+  ; CHECK-NEXT:   liveins: $x10, $x11
   ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT:   %x:gpr = COPY $x10
+  ; CHECK-NEXT:   %base_addr:gpr = COPY $x10
   ; CHECK-NEXT:   %n:gpr = COPY $x11
-  ; CHECK-NEXT:   %k:gpr = COPY $x12
-  ; CHECK-NEXT:   %zero:gpr = COPY $x0
+  ; CHECK-NEXT:   %i_0: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:   %offset:gpr = PHI %i_inc, %bb.1, %i_0, %bb.0
+  ; CHECK-NEXT:   %addr:gpr = ADD %base_addr, %offset
+  ; CHECK-NEXT:   %x:gpr = LW %addr, 0
+  ; CHECK-NEXT:   %const_5:gpr = ADDI $x0, 5
+  ; CHECK-NEXT:   %const_t:gpr = ADDI $x0, 1
+  ; CHECK-NEXT:   %const_f:gpr = ADDI $x0, 2
+  ; CHECK-NEXT:   [[SLTU:%[0-9]+]]:gpr = SLTU %x, %const_5
+  ; CHECK-NEXT:   [[XORI:%[0-9]+]]:gpr = XORI [[SLTU]], 1
+  ; CHECK-NEXT:   [[VT_MASKC:%[0-9]+]]:gpr = VT_MASKC %const_f, [[XORI]]
+  ; CHECK-NEXT:   [[VT_MASKCN:%[0-9]+]]:gpr = VT_MASKCN %const_t, [[XORI]]
+  ; CHECK-NEXT:   %val:gpr = OR [[VT_MASKC]], [[VT_MASKCN]]
+  ; CHECK-NEXT:   SW %val, %addr, 0
+  ; CHECK-NEXT:   %i_inc:gpr = ADDI %offset, 4
+  ; CHECK-NEXT:   BLT %i_inc, %n, %bb.1
+  ; CHECK-NEXT:   PseudoBR %bb.5
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT: bb.5:
   ; CHECK-NEXT:   PseudoRET
   bb.0:
     successors: %bb.1
-    liveins: $x10, $x11, $x12
+    liveins: $x10, $x11
 
-    %x:gpr = COPY $x10
+    %base_addr:gpr = COPY $x10
     %n:gpr = COPY $x11
-    %k:gpr = COPY $x12
-    %zero:gpr = COPY $x0
+    %i_0: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
+    %offset:gpr = PHI %i_inc, %bb.4, %i_0, %bb.0
+    %addr:gpr = ADD %base_addr, %offset
+    %x:gpr = LW %addr, 0
+    %const_5:gpr = ADDI $x0, 5
+    BGEU %x, %const_5, %bb.2
     PseudoBR %bb.3
 
   bb.2:
-    successors: %bb.4
-
-    %add1:gpr = ADDI %x_i, 1
+    %const_t:gpr = ADDI $x0, 1
     PseudoBR %bb.4
 
   bb.3:
-    successors: %bb.4
-
-    %add2:gpr = ADDI %x_i, 2
+    %const_f:gpr = ADDI $x0, 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
+    %val:gpr = PHI %const_t, %bb.2, %const_f, %bb.3
+    SW %val, %addr, 0
+    %i_inc:gpr = ADDI %offset, 4
+    BLT %i_inc, %n, %bb.1
+    PseudoBR %bb.5
 
   bb.5:
     PseudoRET
 ...
 
 ---
-name: bge
+name:            ifcvt_eq
 tracksRegLiveness: true
-body: |
-  ; CHECK-LABEL: name: bge
+body:             |
+  ; CHECK-LABEL: name: ifcvt_eq
   ; CHECK: bb.0:
-  ; CHECK-NEXT:   liveins: $x10, $x11, $x12
+  ; CHECK-NEXT:   liveins: $x10, $x11
   ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT:   %x:gpr = COPY $x10
+  ; CHECK-NEXT:   %base_addr:gpr = COPY $x10
   ; CHECK-NEXT:   %n:gpr = COPY $x11
-  ; CHECK-NEXT:   %k:gpr = COPY $x12
-  ; CHECK-NEXT:   %zero:gpr = COPY $x0
+  ; CHECK-NEXT:   %i_0: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:   %offset:gpr = PHI %i_inc, %bb.1, %i_0, %bb.0
+  ; CHECK-NEXT:   %addr:gpr = ADD %base_addr, %offset
+  ; CHECK-NEXT:   %x:gpr = LW %addr, 0
+  ; CHECK-NEXT:   %const_5:gpr = ADDI $x0, 5
+  ; CHECK-NEXT:   %const_t:gpr = ADDI $x0, 1
+  ; CHECK-NEXT:   %const_f:gpr = ADDI $x0, 2
+  ; CHECK-NEXT:   [[XOR:%[0-9]+]]:gpr = XOR %x, %const_5
+  ; CHECK-NEXT:   [[SLTIU:%[0-9]+]]:gpr = SLTIU [[XOR]], 1
+  ; CHECK-NEXT:   [[VT_MASKC:%[0-9]+]]:gpr = VT_MASKC %const_t, [[SLTIU]]
+  ; CHECK-NEXT:   [[VT_MASKCN:%[0-9]+]]:gpr = VT_MASKCN %const_f, [[SLTIU]]
+  ; CHECK-NEXT:   %val:gpr = OR [[VT_MASKC]], [[VT_MASKCN]]
+  ; CHECK-NEXT:   SW %val, %addr, 0
+  ; CHECK-NEXT:   %i_inc:gpr = ADDI %offset, 4
+  ; CHECK-NEXT:   BLT %i_inc, %n, %bb.1
+  ; CHECK-NEXT:   PseudoBR %bb.5
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT: bb.5:
   ; CHECK-NEXT:   PseudoRET
   bb.0:
     successors: %bb.1
-    liveins: $x10, $x11, $x12
+    liveins: $x10, $x11
 
-    %x:gpr = COPY $x10
+    %base_addr:gpr = COPY $x10
     %n:gpr = COPY $x11
-    %k:gpr = COPY $x12
-    %zero:gpr = COPY $x0
+    %i_0: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
+    %offset:gpr = PHI %i_inc, %bb.4, %i_0, %bb.0
+    %addr:gpr = ADD %base_addr, %offset
+    %x:gpr = LW %addr, 0
+    %const_5:gpr = ADDI $x0, 5
+    BEQ %x, %const_5, %bb.2
     PseudoBR %bb.3
 
   bb.2:
-    successors: %bb.4
-
-    %add1:gpr = ADDI %x_i, 1
+    %const_t:gpr = ADDI $x0, 1
     PseudoBR %bb.4
 
   bb.3:
-    successors: %bb.4
-
-    %add2:gpr = ADDI %x_i, 2
+    %const_f:gpr = ADDI $x0, 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
+    %val:gpr = PHI %const_t, %bb.2, %const_f, %bb.3
+    SW %val, %addr, 0
+    %i_inc:gpr = ADDI %offset, 4
+    BLT %i_inc, %n, %bb.1
+    PseudoBR %bb.5
 
   bb.5:
     PseudoRET
 ...
 
 ---
-name: bgeu
+name:            ifcvt_ne
 tracksRegLiveness: true
-body: |
-  ; CHECK-LABEL: name: bgeu
+body:             |
+  ; CHECK-LABEL: name: ifcvt_ne
   ; CHECK: bb.0:
-  ; CHECK-NEXT:   liveins: $x10, $x11, $x12
+  ; CHECK-NEXT:   liveins: $x10, $x11
   ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT:   %x:gpr = COPY $x10
+  ; CHECK-NEXT:   %base_addr:gpr = COPY $x10
   ; CHECK-NEXT:   %n:gpr = COPY $x11
-  ; CHECK-NEXT:   %k:gpr = COPY $x12
-  ; CHECK-NEXT:   %zero:gpr = COPY $x0
+  ; CHECK-NEXT:   %i_0: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:   %offset:gpr = PHI %i_inc, %bb.1, %i_0, %bb.0
+  ; CHECK-NEXT:   %addr:gpr = ADD %base_addr, %offset
+  ; CHECK-NEXT:   %x:gpr = LW %addr, 0
+  ; CHECK-NEXT:   %const_5:gpr = ADDI $x0, 5
+  ; CHECK-NEXT:   %const_t:gpr = ADDI $x0, 1
+  ; CHECK-NEXT:   %const_f:gpr = ADDI $x0, 2
+  ; CHECK-NEXT:   [[XOR:%[0-9]+]]:gpr = XOR %x, %const_5
+  ; CHECK-NEXT:   [[SLTU:%[0-9]+]]:gpr = SLTU $x0, [[XOR]]
+  ; CHECK-NEXT:   [[VT_MASKC:%[0-9]+]]:gpr = VT_MASKC %const_t, [[SLTU]]
+  ; CHECK-NEXT:   [[VT_MASKCN:%[0-9]+]]:gpr = VT_MASKCN %const_f, [[SLTU]]
+  ; CHECK-NEXT:   %val:gpr = OR [[VT_MASKC]], [[VT_MASKCN]]
+  ; CHECK-NEXT:   SW %val, %addr, 0
+  ; CHECK-NEXT:   %i_inc:gpr = ADDI %offset, 4
+  ; CHECK-NEXT:   BLT %i_inc, %n, %bb.1
+  ; CHECK-NEXT:   PseudoBR %bb.5
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT: bb.5:
   ; CHECK-NEXT:   PseudoRET
   bb.0:
     successors: %bb.1
-    liveins: $x10, $x11, $x12
+    liveins: $x10, $x11
 
-    %x:gpr = COPY $x10
+    %base_addr:gpr = COPY $x10
     %n:gpr = COPY $x11
-    %k:gpr = COPY $x12
-    %zero:gpr = COPY $x0
+    %i_0: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
+    %offset:gpr = PHI %i_inc, %bb.4, %i_0, %bb.0
+    %addr:gpr = ADD %base_addr, %offset
+    %x:gpr = LW %addr, 0
+    %const_5:gpr = ADDI $x0, 5
+    BNE %x, %const_5, %bb.2
     PseudoBR %bb.3
 
   bb.2:
-    successors: %bb.4
-
-    %add1:gpr = ADDI %x_i, 1
+    %const_t:gpr = ADDI $x0, 1
     PseudoBR %bb.4
 
   bb.3:
-    successors: %bb.4
-
-    %add2:gpr = ADDI %x_i, 2
+    %const_f:gpr = ADDI $x0, 2
     PseudoBR %bb.4
 
   bb.4:
-    successors: %bb.1, %bb.5
+    %val:gpr = PHI %const_t, %bb.2, %const_f, %bb.3
+    SW %val, %addr, 0
+    %i_inc:gpr = ADDI %offset, 4
+    BLT %i_inc, %n, %bb.1
+    PseudoBR %bb.5
+
+  bb.5:
+    PseudoRET
+...
+
+---
+name:            ifcvt_eqz
+tracksRegLiveness: true
+body:             |
+  ; CHECK-LABEL: name: ifcvt_eqz
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   liveins: $x10, $x11
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   %base_addr:gpr = COPY $x10
+  ; CHECK-NEXT:   %n:gpr = COPY $x11
+  ; CHECK-NEXT:   %i_0:gpr = COPY $x0
+  ; CHECK-NEXT:   PseudoBR %bb.1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   %offset:gpr = PHI %i_inc, %bb.1, %i_0, %bb.0
+  ; CHECK-NEXT:   %addr:gpr = ADD %base_addr, %offset
+  ; CHECK-NEXT:   %x:gpr = LW %addr, 0
+  ; CHECK-NEXT:   %const_t:gpr = ADDI $x0, 1
+  ; CHECK-NEXT:   %const_f:gpr = ADDI $x0, 2
+  ; CHECK-NEXT:   [[SLTIU:%[0-9]+]]:gpr = SLTIU %x, 1
+  ; CHECK-NEXT:   [[VT_MASKC:%[0-9]+]]:gpr = VT_MASKC %const_t, [[SLTIU]]
+  ; CHECK-NEXT:   [[VT_MASKCN:%[0-9]+]]:gpr = VT_MASKCN %const_f, [[SLTIU]]
+  ; CHECK-NEXT:   %val:gpr = OR [[VT_MASKC]], [[VT_MASKCN]]
+  ; CHECK-NEXT:   SW %val, %addr, 0
+  ; CHECK-NEXT:   %i_inc:gpr = ADDI %offset, 4
+  ; CHECK-NEXT:   BLT %i_inc, %n, %bb.1
+  ; CHECK-NEXT:   PseudoBR %bb.5
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.5:
+  ; CHECK-NEXT:   PseudoRET
+  bb.0:
+    successors: %bb.1
+    liveins: $x10, $x11
 
-    %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
+    %base_addr:gpr = COPY $x10
+    %n:gpr = COPY $x11
+    %i_0:gpr = COPY $x0
     PseudoBR %bb.1
 
+  bb.1:
+    %offset:gpr = PHI %i_inc, %bb.4, %i_0, %bb.0
+    %addr:gpr = ADD %base_addr, %offset
+    %x:gpr = LW %addr, 0
+    BEQ %x, $x0, %bb.2
+    PseudoBR %bb.3
+
+  bb.2:
+    %const_t:gpr = ADDI $x0, 1
+    PseudoBR %bb.4
+
+  bb.3:
+    %const_f:gpr = ADDI $x0, 2
+    PseudoBR %bb.4
+
+  bb.4:
+    %val:gpr = PHI %const_t, %bb.2, %const_f, %bb.3
+    SW %val, %addr, 0
+    %i_inc:gpr = ADDI %offset, 4
+    BLT %i_inc, %n, %bb.1
+    PseudoBR %bb.5
+
   bb.5:
     PseudoRET
 ...
 
 ---
-name: needs_rc_copy_fpr64
+name:            ifcvt_lt_needs_rc_copies
 tracksRegLiveness: true
-body: |
-  ; CHECK-LABEL: name: needs_rc_copy_fpr64
+body:             |
+  ; CHECK-LABEL: name: ifcvt_lt_needs_rc_copies
   ; CHECK: bb.0:
-  ; CHECK-NEXT:   liveins: $x10, $x11, $x12
+  ; CHECK-NEXT:   liveins: $x10, $x11
   ; CHECK-NEXT: {{  $}}
-  ; CHECK-NEXT:   %x:gpr = COPY $x10
+  ; CHECK-NEXT:   %base_addr:gpr = COPY $x10
   ; CHECK-NEXT:   %n:gpr = COPY $x11
-  ; CHECK-NEXT:   %k:gpr = COPY $x12
-  ; CHECK-NEXT:   %zero:gpr = COPY $x0
+  ; CHECK-NEXT:   %i_0: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:   %offset:gpr = PHI %i_inc, %bb.1, %i_0, %bb.0
+  ; CHECK-NEXT:   %addr:gpr = ADD %base_addr, %offset
+  ; CHECK-NEXT:   %x:gpr = LW %addr, 0
+  ; CHECK-NEXT:   %const_1:gpr = ADDI $x0, 1
+  ; CHECK-NEXT:   %const_t:fpr64 = nofpexcept FCVT_D_W %const_1, 0
+  ; CHECK-NEXT:   %const_2:gpr = ADDI $x0, 2
+  ; CHECK-NEXT:   %const_f:fpr64 = nofpexcept FCVT_D_W %const_2, 0
+  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:gpr = COPY %const_t
+  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:gpr = COPY %const_f
+  ; CHECK-NEXT:   [[SLT:%[0-9]+]]:gpr = SLT %x, $x0
   ; 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:   %val_fp:fpr64 = COPY [[OR]]
+  ; CHECK-NEXT:   %val:gpr = nofpexcept FCVT_W_D %val_fp, 1
+  ; CHECK-NEXT:   SW %val, %addr, 0
+  ; CHECK-NEXT:   %i_inc:gpr = ADDI %offset, 4
+  ; CHECK-NEXT:   BLT %i_inc, %n, %bb.1
+  ; CHECK-NEXT:   PseudoBR %bb.5
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT: bb.5:
   ; CHECK-NEXT:   PseudoRET
   bb.0:
     successors: %bb.1
-    liveins: $x10, $x11, $x12
+    liveins: $x10, $x11
 
-    %x:gpr = COPY $x10
+    %base_addr:gpr = COPY $x10
     %n:gpr = COPY $x11
-    %k:gpr = COPY $x12
-    %zero:gpr = COPY $x0
+    %i_0: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
+    %offset:gpr = PHI %i_inc, %bb.4, %i_0, %bb.0
+    %addr:gpr = ADD %base_addr, %offset
+    %x:gpr = LW %addr, 0
+    BLT %x, $x0, %bb.2
     PseudoBR %bb.3
 
   bb.2:
-    successors: %bb.4
-
-    %add1:gpr = ADDI %x_i, 1
-    %itofp1:fpr64 = nofpexcept FCVT_D_W %add1, 0
+    %const_1:gpr = ADDI $x0, 1
+    %const_t:fpr64 = nofpexcept FCVT_D_W %const_1, 0
     PseudoBR %bb.4
 
   bb.3:
-    successors: %bb.4
-
-    %add2:gpr = ADDI %x_i, 2
-    %itofp2:fpr64 = nofpexcept FCVT_D_W %add2, 0
+    %const_2:gpr = ADDI $x0, 2
+    %const_f:fpr64 = nofpexcept FCVT_D_W %const_2, 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
+    %val_fp:fpr64 = PHI %const_t, %bb.2, %const_f, %bb.3
+    %val:gpr = nofpexcept FCVT_W_D %val_fp, 1
+    SW %val, %addr, 0
+    %i_inc:gpr = ADDI %offset, 4
+    BLT %i_inc, %n, %bb.1
+    PseudoBR %bb.5
 
   bb.5:
     PseudoRET



More information about the llvm-commits mailing list