@@ -708,8 +708,32 @@ static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg,
708708 bool Is64Bit = AArch64::GPR64allRegClass.hasSubClassEq (MRI.getRegClass (VReg));
709709 const MachineInstr *DefMI = MRI.getVRegDef (VReg);
710710 unsigned Opc = 0 ;
711- unsigned SrcOpNum = 0 ;
711+ unsigned SrcReg = 0 ;
712712 switch (DefMI->getOpcode ()) {
713+ case AArch64::SUBREG_TO_REG:
714+ // Check for the following way to define an 64-bit immediate:
715+ // %0:gpr32 = MOVi32imm 1
716+ // %1:gpr64 = SUBREG_TO_REG 0, %0:gpr32, %subreg.sub_32
717+ if (!DefMI->getOperand (1 ).isImm () || DefMI->getOperand (1 ).getImm () != 0 )
718+ return 0 ;
719+ if (!DefMI->getOperand (2 ).isReg ())
720+ return 0 ;
721+ if (!DefMI->getOperand (3 ).isImm () ||
722+ DefMI->getOperand (3 ).getImm () != AArch64::sub_32)
723+ return 0 ;
724+ DefMI = MRI.getVRegDef (DefMI->getOperand (2 ).getReg ());
725+ if (DefMI->getOpcode () != AArch64::MOVi32imm)
726+ return 0 ;
727+ // fall-through to MOVi32imm case.
728+ [[fallthrough]];
729+ case AArch64::MOVi32imm:
730+ case AArch64::MOVi64imm:
731+ if (!DefMI->getOperand (1 ).isImm () || DefMI->getOperand (1 ).getImm () != 1 )
732+ return 0 ;
733+ SrcReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
734+ Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
735+ break ;
736+
713737 case AArch64::ADDSXri:
714738 case AArch64::ADDSWri:
715739 // if NZCV is used, do not fold.
@@ -724,7 +748,7 @@ static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg,
724748 if (!DefMI->getOperand (2 ).isImm () || DefMI->getOperand (2 ).getImm () != 1 ||
725749 DefMI->getOperand (3 ).getImm () != 0 )
726750 return 0 ;
727- SrcOpNum = 1 ;
751+ SrcReg = DefMI-> getOperand ( 1 ). getReg () ;
728752 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
729753 break ;
730754
@@ -734,7 +758,7 @@ static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg,
734758 unsigned ZReg = removeCopies (MRI, DefMI->getOperand (1 ).getReg ());
735759 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
736760 return 0 ;
737- SrcOpNum = 2 ;
761+ SrcReg = DefMI-> getOperand ( 2 ). getReg () ;
738762 Opc = Is64Bit ? AArch64::CSINVXr : AArch64::CSINVWr;
739763 break ;
740764 }
@@ -753,17 +777,17 @@ static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg,
753777 unsigned ZReg = removeCopies (MRI, DefMI->getOperand (1 ).getReg ());
754778 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
755779 return 0 ;
756- SrcOpNum = 2 ;
780+ SrcReg = DefMI-> getOperand ( 2 ). getReg () ;
757781 Opc = Is64Bit ? AArch64::CSNEGXr : AArch64::CSNEGWr;
758782 break ;
759783 }
760784 default :
761785 return 0 ;
762786 }
763- assert (Opc && SrcOpNum && " Missing parameters" );
787+ assert (Opc && SrcReg && " Missing parameters" );
764788
765789 if (NewVReg)
766- *NewVReg = DefMI-> getOperand (SrcOpNum). getReg () ;
790+ *NewVReg = SrcReg ;
767791 return Opc;
768792}
769793
@@ -976,6 +1000,14 @@ void AArch64InstrInfo::insertSelect(MachineBasicBlock &MBB,
9761000
9771001 // Fold the operation. Leave any dead instructions for DCE to clean up.
9781002 if (FoldedOpc) {
1003+ // NewVReg might be XZR/WZR. In that case create a COPY into a virtual
1004+ // register.
1005+ if (!Register::isVirtualRegister (NewVReg)) {
1006+ unsigned ZeroReg = NewVReg;
1007+ NewVReg = MRI.createVirtualRegister (RC);
1008+ BuildMI (MBB, I, DL, get (TargetOpcode::COPY), NewVReg).addReg (ZeroReg);
1009+ }
1010+
9791011 FalseReg = NewVReg;
9801012 Opc = FoldedOpc;
9811013 // The extends the live range of NewVReg.
0 commit comments