The renamable flag is useful during MachineCopyPropagation but renamable flag will be dropped after lowerCopy in some case. This patch introduces extra arguments to pass the renamable flag to copyPhysReg.
188 lines
7.4 KiB
C++
188 lines
7.4 KiB
C++
//===- XtensaInstrInfo.cpp - Xtensa Instruction Information ---------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains the Xtensa implementation of the TargetInstrInfo class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "XtensaInstrInfo.h"
|
|
#include "XtensaTargetMachine.h"
|
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
|
|
#define GET_INSTRINFO_CTOR_DTOR
|
|
#include "XtensaGenInstrInfo.inc"
|
|
|
|
using namespace llvm;
|
|
|
|
static const MachineInstrBuilder &
|
|
addFrameReference(const MachineInstrBuilder &MIB, int FI) {
|
|
MachineInstr *MI = MIB;
|
|
MachineFunction &MF = *MI->getParent()->getParent();
|
|
MachineFrameInfo &MFFrame = MF.getFrameInfo();
|
|
const MCInstrDesc &MCID = MI->getDesc();
|
|
MachineMemOperand::Flags Flags = MachineMemOperand::MONone;
|
|
if (MCID.mayLoad())
|
|
Flags |= MachineMemOperand::MOLoad;
|
|
if (MCID.mayStore())
|
|
Flags |= MachineMemOperand::MOStore;
|
|
int64_t Offset = 0;
|
|
Align Alignment = MFFrame.getObjectAlign(FI);
|
|
|
|
MachineMemOperand *MMO =
|
|
MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(MF, FI, Offset),
|
|
Flags, MFFrame.getObjectSize(FI), Alignment);
|
|
return MIB.addFrameIndex(FI).addImm(Offset).addMemOperand(MMO);
|
|
}
|
|
|
|
XtensaInstrInfo::XtensaInstrInfo(const XtensaSubtarget &STI)
|
|
: XtensaGenInstrInfo(Xtensa::ADJCALLSTACKDOWN, Xtensa::ADJCALLSTACKUP),
|
|
RI(STI), STI(STI) {}
|
|
|
|
Register XtensaInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
|
|
int &FrameIndex) const {
|
|
if (MI.getOpcode() == Xtensa::L32I) {
|
|
if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
|
|
MI.getOperand(2).getImm() == 0) {
|
|
FrameIndex = MI.getOperand(1).getIndex();
|
|
return MI.getOperand(0).getReg();
|
|
}
|
|
}
|
|
return Register();
|
|
}
|
|
|
|
Register XtensaInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
|
|
int &FrameIndex) const {
|
|
if (MI.getOpcode() == Xtensa::S32I) {
|
|
if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
|
|
MI.getOperand(2).getImm() == 0) {
|
|
FrameIndex = MI.getOperand(1).getIndex();
|
|
return MI.getOperand(0).getReg();
|
|
}
|
|
}
|
|
return Register();
|
|
}
|
|
|
|
/// Adjust SP by Amount bytes.
|
|
void XtensaInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,
|
|
MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator I) const {
|
|
DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
|
|
|
|
if (Amount == 0)
|
|
return;
|
|
|
|
MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
|
|
const TargetRegisterClass *RC = &Xtensa::ARRegClass;
|
|
|
|
// create virtual reg to store immediate
|
|
unsigned Reg = RegInfo.createVirtualRegister(RC);
|
|
|
|
if (isInt<8>(Amount)) { // addi sp, sp, amount
|
|
BuildMI(MBB, I, DL, get(Xtensa::ADDI), Reg).addReg(SP).addImm(Amount);
|
|
} else { // Expand immediate that doesn't fit in 8-bit.
|
|
unsigned Reg1;
|
|
loadImmediate(MBB, I, &Reg1, Amount);
|
|
BuildMI(MBB, I, DL, get(Xtensa::ADD), Reg)
|
|
.addReg(SP)
|
|
.addReg(Reg1, RegState::Kill);
|
|
}
|
|
|
|
BuildMI(MBB, I, DL, get(Xtensa::OR), SP)
|
|
.addReg(Reg, RegState::Kill)
|
|
.addReg(Reg, RegState::Kill);
|
|
}
|
|
|
|
void XtensaInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator MBBI,
|
|
const DebugLoc &DL, MCRegister DestReg,
|
|
MCRegister SrcReg, bool KillSrc,
|
|
bool RenamableDest, bool RenamableSrc) const {
|
|
// The MOV instruction is not present in core ISA,
|
|
// so use OR instruction.
|
|
if (Xtensa::ARRegClass.contains(DestReg, SrcReg))
|
|
BuildMI(MBB, MBBI, DL, get(Xtensa::OR), DestReg)
|
|
.addReg(SrcReg, getKillRegState(KillSrc))
|
|
.addReg(SrcReg, getKillRegState(KillSrc));
|
|
else
|
|
report_fatal_error("Impossible reg-to-reg copy");
|
|
}
|
|
|
|
void XtensaInstrInfo::storeRegToStackSlot(
|
|
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg,
|
|
bool isKill, int FrameIdx, const TargetRegisterClass *RC,
|
|
const TargetRegisterInfo *TRI, Register VReg) const {
|
|
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
|
unsigned LoadOpcode, StoreOpcode;
|
|
getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode, FrameIdx);
|
|
MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, get(StoreOpcode))
|
|
.addReg(SrcReg, getKillRegState(isKill));
|
|
addFrameReference(MIB, FrameIdx);
|
|
}
|
|
|
|
void XtensaInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator MBBI,
|
|
Register DestReg, int FrameIdx,
|
|
const TargetRegisterClass *RC,
|
|
const TargetRegisterInfo *TRI,
|
|
Register VReg) const {
|
|
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
|
unsigned LoadOpcode, StoreOpcode;
|
|
getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode, FrameIdx);
|
|
addFrameReference(BuildMI(MBB, MBBI, DL, get(LoadOpcode), DestReg), FrameIdx);
|
|
}
|
|
|
|
void XtensaInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC,
|
|
unsigned &LoadOpcode,
|
|
unsigned &StoreOpcode,
|
|
int64_t offset) const {
|
|
assert((RC == &Xtensa::ARRegClass) &&
|
|
"Unsupported regclass to load or store");
|
|
|
|
LoadOpcode = Xtensa::L32I;
|
|
StoreOpcode = Xtensa::S32I;
|
|
}
|
|
|
|
void XtensaInstrInfo::loadImmediate(MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator MBBI,
|
|
unsigned *Reg, int64_t Value) const {
|
|
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
|
MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
|
|
const TargetRegisterClass *RC = &Xtensa::ARRegClass;
|
|
|
|
// create virtual reg to store immediate
|
|
*Reg = RegInfo.createVirtualRegister(RC);
|
|
if (Value >= -2048 && Value <= 2047) {
|
|
BuildMI(MBB, MBBI, DL, get(Xtensa::MOVI), *Reg).addImm(Value);
|
|
} else if (Value >= -32768 && Value <= 32767) {
|
|
int Low = Value & 0xFF;
|
|
int High = Value & ~0xFF;
|
|
|
|
BuildMI(MBB, MBBI, DL, get(Xtensa::MOVI), *Reg).addImm(Low);
|
|
BuildMI(MBB, MBBI, DL, get(Xtensa::ADDMI), *Reg).addReg(*Reg).addImm(High);
|
|
} else if (Value >= -4294967296LL && Value <= 4294967295LL) {
|
|
// 32 bit arbitrary constant
|
|
MachineConstantPool *MCP = MBB.getParent()->getConstantPool();
|
|
uint64_t UVal = ((uint64_t)Value) & 0xFFFFFFFFLL;
|
|
const Constant *CVal = ConstantInt::get(
|
|
Type::getInt32Ty(MBB.getParent()->getFunction().getContext()), UVal,
|
|
false);
|
|
unsigned Idx = MCP->getConstantPoolIndex(CVal, Align(2U));
|
|
// MCSymbol MSym
|
|
BuildMI(MBB, MBBI, DL, get(Xtensa::L32R), *Reg).addConstantPoolIndex(Idx);
|
|
} else {
|
|
// use L32R to let assembler load immediate best
|
|
// TODO replace to L32R
|
|
report_fatal_error("Unsupported load immediate value");
|
|
}
|
|
}
|