Skip to content

Commit d7a0f08

Browse files
committed
[Xtensa] Codegen support for memory operations.
1 parent 5fcc08e commit d7a0f08

File tree

10 files changed

+323
-3
lines changed

10 files changed

+323
-3
lines changed

llvm/lib/Target/Xtensa/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ add_llvm_target(XtensaCodeGen
2424
XtensaRegisterInfo.cpp
2525
XtensaSubtarget.cpp
2626
XtensaTargetMachine.cpp
27+
XtensaUtils.cpp
2728

2829
LINK_COMPONENTS
2930
AsmPrinter

llvm/lib/Target/Xtensa/XtensaISelDAGToDAG.cpp

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414

1515
#include "Xtensa.h"
1616
#include "XtensaTargetMachine.h"
17+
#include "XtensaUtils.h"
1718
#include "llvm/CodeGen/MachineFunction.h"
1819
#include "llvm/CodeGen/MachineRegisterInfo.h"
1920
#include "llvm/CodeGen/SelectionDAGISel.h"
21+
#include "llvm/IR/DiagnosticInfo.h"
2022
#include "llvm/Support/Debug.h"
2123
#include "llvm/Support/raw_ostream.h"
2224

@@ -41,7 +43,54 @@ class XtensaDAGToDAGISel : public SelectionDAGISel {
4143

4244
bool selectMemRegAddr(SDValue Addr, SDValue &Base, SDValue &Offset,
4345
int Scale) {
44-
report_fatal_error("MemReg address is not implemented yet");
46+
EVT ValTy = Addr.getValueType();
47+
48+
// if Address is FI, get the TargetFrameIndex.
49+
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
50+
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
51+
Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), ValTy);
52+
53+
return true;
54+
}
55+
56+
if (TM.isPositionIndependent()) {
57+
DiagnosticInfoUnsupported Diag(
58+
CurDAG->getMachineFunction().getFunction(),
59+
"PIC relocations are not supported ",
60+
Addr.getDebugLoc());
61+
CurDAG->getContext()->diagnose(Diag);
62+
}
63+
64+
if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
65+
Addr.getOpcode() == ISD::TargetGlobalAddress))
66+
return false;
67+
68+
// Addresses of the form FI+const or FI|const
69+
bool Valid = false;
70+
if (CurDAG->isBaseWithConstantOffset(Addr)) {
71+
ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
72+
int64_t OffsetVal = CN->getSExtValue();
73+
74+
Valid = isValidAddrOffset(Scale, OffsetVal);
75+
76+
if (Valid) {
77+
// If the first operand is a FI, get the TargetFI Node
78+
if (FrameIndexSDNode *FIN =
79+
dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
80+
Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
81+
else
82+
Base = Addr.getOperand(0);
83+
84+
Offset =
85+
CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), ValTy);
86+
return true;
87+
}
88+
}
89+
90+
// Last case
91+
Base = Addr;
92+
Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), Addr.getValueType());
93+
return true;
4594
}
4695

4796
bool selectMemRegAddrISH1(SDValue Addr, SDValue &Base, SDValue &Offset) {

llvm/lib/Target/Xtensa/XtensaISelLowering.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ XtensaTargetLowering::XtensaTargetLowering(const TargetMachine &tm,
4646

4747
setMinFunctionAlignment(Align(4));
4848

49+
// No sign extend instructions for i1
50+
for (MVT VT : MVT::integer_valuetypes()) {
51+
setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);
52+
setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote);
53+
setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote);
54+
}
55+
4956
// Compute derived properties from the register classes
5057
computeRegisterProperties(STI.getRegisterInfo());
5158
}

llvm/lib/Target/Xtensa/XtensaInstrInfo.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "XtensaInstrInfo.h"
1616
#include "XtensaTargetMachine.h"
1717
#include "llvm/CodeGen/MachineConstantPool.h"
18+
#include "llvm/CodeGen/MachineFrameInfo.h"
1819
#include "llvm/CodeGen/MachineInstrBuilder.h"
1920
#include "llvm/CodeGen/MachineRegisterInfo.h"
2021

@@ -23,5 +24,73 @@
2324

2425
using namespace llvm;
2526

