@@ -113,3 +113,192 @@ void LoongArchInstrInfo::loadRegFromStackSlot(
113
113
.addImm (0 )
114
114
.addMemOperand (MMO);
115
115
}
116
+
117
+ unsigned LoongArchInstrInfo::getInstSizeInBytes (const MachineInstr &MI) const {
118
+ return MI.getDesc ().getSize ();
119
+ }
120
+
121
+ MachineBasicBlock *
122
+ LoongArchInstrInfo::getBranchDestBlock (const MachineInstr &MI) const {
123
+ assert (MI.getDesc ().isBranch () && " Unexpected opcode!" );
124
+ // The branch target is always the last operand.
125
+ return MI.getOperand (MI.getNumExplicitOperands () - 1 ).getMBB ();
126
+ }
127
+
128
+ static void parseCondBranch (MachineInstr &LastInst, MachineBasicBlock *&Target,
129
+ SmallVectorImpl<MachineOperand> &Cond) {
130
+ // Block ends with fall-through condbranch.
131
+ assert (LastInst.getDesc ().isConditionalBranch () &&
132
+ " Unknown conditional branch" );
133
+ int NumOp = LastInst.getNumExplicitOperands ();
134
+ Target = LastInst.getOperand (NumOp - 1 ).getMBB ();
135
+
136
+ Cond.push_back (MachineOperand::CreateImm (LastInst.getOpcode ()));
137
+ for (int i = 0 ; i < NumOp - 1 ; i++)
138
+ Cond.push_back (LastInst.getOperand (i));
139
+ }
140
+
141
+ bool LoongArchInstrInfo::analyzeBranch (MachineBasicBlock &MBB,
142
+ MachineBasicBlock *&TBB,
143
+ MachineBasicBlock *&FBB,
144
+ SmallVectorImpl<MachineOperand> &Cond,
145
+ bool AllowModify) const {
146
+ TBB = FBB = nullptr ;
147
+ Cond.clear ();
148
+
149
+ // If the block has no terminators, it just falls into the block after it.
150
+ MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr ();
151
+ if (I == MBB.end () || !isUnpredicatedTerminator (*I))
152
+ return false ;
153
+
154
+ // Count the number of terminators and find the first unconditional or
155
+ // indirect branch.
156
+ MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end ();
157
+ int NumTerminators = 0 ;
158
+ for (auto J = I.getReverse (); J != MBB.rend () && isUnpredicatedTerminator (*J);
159
+ J++) {
160
+ NumTerminators++;
161
+ if (J->getDesc ().isUnconditionalBranch () ||
162
+ J->getDesc ().isIndirectBranch ()) {
163
+ FirstUncondOrIndirectBr = J.getReverse ();
164
+ }
165
+ }
166
+
167
+ // If AllowModify is true, we can erase any terminators after
168
+ // FirstUncondOrIndirectBR.
169
+ if (AllowModify && FirstUncondOrIndirectBr != MBB.end ()) {
170
+ while (std::next (FirstUncondOrIndirectBr) != MBB.end ()) {
171
+ std::next (FirstUncondOrIndirectBr)->eraseFromParent ();
172
+ NumTerminators--;
173
+ }
174
+ I = FirstUncondOrIndirectBr;
175
+ }
176
+
177
+ // Handle a single unconditional branch.
178
+ if (NumTerminators == 1 && I->getDesc ().isUnconditionalBranch ()) {
179
+ TBB = getBranchDestBlock (*I);
180
+ return false ;
181
+ }
182
+
183
+ // Handle a single conditional branch.
184
+ if (NumTerminators == 1 && I->getDesc ().isConditionalBranch ()) {
185
+ parseCondBranch (*I, TBB, Cond);
186
+ return false ;
187
+ }
188
+
189
+ // Handle a conditional branch followed by an unconditional branch.
190
+ if (NumTerminators == 2 && std::prev (I)->getDesc ().isConditionalBranch () &&
191
+ I->getDesc ().isUnconditionalBranch ()) {
192
+ parseCondBranch (*std::prev (I), TBB, Cond);
193
+ FBB = getBranchDestBlock (*I);
194
+ return false ;
195
+ }
196
+
197
+ // Otherwise, we can't handle this.
198
+ return true ;
199
+ }
200
+
201
+ unsigned LoongArchInstrInfo::removeBranch (MachineBasicBlock &MBB,
202
+ int *BytesRemoved) const {
203
+ if (BytesRemoved)
204
+ *BytesRemoved = 0 ;
205
+ MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr ();
206
+ if (I == MBB.end ())
207
+ return 0 ;
208
+
209
+ if (!I->getDesc ().isBranch ())
210
+ return 0 ;
211
+
212
+ // Remove the branch.
213
+ if (BytesRemoved)
214
+ *BytesRemoved += getInstSizeInBytes (*I);
215
+ I->eraseFromParent ();
216
+
217
+ I = MBB.end ();
218
+
219
+ if (I == MBB.begin ())
220
+ return 1 ;
221
+ --I;
222
+ if (!I->getDesc ().isConditionalBranch ())
223
+ return 1 ;
224
+
225
+ // Remove the branch.
226
+ if (BytesRemoved)
227
+ *BytesRemoved += getInstSizeInBytes (*I);
228
+ I->eraseFromParent ();
229
+ return 2 ;
230
+ }
231
+
232
+ // Inserts a branch into the end of the specific MachineBasicBlock, returning
233
+ // the number of instructions inserted.
234
+ unsigned LoongArchInstrInfo::insertBranch (
235
+ MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
236
+ ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
237
+ if (BytesAdded)
238
+ *BytesAdded = 0 ;
239
+
240
+ // Shouldn't be a fall through.
241
+ assert (TBB && " insertBranch must not be told to insert a fallthrough" );
242
+ assert (Cond.size () <= 3 && Cond.size () != 1 &&
243
+ " LoongArch branch conditions have at most two components!" );
244
+
245
+ // Unconditional branch.
246
+ if (Cond.empty ()) {
247
+ MachineInstr &MI = *BuildMI (&MBB, DL, get (LoongArch::PseudoBR)).addMBB (TBB);
248
+ if (BytesAdded)
249
+ *BytesAdded += getInstSizeInBytes (MI);
250
+ return 1 ;
251
+ }
252
+
253
+ // Either a one or two-way conditional branch.
254
+ MachineInstrBuilder MIB = BuildMI (&MBB, DL, get (Cond[0 ].getImm ()));
255
+ for (unsigned i = 1 ; i < Cond.size (); ++i)
256
+ MIB.add (Cond[i]);
257
+ MIB.addMBB (TBB);
258
+ if (BytesAdded)
259
+ *BytesAdded += getInstSizeInBytes (*MIB);
260
+
261
+ // One-way conditional branch.
262
+ if (!FBB)
263
+ return 1 ;
264
+
265
+ // Two-way conditional branch.
266
+ MachineInstr &MI = *BuildMI (&MBB, DL, get (LoongArch::PseudoBR)).addMBB (FBB);
267
+ if (BytesAdded)
268
+ *BytesAdded += getInstSizeInBytes (MI);
269
+ return 2 ;
270
+ }
271
+
272
+ static unsigned getOppositeBranchOpc (unsigned Opc) {
273
+ switch (Opc) {
274
+ default :
275
+ llvm_unreachable (" Unrecognized conditional branch" );
276
+ case LoongArch::BEQ:
277
+ return LoongArch::BNE;
278
+ case LoongArch::BNE:
279
+ return LoongArch::BEQ;
280
+ case LoongArch::BEQZ:
281
+ return LoongArch::BNEZ;
282
+ case LoongArch::BNEZ:
283
+ return LoongArch::BEQZ;
284
+ case LoongArch::BCEQZ:
285
+ return LoongArch::BCNEZ;
286
+ case LoongArch::BCNEZ:
287
+ return LoongArch::BCEQZ;
288
+ case LoongArch::BLT:
289
+ return LoongArch::BGE;
290
+ case LoongArch::BGE:
291
+ return LoongArch::BLT;
292
+ case LoongArch::BLTU:
293
+ return LoongArch::BGEU;
294
+ case LoongArch::BGEU:
295
+ return LoongArch::BLTU;
296
+ }
297
+ }
298
+
299
+ bool LoongArchInstrInfo::reverseBranchCondition (
300
+ SmallVectorImpl<MachineOperand> &Cond) const {
301
+ assert ((Cond.size () && Cond.size () <= 3 ) && " Invalid branch condition!" );
302
+ Cond[0 ].setImm (getOppositeBranchOpc (Cond[0 ].getImm ()));
303
+ return false ;
304
+ }
0 commit comments