[InstCombine] Signed saturation patterns
[llvm-core.git] / lib / Target / XCore / XCoreInstrInfo.cpp
blobbbad8e3545864c0f6099a402e395aa807b06e603
1 //===-- XCoreInstrInfo.cpp - XCore Instruction Information ----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains the XCore implementation of the TargetInstrInfo class.
11 //===----------------------------------------------------------------------===//
13 #include "XCoreInstrInfo.h"
14 #include "XCore.h"
15 #include "XCoreMachineFunctionInfo.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/CodeGen/MachineConstantPool.h"
18 #include "llvm/CodeGen/MachineFrameInfo.h"
19 #include "llvm/CodeGen/MachineInstrBuilder.h"
20 #include "llvm/CodeGen/MachineMemOperand.h"
21 #include "llvm/IR/Constants.h"
22 #include "llvm/IR/Function.h"
23 #include "llvm/MC/MCContext.h"
24 #include "llvm/Support/Debug.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/Support/TargetRegistry.h"
28 using namespace llvm;
30 #define GET_INSTRINFO_CTOR_DTOR
31 #include "XCoreGenInstrInfo.inc"
33 namespace llvm {
34 namespace XCore {
36 // XCore Condition Codes
37 enum CondCode {
38 COND_TRUE,
39 COND_FALSE,
40 COND_INVALID
45 // Pin the vtable to this file.
46 void XCoreInstrInfo::anchor() {}
48 XCoreInstrInfo::XCoreInstrInfo()
49 : XCoreGenInstrInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP),
50 RI() {
53 static bool isZeroImm(const MachineOperand &op) {
54 return op.isImm() && op.getImm() == 0;
57 /// isLoadFromStackSlot - If the specified machine instruction is a direct
58 /// load from a stack slot, return the virtual or physical register number of
59 /// the destination along with the FrameIndex of the loaded stack slot. If
60 /// not, return 0. This predicate must return 0 if the instruction has
61 /// any side effects other than loading from the stack slot.
62 unsigned XCoreInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
63 int &FrameIndex) const {
64 int Opcode = MI.getOpcode();
65 if (Opcode == XCore::LDWFI)
67 if ((MI.getOperand(1).isFI()) && // is a stack slot
68 (MI.getOperand(2).isImm()) && // the imm is zero
69 (isZeroImm(MI.getOperand(2)))) {
70 FrameIndex = MI.getOperand(1).getIndex();
71 return MI.getOperand(0).getReg();
74 return 0;
77 /// isStoreToStackSlot - If the specified machine instruction is a direct
78 /// store to a stack slot, return the virtual or physical register number of
79 /// the source reg along with the FrameIndex of the loaded stack slot. If
80 /// not, return 0. This predicate must return 0 if the instruction has
81 /// any side effects other than storing to the stack slot.
82 unsigned XCoreInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
83 int &FrameIndex) const {
84 int Opcode = MI.getOpcode();
85 if (Opcode == XCore::STWFI)
87 if ((MI.getOperand(1).isFI()) && // is a stack slot
88 (MI.getOperand(2).isImm()) && // the imm is zero
89 (isZeroImm(MI.getOperand(2)))) {
90 FrameIndex = MI.getOperand(1).getIndex();
91 return MI.getOperand(0).getReg();
94 return 0;
97 //===----------------------------------------------------------------------===//
98 // Branch Analysis
99 //===----------------------------------------------------------------------===//
101 static inline bool IsBRU(unsigned BrOpc) {
102 return BrOpc == XCore::BRFU_u6
103 || BrOpc == XCore::BRFU_lu6
104 || BrOpc == XCore::BRBU_u6
105 || BrOpc == XCore::BRBU_lu6;
108 static inline bool IsBRT(unsigned BrOpc) {
109 return BrOpc == XCore::BRFT_ru6
110 || BrOpc == XCore::BRFT_lru6
111 || BrOpc == XCore::BRBT_ru6
112 || BrOpc == XCore::BRBT_lru6;
115 static inline bool IsBRF(unsigned BrOpc) {
116 return BrOpc == XCore::BRFF_ru6
117 || BrOpc == XCore::BRFF_lru6
118 || BrOpc == XCore::BRBF_ru6
119 || BrOpc == XCore::BRBF_lru6;
122 static inline bool IsCondBranch(unsigned BrOpc) {
123 return IsBRF(BrOpc) || IsBRT(BrOpc);
126 static inline bool IsBR_JT(unsigned BrOpc) {
127 return BrOpc == XCore::BR_JT
128 || BrOpc == XCore::BR_JT32;
131 /// GetCondFromBranchOpc - Return the XCore CC that matches
132 /// the correspondent Branch instruction opcode.
133 static XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc)
135 if (IsBRT(BrOpc)) {
136 return XCore::COND_TRUE;
137 } else if (IsBRF(BrOpc)) {
138 return XCore::COND_FALSE;
139 } else {
140 return XCore::COND_INVALID;
144 /// GetCondBranchFromCond - Return the Branch instruction
145 /// opcode that matches the cc.
146 static inline unsigned GetCondBranchFromCond(XCore::CondCode CC)
148 switch (CC) {
149 default: llvm_unreachable("Illegal condition code!");
150 case XCore::COND_TRUE : return XCore::BRFT_lru6;
151 case XCore::COND_FALSE : return XCore::BRFF_lru6;
155 /// GetOppositeBranchCondition - Return the inverse of the specified
156 /// condition, e.g. turning COND_E to COND_NE.
157 static inline XCore::CondCode GetOppositeBranchCondition(XCore::CondCode CC)
159 switch (CC) {
160 default: llvm_unreachable("Illegal condition code!");
161 case XCore::COND_TRUE : return XCore::COND_FALSE;
162 case XCore::COND_FALSE : return XCore::COND_TRUE;
166 /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning
167 /// true if it cannot be understood (e.g. it's a switch dispatch or isn't
168 /// implemented for a target). Upon success, this returns false and returns
169 /// with the following information in various cases:
171 /// 1. If this block ends with no branches (it just falls through to its succ)
172 /// just return false, leaving TBB/FBB null.
173 /// 2. If this block ends with only an unconditional branch, it sets TBB to be
174 /// the destination block.
175 /// 3. If this block ends with an conditional branch and it falls through to
176 /// an successor block, it sets TBB to be the branch destination block and a
177 /// list of operands that evaluate the condition. These
178 /// operands can be passed to other TargetInstrInfo methods to create new
179 /// branches.
180 /// 4. If this block ends with an conditional branch and an unconditional
181 /// block, it returns the 'true' destination in TBB, the 'false' destination
182 /// in FBB, and a list of operands that evaluate the condition. These
183 /// operands can be passed to other TargetInstrInfo methods to create new
184 /// branches.
186 /// Note that removeBranch and insertBranch must be implemented to support
187 /// cases where this method returns success.
189 bool XCoreInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
190 MachineBasicBlock *&TBB,
191 MachineBasicBlock *&FBB,
192 SmallVectorImpl<MachineOperand> &Cond,
193 bool AllowModify) const {
194 // If the block has no terminators, it just falls into the block after it.
195 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
196 if (I == MBB.end())
197 return false;
199 if (!isUnpredicatedTerminator(*I))
200 return false;
202 // Get the last instruction in the block.
203 MachineInstr *LastInst = &*I;
205 // If there is only one terminator instruction, process it.
206 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
207 if (IsBRU(LastInst->getOpcode())) {
208 TBB = LastInst->getOperand(0).getMBB();
209 return false;
212 XCore::CondCode BranchCode = GetCondFromBranchOpc(LastInst->getOpcode());
213 if (BranchCode == XCore::COND_INVALID)
214 return true; // Can't handle indirect branch.
216 // Conditional branch
217 // Block ends with fall-through condbranch.
219 TBB = LastInst->getOperand(1).getMBB();
220 Cond.push_back(MachineOperand::CreateImm(BranchCode));
221 Cond.push_back(LastInst->getOperand(0));
222 return false;
225 // Get the instruction before it if it's a terminator.
226 MachineInstr *SecondLastInst = &*I;
228 // If there are three terminators, we don't know what sort of block this is.
229 if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I))
230 return true;
232 unsigned SecondLastOpc = SecondLastInst->getOpcode();
233 XCore::CondCode BranchCode = GetCondFromBranchOpc(SecondLastOpc);
235 // If the block ends with conditional branch followed by unconditional,
236 // handle it.
237 if (BranchCode != XCore::COND_INVALID
238 && IsBRU(LastInst->getOpcode())) {
240 TBB = SecondLastInst->getOperand(1).getMBB();
241 Cond.push_back(MachineOperand::CreateImm(BranchCode));
242 Cond.push_back(SecondLastInst->getOperand(0));
244 FBB = LastInst->getOperand(0).getMBB();
245 return false;
248 // If the block ends with two unconditional branches, handle it. The second
249 // one is not executed, so remove it.
250 if (IsBRU(SecondLastInst->getOpcode()) &&
251 IsBRU(LastInst->getOpcode())) {
252 TBB = SecondLastInst->getOperand(0).getMBB();
253 I = LastInst;
254 if (AllowModify)
255 I->eraseFromParent();
256 return false;
259 // Likewise if it ends with a branch table followed by an unconditional branch.
260 if (IsBR_JT(SecondLastInst->getOpcode()) && IsBRU(LastInst->getOpcode())) {
261 I = LastInst;
262 if (AllowModify)
263 I->eraseFromParent();
264 return true;
267 // Otherwise, can't handle this.
268 return true;
271 unsigned XCoreInstrInfo::insertBranch(MachineBasicBlock &MBB,
272 MachineBasicBlock *TBB,
273 MachineBasicBlock *FBB,
274 ArrayRef<MachineOperand> Cond,
275 const DebugLoc &DL,
276 int *BytesAdded) const {
277 // Shouldn't be a fall through.
278 assert(TBB && "insertBranch must not be told to insert a fallthrough");
279 assert((Cond.size() == 2 || Cond.size() == 0) &&
280 "Unexpected number of components!");
281 assert(!BytesAdded && "code size not handled");
283 if (!FBB) { // One way branch.
284 if (Cond.empty()) {
285 // Unconditional branch
286 BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(TBB);
287 } else {
288 // Conditional branch.
289 unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
290 BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
291 .addMBB(TBB);
293 return 1;
296 // Two-way Conditional branch.
297 assert(Cond.size() == 2 && "Unexpected number of components!");
298 unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm());
299 BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg())
300 .addMBB(TBB);
301 BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(FBB);
302 return 2;
305 unsigned
306 XCoreInstrInfo::removeBranch(MachineBasicBlock &MBB, int *BytesRemoved) const {
307 assert(!BytesRemoved && "code size not handled");
309 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
310 if (I == MBB.end())
311 return 0;
313 if (!IsBRU(I->getOpcode()) && !IsCondBranch(I->getOpcode()))
314 return 0;
316 // Remove the branch.
317 I->eraseFromParent();
319 I = MBB.end();
321 if (I == MBB.begin()) return 1;
322 --I;
323 if (!IsCondBranch(I->getOpcode()))
324 return 1;
326 // Remove the branch.
327 I->eraseFromParent();
328 return 2;
331 void XCoreInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
332 MachineBasicBlock::iterator I,
333 const DebugLoc &DL, unsigned DestReg,
334 unsigned SrcReg, bool KillSrc) const {
335 bool GRDest = XCore::GRRegsRegClass.contains(DestReg);
336 bool GRSrc = XCore::GRRegsRegClass.contains(SrcReg);
338 if (GRDest && GRSrc) {
339 BuildMI(MBB, I, DL, get(XCore::ADD_2rus), DestReg)
340 .addReg(SrcReg, getKillRegState(KillSrc))
341 .addImm(0);
342 return;
345 if (GRDest && SrcReg == XCore::SP) {
346 BuildMI(MBB, I, DL, get(XCore::LDAWSP_ru6), DestReg).addImm(0);
347 return;
350 if (DestReg == XCore::SP && GRSrc) {
351 BuildMI(MBB, I, DL, get(XCore::SETSP_1r))
352 .addReg(SrcReg, getKillRegState(KillSrc));
353 return;
355 llvm_unreachable("Impossible reg-to-reg copy");
358 void XCoreInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
359 MachineBasicBlock::iterator I,
360 unsigned SrcReg, bool isKill,
361 int FrameIndex,
362 const TargetRegisterClass *RC,
363 const TargetRegisterInfo *TRI) const
365 DebugLoc DL;
366 if (I != MBB.end() && !I->isDebugInstr())
367 DL = I->getDebugLoc();
368 MachineFunction *MF = MBB.getParent();
369 const MachineFrameInfo &MFI = MF->getFrameInfo();
370 MachineMemOperand *MMO = MF->getMachineMemOperand(
371 MachinePointerInfo::getFixedStack(*MF, FrameIndex),
372 MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex),
373 MFI.getObjectAlignment(FrameIndex));
374 BuildMI(MBB, I, DL, get(XCore::STWFI))
375 .addReg(SrcReg, getKillRegState(isKill))
376 .addFrameIndex(FrameIndex)
377 .addImm(0)
378 .addMemOperand(MMO);
381 void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
382 MachineBasicBlock::iterator I,
383 unsigned DestReg, int FrameIndex,
384 const TargetRegisterClass *RC,
385 const TargetRegisterInfo *TRI) const
387 DebugLoc DL;
388 if (I != MBB.end() && !I->isDebugInstr())
389 DL = I->getDebugLoc();
390 MachineFunction *MF = MBB.getParent();
391 const MachineFrameInfo &MFI = MF->getFrameInfo();
392 MachineMemOperand *MMO = MF->getMachineMemOperand(
393 MachinePointerInfo::getFixedStack(*MF, FrameIndex),
394 MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex),
395 MFI.getObjectAlignment(FrameIndex));
396 BuildMI(MBB, I, DL, get(XCore::LDWFI), DestReg)
397 .addFrameIndex(FrameIndex)
398 .addImm(0)
399 .addMemOperand(MMO);
402 bool XCoreInstrInfo::
403 reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
404 assert((Cond.size() == 2) &&
405 "Invalid XCore branch condition!");
406 Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm()));
407 return false;
410 static inline bool isImmU6(unsigned val) {
411 return val < (1 << 6);
414 static inline bool isImmU16(unsigned val) {
415 return val < (1 << 16);
418 static bool isImmMskBitp(unsigned val) {
419 if (!isMask_32(val)) {
420 return false;
422 int N = Log2_32(val) + 1;
423 return (N >= 1 && N <= 8) || N == 16 || N == 24 || N == 32;
426 MachineBasicBlock::iterator XCoreInstrInfo::loadImmediate(
427 MachineBasicBlock &MBB,
428 MachineBasicBlock::iterator MI,
429 unsigned Reg, uint64_t Value) const {
430 DebugLoc dl;
431 if (MI != MBB.end() && !MI->isDebugInstr())
432 dl = MI->getDebugLoc();
433 if (isImmMskBitp(Value)) {
434 int N = Log2_32(Value) + 1;
435 return BuildMI(MBB, MI, dl, get(XCore::MKMSK_rus), Reg)
436 .addImm(N)
437 .getInstr();
439 if (isImmU16(Value)) {
440 int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6;
441 return BuildMI(MBB, MI, dl, get(Opcode), Reg).addImm(Value).getInstr();
443 MachineConstantPool *ConstantPool = MBB.getParent()->getConstantPool();
444 const Constant *C = ConstantInt::get(
445 Type::getInt32Ty(MBB.getParent()->getFunction().getContext()), Value);
446 unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
447 return BuildMI(MBB, MI, dl, get(XCore::LDWCP_lru6), Reg)
448 .addConstantPoolIndex(Idx)
449 .getInstr();