27+
static inline 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+
2647
XtensaInstrInfo::XtensaInstrInfo(XtensaSubtarget &sti)
2748
: XtensaGenInstrInfo(), RI(sti), STI(sti) {}
49+
50+
void XtensaInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
51+
MachineBasicBlock::iterator MBBI,
52+
const DebugLoc &DL, MCRegister DestReg,
53+
MCRegister SrcReg, bool KillSrc) const {
54+
// when we are copying a phys reg we want the bits for fp
55+
if (Xtensa::ARRegClass.contains(DestReg, SrcReg))
56+
BuildMI(MBB, MBBI, DL, get(Xtensa::OR), DestReg)
57+
.addReg(SrcReg, getKillRegState(KillSrc))
58+
.addReg(SrcReg, getKillRegState(KillSrc));
59+
else
60+
report_fatal_error("Impossible reg-to-reg copy");
61+
}
62+
63+
void XtensaInstrInfo::storeRegToStackSlot(
64+
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg,
65+
bool isKill, int FrameIdx, const TargetRegisterClass *RC,
66+
const TargetRegisterInfo *TRI, Register VReg) const {
67+
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
68+
unsigned LoadOpcode, StoreOpcode;
69+
getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode, FrameIdx);
70+
addFrameReference(BuildMI(MBB, MBBI, DL, get(StoreOpcode))
71+
.addReg(SrcReg, getKillRegState(isKill)),
72+
FrameIdx);
73+
}
74+
75+
void XtensaInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
76+
MachineBasicBlock::iterator MBBI,
77+
Register DestReg, int FrameIdx,
78+
const TargetRegisterClass *RC,
79+
const TargetRegisterInfo *TRI,
80+
Register VReg) const {
81+
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
82+
unsigned LoadOpcode, StoreOpcode;
83+
getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode, FrameIdx);
84+
addFrameReference(BuildMI(MBB, MBBI, DL, get(LoadOpcode), DestReg), FrameIdx);
85+
}
86+
87+
void XtensaInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC,
88+
unsigned &LoadOpcode,
89+
unsigned &StoreOpcode,
90+
int64_t offset) const {
91+
if (RC == &Xtensa::ARRegClass) {
92+
LoadOpcode = Xtensa::L32I;
93+
StoreOpcode = Xtensa::S32I;
94+
} else
95+
report_fatal_error("Unsupported regclass to load or store");
96+
}

llvm/lib/Target/Xtensa/XtensaInstrInfo.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,25 @@ class XtensaInstrInfo : public XtensaGenInstrInfo {
3737

3838
// Return the XtensaRegisterInfo, which this class owns.
3939
const XtensaRegisterInfo &getRegisterInfo() const { return RI; }
40+
41+
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
42+
const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg,
43+
bool KillSrc) const override;
44+
void storeRegToStackSlot(MachineBasicBlock &MBB,
45+
MachineBasicBlock::iterator MBBI, Register SrcReg,
46+
bool isKill, int FrameIndex,
47+
const TargetRegisterClass *RC,
48+
const TargetRegisterInfo *TRI,
49+
Register VReg) const override;
50+
void loadRegFromStackSlot(MachineBasicBlock &MBB,
51+
MachineBasicBlock::iterator MBBI, Register DestReg,
52+
int FrameIdx, const TargetRegisterClass *RC,
53+
const TargetRegisterInfo *TRI,
54+
Register VReg) const override;
55+
56+
// Get the load and store opcodes for a given register class and offset.
57+
void getLoadStoreOpcodes(const TargetRegisterClass *RC, unsigned &LoadOpcode,
58+
unsigned &StoreOpcode, int64_t offset) const;
4059
};
4160
} // end namespace llvm
4261

llvm/lib/Target/Xtensa/XtensaRegisterInfo.cpp

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
#include "XtensaRegisterInfo.h"
1616
#include "XtensaInstrInfo.h"
1717
#include "XtensaSubtarget.h"
18+
#include "XtensaUtils.h"
19+
#include "llvm/CodeGen/MachineFrameInfo.h"
20+
#include "llvm/CodeGen/MachineFunction.h"
1821
#include "llvm/CodeGen/MachineInstrBuilder.h"
1922
#include "llvm/CodeGen/MachineRegisterInfo.h"
2023
#include "llvm/Support/Debug.h"
@@ -57,11 +60,56 @@ BitVector XtensaRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
5760
return Reserved;
5861
}
5962

