Skip to content

Commit e0e0891

Browse files
committed
[RISCV][GISel] Select G_BRCOND and G_ICMP together when possible.
This allows us to fold the G_ICMP operands into the conditional branch. This reuses the helper function we have for folding a G_ICMP into G_SELECT.
1 parent c2205ab commit e0e0891

File tree

3 files changed

+105
-99
lines changed

3 files changed

+105
-99
lines changed

llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp

Lines changed: 93 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,92 @@ RISCVInstructionSelector::selectAddrRegImm(MachineOperand &Root) const {
296296
[=](MachineInstrBuilder &MIB) { MIB.addImm(0); }}};
297297
}
298298

299+
/// Returns the RISCVCC::CondCode that corresponds to the CmpInst::Predicate CC.
300+
/// CC Must be an ICMP Predicate.
301+
static RISCVCC::CondCode getRISCVCCFromICmp(CmpInst::Predicate CC) {
302+
switch (CC) {
303+
default:
304+
llvm_unreachable("Expected ICMP CmpInst::Predicate.");
305+
case CmpInst::Predicate::ICMP_EQ:
306+
return RISCVCC::COND_EQ;
307+
case CmpInst::Predicate::ICMP_NE:
308+
return RISCVCC::COND_NE;
309+
case CmpInst::Predicate::ICMP_ULT:
310+
return RISCVCC::COND_LTU;
311+
case CmpInst::Predicate::ICMP_SLT:
312+
return RISCVCC::COND_LT;
313+
case CmpInst::Predicate::ICMP_UGE:
314+
return RISCVCC::COND_GEU;
315+
case CmpInst::Predicate::ICMP_SGE:
316+
return RISCVCC::COND_GE;
317+
}
318+
}
319+
320+
static void getOperandsForBranch(Register CondReg, MachineRegisterInfo &MRI,
321+
RISCVCC::CondCode &CC, Register &LHS,
322+
Register &RHS) {
323+
// Try to fold an ICmp. If that fails, use a NE compare with X0.
324+
CmpInst::Predicate Pred = CmpInst::BAD_ICMP_PREDICATE;
325+
if (!mi_match(CondReg, MRI, m_GICmp(m_Pred(Pred), m_Reg(LHS), m_Reg(RHS)))) {
326+
LHS = CondReg;
327+
RHS = RISCV::X0;
328+
CC = RISCVCC::COND_NE;
329+
return;
330+
}
331+
332+
// We found an ICmp, do some canonicalizations.
333+
334+
// Adjust comparisons to use comparison with 0 if possible.
335+
if (auto Constant = getIConstantVRegSExtVal(RHS, MRI)) {
336+
switch (Pred) {
337+
case CmpInst::Predicate::ICMP_SGT:
338+
// Convert X > -1 to X >= 0
339+
if (*Constant == -1) {
340+
CC = RISCVCC::COND_GE;
341+
RHS = RISCV::X0;
342+
return;
343+
}
344+
break;
345+
case CmpInst::Predicate::ICMP_SLT:
346+
// Convert X < 1 to 0 >= X
347+
if (*Constant == 1) {
348+
CC = RISCVCC::COND_GE;
349+
RHS = LHS;
350+
LHS = RISCV::X0;
351+
return;
352+
}
353+
break;
354+
default:
355+
break;
356+
}
357+
}
358+
359+
switch (Pred) {
360+
default:
361+
llvm_unreachable("Expected ICMP CmpInst::Predicate.");
362+
case CmpInst::Predicate::ICMP_EQ:
363+
case CmpInst::Predicate::ICMP_NE:
364+
case CmpInst::Predicate::ICMP_ULT:
365+
case CmpInst::Predicate::ICMP_SLT:
366+
case CmpInst::Predicate::ICMP_UGE:
367+
case CmpInst::Predicate::ICMP_SGE:
368+
// These CCs are supported directly by RISC-V branches.
369+
break;
370+
case CmpInst::Predicate::ICMP_SGT:
371+
case CmpInst::Predicate::ICMP_SLE:
372+
case CmpInst::Predicate::ICMP_UGT:
373+
case CmpInst::Predicate::ICMP_ULE:
374+
// These CCs are not supported directly by RISC-V branches, but changing the
375+
// direction of the CC and swapping LHS and RHS are.
376+
Pred = CmpInst::getSwappedPredicate(Pred);
377+
std::swap(LHS, RHS);
378+
break;
379+
}
380+
381+
CC = getRISCVCCFromICmp(Pred);
382+
return;
383+
}
384+
299385
bool RISCVInstructionSelector::select(MachineInstr &MI) {
300386
MachineBasicBlock &MBB = *MI.getParent();
301387
MachineFunction &MF = *MBB.getParent();
@@ -398,10 +484,12 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
398484
case TargetOpcode::G_GLOBAL_VALUE:
399485
return selectGlobalValue(MI, MIB, MRI);
400486
case TargetOpcode::G_BRCOND: {
401-
// TODO: Fold with G_ICMP.
402-
auto Bcc =
403-
MIB.buildInstr(RISCV::BNE, {}, {MI.getOperand(0), Register(RISCV::X0)})
404-
.addMBB(MI.getOperand(1).getMBB());
487+
Register LHS, RHS;
488+
RISCVCC::CondCode CC;
489+
getOperandsForBranch(MI.getOperand(0).getReg(), MRI, CC, LHS, RHS);
490+
491+
auto Bcc = MIB.buildInstr(RISCVCC::getBrCond(CC), {}, {LHS, RHS})
492+
.addMBB(MI.getOperand(1).getMBB());
405493
MI.eraseFromParent();
406494
return constrainSelectedInstRegOperands(*Bcc, TII, TRI, RBI);
407495
}
@@ -719,101 +807,14 @@ bool RISCVInstructionSelector::selectSExtInreg(MachineInstr &MI,
719807
return true;
720808
}
721809

722-
/// Returns the RISCVCC::CondCode that corresponds to the CmpInst::Predicate CC.
723-
/// CC Must be an ICMP Predicate.
724-
static RISCVCC::CondCode getRISCVCCFromICMP(CmpInst::Predicate CC) {
725-
switch (CC) {
726-
default:
727-
llvm_unreachable("Expected ICMP CmpInst::Predicate.");
728-
case CmpInst::Predicate::ICMP_EQ:
729-
return RISCVCC::COND_EQ;
730-
case CmpInst::Predicate::ICMP_NE:
731-
return RISCVCC::COND_NE;
732-
case CmpInst::Predicate::ICMP_ULT:
733-
return RISCVCC::COND_LTU;
734-
case CmpInst::Predicate::ICMP_SLT:
735-
return RISCVCC::COND_LT;
736-
case CmpInst::Predicate::ICMP_UGE:
737-
return RISCVCC::COND_GEU;
738-
case CmpInst::Predicate::ICMP_SGE:
739-
return RISCVCC::COND_GE;
740-
}
741-
}
742-
743-
static void getOperandsForBranch(Register CondReg, MachineIRBuilder &MIB,
744-
MachineRegisterInfo &MRI,
745-
RISCVCC::CondCode &CC, Register &LHS,
746-
Register &RHS) {
747-
// Try to fold an ICmp. If that fails, use a NE compare with X0.
748-
CmpInst::Predicate Pred = CmpInst::BAD_ICMP_PREDICATE;
749-
if (!mi_match(CondReg, MRI, m_GICmp(m_Pred(Pred), m_Reg(LHS), m_Reg(RHS)))) {
750-
LHS = CondReg;
751-
RHS = RISCV::X0;
752-
CC = RISCVCC::COND_NE;
753-
return;
754-
}
755-
756-
// We found an ICmp, do some canonicalizations.
757-
758-
// Adjust comparisons to use comparison with 0 if possible.
759-
if (auto Constant = getIConstantVRegSExtVal(RHS, MRI)) {
760-
switch (Pred) {
761-
case CmpInst::Predicate::ICMP_SGT:
762-
// Convert X > -1 to X >= 0
763-
if (*Constant == -1) {
764-
CC = RISCVCC::COND_GE;
765-
RHS = RISCV::X0;
766-
return;
767-
}
768-
break;
769-
case CmpInst::Predicate::ICMP_SLT:
770-
// Convert X < 1 to 0 >= X
771-
if (*Constant == 1) {
772-
CC = RISCVCC::COND_GE;
773-
RHS = LHS;
774-
LHS = RISCV::X0;
775-
return;
776-
}
777-
break;
778-
default:
779-
break;
780-
}
781-
}
782-
783-
switch (Pred) {
784-
default:
785-
llvm_unreachable("Expected ICMP CmpInst::Predicate.");
786-
case CmpInst::Predicate::ICMP_EQ:
787-
case CmpInst::Predicate::ICMP_NE:
788-
case CmpInst::Predicate::ICMP_ULT:
789-
case CmpInst::Predicate::ICMP_SLT:
790-
case CmpInst::Predicate::ICMP_UGE:
791-
case CmpInst::Predicate::ICMP_SGE:
792-
// These CCs are supported directly by RISC-V branches.
793-
break;
794-
case CmpInst::Predicate::ICMP_SGT:
795-
case CmpInst::Predicate::ICMP_SLE:
796-
case CmpInst::Predicate::ICMP_UGT:
797-
case CmpInst::Predicate::ICMP_ULE:
798-
// These CCs are not supported directly by RISC-V branches, but changing the
799-
// direction of the CC and swapping LHS and RHS are.
800-
Pred = CmpInst::getSwappedPredicate(Pred);
801-
std::swap(LHS, RHS);
802-
break;
803-
}
804-
805-
CC = getRISCVCCFromICMP(Pred);
806-
return;
807-
}
808-
809810
bool RISCVInstructionSelector::selectSelect(MachineInstr &MI,
810811
MachineIRBuilder &MIB,
811812
MachineRegisterInfo &MRI) const {
812813
auto &SelectMI = cast<GSelect>(MI);
813814

814815
Register LHS, RHS;
815816
RISCVCC::CondCode CC;
816-
getOperandsForBranch(SelectMI.getCondReg(), MIB, MRI, CC, LHS, RHS);
817+
getOperandsForBranch(SelectMI.getCondReg(), MRI, CC, LHS, RHS);
817818

818819
MachineInstr *Result = MIB.buildInstr(RISCV::Select_GPR_Using_CC_GPR)
819820
.addDef(SelectMI.getReg(0))

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -904,25 +904,29 @@ static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target,
904904
Cond.push_back(LastInst.getOperand(1));
905905
}
906906

907-
const MCInstrDesc &RISCVInstrInfo::getBrCond(RISCVCC::CondCode CC) const {
907+
unsigned RISCVCC::getBrCond(RISCVCC::CondCode CC) {
908908
switch (CC) {
909909
default:
910910
llvm_unreachable("Unknown condition code!");
911911
case RISCVCC::COND_EQ:
912-
return get(RISCV::BEQ);
912+
return RISCV::BEQ;
913913
case RISCVCC::COND_NE:
914-
return get(RISCV::BNE);
914+
return RISCV::BNE;
915915
case RISCVCC::COND_LT:
916-
return get(RISCV::BLT);
916+
return RISCV::BLT;
917917
case RISCVCC::COND_GE:
918-
return get(RISCV::BGE);
918+
return RISCV::BGE;
919919
case RISCVCC::COND_LTU:
920-
return get(RISCV::BLTU);
920+
return RISCV::BLTU;
921921
case RISCVCC::COND_GEU:
922-
return get(RISCV::BGEU);
922+
return RISCV::BGEU;
923923
}
924924
}
925925

926+
const MCInstrDesc &RISCVInstrInfo::getBrCond(RISCVCC::CondCode CC) const {
927+
return get(RISCVCC::getBrCond(CC));
928+
}
929+
926930
RISCVCC::CondCode RISCVCC::getOppositeBranchCondition(RISCVCC::CondCode CC) {
927931
switch (CC) {
928932
default:

llvm/lib/Target/RISCV/RISCVInstrInfo.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ enum CondCode {
4343
};
4444

4545
CondCode getOppositeBranchCondition(CondCode);
46+
unsigned getBrCond(CondCode CC);
4647

4748
} // end of namespace RISCVCC
4849

0 commit comments

Comments
 (0)