[LoongArch] Eliminate the redundant sign extension of division (#107971)
[llvm-project.git] / llvm / lib / Target / Xtensa / XtensaInstrInfo.cpp
blob491defb8676437788f296773e6c9b6aeccbe312d
1 //===- XtensaInstrInfo.cpp - Xtensa Instruction Information ---------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6 // See https://llvm.org/LICENSE.txt for license information.
7 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //
9 //===----------------------------------------------------------------------===//
11 // This file contains the Xtensa implementation of the TargetInstrInfo class.
13 //===----------------------------------------------------------------------===//
15 #include "XtensaInstrInfo.h"
16 #include "XtensaTargetMachine.h"
17 #include "llvm/CodeGen/MachineConstantPool.h"
18 #include "llvm/CodeGen/MachineFrameInfo.h"
19 #include "llvm/CodeGen/MachineInstrBuilder.h"
20 #include "llvm/CodeGen/MachineRegisterInfo.h"
22 #define GET_INSTRINFO_CTOR_DTOR
23 #include "XtensaGenInstrInfo.inc"
25 using namespace llvm;
27 static const MachineInstrBuilder &
28 addFrameReference(const MachineInstrBuilder &MIB, int FI) {
29 MachineInstr *MI = MIB;
30 MachineFunction &MF = *MI->getParent()->getParent();
31 MachineFrameInfo &MFFrame = MF.getFrameInfo();
32 const MCInstrDesc &MCID = MI->getDesc();
33 MachineMemOperand::Flags Flags = MachineMemOperand::MONone;
34 if (MCID.mayLoad())
35 Flags |= MachineMemOperand::MOLoad;
36 if (MCID.mayStore())
37 Flags |= MachineMemOperand::MOStore;
38 int64_t Offset = 0;
39 Align Alignment = MFFrame.getObjectAlign(FI);
41 MachineMemOperand *MMO =
42 MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(MF, FI, Offset),
43 Flags, MFFrame.getObjectSize(FI), Alignment);
44 return MIB.addFrameIndex(FI).addImm(Offset).addMemOperand(MMO);
47 XtensaInstrInfo::XtensaInstrInfo(const XtensaSubtarget &STI)
48 : XtensaGenInstrInfo(Xtensa::ADJCALLSTACKDOWN, Xtensa::ADJCALLSTACKUP),
49 RI(STI), STI(STI) {}
51 Register XtensaInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
52 int &FrameIndex) const {
53 if (MI.getOpcode() == Xtensa::L32I) {
54 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
55 MI.getOperand(2).getImm() == 0) {
56 FrameIndex = MI.getOperand(1).getIndex();
57 return MI.getOperand(0).getReg();
60 return Register();
63 Register XtensaInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
64 int &FrameIndex) const {
65 if (MI.getOpcode() == Xtensa::S32I) {
66 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
67 MI.getOperand(2).getImm() == 0) {
68 FrameIndex = MI.getOperand(1).getIndex();
69 return MI.getOperand(0).getReg();
72 return Register();
75 /// Adjust SP by Amount bytes.
76 void XtensaInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,
77 MachineBasicBlock &MBB,
78 MachineBasicBlock::iterator I) const {
79 DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
81 if (Amount == 0)
82 return;
84 MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
85 const TargetRegisterClass *RC = &Xtensa::ARRegClass;
87 // create virtual reg to store immediate
88 unsigned Reg = RegInfo.createVirtualRegister(RC);
90 if (isInt<8>(Amount)) { // addi sp, sp, amount
91 BuildMI(MBB, I, DL, get(Xtensa::ADDI), Reg).addReg(SP).addImm(Amount);
92 } else { // Expand immediate that doesn't fit in 8-bit.
93 unsigned Reg1;
94 loadImmediate(MBB, I, &Reg1, Amount);
95 BuildMI(MBB, I, DL, get(Xtensa::ADD), Reg)
96 .addReg(SP)
97 .addReg(Reg1, RegState::Kill);
100 BuildMI(MBB, I, DL, get(Xtensa::OR), SP)
101 .addReg(Reg, RegState::Kill)
102 .addReg(Reg, RegState::Kill);
105 void XtensaInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
106 MachineBasicBlock::iterator MBBI,
107 const DebugLoc &DL, MCRegister DestReg,
108 MCRegister SrcReg, bool KillSrc) const {
109 // The MOV instruction is not present in core ISA,
110 // so use OR instruction.
111 if (Xtensa::ARRegClass.contains(DestReg, SrcReg))
112 BuildMI(MBB, MBBI, DL, get(Xtensa::OR), DestReg)
113 .addReg(SrcReg, getKillRegState(KillSrc))
114 .addReg(SrcReg, getKillRegState(KillSrc));
115 else
116 report_fatal_error("Impossible reg-to-reg copy");
119 void XtensaInstrInfo::storeRegToStackSlot(
120 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg,
121 bool isKill, int FrameIdx, const TargetRegisterClass *RC,
122 const TargetRegisterInfo *TRI, Register VReg) const {
123 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
124 unsigned LoadOpcode, StoreOpcode;
125 getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode, FrameIdx);
126 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, get(StoreOpcode))
127 .addReg(SrcReg, getKillRegState(isKill));
128 addFrameReference(MIB, FrameIdx);
131 void XtensaInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
132 MachineBasicBlock::iterator MBBI,
133 Register DestReg, int FrameIdx,
134 const TargetRegisterClass *RC,
135 const TargetRegisterInfo *TRI,
136 Register VReg) const {
137 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
138 unsigned LoadOpcode, StoreOpcode;
139 getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode, FrameIdx);
140 addFrameReference(BuildMI(MBB, MBBI, DL, get(LoadOpcode), DestReg), FrameIdx);
143 void XtensaInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC,
144 unsigned &LoadOpcode,
145 unsigned &StoreOpcode,
146 int64_t offset) const {
147 assert((RC == &Xtensa::ARRegClass) &&
148 "Unsupported regclass to load or store");
150 LoadOpcode = Xtensa::L32I;
151 StoreOpcode = Xtensa::S32I;
154 void XtensaInstrInfo::loadImmediate(MachineBasicBlock &MBB,
155 MachineBasicBlock::iterator MBBI,
156 unsigned *Reg, int64_t Value) const {
157 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
158 MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
159 const TargetRegisterClass *RC = &Xtensa::ARRegClass;
161 // create virtual reg to store immediate
162 *Reg = RegInfo.createVirtualRegister(RC);
163 if (Value >= -2048 && Value <= 2047) {
164 BuildMI(MBB, MBBI, DL, get(Xtensa::MOVI), *Reg).addImm(Value);
165 } else if (Value >= -32768 && Value <= 32767) {
166 int Low = Value & 0xFF;
167 int High = Value & ~0xFF;
169 BuildMI(MBB, MBBI, DL, get(Xtensa::MOVI), *Reg).addImm(Low);
170 BuildMI(MBB, MBBI, DL, get(Xtensa::ADDMI), *Reg).addReg(*Reg).addImm(High);
171 } else if (Value >= -4294967296LL && Value <= 4294967295LL) {
172 // 32 bit arbitrary constant
173 MachineConstantPool *MCP = MBB.getParent()->getConstantPool();
174 uint64_t UVal = ((uint64_t)Value) & 0xFFFFFFFFLL;
175 const Constant *CVal = ConstantInt::get(
176 Type::getInt32Ty(MBB.getParent()->getFunction().getContext()), UVal,
177 false);
178 unsigned Idx = MCP->getConstantPoolIndex(CVal, Align(2U));
179 // MCSymbol MSym
180 BuildMI(MBB, MBBI, DL, get(Xtensa::L32R), *Reg).addConstantPoolIndex(Idx);
181 } else {
182 // use L32R to let assembler load immediate best
183 // TODO replace to L32R
184 report_fatal_error("Unsupported load immediate value");