@@ -50,6 +50,15 @@ class RISCVInstructionSelector : public InstructionSelector {
5050 bool selectConstant (MachineInstr &MI, MachineIRBuilder &MIB,
5151 MachineRegisterInfo &MRI) const ;
5252
53+ bool earlySelectShift (unsigned Opc, MachineInstr &I, MachineIRBuilder &MIB,
54+ const MachineRegisterInfo &MRI);
55+
56+ ComplexRendererFns selectShiftMask (MachineOperand &Root) const ;
57+
58+ // Custom renderers for tablegen
59+ void renderNegImm (MachineInstrBuilder &MIB, const MachineInstr &MI,
60+ int OpIdx) const ;
61+
5362 const RISCVSubtarget &STI;
5463 const RISCVInstrInfo &TII;
5564 const RISCVRegisterInfo &TRI;
@@ -89,12 +98,43 @@ RISCVInstructionSelector::RISCVInstructionSelector(
8998{
9099}
91100
101+ InstructionSelector::ComplexRendererFns
102+ RISCVInstructionSelector::selectShiftMask (MachineOperand &Root) const {
103+ // TODO: Also check if we are seeing the result of an AND operation which
104+ // could be bypassed since we only check the lower log2(xlen) bits.
105+ return {{[=](MachineInstrBuilder &MIB) { MIB.add (Root); }}};
106+ }
107+
108+ // Tablegen doesn't allow us to write SRLIW/SRAIW/SLLIW patterns because the
109+ // immediate Operand has type XLenVT. GlobalISel wants it to be i32.
110+ bool RISCVInstructionSelector::earlySelectShift (
111+ unsigned Opc, MachineInstr &I, MachineIRBuilder &MIB,
112+ const MachineRegisterInfo &MRI) {
113+ if (!Subtarget->is64Bit ())
114+ return false ;
115+
116+ LLT Ty = MRI.getType (I.getOperand (0 ).getReg ());
117+ if (!Ty.isScalar () || Ty.getSizeInBits () != 32 )
118+ return false ;
119+
120+ std::optional<int64_t > CstVal =
121+ getIConstantVRegSExtVal (I.getOperand (2 ).getReg (), MRI);
122+ if (!CstVal || !isUInt<5 >(*CstVal))
123+ return false ;
124+
125+ auto NewI = MIB.buildInstr (Opc, {I.getOperand (0 ).getReg ()},
126+ {I.getOperand (1 ).getReg ()})
127+ .addImm (*CstVal);
128+ I.eraseFromParent ();
129+ return constrainSelectedInstRegOperands (*NewI, TII, TRI, RBI);
130+ }
131+
92132bool RISCVInstructionSelector::select (MachineInstr &MI) {
93133 unsigned Opc = MI.getOpcode ();
94134 MachineBasicBlock &MBB = *MI.getParent ();
95135 MachineFunction &MF = *MBB.getParent ();
96136 MachineRegisterInfo &MRI = MF.getRegInfo ();
97- MachineIRBuilder MIB (MF );
137+ MachineIRBuilder MIB (MI );
98138
99139 if (!isPreISelGenericOpcode (Opc)) {
100140 // Certain non-generic instructions also need some special handling.
@@ -104,13 +144,61 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
104144 return true ;
105145 }
106146
147+ switch (Opc) {
148+ case TargetOpcode::G_ADD: {
149+ // Tablegen doesn't pick up the ADDIW pattern because i32 isn't a legal
150+ // type for RV64 in SelectionDAG. Manually select it here.
151+ LLT Ty = MRI.getType (MI.getOperand (0 ).getReg ());
152+ if (Subtarget->is64Bit () && Ty.isScalar () && Ty.getSizeInBits () == 32 ) {
153+ std::optional<int64_t > CstVal =
154+ getIConstantVRegSExtVal (MI.getOperand (2 ).getReg (), MRI);
155+ if (CstVal && isInt<12 >(*CstVal)) {
156+ auto NewI = MIB.buildInstr (RISCV::ADDIW, {MI.getOperand (0 ).getReg ()},
157+ {MI.getOperand (1 ).getReg ()})
158+ .addImm (*CstVal);
159+ MI.eraseFromParent ();
160+ return constrainSelectedInstRegOperands (*NewI, TII, TRI, RBI);
161+ }
162+ }
163+ break ;
164+ }
165+ case TargetOpcode::G_SUB: {
166+ // Tablegen doesn't pick up the ADDIW pattern because i32 isn't a legal
167+ // type for RV64 in SelectionDAG. Manually select it here.
168+ LLT Ty = MRI.getType (MI.getOperand (0 ).getReg ());
169+ if (Subtarget->is64Bit () && Ty.isScalar () && Ty.getSizeInBits () == 32 ) {
170+ std::optional<int64_t > CstVal =
171+ getIConstantVRegSExtVal (MI.getOperand (2 ).getReg (), MRI);
172+ if (CstVal && ((isInt<12 >(*CstVal) && *CstVal != -2048 ) || *CstVal == 2048 )) {
173+ auto NewI = MIB.buildInstr (RISCV::ADDIW, {MI.getOperand (0 ).getReg ()},
174+ {MI.getOperand (1 ).getReg ()})
175+ .addImm (-*CstVal);
176+ MI.eraseFromParent ();
177+ return constrainSelectedInstRegOperands (*NewI, TII, TRI, RBI);
178+ }
179+ }
180+ break ;
181+ }
182+ case TargetOpcode::G_ASHR:
183+ if (earlySelectShift (RISCV::SRAIW, MI, MIB, MRI))
184+ return true ;
185+ break ;
186+ case TargetOpcode::G_LSHR:
187+ if (earlySelectShift (RISCV::SRLIW, MI, MIB, MRI))
188+ return true ;
189+ break ;
190+ case TargetOpcode::G_SHL:
191+ if (earlySelectShift (RISCV::SLLIW, MI, MIB, MRI))
192+ return true ;
193+ break ;
194+ }
195+
107196 if (selectImpl (MI, *CoverageInfo))
108197 return true ;
109198
110- MIB.setInstrAndDebugLoc (MI);
111-
112199 switch (Opc) {
113200 case TargetOpcode::G_ANYEXT:
201+ case TargetOpcode::G_TRUNC:
114202 MI.setDesc (TII.get (TargetOpcode::COPY));
115203 return true ;
116204 case TargetOpcode::G_CONSTANT:
@@ -126,10 +214,19 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
126214 return true ;
127215}
128216
217+ void RISCVInstructionSelector::renderNegImm (MachineInstrBuilder &MIB,
218+ const MachineInstr &MI,
219+ int OpIdx) const {
220+ assert (MI.getOpcode () == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
221+ " Expected G_CONSTANT" );
222+ int64_t CstVal = MI.getOperand (1 ).getCImm ()->getSExtValue ();
223+ MIB.addImm (-CstVal);
224+ }
225+
129226const TargetRegisterClass *RISCVInstructionSelector::getRegClassForTypeOnBank (
130227 LLT Ty, const RegisterBank &RB, bool GetAllRegSet) const {
131228 if (RB.getID () == RISCV::GPRRegBankID) {
132- if (Ty.getSizeInBits () == (STI.is64Bit () ? 64 : 32 ))
229+ if (Ty.getSizeInBits () <= 32 || (STI.is64Bit () && Ty. getSizeInBits () == 64 ))
133230 return &RISCV::GPRRegClass;
134231 }
135232
0 commit comments