@@ -83,6 +83,11 @@ class RISCVInstructionSelector : public InstructionSelector {
83
83
void renderImm (MachineInstrBuilder &MIB, const MachineInstr &MI,
84
84
int OpIdx) const ;
85
85
86
+ // / Returns a G_ICMP that is equivalent to MI, whose condition code matches
87
+ // / one of the comparisons supported directly by branches in the RISC-V ISA.
88
+ MachineInstr *createICMPForBranch (MachineInstr *MI, MachineIRBuilder &MIB,
89
+ MachineRegisterInfo &MRI) const ;
90
+
86
91
const RISCVSubtarget &STI;
87
92
const RISCVInstrInfo &TII;
88
93
const RISCVRegisterInfo &TRI;
@@ -498,23 +503,120 @@ bool RISCVInstructionSelector::selectSExtInreg(MachineInstr &MI,
498
503
return true ;
499
504
}
500
505
506
+ // / Returns the RISCVCC::CondCode that corresponds to the CmpInst::Predicate CC.
507
+ // / CC Must be an ICMP Predicate.
508
+ static RISCVCC::CondCode getRISCVCCFromICMP (CmpInst::Predicate CC) {
509
+ switch (CC) {
510
+ default :
511
+ llvm_unreachable (" Expected ICMP CmpInst::Predicate." );
512
+ case CmpInst::Predicate::ICMP_EQ:
513
+ return RISCVCC::COND_EQ;
514
+ case CmpInst::Predicate::ICMP_NE:
515
+ return RISCVCC::COND_NE;
516
+ case CmpInst::Predicate::ICMP_ULT:
517
+ return RISCVCC::COND_LTU;
518
+ case CmpInst::Predicate::ICMP_SLT:
519
+ return RISCVCC::COND_LT;
520
+ case CmpInst::Predicate::ICMP_UGE:
521
+ return RISCVCC::COND_GEU;
522
+ case CmpInst::Predicate::ICMP_SGE:
523
+ return RISCVCC::COND_GE;
524
+ }
525
+ }
526
+
527
+ MachineInstr *RISCVInstructionSelector::createICMPForBranch (
528
+ MachineInstr *MI, MachineIRBuilder &MIB, MachineRegisterInfo &MRI) const {
529
+ assert (MI->getOpcode () == TargetOpcode::G_ICMP);
530
+ CmpInst::Predicate CC =
531
+ static_cast <CmpInst::Predicate>(MI->getOperand (1 ).getPredicate ());
532
+ MachineOperand &LHS = MI->getOperand (2 );
533
+ MachineOperand &RHS = MI->getOperand (3 );
534
+
535
+ // Adjust comparisons to use comparison with 0 if possible.
536
+ MachineInstr *MaybeConstant = MRI.getVRegDef (RHS.getReg ());
537
+ if (MaybeConstant && MaybeConstant->getOpcode () == TargetOpcode::G_CONSTANT) {
538
+ switch (CC) {
539
+ case CmpInst::Predicate::ICMP_SGT:
540
+ // Convert X > -1 to X >= 0
541
+ if (MaybeConstant->getOperand (1 ).getCImm ()->getSExtValue () == -1 ) {
542
+ MachineInstr *Zero = MIB.buildConstant (
543
+ MRI.getType (MaybeConstant->getOperand (0 ).getReg ()), 0 );
544
+ selectConstant (*Zero, MIB, MRI);
545
+ return MIB.buildICmp (CmpInst::Predicate::ICMP_SGE, MI->getOperand (0 ),
546
+ LHS, Zero->getOperand (0 ));
547
+ }
548
+ break ;
549
+ case CmpInst::Predicate::ICMP_SLT:
550
+ // Convert X < 1 to 0 >= X
551
+ if (MaybeConstant->getOperand (1 ).getCImm ()->getSExtValue () == 1 ) {
552
+ MachineInstr *Zero= MIB.buildConstant (
553
+ MRI.getType (MaybeConstant->getOperand (0 ).getReg ()), 0 );
554
+ selectConstant (*Zero, MIB, MRI);
555
+ return MIB.buildICmp (CmpInst::Predicate::ICMP_SGE, MI->getOperand (0 ),
556
+ Zero->getOperand (0 ), LHS);
557
+ }
558
+ break ;
559
+ default :
560
+ break ;
561
+ }
562
+ }
563
+
564
+ switch (CC) {
565
+ default :
566
+ llvm_unreachable (" Expected ICMP CmpInst::Predicate." );
567
+ case CmpInst::Predicate::ICMP_EQ:
568
+ case CmpInst::Predicate::ICMP_NE:
569
+ case CmpInst::Predicate::ICMP_ULT:
570
+ case CmpInst::Predicate::ICMP_SLT:
571
+ case CmpInst::Predicate::ICMP_UGE:
572
+ case CmpInst::Predicate::ICMP_SGE:
573
+ // These CCs are supported directly by RISC-V branches.
574
+ return MI;
575
+ case CmpInst::Predicate::ICMP_SGT:
576
+ case CmpInst::Predicate::ICMP_SLE:
577
+ case CmpInst::Predicate::ICMP_UGT:
578
+ case CmpInst::Predicate::ICMP_ULE:
579
+ // These CCs are not supported directly by RISC-V branches, but changing the
580
+ // direction of the CC and swapping LHS and RHS are.
581
+ return MIB.buildICmp (CmpInst::getSwappedPredicate (CC), MI->getOperand (0 ),
582
+ RHS, LHS);
583
+ }
584
+ }
585
+
501
586
bool RISCVInstructionSelector::selectSelect (MachineInstr &MI,
502
587
MachineIRBuilder &MIB,
503
588
MachineRegisterInfo &MRI) const {
504
- // TODO: Currently we check that the conditional code passed to G_SELECT is
505
- // not equal to zero; however, in the future, we might want to try and check
506
- // if the conditional code comes from a G_ICMP. If it does, we can directly
507
- // use G_ICMP to get the first three input operands of the
508
- // Select_GPR_Using_CC_GPR. This might be done here, or in the appropriate
509
- // combiner.
510
589
assert (MI.getOpcode () == TargetOpcode::G_SELECT);
511
- MachineInstr *Result = MIB.buildInstr (RISCV::Select_GPR_Using_CC_GPR)
512
- .addDef (MI.getOperand (0 ).getReg ())
513
- .addReg (MI.getOperand (1 ).getReg ())
514
- .addReg (RISCV::X0)
515
- .addImm (RISCVCC::COND_NE)
516
- .addReg (MI.getOperand (2 ).getReg ())
517
- .addReg (MI.getOperand (3 ).getReg ());
590
+ MachineInstr *Result;
591
+ MachineInstr *MaybeICMP = MRI.getVRegDef (MI.getOperand (1 ).getReg ());
592
+ if (MaybeICMP && MaybeICMP->getOpcode () == TargetOpcode::G_ICMP) {
593
+ // If MI is a G_SELECT(G_ICMP(tst, A, B), C, D) then we can use (A, B, tst)
594
+ // as the (LHS, RHS, CC) of the Select_GPR_Using_CC_GPR.
595
+ MachineInstr *ICMPForBranch = createICMPForBranch (MaybeICMP, MIB, MRI);
596
+ CmpInst::Predicate CC = static_cast <CmpInst::Predicate>(
597
+ ICMPForBranch->getOperand (1 ).getPredicate ());
598
+ Result = MIB.buildInstr (RISCV::Select_GPR_Using_CC_GPR)
599
+ .addDef (MI.getOperand (0 ).getReg ());
600
+ Result->addOperand (ICMPForBranch->getOperand (2 ));
601
+ Result->addOperand (ICMPForBranch->getOperand (3 ));
602
+ Result->addOperand (
603
+ MachineOperand::CreateImm (getRISCVCCFromICMP (CC)));
604
+ Result->addOperand (MI.getOperand (2 ));
605
+ Result->addOperand (MI.getOperand (3 ));
606
+
607
+ // Delete ICMPForBranch since we know it has no users. Let the original
608
+ // G_ICMP be selected normally in case it has other users.
609
+ if (ICMPForBranch != MaybeICMP)
610
+ ICMPForBranch->eraseFromParent ();
611
+ } else {
612
+ Result = MIB.buildInstr (RISCV::Select_GPR_Using_CC_GPR)
613
+ .addDef (MI.getOperand (0 ).getReg ())
614
+ .addReg (MI.getOperand (1 ).getReg ())
615
+ .addReg (RISCV::X0)
616
+ .addImm (RISCVCC::COND_NE)
617
+ .addReg (MI.getOperand (2 ).getReg ())
618
+ .addReg (MI.getOperand (3 ).getReg ());
619
+ }
518
620
MI.eraseFromParent ();
519
621
return constrainSelectedInstRegOperands (*Result, TII, TRI, RBI);
520
622
}
0 commit comments