63+
bool XtensaRegisterInfo::eliminateFI(MachineBasicBlock::iterator II,
64+
unsigned OpNo, int FrameIndex,
65+
uint64_t StackSize,
66+
int64_t SPOffset) const {
67+
MachineInstr &MI = *II;
68+
unsigned FrameReg = Xtensa::SP;
69+
70+
// Calculate final offset.
71+
// - There is no need to change the offset if the frame object is one of the
72+
// following: an outgoing argument, pointer to a dynamically allocated
73+
// stack space or a $gp restore location,
74+
// - If the frame object is any of the following, its offset must be adjusted
75+
// by adding the size of the stack:
76+
// incoming argument, callee-saved register location or local variable.
77+
bool IsKill = false;
78+
int64_t Offset =
79+
SPOffset + (int64_t)StackSize + MI.getOperand(OpNo + 1).getImm();
80+
81+
LLVM_DEBUG(errs() << "Offset : " << Offset << "\n"
82+
<< "<--------->\n");
83+
84+
bool Valid = isValidAddrOffset(MI, Offset);
85+
86+
// If MI is not a debug value, make sure Offset fits in the 16-bit immediate
87+
// field.
88+
if (!MI.isDebugValue() && !Valid) {
89+
report_fatal_error("Load immediate not supported yet");
90+
}
91+
92+
MI.getOperand(OpNo).ChangeToRegister(FrameReg, false, false, IsKill);
93+
MI.getOperand(OpNo + 1).ChangeToImmediate(Offset);
94+
95+
return false;
96+
}
97+
6098
bool XtensaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
6199
int SPAdj, unsigned FIOperandNum,
62100
RegScavenger *RS) const {
63-
report_fatal_error("Eliminate frame index not supported yet");
64-
return false;
101+
MachineInstr &MI = *II;
102+
MachineFunction &MF = *MI.getParent()->getParent();
103+
LLVM_DEBUG(errs() << "\nFunction : " << MF.getName() << "\n";
104+
errs() << "<--------->\n"
105+
<< MI);
106+
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
107+
uint64_t stackSize = MF.getFrameInfo().getStackSize();
108+
int64_t spOffset = MF.getFrameInfo().getObjectOffset(FrameIndex);
109+
LLVM_DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n"
110+
<< "spOffset : " << spOffset << "\n"
111+
<< "stackSize : " << stackSize << "\n");
112+
return eliminateFI(MI, FIOperandNum, FrameIndex, stackSize, spOffset);
65113
}
66114

67115
Register XtensaRegisterInfo::getFrameRegister(const MachineFunction &MF) const {

llvm/lib/Target/Xtensa/XtensaRegisterInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ struct XtensaRegisterInfo : public XtensaGenRegisterInfo {
4949
unsigned FIOperandNum,
5050
RegScavenger *RS = nullptr) const override;
5151
Register getFrameRegister(const MachineFunction &MF) const override;
52+
53+
private:
54+
bool eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo,
55+
int FrameIndex, uint64_t StackSize, int64_t SPOffset) const;
5256
};
5357

5458
} // end namespace llvm
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//===--- XtensaUtils.cpp ---- Xtensa Utility Functions ----------*- C++ -*-===//
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 miscellaneous utility functions.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "XtensaUtils.h"
14+
15+
namespace llvm {
16+
17+
// Check address offset for load/store instructions
18+
// The offset should be multiple of scale
19+
bool isValidAddrOffset(int Scale, int64_t OffsetVal) {
20+
bool Valid = false;
21+
22+
switch (Scale) {
23+
case 1:
24+
Valid = (OffsetVal >= 0 && OffsetVal <= 255);
25+
break;
26+
case 2:
27+
Valid = (OffsetVal >= 0 && OffsetVal <= 510) && ((OffsetVal & 0x1) == 0);
28+
break;
29+
case 4:
30+
Valid = (OffsetVal >= 0 && OffsetVal <= 1020) && ((OffsetVal & 0x3) == 0);
31+
break;
32+
default:
33+
break;
34+
}
35+
return Valid;
36+
}
37+
38+
// Check address offset for load/store instructions
39+
bool isValidAddrOffset(MachineInstr &MI, int64_t Offset) {
40+
int Scale = 0;
41+
42+
switch (MI.getOpcode()) {
43+
case Xtensa::L8UI:
44+
case Xtensa::S8I:
45+
Scale = 1;
46+
break;
47+
case Xtensa::L16SI:
48+
case Xtensa::L16UI:
49+
case Xtensa::S16I:
50+
Scale = 2;
51+
break;
52+
default:
53+
// assume that MI is 32-bit load/store operation
54+
Scale = 4;
55+
break;
56+
}
57+
return isValidAddrOffset(Scale, Offset);
58+
}
59+
60+
} // namespace llvm

llvm/lib/Target/Xtensa/XtensaUtils.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===--- XtensaUtils.h ---- Xtensa Utility Functions ------------*- C++ -*-===//
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 miscellaneous utility functions.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef LLVM_LIB_TARGET_XTENSA_XTENSAUTILS_H
14+
#define LLVM_LIB_TARGET_XTENSA_XTENSAUTILS_H
15+
16+
#include "XtensaInstrInfo.h"
17+
#include "llvm/CodeGen/MachineInstr.h"
18+
19+
namespace llvm {
20+
// Check address offset for load/store instructions
21+
// The offset should be multiple of scale
22+
bool isValidAddrOffset(int Scale, int64_t OffsetVal);
23+
24+
// Check address offset for load/store instructions
25+
bool isValidAddrOffset(MachineInstr &MI, int64_t Offset);
26+
} // namespace llvm
27+
#endif // LLVM_LIB_TARGET_XTENSA_XTENSAUTILS_H

0 commit comments

Comments
 (0)