[lanai] Fix for LanaiDelaySlotFiller and LanaiMCInstLower.cpp

Summary:
* Fix to stop delay slot filler from inserting SP modifying instructions in the newly expanded call/return instructions.
* In LowerSymbol the outermost type was not LanaiMCExpr if there was a binary expression
* Remove printExpr in LanaiInstPrinter

Subscribers: joker.eph, llvm-commits

Differential Revision: http://reviews.llvm.org/D18734

llvm-svn: 265251
This commit is contained in:
Jacques Pienaar 2016-04-03 00:49:27 +00:00
parent c4965009bd
commit 796975d311
3 changed files with 87 additions and 104 deletions

View File

@ -29,18 +29,17 @@ using namespace llvm;
#define PRINT_ALIAS_INSTR #define PRINT_ALIAS_INSTR
#include "LanaiGenAsmWriter.inc" #include "LanaiGenAsmWriter.inc"
void LanaiInstPrinter::printRegName(raw_ostream &Ostream, void LanaiInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
unsigned RegNo) const { OS << StringRef(getRegisterName(RegNo)).lower();
Ostream << StringRef(getRegisterName(RegNo)).lower();
} }
bool LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &Ostream, bool LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
StringRef Alias, unsigned OpNo0, StringRef Alias, unsigned OpNo0,
unsigned OpNo1) { unsigned OpNo1) {
Ostream << "\t" << Alias << " "; OS << "\t" << Alias << " ";
printOperand(MI, OpNo0, Ostream); printOperand(MI, OpNo0, OS);
Ostream << ", "; OS << ", ";
printOperand(MI, OpNo1, Ostream); printOperand(MI, OpNo1, OS);
return true; return true;
} }
@ -68,191 +67,169 @@ static StringRef decIncOperator(const MCInst *MI) {
} }
bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI, bool LanaiInstPrinter::printMemoryLoadIncrement(const MCInst *MI,
raw_ostream &Ostream, raw_ostream &OS,
StringRef Opcode, StringRef Opcode,
int AddOffset) { int AddOffset) {
if (isPreIncrementForm(MI, AddOffset)) { if (isPreIncrementForm(MI, AddOffset)) {
Ostream << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%" OS << "\t" << Opcode << "\t[" << decIncOperator(MI) << "%"
<< getRegisterName(MI->getOperand(1).getReg()) << "], %" << getRegisterName(MI->getOperand(1).getReg()) << "], %"
<< getRegisterName(MI->getOperand(0).getReg()); << getRegisterName(MI->getOperand(0).getReg());
return true; return true;
} }
if (isPostIncrementForm(MI, AddOffset)) { if (isPostIncrementForm(MI, AddOffset)) {
Ostream << "\t" << Opcode << "\t[%" OS << "\t" << Opcode << "\t[%"
<< getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI) << getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI)
<< "], %" << getRegisterName(MI->getOperand(0).getReg()); << "], %" << getRegisterName(MI->getOperand(0).getReg());
return true; return true;
} }
return false; return false;
} }
bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI, bool LanaiInstPrinter::printMemoryStoreIncrement(const MCInst *MI,
raw_ostream &Ostream, raw_ostream &OS,
StringRef Opcode, StringRef Opcode,
int AddOffset) { int AddOffset) {
if (isPreIncrementForm(MI, AddOffset)) { if (isPreIncrementForm(MI, AddOffset)) {
Ostream << "\t" << Opcode << "\t%" OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
<< getRegisterName(MI->getOperand(0).getReg()) << ", [" << ", [" << decIncOperator(MI) << "%"
<< decIncOperator(MI) << "%" << getRegisterName(MI->getOperand(1).getReg()) << "]";
<< getRegisterName(MI->getOperand(1).getReg()) << "]";
return true; return true;
} }
if (isPostIncrementForm(MI, AddOffset)) { if (isPostIncrementForm(MI, AddOffset)) {
Ostream << "\t" << Opcode << "\t%" OS << "\t" << Opcode << "\t%" << getRegisterName(MI->getOperand(0).getReg())
<< getRegisterName(MI->getOperand(0).getReg()) << ", [%" << ", [%" << getRegisterName(MI->getOperand(1).getReg())
<< getRegisterName(MI->getOperand(1).getReg()) << decIncOperator(MI) << decIncOperator(MI) << "]";
<< "]";
return true; return true;
} }
return false; return false;
} }
bool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &Ostream) { bool LanaiInstPrinter::printAlias(const MCInst *MI, raw_ostream &OS) {
switch (MI->getOpcode()) { switch (MI->getOpcode()) {
case Lanai::LDW_RI: case Lanai::LDW_RI:
// ld 4[*%rN], %rX => ld [++imm], %rX // ld 4[*%rN], %rX => ld [++imm], %rX
// ld -4[*%rN], %rX => ld [--imm], %rX // ld -4[*%rN], %rX => ld [--imm], %rX
// ld 4[%rN*], %rX => ld [imm++], %rX // ld 4[%rN*], %rX => ld [imm++], %rX
// ld -4[%rN*], %rX => ld [imm--], %rX // ld -4[%rN*], %rX => ld [imm--], %rX
return printMemoryLoadIncrement(MI, Ostream, "ld", 4); return printMemoryLoadIncrement(MI, OS, "ld", 4);
case Lanai::LDHs_RI: case Lanai::LDHs_RI:
return printMemoryLoadIncrement(MI, Ostream, "ld.h", 2); return printMemoryLoadIncrement(MI, OS, "ld.h", 2);
case Lanai::LDHz_RI: case Lanai::LDHz_RI:
return printMemoryLoadIncrement(MI, Ostream, "uld.h", 2); return printMemoryLoadIncrement(MI, OS, "uld.h", 2);
case Lanai::LDBs_RI: case Lanai::LDBs_RI:
return printMemoryLoadIncrement(MI, Ostream, "ld.b", 1); return printMemoryLoadIncrement(MI, OS, "ld.b", 1);
case Lanai::LDBz_RI: case Lanai::LDBz_RI:
return printMemoryLoadIncrement(MI, Ostream, "uld.b", 1); return printMemoryLoadIncrement(MI, OS, "uld.b", 1);
case Lanai::SW_RI: case Lanai::SW_RI:
// st %rX, 4[*%rN] => st %rX, [++imm] // st %rX, 4[*%rN] => st %rX, [++imm]
// st %rX, -4[*%rN] => st %rX, [--imm] // st %rX, -4[*%rN] => st %rX, [--imm]
// st %rX, 4[%rN*] => st %rX, [imm++] // st %rX, 4[%rN*] => st %rX, [imm++]
// st %rX, -4[%rN*] => st %rX, [imm--] // st %rX, -4[%rN*] => st %rX, [imm--]
return printMemoryStoreIncrement(MI, Ostream, "st", 4); return printMemoryStoreIncrement(MI, OS, "st", 4);
case Lanai::STH_RI: case Lanai::STH_RI:
return printMemoryStoreIncrement(MI, Ostream, "st.h", 2); return printMemoryStoreIncrement(MI, OS, "st.h", 2);
case Lanai::STB_RI: case Lanai::STB_RI:
return printMemoryStoreIncrement(MI, Ostream, "st.b", 1); return printMemoryStoreIncrement(MI, OS, "st.b", 1);
default: default:
return false; return false;
} }
} }
void LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &Ostream, void LanaiInstPrinter::printInst(const MCInst *MI, raw_ostream &OS,
StringRef Annotation, StringRef Annotation,
const MCSubtargetInfo &STI) { const MCSubtargetInfo &STI) {
if (!printAlias(MI, Ostream) && !printAliasInstr(MI, Ostream)) if (!printAlias(MI, OS) && !printAliasInstr(MI, OS)) printInstruction(MI, OS);
printInstruction(MI, Ostream); printAnnotation(OS, Annotation);
printAnnotation(Ostream, Annotation);
}
static void printExpr(const MCAsmInfo &MAI, const MCExpr &Expr,
raw_ostream &Ostream) {
const MCExpr *SRE;
if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(&Expr))
SRE = dyn_cast<LanaiMCExpr>(BE->getLHS());
else if (isa<LanaiMCExpr>(&Expr)) {
SRE = dyn_cast<LanaiMCExpr>(&Expr);
} else {
SRE = dyn_cast<MCSymbolRefExpr>(&Expr);
}
assert(SRE && "Unexpected MCExpr type.");
SRE->print(Ostream, &MAI);
} }
void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, void LanaiInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &Ostream, raw_ostream &OS, const char *Modifier) {
const char *Modifier) {
assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
const MCOperand &Op = MI->getOperand(OpNo); const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isReg()) if (Op.isReg())
Ostream << "%" << getRegisterName(Op.getReg()); OS << "%" << getRegisterName(Op.getReg());
else if (Op.isImm()) else if (Op.isImm())
Ostream << formatHex(Op.getImm()); OS << formatHex(Op.getImm());
else { else {
assert(Op.isExpr() && "Expected an expression"); assert(Op.isExpr() && "Expected an expression");
printExpr(MAI, *Op.getExpr(), Ostream); Op.getExpr()->print(OS, &MAI);
} }
} }
void LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo, void LanaiInstPrinter::printMemImmOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &Ostream) { raw_ostream &OS) {
const MCOperand &Op = MI->getOperand(OpNo); const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isImm()) { if (Op.isImm()) {
Ostream << '[' << formatHex(Op.getImm()) << ']'; OS << '[' << formatHex(Op.getImm()) << ']';
} else { } else {
// Symbolic operand will be lowered to immediate value by linker // Symbolic operand will be lowered to immediate value by linker
assert(Op.isExpr() && "Expected an expression"); assert(Op.isExpr() && "Expected an expression");
Ostream << '['; OS << '[';
printExpr(MAI, *Op.getExpr(), Ostream); Op.getExpr()->print(OS, &MAI);
Ostream << ']'; OS << ']';
} }
} }
void LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo, void LanaiInstPrinter::printHi16ImmOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &Ostream) { raw_ostream &OS) {
const MCOperand &Op = MI->getOperand(OpNo); const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isImm()) { if (Op.isImm()) {
Ostream << formatHex(Op.getImm() << 16); OS << formatHex(Op.getImm() << 16);
} else { } else {
// Symbolic operand will be lowered to immediate value by linker // Symbolic operand will be lowered to immediate value by linker
assert(Op.isExpr() && "Expected an expression"); assert(Op.isExpr() && "Expected an expression");
printExpr(MAI, *Op.getExpr(), Ostream); Op.getExpr()->print(OS, &MAI);
} }
} }
void LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo, void LanaiInstPrinter::printHi16AndImmOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &Ostream) { raw_ostream &OS) {
const MCOperand &Op = MI->getOperand(OpNo); const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isImm()) { if (Op.isImm()) {
Ostream << formatHex((Op.getImm() << 16) | 0xffff); OS << formatHex((Op.getImm() << 16) | 0xffff);
} else { } else {
// Symbolic operand will be lowered to immediate value by linker // Symbolic operand will be lowered to immediate value by linker
assert(Op.isExpr() && "Expected an expression"); assert(Op.isExpr() && "Expected an expression");
printExpr(MAI, *Op.getExpr(), Ostream); Op.getExpr()->print(OS, &MAI);
} }
} }
void LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo, void LanaiInstPrinter::printLo16AndImmOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &Ostream) { raw_ostream &OS) {
const MCOperand &Op = MI->getOperand(OpNo); const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isImm()) { if (Op.isImm()) {
Ostream << formatHex(0xffff0000 | Op.getImm()); OS << formatHex(0xffff0000 | Op.getImm());
} else { } else {
// Symbolic operand will be lowered to immediate value by linker // Symbolic operand will be lowered to immediate value by linker
assert(Op.isExpr() && "Expected an expression"); assert(Op.isExpr() && "Expected an expression");
printExpr(MAI, *Op.getExpr(), Ostream); Op.getExpr()->print(OS, &MAI);
} }
} }
static void printMemoryBaseRegister(raw_ostream &Ostream, const unsigned AluCode, static void printMemoryBaseRegister(raw_ostream &OS, const unsigned AluCode,
const MCOperand &RegOp) { const MCOperand &RegOp) {
assert(RegOp.isReg() && "Register operand expected"); assert(RegOp.isReg() && "Register operand expected");
Ostream << "["; OS << "[";
if (LPAC::isPreOp(AluCode)) if (LPAC::isPreOp(AluCode)) OS << "*";
Ostream << "*"; OS << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg());
Ostream << "%" << LanaiInstPrinter::getRegisterName(RegOp.getReg()); if (LPAC::isPostOp(AluCode)) OS << "*";
if (LPAC::isPostOp(AluCode)) OS << "]";
Ostream << "*";
Ostream << "]";
} }
template <unsigned SizeInBits> template <unsigned SizeInBits>
static void printMemoryImmediateOffset(const MCAsmInfo &MAI, static void printMemoryImmediateOffset(const MCAsmInfo &MAI,
const MCOperand &OffsetOp, const MCOperand &OffsetOp,
raw_ostream &Ostream) { raw_ostream &OS) {
assert((OffsetOp.isImm() || OffsetOp.isExpr()) && "Immediate expected"); assert((OffsetOp.isImm() || OffsetOp.isExpr()) && "Immediate expected");
if (OffsetOp.isImm()) { if (OffsetOp.isImm()) {
assert(isInt<SizeInBits>(OffsetOp.getImm()) && "Constant value truncated"); assert(isInt<SizeInBits>(OffsetOp.getImm()) && "Constant value truncated");
Ostream << OffsetOp.getImm(); OS << OffsetOp.getImm();
} else } else
printExpr(MAI, *OffsetOp.getExpr(), Ostream); OffsetOp.getExpr()->print(OS, &MAI);
} }
void LanaiInstPrinter::printMemRiOperand(const MCInst *MI, int OpNo, void LanaiInstPrinter::printMemRiOperand(const MCInst *MI, int OpNo,
raw_ostream &Ostream, raw_ostream &OS,
const char *Modifier) { const char *Modifier) {
const MCOperand &RegOp = MI->getOperand(OpNo); const MCOperand &RegOp = MI->getOperand(OpNo);
const MCOperand &OffsetOp = MI->getOperand(OpNo + 1); const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
@ -260,14 +237,14 @@ void LanaiInstPrinter::printMemRiOperand(const MCInst *MI, int OpNo,
const unsigned AluCode = AluOp.getImm(); const unsigned AluCode = AluOp.getImm();
// Offset // Offset
printMemoryImmediateOffset<16>(MAI, OffsetOp, Ostream); printMemoryImmediateOffset<16>(MAI, OffsetOp, OS);
// Register // Register
printMemoryBaseRegister(Ostream, AluCode, RegOp); printMemoryBaseRegister(OS, AluCode, RegOp);
} }
void LanaiInstPrinter::printMemRrOperand(const MCInst *MI, int OpNo, void LanaiInstPrinter::printMemRrOperand(const MCInst *MI, int OpNo,
raw_ostream &Ostream, raw_ostream &OS,
const char *Modifier) { const char *Modifier) {
const MCOperand &RegOp = MI->getOperand(OpNo); const MCOperand &RegOp = MI->getOperand(OpNo);
const MCOperand &OffsetOp = MI->getOperand(OpNo + 1); const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
@ -276,19 +253,17 @@ void LanaiInstPrinter::printMemRrOperand(const MCInst *MI, int OpNo,
assert(OffsetOp.isReg() && RegOp.isReg() && "Registers expected."); assert(OffsetOp.isReg() && RegOp.isReg() && "Registers expected.");
// [ Base OP Offset ] // [ Base OP Offset ]
Ostream << "["; OS << "[";
if (LPAC::isPreOp(AluCode)) if (LPAC::isPreOp(AluCode)) OS << "*";
Ostream << "*"; OS << "%" << getRegisterName(RegOp.getReg());
Ostream << "%" << getRegisterName(RegOp.getReg()); if (LPAC::isPostOp(AluCode)) OS << "*";
if (LPAC::isPostOp(AluCode)) OS << " " << LPAC::lanaiAluCodeToString(AluCode) << " ";
Ostream << "*"; OS << "%" << getRegisterName(OffsetOp.getReg());
Ostream << " " << LPAC::lanaiAluCodeToString(AluCode) << " "; OS << "]";
Ostream << "%" << getRegisterName(OffsetOp.getReg());
Ostream << "]";
} }
void LanaiInstPrinter::printMemSplsOperand(const MCInst *MI, int OpNo, void LanaiInstPrinter::printMemSplsOperand(const MCInst *MI, int OpNo,
raw_ostream &Ostream, raw_ostream &OS,
const char *Modifier) { const char *Modifier) {
const MCOperand &RegOp = MI->getOperand(OpNo); const MCOperand &RegOp = MI->getOperand(OpNo);
const MCOperand &OffsetOp = MI->getOperand(OpNo + 1); const MCOperand &OffsetOp = MI->getOperand(OpNo + 1);
@ -296,14 +271,14 @@ void LanaiInstPrinter::printMemSplsOperand(const MCInst *MI, int OpNo,
const unsigned AluCode = AluOp.getImm(); const unsigned AluCode = AluOp.getImm();
// Offset // Offset
printMemoryImmediateOffset<10>(MAI, OffsetOp, Ostream); printMemoryImmediateOffset<10>(MAI, OffsetOp, OS);
// Register // Register
printMemoryBaseRegister(Ostream, AluCode, RegOp); printMemoryBaseRegister(OS, AluCode, RegOp);
} }
void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo, void LanaiInstPrinter::printCCOperand(const MCInst *MI, int OpNo,
raw_ostream &Ostream) { raw_ostream &OS) {
const int CC = static_cast<const int>(MI->getOperand(OpNo).getImm()); const int CC = static_cast<const int>(MI->getOperand(OpNo).getImm());
Ostream << lanaiCondCodeToString(static_cast<LPCC::CondCode>(CC)); OS << lanaiCondCodeToString(static_cast<LPCC::CondCode>(CC));
} }

View File

@ -238,6 +238,13 @@ void Filler::insertDefsUses(MachineBasicBlock::instr_iterator MI,
else if (MO.isUse()) else if (MO.isUse())
RegUses.insert(Reg); RegUses.insert(Reg);
} }
// Call & return instructions defines SP implicitly. Implicit defines are not
// included in the RegDefs set of calls but instructions modifying SP cannot
// be inserted in the delay slot of a call/return as these instructions are
// expanded to multiple instructions with SP modified before the branch that
// has the delay slot.
if (MI->isCall() || MI->isReturn()) RegDefs.insert(Lanai::SP);
} }
// Returns true if the Reg or its alias is in the RegSet. // Returns true if the Reg or its alias is in the RegSet.

View File

@ -83,11 +83,12 @@ MCOperand LanaiMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
llvm_unreachable("Unknown target flag on GV operand"); llvm_unreachable("Unknown target flag on GV operand");
} }
const MCSymbolRefExpr *Symbol = MCSymbolRefExpr::create(Sym, Ctx); const MCExpr *Expr =
const MCExpr *Expr = LanaiMCExpr::create(Kind, Symbol, Ctx); MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
if (!MO.isJTI() && MO.getOffset()) if (!MO.isJTI() && MO.getOffset())
Expr = MCBinaryExpr::createAdd( Expr = MCBinaryExpr::createAdd(
Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
Expr = LanaiMCExpr::create(Kind, Expr, Ctx);
return MCOperand::createExpr(Expr); return MCOperand::createExpr(Expr);
} }