@@ -17655,6 +17655,167 @@ static MachineBasicBlock *emitFROUND(MachineInstr &MI, MachineBasicBlock *MBB,
17655
17655
return DoneMBB;
17656
17656
}
17657
17657
17658
+ static MachineBasicBlock *emitSTRCMPI(MachineInstr &MI, MachineBasicBlock *MBB,
17659
+ const RISCVSubtarget &Subtarget) {
17660
+
17661
+ const RISCVInstrInfo &TII = *Subtarget.getInstrInfo();
17662
+ MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
17663
+ MachineFunction &MF = *MI.getParent()->getParent();
17664
+ DebugLoc DL = MI.getDebugLoc();
17665
+
17666
+ const GlobalVariable *GV = cast<GlobalVariable>(MI.getOperand(2).getGlobal());
17667
+ StringRef Str = cast<ConstantDataArray>(GV->getInitializer())->getAsCString();
17668
+ int NumOfBytes = Str.str().length();
17669
+ const BasicBlock *LLVM_BB = MBB->getBasicBlock();
17670
+ MachineFunction::iterator MBBI = ++MBB->getIterator();
17671
+
17672
+ MachineBasicBlock *ExitMBB = MF.CreateMachineBasicBlock(LLVM_BB);
17673
+ MF.insert(MBBI, ExitMBB);
17674
+ ExitMBB->splice(ExitMBB->end(), MBB, std::next(MI.getIterator()), MBB->end());
17675
+ ExitMBB->transferSuccessorsAndUpdatePHIs(MBB);
17676
+ MBBI = ExitMBB->getIterator();
17677
+
17678
+ // In the code below we assume that the constant string is second argument
17679
+ // and negate the result if needed.
17680
+ bool NeedToNegateResult = MI.getOperand(3).getImm() == 0;
17681
+ Register PHIReg = NeedToNegateResult
17682
+ ? MRI.createVirtualRegister(&RISCV::GPRRegClass)
17683
+ : MI.getOperand(0).getReg();
17684
+ MachineInstrBuilder PHI_MIB =
17685
+ BuildMI(*ExitMBB, ExitMBB->begin(), DL, TII.get(RISCV::PHI), PHIReg);
17686
+ if (NeedToNegateResult) {
17687
+ BuildMI(*ExitMBB, ++ExitMBB->begin(), DL, TII.get(RISCV::SUB),
17688
+ MI.getOperand(0).getReg())
17689
+ .addReg(RISCV::X0)
17690
+ .addReg(PHIReg);
17691
+ }
17692
+
17693
+ MachineBasicBlock *ReturnEarlyNullByteMBB =
17694
+ MF.CreateMachineBasicBlock(LLVM_BB);
17695
+ MF.insert(MBBI, ReturnEarlyNullByteMBB);
17696
+ Register NegReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
17697
+ BuildMI(*ReturnEarlyNullByteMBB, ReturnEarlyNullByteMBB->end(), DL,
17698
+ TII.get(RISCV::ADDI), NegReg)
17699
+ .addReg(RISCV::X0)
17700
+ .addImm(-1);
17701
+ ReturnEarlyNullByteMBB->addSuccessor(ExitMBB);
17702
+ PHI_MIB.addReg(NegReg).addMBB(ReturnEarlyNullByteMBB);
17703
+ MBBI = ReturnEarlyNullByteMBB->getIterator();
17704
+
17705
+ Register BaseReg = MI.getOperand(1).getReg();
17706
+ MachineMemOperand &MMO = *MI.memoperands()[0];
17707
+
17708
+ MachineBasicBlock *CheckNullByteMBB = MF.CreateMachineBasicBlock(LLVM_BB);
17709
+ MF.insert(MBBI, CheckNullByteMBB);
17710
+ Register LoadedLastByteReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
17711
+ MachineInstr &LoadLastByteMI =
17712
+ *BuildMI(*CheckNullByteMBB, CheckNullByteMBB->end(), DL,
17713
+ TII.get(RISCV::LBU), LoadedLastByteReg)
17714
+ .addReg(BaseReg)
17715
+ .addImm(NumOfBytes)
17716
+ .cloneMemRefs(MI)
17717
+ .getInstr();
17718
+ MachineMemOperand *NewMMO = MF.getMachineMemOperand(
17719
+ MMO.getPointerInfo(), MachineMemOperand::MOLoad, LLT(MVT::i8), Align(1));
17720
+ LoadLastByteMI.setMemRefs(MF, {NewMMO});
17721
+ LoadLastByteMI.memoperands()[0]->setOffset(NumOfBytes);
17722
+
17723
+ Register NegLoadedLastByteReg =
17724
+ MRI.createVirtualRegister(&RISCV::GPRRegClass);
17725
+ BuildMI(*CheckNullByteMBB, CheckNullByteMBB->end(), DL, TII.get(RISCV::SUB),
17726
+ NegLoadedLastByteReg)
17727
+ .addReg(RISCV::X0)
17728
+ .addReg(LoadedLastByteReg);
17729
+ BuildMI(*CheckNullByteMBB, CheckNullByteMBB->end(), DL,
17730
+ TII.get(RISCV::PseudoBR))
17731
+ .addMBB(ExitMBB);
17732
+ CheckNullByteMBB->addSuccessor(ExitMBB);
17733
+ PHI_MIB.addReg(NegLoadedLastByteReg).addMBB(CheckNullByteMBB);
17734
+ MBBI = CheckNullByteMBB->getIterator();
17735
+
17736
+ // First byte will be processed in the original MBB.
17737
+ // Create NewMBBs for all other (non-null) bytes.
17738
+ MachineFunction::iterator NewMBBI = MBBI;
17739
+ SmallVector<MachineBasicBlock *> NewMBBs(NumOfBytes);
17740
+ for (int i = NumOfBytes - 2; i >= 0; --i) {
17741
+ MachineBasicBlock *NewMBB = MF.CreateMachineBasicBlock(LLVM_BB);
17742
+ NewMBBs[i] = NewMBB;
17743
+ MF.insert(NewMBBI, NewMBB);
17744
+ NewMBBI = NewMBB->getIterator();
17745
+ }
17746
+ // The CheckNullByteMBB will be a fall-through successor
17747
+ // of the block checking last non-null byte.
17748
+ NewMBBs[NumOfBytes - 1] = CheckNullByteMBB;
17749
+
17750
+ int64_t Offset = 0;
17751
+ char Byte = Str[0];
17752
+ MachineBasicBlock::iterator MII = std::next(MI.getIterator());
17753
+ MachineBasicBlock *CurrMBB = MBB;
17754
+ MachineBasicBlock *NextMBB = NewMBBs[0];
17755
+
17756
+ auto emitCodeToCheckOneByteEquality = [&] {
17757
+ Register LoadedByteReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
17758
+ MachineInstr &LoadByteMI =
17759
+ *BuildMI(*CurrMBB, MII, DL, TII.get(RISCV::LBU), LoadedByteReg)
17760
+ .addReg(BaseReg)
17761
+ .addImm(Offset)
17762
+ .cloneMemRefs(MI)
17763
+ .getInstr();
17764
+ MachineMemOperand *NewMMO =
17765
+ MF.getMachineMemOperand(MMO.getPointerInfo(), MachineMemOperand::MOLoad,
17766
+ LLT(MVT::i8), Align(1));
17767
+ LoadByteMI.setMemRefs(MF, {NewMMO});
17768
+ LoadByteMI.memoperands()[0]->setOffset(Offset);
17769
+
17770
+ BuildMI(*CurrMBB, MII, DL, TII.get(RISCV::BEQ))
17771
+ .addReg(LoadedByteReg)
17772
+ .addReg(RISCV::X0)
17773
+ .addMBB(ReturnEarlyNullByteMBB);
17774
+
17775
+ MBBI = NextMBB->getIterator();
17776
+ MachineBasicBlock *CheckBytesEqualMBB = MF.CreateMachineBasicBlock(LLVM_BB);
17777
+ MF.insert(MBBI, CheckBytesEqualMBB);
17778
+ CurrMBB->addSuccessor(ReturnEarlyNullByteMBB);
17779
+ CurrMBB->addSuccessor(CheckBytesEqualMBB);
17780
+
17781
+ MachineBasicBlock::iterator CheckBytesEqualMMBI =
17782
+ CheckBytesEqualMBB->begin();
17783
+ Register DiffReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
17784
+ BuildMI(*CheckBytesEqualMBB, CheckBytesEqualMMBI, DL, TII.get(RISCV::ADDI),
17785
+ DiffReg)
17786
+ .addReg(LoadedByteReg)
17787
+ .addImm(-Byte);
17788
+
17789
+ BuildMI(*CheckBytesEqualMBB, CheckBytesEqualMMBI, DL, TII.get(RISCV::BNE))
17790
+ .addReg(DiffReg)
17791
+ .addReg(RISCV::X0)
17792
+ .addMBB(ExitMBB);
17793
+
17794
+ CheckBytesEqualMBB->addSuccessor(ExitMBB);
17795
+ PHI_MIB.addReg(DiffReg).addMBB(CheckBytesEqualMBB);
17796
+ CheckBytesEqualMBB->addSuccessor(NextMBB);
17797
+ };
17798
+
17799
+ // Check the first byte.
17800
+ emitCodeToCheckOneByteEquality();
17801
+
17802
+ for (int i = 0; i < NumOfBytes - 1; ++i) {
17803
+ ++Offset;
17804
+ Byte = Str[i + 1];
17805
+ CurrMBB = NewMBBs[i];
17806
+ MII = CurrMBB->begin();
17807
+ NextMBB = NewMBBs[i + 1];
17808
+ // Check all other non-null bytes.
17809
+ // On the last iteration of this loop,
17810
+ // NextMBB is CheckNullByteMBB, so it will become
17811
+ // a fall-through successor of basic block checking last non-null byte.
17812
+ emitCodeToCheckOneByteEquality();
17813
+ }
17814
+
17815
+ MI.eraseFromParent();
17816
+ return ExitMBB;
17817
+ }
17818
+
17658
17819
MachineBasicBlock *
17659
17820
RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
17660
17821
MachineBasicBlock *BB) const {
@@ -17737,6 +17898,8 @@ RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
17737
17898
case RISCV::PseudoFROUND_D_INX:
17738
17899
case RISCV::PseudoFROUND_D_IN32X:
17739
17900
return emitFROUND(MI, BB, Subtarget);
17901
+ case RISCV::PseudoSTRCMPI:
17902
+ return emitSTRCMPI(MI, BB, Subtarget);
17740
17903
case TargetOpcode::STATEPOINT:
17741
17904
case TargetOpcode::STACKMAP:
17742
17905
case TargetOpcode::PATCHPOINT:
@@ -19512,6 +19675,7 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
19512
19675
NODE_NAME_CASE(SWAP_CSR)
19513
19676
NODE_NAME_CASE(CZERO_EQZ)
19514
19677
NODE_NAME_CASE(CZERO_NEZ)
19678
+ NODE_NAME_CASE(STRCMP)
19515
19679
NODE_NAME_CASE(SF_VC_XV_SE)
19516
19680
NODE_NAME_CASE(SF_VC_IV_SE)
19517
19681
NODE_NAME_CASE(SF_VC_VV_SE)
0 commit comments