@@ -50,6 +50,11 @@ struct FoldCandidate {
5050 }
5151 }
5252
53+ FoldCandidate (MachineInstr *MI, unsigned OpNo, int64_t FoldImm,
54+ bool Commuted_ = false , int ShrinkOp = -1 )
55+ : UseMI(MI), ImmToFold(FoldImm), ShrinkOpcode(ShrinkOp), UseOpNo(OpNo),
56+ Kind(MachineOperand::MO_Immediate), Commuted(Commuted_) {}
57+
5358 bool isFI () const {
5459 return Kind == MachineOperand::MO_FrameIndex;
5560 }
@@ -578,16 +583,29 @@ bool SIFoldOperandsImpl::updateOperand(FoldCandidate &Fold) const {
578583}
579584
580585static void appendFoldCandidate (SmallVectorImpl<FoldCandidate> &FoldList,
581- MachineInstr *MI, unsigned OpNo,
582- MachineOperand *FoldOp, bool Commuted = false ,
583- int ShrinkOp = -1 ) {
586+ FoldCandidate &&Entry) {
584587 // Skip additional folding on the same operand.
585588 for (FoldCandidate &Fold : FoldList)
586- if (Fold.UseMI == MI && Fold.UseOpNo == OpNo )
589+ if (Fold.UseMI == Entry. UseMI && Fold.UseOpNo == Entry. UseOpNo )
587590 return ;
588- LLVM_DEBUG (dbgs () << " Append " << (Commuted ? " commuted" : " normal" )
589- << " operand " << OpNo << " \n " << *MI);
590- FoldList.emplace_back (MI, OpNo, FoldOp, Commuted, ShrinkOp);
591+ LLVM_DEBUG (dbgs () << " Append " << (Entry.Commuted ? " commuted" : " normal" )
592+ << " operand " << Entry.UseOpNo << " \n " << *Entry.UseMI );
593+ FoldList.push_back (Entry);
594+ }
595+
596+ static void appendFoldCandidate (SmallVectorImpl<FoldCandidate> &FoldList,
597+ MachineInstr *MI, unsigned OpNo,
598+ MachineOperand *FoldOp, bool Commuted = false ,
599+ int ShrinkOp = -1 ) {
600+ appendFoldCandidate (FoldList,
601+ FoldCandidate (MI, OpNo, FoldOp, Commuted, ShrinkOp));
602+ }
603+
604+ static void appendFoldCandidate (SmallVectorImpl<FoldCandidate> &FoldList,
605+ MachineInstr *MI, unsigned OpNo, int64_t ImmVal,
606+ bool Commuted = false , int ShrinkOp = -1 ) {
607+ appendFoldCandidate (FoldList,
608+ FoldCandidate (MI, OpNo, ImmVal, Commuted, ShrinkOp));
591609}
592610
593611bool SIFoldOperandsImpl::tryAddToFoldList (
@@ -847,11 +865,35 @@ bool SIFoldOperandsImpl::tryToFoldACImm(
847865 return false ;
848866
849867 uint8_t OpTy = Desc.operands ()[UseOpIdx].OperandType ;
850- if (OpToFold.isImm () && TII->isOperandLegal (*UseMI, UseOpIdx, &OpToFold)) {
851- appendFoldCandidate (FoldList, UseMI, UseOpIdx, &OpToFold);
852- return true ;
868+ MachineOperand &UseOp = UseMI->getOperand (UseOpIdx);
869+ if (OpToFold.isImm ()) {
870+ if (unsigned UseSubReg = UseOp.getSubReg ()) {
871+ std::optional<int64_t > SubImm =
872+ SIInstrInfo::extractSubregFromImm (OpToFold.getImm (), UseSubReg);
873+ if (!SubImm)
874+ return false ;
875+
876+ // TODO: Avoid the temporary MachineOperand
877+ MachineOperand TmpOp = MachineOperand::CreateImm (*SubImm);
878+ if (TII->isOperandLegal (*UseMI, UseOpIdx, &TmpOp)) {
879+ appendFoldCandidate (FoldList, UseMI, UseOpIdx, *SubImm);
880+ return true ;
881+ }
882+
883+ return false ;
884+ }
885+
886+ if (TII->isOperandLegal (*UseMI, UseOpIdx, &OpToFold)) {
887+ appendFoldCandidate (FoldList, UseMI, UseOpIdx, &OpToFold);
888+ return true ;
889+ }
853890 }
854891
892+ // TODO: Verify the following code handles subregisters correctly.
893+ // TODO: Handle extract of global reference
894+ if (UseOp.getSubReg ())
895+ return false ;
896+
855897 if (!OpToFold.isReg ())
856898 return false ;
857899
@@ -861,8 +903,7 @@ bool SIFoldOperandsImpl::tryToFoldACImm(
861903
862904 // Maybe it is just a COPY of an immediate itself.
863905 MachineInstr *Def = MRI->getVRegDef (UseReg);
864- MachineOperand &UseOp = UseMI->getOperand (UseOpIdx);
865- if (!UseOp.getSubReg () && Def && TII->isFoldableCopy (*Def)) {
906+ if (Def && TII->isFoldableCopy (*Def)) {
866907 MachineOperand &DefOp = Def->getOperand (1 );
867908 if (DefOp.isImm () && TII->isOperandLegal (*UseMI, UseOpIdx, &DefOp)) {
868909 appendFoldCandidate (FoldList, UseMI, UseOpIdx, &DefOp);
0 commit comments