-
Notifications
You must be signed in to change notification settings - Fork 12.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RISCV] Codegen support for XCVbi extension #89719
Conversation
@llvm/pr-subscribers-backend-risc-v Author: Liao Chunyu (ChunyuLiao) ChangesFull diff: https://github.com/llvm/llvm-project/pull/89719.diff 7 Files Affected:
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 41483c49ae03cd..d9f3ed8833098f 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -7608,6 +7608,15 @@ SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
TargetCC = DAG.getCondCode(ISD::getSetCCInverse(CCVal, LHS.getValueType()));
}
+ if (Subtarget.hasVendorXCVbi() &&
+ (CCVal == ISD::SETEQ || CCVal == ISD::SETNE) &&
+ isa<ConstantSDNode>(RHS)) {
+ int32_t RHSImm = cast<ConstantSDNode>(RHS)->getSExtValue();
+ if (isInt<5>(RHSImm)) {
+ SDValue Ops[] = {LHS, RHS, TargetCC, TrueV, FalseV};
+ return DAG.getNode(RISCVISD::SELECTIMM_CC, DL, VT, Ops);
+ }
+ }
SDValue Ops[] = {LHS, RHS, TargetCC, TrueV, FalseV};
return DAG.getNode(RISCVISD::SELECT_CC, DL, VT, Ops);
}
@@ -17656,7 +17665,9 @@ static MachineBasicBlock *emitSelectPseudo(MachineInstr &MI,
// is checked here and handled by a separate function -
// EmitLoweredCascadedSelect.
Register LHS = MI.getOperand(1).getReg();
- Register RHS = MI.getOperand(2).getReg();
+ Register RHS;
+ if (MI.getOpcode() != RISCV::Select_IMM_Using_CC_GPR)
+ RHS = MI.getOperand(2).getReg();
auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm());
SmallVector<MachineInstr *, 4> SelectDebugValues;
@@ -17727,10 +17738,16 @@ static MachineBasicBlock *emitSelectPseudo(MachineInstr &MI,
HeadMBB->addSuccessor(TailMBB);
// Insert appropriate branch.
- BuildMI(HeadMBB, DL, TII.getBrCond(CC))
- .addReg(LHS)
- .addReg(RHS)
- .addMBB(TailMBB);
+ if (MI.getOperand(2).isImm())
+ BuildMI(HeadMBB, DL, TII.getBrCond(CC, MI.getOperand(2).isImm()))
+ .addReg(LHS)
+ .addImm(MI.getOperand(2).getImm())
+ .addMBB(TailMBB);
+ else
+ BuildMI(HeadMBB, DL, TII.getBrCond(CC))
+ .addReg(LHS)
+ .addReg(RHS)
+ .addMBB(TailMBB);
// IfFalseMBB just falls through to TailMBB.
IfFalseMBB->addSuccessor(TailMBB);
@@ -17741,7 +17758,8 @@ static MachineBasicBlock *emitSelectPseudo(MachineInstr &MI,
auto InsertionPoint = TailMBB->begin();
while (SelectMBBI != SelectEnd) {
auto Next = std::next(SelectMBBI);
- if (isSelectPseudo(*SelectMBBI)) {
+ if (isSelectPseudo(*SelectMBBI) ||
+ MI.getOpcode() == RISCV::Select_IMM_Using_CC_GPR) {
// %Result = phi [ %TrueValue, HeadMBB ], [ %FalseValue, IfFalseMBB ]
BuildMI(*TailMBB, InsertionPoint, SelectMBBI->getDebugLoc(),
TII.get(RISCV::PHI), SelectMBBI->getOperand(0).getReg())
@@ -18035,6 +18053,7 @@ RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
"ReadCounterWide is only to be used on riscv32");
return emitReadCounterWidePseudo(MI, BB);
case RISCV::Select_GPR_Using_CC_GPR:
+ case RISCV::Select_IMM_Using_CC_GPR:
case RISCV::Select_FPR16_Using_CC_GPR:
case RISCV::Select_FPR16INX_Using_CC_GPR:
case RISCV::Select_FPR32_Using_CC_GPR:
@@ -19660,6 +19679,7 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
NODE_NAME_CASE(MRET_GLUE)
NODE_NAME_CASE(CALL)
NODE_NAME_CASE(SELECT_CC)
+ NODE_NAME_CASE(SELECTIMM_CC)
NODE_NAME_CASE(BR_CC)
NODE_NAME_CASE(BuildPairF64)
NODE_NAME_CASE(SplitF64)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index b10da3d40befb7..e0d3f9ee655faa 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -41,6 +41,7 @@ enum NodeType : unsigned {
/// The lhs and rhs are XLenVT integers. The true and false values can be
/// integer or floating point.
SELECT_CC,
+ SELECTIMM_CC,
BR_CC,
BuildPairF64,
SplitF64,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 8331fc0b8c3024..12d23bef0f602b 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -826,6 +826,10 @@ static RISCVCC::CondCode getCondFromBranchOpc(unsigned Opc) {
switch (Opc) {
default:
return RISCVCC::COND_INVALID;
+ case RISCV::CV_BEQIMM:
+ return RISCVCC::COND_EQ;
+ case RISCV::CV_BNEIMM:
+ return RISCVCC::COND_NE;
case RISCV::BEQ:
return RISCVCC::COND_EQ;
case RISCV::BNE:
@@ -856,14 +860,14 @@ static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target,
Cond.push_back(LastInst.getOperand(1));
}
-unsigned RISCVCC::getBrCond(RISCVCC::CondCode CC) {
+unsigned RISCVCC::getBrCond(RISCVCC::CondCode CC, bool Imm) {
switch (CC) {
default:
llvm_unreachable("Unknown condition code!");
case RISCVCC::COND_EQ:
- return RISCV::BEQ;
+ return Imm ? RISCV::CV_BEQIMM : RISCV::BEQ;
case RISCVCC::COND_NE:
- return RISCV::BNE;
+ return Imm ? RISCV::CV_BNEIMM : RISCV::BNE;
case RISCVCC::COND_LT:
return RISCV::BLT;
case RISCVCC::COND_GE:
@@ -875,8 +879,9 @@ unsigned RISCVCC::getBrCond(RISCVCC::CondCode CC) {
}
}
-const MCInstrDesc &RISCVInstrInfo::getBrCond(RISCVCC::CondCode CC) const {
- return get(RISCVCC::getBrCond(CC));
+const MCInstrDesc &RISCVInstrInfo::getBrCond(RISCVCC::CondCode CC,
+ bool Imm) const {
+ return get(RISCVCC::getBrCond(CC, Imm));
}
RISCVCC::CondCode RISCVCC::getOppositeBranchCondition(RISCVCC::CondCode CC) {
@@ -1025,8 +1030,10 @@ unsigned RISCVInstrInfo::insertBranch(
// Either a one or two-way conditional branch.
auto CC = static_cast<RISCVCC::CondCode>(Cond[0].getImm());
- MachineInstr &CondMI =
- *BuildMI(&MBB, DL, getBrCond(CC)).add(Cond[1]).add(Cond[2]).addMBB(TBB);
+ MachineInstr &CondMI = *BuildMI(&MBB, DL, getBrCond(CC, Cond[2].isImm()))
+ .add(Cond[1])
+ .add(Cond[2])
+ .addMBB(TBB);
if (BytesAdded)
*BytesAdded += getInstSizeInBytes(CondMI);
@@ -1250,6 +1257,8 @@ bool RISCVInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
case RISCV::BGE:
case RISCV::BLTU:
case RISCV::BGEU:
+ case RISCV::CV_BEQIMM:
+ case RISCV::CV_BNEIMM:
return isIntN(13, BrOffset);
case RISCV::JAL:
case RISCV::PseudoBR:
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.h b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
index 70fe7da85be0e7..38badb39deea43 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.h
@@ -45,7 +45,7 @@ enum CondCode {
};
CondCode getOppositeBranchCondition(CondCode);
-unsigned getBrCond(CondCode CC);
+unsigned getBrCond(CondCode CC, bool Imm = false);
} // end of namespace RISCVCC
@@ -65,7 +65,7 @@ class RISCVInstrInfo : public RISCVGenInstrInfo {
explicit RISCVInstrInfo(RISCVSubtarget &STI);
MCInst getNop() const override;
- const MCInstrDesc &getBrCond(RISCVCC::CondCode CC) const;
+ const MCInstrDesc &getBrCond(RISCVCC::CondCode CC, bool Imm = false) const;
Register isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const override;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
index 924e91e15c348f..36c9298c6f2f6b 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXCV.td
@@ -10,6 +10,14 @@
//
//===----------------------------------------------------------------------===//
+def SDT_RISCVSelectImmCC : SDTypeProfile<1, 5, [SDTCisSameAs<0, 1>,
+ SDTCisVT<2, i32>,
+ SDTCisVT<3, OtherVT>,
+ SDTCisSameAs<0, 4>,
+ SDTCisSameAs<4, 5>]>;
+
+def riscv_selectimmcc : SDNode<"RISCVISD::SELECTIMM_CC", SDT_RISCVSelectImmCC>;
+
let DecoderNamespace = "XCVbitmanip" in {
class CVInstBitManipRII<bits<2> funct2, bits<3> funct3, dag outs, dag ins,
string opcodestr, string argstr>
@@ -704,3 +712,40 @@ let Predicates = [HasVendorXCVbitmanip, IsRV32] in {
(CV_BITREV GPR:$rs1, cv_tuimm2:$radix, cv_tuimm5:$pts)>;
def : Pat<(bitreverse (XLenVT GPR:$rs)), (CV_BITREV GPR:$rs, 0, 0)>;
}
+
+//===----------------------------------------------------------------------===//
+// Patterns for immediate branching operations
+//===----------------------------------------------------------------------===//
+
+def IMMCCtoRISCVCC : SDNodeXForm<riscv_selectimmcc, [{
+ ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
+ RISCVCC::CondCode BrCC = getRISCVCCForIntCC(CC);
+ return CurDAG->getTargetConstant(BrCC, SDLoc(N), Subtarget->getXLenVT());
+}]>;
+
+def riscv_selectimmcc_frag : PatFrag<(ops node:$lhs, node:$rhs, node:$cc,
+ node:$truev, node:$falsev),
+ (riscv_selectimmcc node:$lhs, node:$rhs,
+ node:$cc, node:$truev,
+ node:$falsev), [{}],
+ IMMCCtoRISCVCC>;
+
+let Predicates = [HasVendorXCVbi, IsRV32] in {
+ def : Pat<(riscv_brcc GPR:$rs1, simm5:$imm5, SETEQ, bb:$imm12),
+ (CV_BEQIMM GPR:$rs1, simm5:$imm5, simm13_lsb0:$imm12)>;
+ def : Pat<(riscv_brcc GPR:$rs1, simm5:$imm5, SETNE, bb:$imm12),
+ (CV_BNEIMM GPR:$rs1, simm5:$imm5, simm13_lsb0:$imm12)>;
+
+ let usesCustomInserter = 1 in
+ def Select_IMM_Using_CC_GPR : Pseudo<(outs GPR:$dst),
+ (ins GPR:$lhs, simm5:$imm5, ixlenimm:$cc,
+ GPR:$truev, GPR:$falsev),
+ [(set GPR:$dst,
+ (riscv_selectimmcc_frag:$cc (i32 GPR:$lhs), simm5:$imm5, cond,
+ (i32 GPR:$truev), GPR:$falsev))]>;
+
+ def : Pat<(riscv_selectimmcc_frag:$cc (i32 GPR:$lhs), simm5:$Constant, SETEQ, (i32 GPR:$truev),
+ GPR:$falsev),
+ (Select_IMM_Using_CC_GPR GPR:$lhs, simm5:$Constant,
+ (IMMCCtoRISCVCC $cc), GPR:$truev, GPR:$falsev)>;
+}
diff --git a/llvm/lib/Target/RISCV/RISCVRedundantCopyElimination.cpp b/llvm/lib/Target/RISCV/RISCVRedundantCopyElimination.cpp
index 61d605fda3f53a..65ff67b424796c 100644
--- a/llvm/lib/Target/RISCV/RISCVRedundantCopyElimination.cpp
+++ b/llvm/lib/Target/RISCV/RISCVRedundantCopyElimination.cpp
@@ -77,9 +77,11 @@ guaranteesZeroRegInBlock(MachineBasicBlock &MBB,
assert(Cond.size() == 3 && "Unexpected number of operands");
assert(TBB != nullptr && "Expected branch target basic block");
auto CC = static_cast<RISCVCC::CondCode>(Cond[0].getImm());
- if (CC == RISCVCC::COND_EQ && Cond[2].getReg() == RISCV::X0 && TBB == &MBB)
+ if (CC == RISCVCC::COND_EQ && Cond[2].isReg() &&
+ Cond[2].getReg() == RISCV::X0 && TBB == &MBB)
return true;
- if (CC == RISCVCC::COND_NE && Cond[2].getReg() == RISCV::X0 && TBB != &MBB)
+ if (CC == RISCVCC::COND_NE && Cond[2].isReg() &&
+ Cond[2].getReg() == RISCV::X0 && TBB != &MBB)
return true;
return false;
}
diff --git a/llvm/test/CodeGen/RISCV/xcvbi.ll b/llvm/test/CodeGen/RISCV/xcvbi.ll
new file mode 100644
index 00000000000000..afd30faa56f90b
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/xcvbi.ll
@@ -0,0 +1,248 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -O0 -mtriple=riscv32 -mattr=+xcvbi -verify-machineinstrs < %s \
+; RUN: | FileCheck %s --check-prefixes=CHECK_NOPT
+; RUN: llc -O3 -mtriple=riscv32 -mattr=+xcvbi -verify-machineinstrs < %s \
+; RUN: | FileCheck %s --check-prefixes=CHECK_OPT
+
+define i32 @beqimm(i32 %a) {
+; CHECK_NOPT-LABEL: beqimm:
+; CHECK_NOPT: # %bb.0:
+; CHECK_NOPT-NEXT: cv.beqimm a0, 5, .LBB0_2
+; CHECK_NOPT-NEXT: j .LBB0_1
+; CHECK_NOPT-NEXT: .LBB0_1: # %f
+; CHECK_NOPT-NEXT: li a0, 0
+; CHECK_NOPT-NEXT: ret
+; CHECK_NOPT-NEXT: .LBB0_2: # %t
+; CHECK_NOPT-NEXT: li a0, 1
+; CHECK_NOPT-NEXT: ret
+;
+; CHECK_OPT-LABEL: beqimm:
+; CHECK_OPT: # %bb.0:
+; CHECK_OPT-NEXT: cv.bneimm a0, 5, .LBB0_2
+; CHECK_OPT-NEXT: # %bb.1: # %t
+; CHECK_OPT-NEXT: li a0, 1
+; CHECK_OPT-NEXT: ret
+; CHECK_OPT-NEXT: .LBB0_2: # %f
+; CHECK_OPT-NEXT: li a0, 0
+; CHECK_OPT-NEXT: ret
+ %1 = icmp eq i32 %a, 5
+ br i1 %1, label %t, label %f
+f:
+ ret i32 0
+t:
+ ret i32 1
+}
+
+define i32 @bneimm(i32 %a) {
+; CHECK_NOPT-LABEL: bneimm:
+; CHECK_NOPT: # %bb.0:
+; CHECK_NOPT-NEXT: cv.bneimm a0, 5, .LBB1_2
+; CHECK_NOPT-NEXT: j .LBB1_1
+; CHECK_NOPT-NEXT: .LBB1_1: # %f
+; CHECK_NOPT-NEXT: li a0, 0
+; CHECK_NOPT-NEXT: ret
+; CHECK_NOPT-NEXT: .LBB1_2: # %t
+; CHECK_NOPT-NEXT: li a0, 1
+; CHECK_NOPT-NEXT: ret
+;
+; CHECK_OPT-LABEL: bneimm:
+; CHECK_OPT: # %bb.0:
+; CHECK_OPT-NEXT: cv.beqimm a0, 5, .LBB1_2
+; CHECK_OPT-NEXT: # %bb.1: # %t
+; CHECK_OPT-NEXT: li a0, 1
+; CHECK_OPT-NEXT: ret
+; CHECK_OPT-NEXT: .LBB1_2: # %f
+; CHECK_OPT-NEXT: li a0, 0
+; CHECK_OPT-NEXT: ret
+ %1 = icmp ne i32 %a, 5
+ br i1 %1, label %t, label %f
+f:
+ ret i32 0
+t:
+ ret i32 1
+}
+
+define i32 @select_beqimm_1(i32 %a, i32 %x, i32 %y) {
+; CHECK_NOPT-LABEL: select_beqimm_1:
+; CHECK_NOPT: # %bb.0: # %entry
+; CHECK_NOPT-NEXT: addi sp, sp, -16
+; CHECK_NOPT-NEXT: .cfi_def_cfa_offset 16
+; CHECK_NOPT-NEXT: sw a1, 8(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: sw a2, 12(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: cv.beqimm a0, -16, .LBB2_2
+; CHECK_NOPT-NEXT: # %bb.1: # %entry
+; CHECK_NOPT-NEXT: lw a0, 8(sp) # 4-byte Folded Reload
+; CHECK_NOPT-NEXT: sw a0, 12(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: .LBB2_2: # %entry
+; CHECK_NOPT-NEXT: lw a0, 12(sp) # 4-byte Folded Reload
+; CHECK_NOPT-NEXT: addi sp, sp, 16
+; CHECK_NOPT-NEXT: ret
+;
+; CHECK_OPT-LABEL: select_beqimm_1:
+; CHECK_OPT: # %bb.0: # %entry
+; CHECK_OPT-NEXT: cv.beqimm a0, -16, .LBB2_2
+; CHECK_OPT-NEXT: # %bb.1: # %entry
+; CHECK_OPT-NEXT: mv a2, a1
+; CHECK_OPT-NEXT: .LBB2_2: # %entry
+; CHECK_OPT-NEXT: mv a0, a2
+; CHECK_OPT-NEXT: ret
+entry:
+ %cmp.not = icmp eq i32 %a, -16
+ %cond = select i1 %cmp.not, i32 %y, i32 %x
+ ret i32 %cond
+}
+
+define i32 @select_beqimm_2(i32 %a, i32 %x, i32 %y) {
+; CHECK_NOPT-LABEL: select_beqimm_2:
+; CHECK_NOPT: # %bb.0: # %entry
+; CHECK_NOPT-NEXT: addi sp, sp, -16
+; CHECK_NOPT-NEXT: .cfi_def_cfa_offset 16
+; CHECK_NOPT-NEXT: sw a1, 8(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: sw a2, 12(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: cv.beqimm a0, 0, .LBB3_2
+; CHECK_NOPT-NEXT: # %bb.1: # %entry
+; CHECK_NOPT-NEXT: lw a0, 8(sp) # 4-byte Folded Reload
+; CHECK_NOPT-NEXT: sw a0, 12(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: .LBB3_2: # %entry
+; CHECK_NOPT-NEXT: lw a0, 12(sp) # 4-byte Folded Reload
+; CHECK_NOPT-NEXT: addi sp, sp, 16
+; CHECK_NOPT-NEXT: ret
+;
+; CHECK_OPT-LABEL: select_beqimm_2:
+; CHECK_OPT: # %bb.0: # %entry
+; CHECK_OPT-NEXT: cv.beqimm a0, 0, .LBB3_2
+; CHECK_OPT-NEXT: # %bb.1: # %entry
+; CHECK_OPT-NEXT: mv a2, a1
+; CHECK_OPT-NEXT: .LBB3_2: # %entry
+; CHECK_OPT-NEXT: mv a0, a2
+; CHECK_OPT-NEXT: ret
+entry:
+ %cmp.not = icmp eq i32 %a, 0
+ %cond = select i1 %cmp.not, i32 %y, i32 %x
+ ret i32 %cond
+}
+
+define i32 @select_beqimm_3(i32 %a, i32 %x, i32 %y) {
+; CHECK_NOPT-LABEL: select_beqimm_3:
+; CHECK_NOPT: # %bb.0: # %entry
+; CHECK_NOPT-NEXT: addi sp, sp, -16
+; CHECK_NOPT-NEXT: .cfi_def_cfa_offset 16
+; CHECK_NOPT-NEXT: sw a1, 8(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: sw a2, 12(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: cv.beqimm a0, 15, .LBB4_2
+; CHECK_NOPT-NEXT: # %bb.1: # %entry
+; CHECK_NOPT-NEXT: lw a0, 8(sp) # 4-byte Folded Reload
+; CHECK_NOPT-NEXT: sw a0, 12(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: .LBB4_2: # %entry
+; CHECK_NOPT-NEXT: lw a0, 12(sp) # 4-byte Folded Reload
+; CHECK_NOPT-NEXT: addi sp, sp, 16
+; CHECK_NOPT-NEXT: ret
+;
+; CHECK_OPT-LABEL: select_beqimm_3:
+; CHECK_OPT: # %bb.0: # %entry
+; CHECK_OPT-NEXT: cv.beqimm a0, 15, .LBB4_2
+; CHECK_OPT-NEXT: # %bb.1: # %entry
+; CHECK_OPT-NEXT: mv a2, a1
+; CHECK_OPT-NEXT: .LBB4_2: # %entry
+; CHECK_OPT-NEXT: mv a0, a2
+; CHECK_OPT-NEXT: ret
+entry:
+ %cmp.not = icmp eq i32 %a, 15
+ %cond = select i1 %cmp.not, i32 %y, i32 %x
+ ret i32 %cond
+}
+
+define i32 @select_no_beqimm_1(i32 %a, i32 %x, i32 %y) {
+; CHECK_NOPT-LABEL: select_no_beqimm_1:
+; CHECK_NOPT: # %bb.0: # %entry
+; CHECK_NOPT-NEXT: addi sp, sp, -16
+; CHECK_NOPT-NEXT: .cfi_def_cfa_offset 16
+; CHECK_NOPT-NEXT: sw a1, 8(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: li a1, -17
+; CHECK_NOPT-NEXT: sw a2, 12(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: beq a0, a1, .LBB5_2
+; CHECK_NOPT-NEXT: # %bb.1: # %entry
+; CHECK_NOPT-NEXT: lw a0, 8(sp) # 4-byte Folded Reload
+; CHECK_NOPT-NEXT: sw a0, 12(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: .LBB5_2: # %entry
+; CHECK_NOPT-NEXT: lw a0, 12(sp) # 4-byte Folded Reload
+; CHECK_NOPT-NEXT: addi sp, sp, 16
+; CHECK_NOPT-NEXT: ret
+;
+; CHECK_OPT-LABEL: select_no_beqimm_1:
+; CHECK_OPT: # %bb.0: # %entry
+; CHECK_OPT-NEXT: li a3, -17
+; CHECK_OPT-NEXT: beq a0, a3, .LBB5_2
+; CHECK_OPT-NEXT: # %bb.1: # %entry
+; CHECK_OPT-NEXT: mv a2, a1
+; CHECK_OPT-NEXT: .LBB5_2: # %entry
+; CHECK_OPT-NEXT: mv a0, a2
+; CHECK_OPT-NEXT: ret
+entry:
+ %cmp.not = icmp eq i32 %a, -17
+ %cond = select i1 %cmp.not, i32 %y, i32 %x
+ ret i32 %cond
+}
+
+define i32 @select_no_beqimm_2(i32 %a, i32 %x, i32 %y) {
+; CHECK_NOPT-LABEL: select_no_beqimm_2:
+; CHECK_NOPT: # %bb.0: # %entry
+; CHECK_NOPT-NEXT: addi sp, sp, -16
+; CHECK_NOPT-NEXT: .cfi_def_cfa_offset 16
+; CHECK_NOPT-NEXT: sw a1, 8(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: li a1, 16
+; CHECK_NOPT-NEXT: sw a2, 12(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: beq a0, a1, .LBB6_2
+; CHECK_NOPT-NEXT: # %bb.1: # %entry
+; CHECK_NOPT-NEXT: lw a0, 8(sp) # 4-byte Folded Reload
+; CHECK_NOPT-NEXT: sw a0, 12(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: .LBB6_2: # %entry
+; CHECK_NOPT-NEXT: lw a0, 12(sp) # 4-byte Folded Reload
+; CHECK_NOPT-NEXT: addi sp, sp, 16
+; CHECK_NOPT-NEXT: ret
+;
+; CHECK_OPT-LABEL: select_no_beqimm_2:
+; CHECK_OPT: # %bb.0: # %entry
+; CHECK_OPT-NEXT: li a3, 16
+; CHECK_OPT-NEXT: beq a0, a3, .LBB6_2
+; CHECK_OPT-NEXT: # %bb.1: # %entry
+; CHECK_OPT-NEXT: mv a2, a1
+; CHECK_OPT-NEXT: .LBB6_2: # %entry
+; CHECK_OPT-NEXT: mv a0, a2
+; CHECK_OPT-NEXT: ret
+entry:
+ %cmp.not = icmp eq i32 %a, 16
+ %cond = select i1 %cmp.not, i32 %y, i32 %x
+ ret i32 %cond
+}
+
+define i32 @select_bneimm_1(i32 %a, i32 %x, i32 %y) {
+; CHECK_NOPT-LABEL: select_bneimm_1:
+; CHECK_NOPT: # %bb.0: # %entry
+; CHECK_NOPT-NEXT: addi sp, sp, -16
+; CHECK_NOPT-NEXT: .cfi_def_cfa_offset 16
+; CHECK_NOPT-NEXT: sw a1, 8(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: sw a2, 12(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: cv.bneimm a0, 0, .LBB7_2
+; CHECK_NOPT-NEXT: # %bb.1: # %entry
+; CHECK_NOPT-NEXT: lw a0, 8(sp) # 4-byte Folded Reload
+; CHECK_NOPT-NEXT: sw a0, 12(sp) # 4-byte Folded Spill
+; CHECK_NOPT-NEXT: .LBB7_2: # %entry
+; CHECK_NOPT-NEXT: lw a0, 12(sp) # 4-byte Folded Reload
+; CHECK_NOPT-NEXT: addi sp, sp, 16
+; CHECK_NOPT-NEXT: ret
+;
+; CHECK_OPT-LABEL: select_bneimm_1:
+; CHECK_OPT: # %bb.0: # %entry
+; CHECK_OPT-NEXT: cv.bneimm a0, 0, .LBB7_2
+; CHECK_OPT-NEXT: # %bb.1: # %entry
+; CHECK_OPT-NEXT: mv a2, a1
+; CHECK_OPT-NEXT: .LBB7_2: # %entry
+; CHECK_OPT-NEXT: mv a0, a2
+; CHECK_OPT-NEXT: ret
+entry:
+ %cmp.not = icmp ne i32 %a, 0
+ %cond = select i1 %cmp.not, i32 %y, i32 %x
+ ret i32 %cond
+}
+
|
int32_t RHSImm = cast<ConstantSDNode>(RHS)->getSExtValue(); | ||
if (isInt<5>(RHSImm)) { | ||
SDValue Ops[] = {LHS, RHS, TargetCC, TrueV, FalseV}; | ||
return DAG.getNode(RISCVISD::SELECTIMM_CC, DL, VT, Ops); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need a new node? Can't we match simm5 operand to RISCVISD::SELECT_CC in tablegen like you did for BR_CC?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New node(RISCVISD::SELECT_CC) deleted. Thanks.
@@ -18035,6 +18053,7 @@ RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, | |||
"ReadCounterWide is only to be used on riscv32"); | |||
return emitReadCounterWidePseudo(MI, BB); | |||
case RISCV::Select_GPR_Using_CC_GPR: | |||
case RISCV::Select_IMM_Using_CC_GPR: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is misnamed. It should be Select_GPR_Using_CC_Imm
. The first type is the of the register the instruction produces.
@@ -18035,6 +18053,7 @@ RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, | |||
"ReadCounterWide is only to be used on riscv32"); | |||
return emitReadCounterWidePseudo(MI, BB); | |||
case RISCV::Select_GPR_Using_CC_GPR: | |||
case RISCV::Select_IMM_Using_CC_GPR: | |||
case RISCV::Select_FPR16_Using_CC_GPR: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we need versions of all of these opcodes with an immediate condition? When you created RISCVISD::SELECTIMM_CC, you didn't check that the result type was integer so FP is possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deleted the new node. Doesn't seem to have this problem anymore?
@@ -7608,6 +7608,15 @@ SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const { | |||
TargetCC = DAG.getCondCode(ISD::getSetCCInverse(CCVal, LHS.getValueType())); | |||
} | |||
|
|||
if (Subtarget.hasVendorXCVbi() && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to check RV32?
@@ -17741,7 +17749,7 @@ static MachineBasicBlock *emitSelectPseudo(MachineInstr &MI, | |||
auto InsertionPoint = TailMBB->begin(); | |||
while (SelectMBBI != SelectEnd) { | |||
auto Next = std::next(SelectMBBI); | |||
if (isSelectPseudo(*SelectMBBI)) { | |||
if (isSelectPseudo(*SelectMBBI) || MI.getOperand(2).isImm()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain this change? There are no other references to MI in this loop so I'm not sure what MI's operand has to do with anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
try to generate the phi node. RISCV::Select_GPR_Using_CC_Imm is added to the isSelectPseudo function now.
Register RHS = MI.getOperand(2).getReg(); | ||
Register RHS; | ||
if (MI.getOperand(2).isReg()) | ||
RHS = MI.getOperand(2).getReg(); | ||
auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm()); | ||
|
||
SmallVector<MachineInstr *, 4> SelectDebugValues; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you need to add MI.getOpcode() != RISCV::Select_GPR_Using_CC_Imm
to condition on line 17670 to avoid entering EmitLoweredCascadedSelect
which was intended for FP.
(riscv_selectcc_frag:$cc (i32 GPR:$lhs), simm5:$imm5, cond, | ||
(i32 GPR:$truev), GPR:$falsev))]>; | ||
|
||
def : Pat<(riscv_selectcc_frag:$cc (i32 GPR:$lhs), simm5:$Constant, SETEQ, (i32 GPR:$truev), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you need a SETNE pattern too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SETEQ/SETNE should be riscv_selectcc_frag:$cc controlled, now changed to be consistent with RISCVInstrInfo.td (cond).
(riscv_selectcc_frag:$cc (i32 GPR:$lhs), simm5:$imm5, cond, | ||
(i32 GPR:$truev), GPR:$falsev))]>; | ||
|
||
def : Pat<(riscv_selectcc_frag:$cc (i32 GPR:$lhs), simm5:$Constant, cond, (i32 GPR:$truev), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think using cond
here will allow Select_GPR_Using_CC_Imm with conditions other than EQ/NE to be created which I don't think you want.
@@ -17665,8 +17668,9 @@ static MachineBasicBlock *emitSelectPseudo(MachineInstr &MI, | |||
|
|||
MachineInstr *LastSelectPseudo = &MI; | |||
auto Next = next_nodbg(MI.getIterator(), BB->instr_end()); | |||
if (MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR && Next != BB->end() && | |||
Next->getOpcode() == MI.getOpcode() && | |||
if ((MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR || |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be &&
not ||
I think.
I think MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR || MI.getOpcode() != RISCV::Select_GPR_Using_CC_Imm
is always true. If MI.getOpcode() is RISCV::Select_GPR_Using_CC_GPR then MI.getOpcode() != RISCV::Select_GPR_Using_CC_Imm is true. If MI.getOpcode() is RISCV::Select_GPR_Using_CC_Imm then MI.getOpcode() != RISCV::Select_GPR_Using_CC_GPR is true.
@@ -17678,7 +17682,8 @@ static MachineBasicBlock *emitSelectPseudo(MachineInstr &MI, | |||
continue; | |||
if (isSelectPseudo(*SequenceMBBI)) { | |||
if (SequenceMBBI->getOperand(1).getReg() != LHS || | |||
SequenceMBBI->getOperand(2).getReg() != RHS || | |||
(SequenceMBBI->getOperand(2).isReg() && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If its not a register this entire if
needs to evaluate to false instead of just skipping the operand.
SequenceMBBI->getOperand(1).getReg() != LHS ||
!SequenceMBBI->getOperand(2).isReg() ||
SequenceMBBI->getOperand(2).getReg() != RHS ||
SequenceMBBI->getOperand(3).getImm() != CC ||
...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks
|
||
|
||
class Selectbi<CondCode Cond> | ||
: Pat<(riscv_selectcc_frag:$cc (i32 GPR:$lhs), simm5:$Constant, Cond, (i32 GPR:$truev), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move (i32 GPR:$truev),
to the next line so this line won't exceed 80 characters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
spec: https://github.com/openhwgroup/cv32e40p/blob/master/docs/source/instruction_set_extensions.rst#immediate-branching-operations
Contributors: @CharKeaney, @jeremybennett, @lewis-revill, @NandniJamnadas,
@PaoloS02, @simonpcook, @xingmingjie, @realqhc, @PhilippvK,@melonedo