Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp
35271 views
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
//===----------------------------------------------------------------------===//
10
//
11
// This file contains the Xtensa implementation of the TargetInstrInfo class.
12
//
13
//===----------------------------------------------------------------------===//
14
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"
21
22
#define GET_INSTRINFO_CTOR_DTOR
23
#include "XtensaGenInstrInfo.inc"
24
25
using namespace llvm;
26
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);
40
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);
45
}
46
47
XtensaInstrInfo::XtensaInstrInfo(const XtensaSubtarget &STI)
48
: XtensaGenInstrInfo(Xtensa::ADJCALLSTACKDOWN, Xtensa::ADJCALLSTACKUP),
49
RI(STI), STI(STI) {}
50
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();
58
}
59
}
60
return Register();
61
}
62
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();
70
}
71
}
72
return Register();
73
}
74
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();
80
81
if (Amount == 0)
82
return;
83
84
MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
85
const TargetRegisterClass *RC = &Xtensa::ARRegClass;
86
87
// create virtual reg to store immediate
88
unsigned Reg = RegInfo.createVirtualRegister(RC);
89
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);
98
}
99
100
BuildMI(MBB, I, DL, get(Xtensa::OR), SP)
101
.addReg(Reg, RegState::Kill)
102
.addReg(Reg, RegState::Kill);
103
}
104
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");
117
}
118
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);
129
}
130
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);
141
}
142
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");
149
150
LoadOpcode = Xtensa::L32I;
151
StoreOpcode = Xtensa::S32I;
152
}
153
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;
160
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;
168
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");
185
}
186
}
187
188