mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
[Hexagon] Fix some Clang-tidy modernize and Include What You Use warnings; other minor fixes (NFC).
llvm-svn: 289604
This commit is contained in:
parent
4a5c82b02b
commit
271b3b84f5
@ -10,39 +10,53 @@
|
||||
#define DEBUG_TYPE "mcasmparser"
|
||||
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonRegisterInfo.h"
|
||||
#include "HexagonTargetStreamer.h"
|
||||
#include "MCTargetDesc/HexagonBaseInfo.h"
|
||||
#include "MCTargetDesc/HexagonMCAsmInfo.h"
|
||||
#include "MCTargetDesc/HexagonMCChecker.h"
|
||||
#include "MCTargetDesc/HexagonMCELFStreamer.h"
|
||||
#include "MCTargetDesc/HexagonMCExpr.h"
|
||||
#include "MCTargetDesc/HexagonMCShuffler.h"
|
||||
#include "MCTargetDesc/HexagonMCInstrInfo.h"
|
||||
#include "MCTargetDesc/HexagonMCTargetDesc.h"
|
||||
#include "MCTargetDesc/HexagonShuffler.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCDirectives.h"
|
||||
#include "llvm/MC/MCELFStreamer.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCParser/MCAsmLexer.h"
|
||||
#include "llvm/MC/MCParser/MCAsmParser.h"
|
||||
#include "llvm/MC/MCParser/MCAsmParserExtension.h"
|
||||
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
|
||||
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCSectionELF.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/SMLoc.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -65,8 +79,8 @@ static cl::opt<bool> ErrorNoncontigiousRegister("merror-noncontigious-register",
|
||||
cl::desc("Error for register names that aren't contigious"),
|
||||
cl::init(false));
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
struct HexagonOperand;
|
||||
|
||||
class HexagonAsmParser : public MCTargetAsmParser {
|
||||
@ -93,9 +107,7 @@ class HexagonAsmParser : public MCTargetAsmParser {
|
||||
bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
|
||||
bool ParseDirectiveFalign(unsigned Size, SMLoc L);
|
||||
|
||||
virtual bool ParseRegister(unsigned &RegNo,
|
||||
SMLoc &StartLoc,
|
||||
SMLoc &EndLoc) override;
|
||||
bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
|
||||
bool ParseDirectiveSubsection(SMLoc L);
|
||||
bool ParseDirectiveValue(unsigned Size, SMLoc L);
|
||||
bool ParseDirectiveComm(bool IsLocal, SMLoc L);
|
||||
@ -141,14 +153,14 @@ public:
|
||||
MCII (MII), MCB(HexagonMCInstrInfo::createBundle()), InBrackets(false) {
|
||||
setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
|
||||
|
||||
MCAsmParserExtension::Initialize(_Parser);
|
||||
MCAsmParserExtension::Initialize(_Parser);
|
||||
|
||||
Assembler = nullptr;
|
||||
// FIXME: need better way to detect AsmStreamer (upstream removed getKind())
|
||||
if (!Parser.getStreamer().hasRawTextSupport()) {
|
||||
MCELFStreamer *MES = static_cast<MCELFStreamer *>(&Parser.getStreamer());
|
||||
Assembler = &MES->getAssembler();
|
||||
}
|
||||
Assembler = nullptr;
|
||||
// FIXME: need better way to detect AsmStreamer (upstream removed getKind())
|
||||
if (!Parser.getStreamer().hasRawTextSupport()) {
|
||||
MCELFStreamer *MES = static_cast<MCELFStreamer *>(&Parser.getStreamer());
|
||||
Assembler = &MES->getAssembler();
|
||||
}
|
||||
}
|
||||
|
||||
bool splitIdentifier(OperandVector &Operands);
|
||||
@ -157,15 +169,17 @@ public:
|
||||
bool implicitExpressionLocation(OperandVector &Operands);
|
||||
bool parseExpressionOrOperand(OperandVector &Operands);
|
||||
bool parseExpression(MCExpr const *& Expr);
|
||||
virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
|
||||
SMLoc NameLoc, OperandVector &Operands) override
|
||||
|
||||
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
|
||||
SMLoc NameLoc, OperandVector &Operands) override
|
||||
{
|
||||
llvm_unreachable("Unimplemented");
|
||||
}
|
||||
virtual bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
|
||||
AsmToken ID, OperandVector &Operands) override;
|
||||
|
||||
virtual bool ParseDirective(AsmToken DirectiveID) override;
|
||||
bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, AsmToken ID,
|
||||
OperandVector &Operands) override;
|
||||
|
||||
bool ParseDirective(AsmToken DirectiveID) override;
|
||||
};
|
||||
|
||||
/// HexagonOperand - Instances of this class represent a parsed Hexagon machine
|
||||
@ -219,12 +233,12 @@ public:
|
||||
}
|
||||
|
||||
/// getStartLoc - Get the location of the first token of this operand.
|
||||
SMLoc getStartLoc() const { return StartLoc; }
|
||||
SMLoc getStartLoc() const override { return StartLoc; }
|
||||
|
||||
/// getEndLoc - Get the location of the last token of this operand.
|
||||
SMLoc getEndLoc() const { return EndLoc; }
|
||||
SMLoc getEndLoc() const override { return EndLoc; }
|
||||
|
||||
unsigned getReg() const {
|
||||
unsigned getReg() const override {
|
||||
assert(Kind == Register && "Invalid access!");
|
||||
return Reg.RegNum;
|
||||
}
|
||||
@ -234,10 +248,10 @@ public:
|
||||
return Imm.Val;
|
||||
}
|
||||
|
||||
bool isToken() const { return Kind == Token; }
|
||||
bool isImm() const { return Kind == Immediate; }
|
||||
bool isMem() const { llvm_unreachable("No isMem"); }
|
||||
bool isReg() const { return Kind == Register; }
|
||||
bool isToken() const override { return Kind == Token; }
|
||||
bool isImm() const override { return Kind == Immediate; }
|
||||
bool isMem() const override { llvm_unreachable("No isMem"); }
|
||||
bool isReg() const override { return Kind == Register; }
|
||||
|
||||
bool CheckImmRange(int immBits, int zeroBits, bool isSigned,
|
||||
bool isRelocatable, bool Extendable) const {
|
||||
@ -259,11 +273,11 @@ public:
|
||||
if (bits == 64)
|
||||
return true;
|
||||
if (Res >= 0)
|
||||
return ((uint64_t)Res < (uint64_t)(1ULL << bits)) ? true : false;
|
||||
return ((uint64_t)Res < (uint64_t)(1ULL << bits));
|
||||
else {
|
||||
const int64_t high_bit_set = 1ULL << 63;
|
||||
const uint64_t mask = (high_bit_set >> (63 - bits));
|
||||
return (((uint64_t)Res & mask) == mask) ? true : false;
|
||||
return (((uint64_t)Res & mask) == mask);
|
||||
}
|
||||
}
|
||||
} else if (myMCExpr->getKind() == MCExpr::SymbolRef && isRelocatable)
|
||||
@ -565,7 +579,7 @@ public:
|
||||
return StringRef(Tok.Data, Tok.Length);
|
||||
}
|
||||
|
||||
virtual void print(raw_ostream &OS) const;
|
||||
void print(raw_ostream &OS) const override;
|
||||
|
||||
static std::unique_ptr<HexagonOperand> CreateToken(StringRef Str, SMLoc S) {
|
||||
HexagonOperand *Op = new HexagonOperand(Token);
|
||||
@ -595,7 +609,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace.
|
||||
} // end anonymous namespace
|
||||
|
||||
void HexagonOperand::print(raw_ostream &OS) const {
|
||||
switch (Kind) {
|
||||
@ -625,7 +639,7 @@ bool HexagonAsmParser::finishBundle(SMLoc IDLoc, MCStreamer &Out) {
|
||||
getContext(), MCB,
|
||||
&Check);
|
||||
|
||||
while (Check.getNextErrInfo() == true) {
|
||||
while (Check.getNextErrInfo()) {
|
||||
unsigned Reg = Check.getErrRegister();
|
||||
Twine R(RI->getName(Reg));
|
||||
|
||||
@ -876,7 +890,7 @@ bool HexagonAsmParser::ParseDirective(AsmToken DirectiveID) {
|
||||
return true;
|
||||
}
|
||||
bool HexagonAsmParser::ParseDirectiveSubsection(SMLoc L) {
|
||||
const MCExpr *Subsection = 0;
|
||||
const MCExpr *Subsection = nullptr;
|
||||
int64_t Res;
|
||||
|
||||
assert((getLexer().isNot(AsmToken::EndOfStatement)) &&
|
||||
@ -912,7 +926,7 @@ bool HexagonAsmParser::ParseDirectiveFalign(unsigned Size, SMLoc L) {
|
||||
SMLoc ExprLoc = L;
|
||||
|
||||
// Make sure we have a number (false is returned if expression is a number)
|
||||
if (getParser().parseExpression(Value) == false) {
|
||||
if (!getParser().parseExpression(Value)) {
|
||||
// Make sure this is a number that is in range
|
||||
const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value);
|
||||
uint64_t IntValue = MCE->getValue();
|
||||
@ -934,8 +948,7 @@ bool HexagonAsmParser::ParseDirectiveFalign(unsigned Size, SMLoc L) {
|
||||
/// ::= .word [ expression (, expression)* ]
|
||||
bool HexagonAsmParser::ParseDirectiveValue(unsigned Size, SMLoc L) {
|
||||
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
||||
|
||||
for (;;) {
|
||||
while (true) {
|
||||
const MCExpr *Value;
|
||||
SMLoc ExprLoc = L;
|
||||
if (getParser().parseExpression(Value))
|
||||
@ -1067,8 +1080,8 @@ extern "C" void LLVMInitializeHexagonAsmParser() {
|
||||
#define GET_REGISTER_MATCHER
|
||||
#include "HexagonGenAsmMatcher.inc"
|
||||
|
||||
namespace {
|
||||
bool previousEqual(OperandVector &Operands, size_t Index, StringRef String) {
|
||||
static bool previousEqual(OperandVector &Operands, size_t Index,
|
||||
StringRef String) {
|
||||
if (Index >= Operands.size())
|
||||
return false;
|
||||
MCParsedAsmOperand &Operand = *Operands[Operands.size() - Index - 1];
|
||||
@ -1076,14 +1089,14 @@ bool previousEqual(OperandVector &Operands, size_t Index, StringRef String) {
|
||||
return false;
|
||||
return static_cast<HexagonOperand &>(Operand).getToken().equals_lower(String);
|
||||
}
|
||||
bool previousIsLoop(OperandVector &Operands, size_t Index) {
|
||||
|
||||
static bool previousIsLoop(OperandVector &Operands, size_t Index) {
|
||||
return previousEqual(Operands, Index, "loop0") ||
|
||||
previousEqual(Operands, Index, "loop1") ||
|
||||
previousEqual(Operands, Index, "sp1loop0") ||
|
||||
previousEqual(Operands, Index, "sp2loop0") ||
|
||||
previousEqual(Operands, Index, "sp3loop0");
|
||||
}
|
||||
}
|
||||
|
||||
bool HexagonAsmParser::splitIdentifier(OperandVector &Operands) {
|
||||
AsmToken const &Token = getParser().getTok();
|
||||
@ -1172,7 +1185,7 @@ bool HexagonAsmParser::isLabel(AsmToken &Token) {
|
||||
StringRef Raw (String.data(), Third.getString().data() - String.data() +
|
||||
Third.getString().size());
|
||||
std::string Collapsed = Raw;
|
||||
Collapsed.erase(remove_if(Collapsed, isspace), Collapsed.end());
|
||||
Collapsed.erase(llvm::remove_if(Collapsed, isspace), Collapsed.end());
|
||||
StringRef Whole = Collapsed;
|
||||
std::pair<StringRef, StringRef> DotSplit = Whole.split('.');
|
||||
if (!matchRegister(DotSplit.first.lower()))
|
||||
@ -1216,7 +1229,7 @@ bool HexagonAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &En
|
||||
NeededWorkaround = NeededWorkaround || (Again && !(Contigious && Type));
|
||||
}
|
||||
std::string Collapsed = RawString;
|
||||
Collapsed.erase(remove_if(Collapsed, isspace), Collapsed.end());
|
||||
Collapsed.erase(llvm::remove_if(Collapsed, isspace), Collapsed.end());
|
||||
StringRef FullString = Collapsed;
|
||||
std::pair<StringRef, StringRef> DotSplit = FullString.split('.');
|
||||
unsigned DotReg = matchRegister(DotSplit.first.lower());
|
||||
@ -1273,7 +1286,7 @@ bool HexagonAsmParser::implicitExpressionLocation(OperandVector &Operands) {
|
||||
}
|
||||
|
||||
bool HexagonAsmParser::parseExpression(MCExpr const *& Expr) {
|
||||
llvm::SmallVector<AsmToken, 4> Tokens;
|
||||
SmallVector<AsmToken, 4> Tokens;
|
||||
MCAsmLexer &Lexer = getLexer();
|
||||
bool Done = false;
|
||||
static char const * Comma = ",";
|
||||
@ -1452,9 +1465,8 @@ bool HexagonAsmParser::ParseInstruction(ParseInstructionInfo &Info,
|
||||
return parseInstruction(Operands);
|
||||
}
|
||||
|
||||
namespace {
|
||||
MCInst makeCombineInst(int opCode, MCOperand &Rdd,
|
||||
MCOperand &MO1, MCOperand &MO2) {
|
||||
static MCInst makeCombineInst(int opCode, MCOperand &Rdd,
|
||||
MCOperand &MO1, MCOperand &MO2) {
|
||||
MCInst TmpInst;
|
||||
TmpInst.setOpcode(opCode);
|
||||
TmpInst.addOperand(Rdd);
|
||||
@ -1463,7 +1475,6 @@ MCInst makeCombineInst(int opCode, MCOperand &Rdd,
|
||||
|
||||
return TmpInst;
|
||||
}
|
||||
}
|
||||
|
||||
// Define this matcher function after the auto-generated include so we
|
||||
// have the match class enum definitions.
|
||||
@ -1590,11 +1601,11 @@ int HexagonAsmParser::processInstruction(MCInst &Inst,
|
||||
case Hexagon::A2_tfrp: {
|
||||
MCOperand &MO = Inst.getOperand(1);
|
||||
unsigned int RegPairNum = RI->getEncodingValue(MO.getReg());
|
||||
std::string R1 = r + llvm::utostr(RegPairNum + 1);
|
||||
std::string R1 = r + utostr(RegPairNum + 1);
|
||||
StringRef Reg1(R1);
|
||||
MO.setReg(matchRegister(Reg1));
|
||||
// Add a new operand for the second register in the pair.
|
||||
std::string R2 = r + llvm::utostr(RegPairNum);
|
||||
std::string R2 = r + utostr(RegPairNum);
|
||||
StringRef Reg2(R2);
|
||||
Inst.addOperand(MCOperand::createReg(matchRegister(Reg2)));
|
||||
Inst.setOpcode(Hexagon::A2_combinew);
|
||||
@ -1605,11 +1616,11 @@ int HexagonAsmParser::processInstruction(MCInst &Inst,
|
||||
case Hexagon::A2_tfrpf: {
|
||||
MCOperand &MO = Inst.getOperand(2);
|
||||
unsigned int RegPairNum = RI->getEncodingValue(MO.getReg());
|
||||
std::string R1 = r + llvm::utostr(RegPairNum + 1);
|
||||
std::string R1 = r + utostr(RegPairNum + 1);
|
||||
StringRef Reg1(R1);
|
||||
MO.setReg(matchRegister(Reg1));
|
||||
// Add a new operand for the second register in the pair.
|
||||
std::string R2 = r + llvm::utostr(RegPairNum);
|
||||
std::string R2 = r + utostr(RegPairNum);
|
||||
StringRef Reg2(R2);
|
||||
Inst.addOperand(MCOperand::createReg(matchRegister(Reg2)));
|
||||
Inst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrpt)
|
||||
@ -1621,11 +1632,11 @@ int HexagonAsmParser::processInstruction(MCInst &Inst,
|
||||
case Hexagon::A2_tfrpfnew: {
|
||||
MCOperand &MO = Inst.getOperand(2);
|
||||
unsigned int RegPairNum = RI->getEncodingValue(MO.getReg());
|
||||
std::string R1 = r + llvm::utostr(RegPairNum + 1);
|
||||
std::string R1 = r + utostr(RegPairNum + 1);
|
||||
StringRef Reg1(R1);
|
||||
MO.setReg(matchRegister(Reg1));
|
||||
// Add a new operand for the second register in the pair.
|
||||
std::string R2 = r + llvm::utostr(RegPairNum);
|
||||
std::string R2 = r + utostr(RegPairNum);
|
||||
StringRef Reg2(R2);
|
||||
Inst.addOperand(MCOperand::createReg(matchRegister(Reg2)));
|
||||
Inst.setOpcode((Inst.getOpcode() == Hexagon::A2_tfrptnew)
|
||||
@ -1638,10 +1649,10 @@ int HexagonAsmParser::processInstruction(MCInst &Inst,
|
||||
case Hexagon::V6_vassignp: {
|
||||
MCOperand &MO = Inst.getOperand(1);
|
||||
unsigned int RegPairNum = RI->getEncodingValue(MO.getReg());
|
||||
std::string R1 = v + llvm::utostr(RegPairNum + 1);
|
||||
std::string R1 = v + utostr(RegPairNum + 1);
|
||||
MO.setReg(MatchRegisterName(R1));
|
||||
// Add a new operand for the second register in the pair.
|
||||
std::string R2 = v + llvm::utostr(RegPairNum);
|
||||
std::string R2 = v + utostr(RegPairNum);
|
||||
Inst.addOperand(MCOperand::createReg(MatchRegisterName(R2)));
|
||||
Inst.setOpcode(Hexagon::V6_vcombine);
|
||||
break;
|
||||
@ -1711,8 +1722,8 @@ int HexagonAsmParser::processInstruction(MCInst &Inst,
|
||||
getStreamer().EmitIntValue(Value, byteSize);
|
||||
}
|
||||
} else if (MO_1.isExpr()) {
|
||||
const char *StringStart = 0;
|
||||
const char *StringEnd = 0;
|
||||
const char *StringStart = nullptr;
|
||||
const char *StringEnd = nullptr;
|
||||
if (*Operands[4]->getStartLoc().getPointer() == '#') {
|
||||
StringStart = Operands[5]->getStartLoc().getPointer();
|
||||
StringEnd = Operands[6]->getStartLoc().getPointer();
|
||||
@ -1818,10 +1829,9 @@ int HexagonAsmParser::processInstruction(MCInst &Inst,
|
||||
break;
|
||||
}
|
||||
|
||||
case Hexagon::S2_tableidxb_goodsyntax: {
|
||||
case Hexagon::S2_tableidxb_goodsyntax:
|
||||
Inst.setOpcode(Hexagon::S2_tableidxb);
|
||||
break;
|
||||
}
|
||||
|
||||
case Hexagon::S2_tableidxh_goodsyntax: {
|
||||
MCInst TmpInst;
|
||||
@ -1880,10 +1890,9 @@ int HexagonAsmParser::processInstruction(MCInst &Inst,
|
||||
break;
|
||||
}
|
||||
|
||||
case Hexagon::M2_mpyui: {
|
||||
case Hexagon::M2_mpyui:
|
||||
Inst.setOpcode(Hexagon::M2_mpyi);
|
||||
break;
|
||||
}
|
||||
case Hexagon::M2_mpysmi: {
|
||||
MCInst TmpInst;
|
||||
MCOperand &Rd = Inst.getOperand(0);
|
||||
@ -1956,11 +1965,11 @@ int HexagonAsmParser::processInstruction(MCInst &Inst,
|
||||
if (Value == 0) { // convert to $Rdd = combine ($Rs[0], $Rs[1])
|
||||
MCInst TmpInst;
|
||||
unsigned int RegPairNum = RI->getEncodingValue(Rss.getReg());
|
||||
std::string R1 = r + llvm::utostr(RegPairNum + 1);
|
||||
std::string R1 = r + utostr(RegPairNum + 1);
|
||||
StringRef Reg1(R1);
|
||||
Rss.setReg(matchRegister(Reg1));
|
||||
// Add a new operand for the second register in the pair.
|
||||
std::string R2 = r + llvm::utostr(RegPairNum);
|
||||
std::string R2 = r + utostr(RegPairNum);
|
||||
StringRef Reg2(R2);
|
||||
TmpInst.setOpcode(Hexagon::A2_combinew);
|
||||
TmpInst.addOperand(Rdd);
|
||||
@ -1982,14 +1991,12 @@ int HexagonAsmParser::processInstruction(MCInst &Inst,
|
||||
unsigned int RegNum = RI->getEncodingValue(Rs.getReg());
|
||||
if (RegNum & 1) { // Odd mapped to raw:hi, regpair is rodd:odd-1, like r3:2
|
||||
Inst.setOpcode(Hexagon::A4_boundscheck_hi);
|
||||
std::string Name =
|
||||
r + llvm::utostr(RegNum) + Colon + llvm::utostr(RegNum - 1);
|
||||
std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
|
||||
StringRef RegPair = Name;
|
||||
Rs.setReg(matchRegister(RegPair));
|
||||
} else { // raw:lo
|
||||
Inst.setOpcode(Hexagon::A4_boundscheck_lo);
|
||||
std::string Name =
|
||||
r + llvm::utostr(RegNum + 1) + Colon + llvm::utostr(RegNum);
|
||||
std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
|
||||
StringRef RegPair = Name;
|
||||
Rs.setReg(matchRegister(RegPair));
|
||||
}
|
||||
@ -2001,14 +2008,12 @@ int HexagonAsmParser::processInstruction(MCInst &Inst,
|
||||
unsigned int RegNum = RI->getEncodingValue(Rs.getReg());
|
||||
if (RegNum & 1) { // Odd mapped to raw:hi
|
||||
Inst.setOpcode(Hexagon::A2_addsph);
|
||||
std::string Name =
|
||||
r + llvm::utostr(RegNum) + Colon + llvm::utostr(RegNum - 1);
|
||||
std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
|
||||
StringRef RegPair = Name;
|
||||
Rs.setReg(matchRegister(RegPair));
|
||||
} else { // Even mapped raw:lo
|
||||
Inst.setOpcode(Hexagon::A2_addspl);
|
||||
std::string Name =
|
||||
r + llvm::utostr(RegNum + 1) + Colon + llvm::utostr(RegNum);
|
||||
std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
|
||||
StringRef RegPair = Name;
|
||||
Rs.setReg(matchRegister(RegPair));
|
||||
}
|
||||
@ -2020,14 +2025,12 @@ int HexagonAsmParser::processInstruction(MCInst &Inst,
|
||||
unsigned int RegNum = RI->getEncodingValue(Rt.getReg());
|
||||
if (RegNum & 1) { // Odd mapped to sat:raw:hi
|
||||
Inst.setOpcode(Hexagon::M2_vrcmpys_s1_h);
|
||||
std::string Name =
|
||||
r + llvm::utostr(RegNum) + Colon + llvm::utostr(RegNum - 1);
|
||||
std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
|
||||
StringRef RegPair = Name;
|
||||
Rt.setReg(matchRegister(RegPair));
|
||||
} else { // Even mapped sat:raw:lo
|
||||
Inst.setOpcode(Hexagon::M2_vrcmpys_s1_l);
|
||||
std::string Name =
|
||||
r + llvm::utostr(RegNum + 1) + Colon + llvm::utostr(RegNum);
|
||||
std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
|
||||
StringRef RegPair = Name;
|
||||
Rt.setReg(matchRegister(RegPair));
|
||||
}
|
||||
@ -2042,14 +2045,12 @@ int HexagonAsmParser::processInstruction(MCInst &Inst,
|
||||
unsigned int RegNum = RI->getEncodingValue(Rt.getReg());
|
||||
if (RegNum & 1) { // Odd mapped to sat:raw:hi
|
||||
TmpInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_h);
|
||||
std::string Name =
|
||||
r + llvm::utostr(RegNum) + Colon + llvm::utostr(RegNum - 1);
|
||||
std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
|
||||
StringRef RegPair = Name;
|
||||
Rt.setReg(matchRegister(RegPair));
|
||||
} else { // Even mapped sat:raw:lo
|
||||
TmpInst.setOpcode(Hexagon::M2_vrcmpys_acc_s1_l);
|
||||
std::string Name =
|
||||
r + llvm::utostr(RegNum + 1) + Colon + llvm::utostr(RegNum);
|
||||
std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
|
||||
StringRef RegPair = Name;
|
||||
Rt.setReg(matchRegister(RegPair));
|
||||
}
|
||||
@ -2067,14 +2068,12 @@ int HexagonAsmParser::processInstruction(MCInst &Inst,
|
||||
unsigned int RegNum = RI->getEncodingValue(Rt.getReg());
|
||||
if (RegNum & 1) { // Odd mapped to rnd:sat:raw:hi
|
||||
Inst.setOpcode(Hexagon::M2_vrcmpys_s1rp_h);
|
||||
std::string Name =
|
||||
r + llvm::utostr(RegNum) + Colon + llvm::utostr(RegNum - 1);
|
||||
std::string Name = r + utostr(RegNum) + Colon + utostr(RegNum - 1);
|
||||
StringRef RegPair = Name;
|
||||
Rt.setReg(matchRegister(RegPair));
|
||||
} else { // Even mapped rnd:sat:raw:lo
|
||||
Inst.setOpcode(Hexagon::M2_vrcmpys_s1rp_l);
|
||||
std::string Name =
|
||||
r + llvm::utostr(RegNum + 1) + Colon + llvm::utostr(RegNum);
|
||||
std::string Name = r + utostr(RegNum + 1) + Colon + utostr(RegNum);
|
||||
StringRef RegPair = Name;
|
||||
Rt.setReg(matchRegister(RegPair));
|
||||
}
|
||||
@ -2110,11 +2109,11 @@ int HexagonAsmParser::processInstruction(MCInst &Inst,
|
||||
if (Value == 0) {
|
||||
MCInst TmpInst;
|
||||
unsigned int RegPairNum = RI->getEncodingValue(Rss.getReg());
|
||||
std::string R1 = r + llvm::utostr(RegPairNum + 1);
|
||||
std::string R1 = r + utostr(RegPairNum + 1);
|
||||
StringRef Reg1(R1);
|
||||
Rss.setReg(matchRegister(Reg1));
|
||||
// Add a new operand for the second register in the pair.
|
||||
std::string R2 = r + llvm::utostr(RegPairNum);
|
||||
std::string R2 = r + utostr(RegPairNum);
|
||||
StringRef Reg2(R2);
|
||||
TmpInst.setOpcode(Hexagon::A2_combinew);
|
||||
TmpInst.addOperand(Rdd);
|
||||
@ -2148,7 +2147,6 @@ int HexagonAsmParser::processInstruction(MCInst &Inst,
|
||||
return Match_Success;
|
||||
}
|
||||
|
||||
|
||||
unsigned HexagonAsmParser::matchRegister(StringRef Name) {
|
||||
if (unsigned Reg = MatchRegisterName(Name))
|
||||
return Reg;
|
||||
|
@ -14,21 +14,23 @@
|
||||
#include "MCTargetDesc/HexagonMCChecker.h"
|
||||
#include "MCTargetDesc/HexagonMCTargetDesc.h"
|
||||
#include "MCTargetDesc/HexagonMCInstrInfo.h"
|
||||
#include "MCTargetDesc/HexagonInstPrinter.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCFixedLenDisassembler.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCInstrDesc.h"
|
||||
#include "llvm/MC/MCInstrInfo.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/LEB128.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace Hexagon;
|
||||
@ -36,11 +38,13 @@ using namespace Hexagon;
|
||||
typedef MCDisassembler::DecodeStatus DecodeStatus;
|
||||
|
||||
namespace {
|
||||
|
||||
/// \brief Hexagon disassembler for all Hexagon platforms.
|
||||
class HexagonDisassembler : public MCDisassembler {
|
||||
public:
|
||||
std::unique_ptr<MCInstrInfo const> const MCII;
|
||||
std::unique_ptr<MCInst *> CurrentBundle;
|
||||
|
||||
HexagonDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
|
||||
MCInstrInfo const *MCII)
|
||||
: MCDisassembler(STI, Ctx), MCII(MCII), CurrentBundle(new MCInst *) {}
|
||||
@ -57,7 +61,8 @@ public:
|
||||
void adjustExtendedInstructions(MCInst &MCI, MCInst const &MCB) const;
|
||||
void addSubinstOperands(MCInst *MI, unsigned opcode, unsigned inst) const;
|
||||
};
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
// Forward declare these because the auto-generated code will reference them.
|
||||
// Definitions are further down.
|
||||
@ -161,7 +166,7 @@ DecodeStatus HexagonDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
|
||||
|
||||
*CurrentBundle = &MI;
|
||||
MI = HexagonMCInstrInfo::createBundle();
|
||||
while (Result == Success && Complete == false) {
|
||||
while (Result == Success && !Complete) {
|
||||
if (Bytes.size() < HEXAGON_INSTR_SIZE)
|
||||
return MCDisassembler::Fail;
|
||||
MCInst *Inst = new (getContext()) MCInst;
|
||||
@ -178,14 +183,13 @@ DecodeStatus HexagonDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
namespace {
|
||||
HexagonDisassembler const &disassembler(void const *Decoder) {
|
||||
static HexagonDisassembler const &disassembler(void const *Decoder) {
|
||||
return *static_cast<HexagonDisassembler const *>(Decoder);
|
||||
}
|
||||
MCContext &contextFromDecoder(void const *Decoder) {
|
||||
|
||||
static MCContext &contextFromDecoder(void const *Decoder) {
|
||||
return disassembler(Decoder).getContext();
|
||||
}
|
||||
}
|
||||
|
||||
DecodeStatus HexagonDisassembler::getSingleInstruction(
|
||||
MCInst &MI, MCInst &MCB, ArrayRef<uint8_t> Bytes, uint64_t Address,
|
||||
@ -328,8 +332,7 @@ DecodeStatus HexagonDisassembler::getSingleInstruction(
|
||||
// follow the duplex model, so the register values in the MCInst are
|
||||
// incorrect. If the instruction is a compound, loop through the
|
||||
// operands and change registers appropriately.
|
||||
if (llvm::HexagonMCInstrInfo::getType(*MCII, MI) ==
|
||||
HexagonII::TypeCOMPOUND) {
|
||||
if (HexagonMCInstrInfo::getType(*MCII, MI) == HexagonII::TypeCOMPOUND) {
|
||||
for (MCInst::iterator i = MI.begin(), last = MI.end(); i < last; ++i) {
|
||||
if (i->isReg()) {
|
||||
unsigned reg = i->getReg() - Hexagon::R0;
|
||||
@ -496,10 +499,6 @@ void HexagonDisassembler::adjustExtendedInstructions(MCInst &MCI,
|
||||
}
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
extern const MCInstrDesc HexagonInsts[];
|
||||
}
|
||||
|
||||
static DecodeStatus DecodeRegisterClass(MCInst &Inst, unsigned RegNo,
|
||||
ArrayRef<MCPhysReg> Table) {
|
||||
if (RegNo < Table.size()) {
|
||||
@ -651,11 +650,8 @@ static DecodeStatus DecodeModRegsRegisterClass(MCInst &Inst, unsigned RegNo,
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
|
||||
namespace {
|
||||
uint32_t fullValue(MCInstrInfo const &MCII,
|
||||
MCInst &MCB,
|
||||
MCInst &MI,
|
||||
int64_t Value) {
|
||||
static uint32_t fullValue(MCInstrInfo const &MCII, MCInst &MCB, MCInst &MI,
|
||||
int64_t Value) {
|
||||
MCInst const *Extender = HexagonMCInstrInfo::extenderForIndex(
|
||||
MCB, HexagonMCInstrInfo::bundleSize(MCB));
|
||||
if(!Extender || MI.size() != HexagonMCInstrInfo::getExtendableOp(MCII, MI))
|
||||
@ -669,8 +665,9 @@ uint32_t fullValue(MCInstrInfo const &MCII,
|
||||
uint32_t Operand = Upper26 | Lower6;
|
||||
return Operand;
|
||||
}
|
||||
|
||||
template <size_t T>
|
||||
void signedDecoder(MCInst &MI, unsigned tmp, const void *Decoder) {
|
||||
static void signedDecoder(MCInst &MI, unsigned tmp, const void *Decoder) {
|
||||
HexagonDisassembler const &Disassembler = disassembler(Decoder);
|
||||
int64_t FullValue = fullValue(*Disassembler.MCII,
|
||||
**Disassembler.CurrentBundle,
|
||||
@ -679,7 +676,6 @@ void signedDecoder(MCInst &MI, unsigned tmp, const void *Decoder) {
|
||||
HexagonMCInstrInfo::addConstant(MI, Extended,
|
||||
Disassembler.getContext());
|
||||
}
|
||||
}
|
||||
|
||||
static DecodeStatus unsignedImmDecoder(MCInst &MI, unsigned tmp,
|
||||
uint64_t /*Address*/,
|
||||
@ -859,7 +855,6 @@ static const size_t NumCondS = array_lengthof(StoreConditionalOpcodeData);
|
||||
static const size_t NumLS = array_lengthof(LoadStoreOpcodeData);
|
||||
|
||||
static DecodeStatus decodeSpecial(MCInst &MI, uint32_t insn) {
|
||||
|
||||
unsigned MachineOpcode = 0;
|
||||
unsigned LLVMOpcode = 0;
|
||||
|
||||
@ -898,19 +893,18 @@ static DecodeStatus decodeSpecial(MCInst &MI, uint32_t insn) {
|
||||
case Hexagon::S4_pstorerdf_abs:
|
||||
case Hexagon::S4_pstorerdt_abs:
|
||||
case Hexagon::S4_pstorerdfnew_abs:
|
||||
case Hexagon::S4_pstorerdtnew_abs: {
|
||||
case Hexagon::S4_pstorerdtnew_abs:
|
||||
// op: Pv
|
||||
Value = insn & UINT64_C(3);
|
||||
DecodePredRegsRegisterClass(MI, Value, 0, 0);
|
||||
DecodePredRegsRegisterClass(MI, Value, 0, nullptr);
|
||||
// op: u6
|
||||
Value = (insn >> 12) & UINT64_C(48);
|
||||
Value |= (insn >> 3) & UINT64_C(15);
|
||||
MI.addOperand(MCOperand::createImm(Value));
|
||||
// op: Rtt
|
||||
Value = (insn >> 8) & UINT64_C(31);
|
||||
DecodeDoubleRegsRegisterClass(MI, Value, 0, 0);
|
||||
DecodeDoubleRegsRegisterClass(MI, Value, 0, nullptr);
|
||||
break;
|
||||
}
|
||||
|
||||
case Hexagon::S4_pstorerbnewf_abs:
|
||||
case Hexagon::S4_pstorerbnewt_abs:
|
||||
@ -923,19 +917,18 @@ static DecodeStatus decodeSpecial(MCInst &MI, uint32_t insn) {
|
||||
case Hexagon::S4_pstorerinewf_abs:
|
||||
case Hexagon::S4_pstorerinewt_abs:
|
||||
case Hexagon::S4_pstorerinewfnew_abs:
|
||||
case Hexagon::S4_pstorerinewtnew_abs: {
|
||||
case Hexagon::S4_pstorerinewtnew_abs:
|
||||
// op: Pv
|
||||
Value = insn & UINT64_C(3);
|
||||
DecodePredRegsRegisterClass(MI, Value, 0, 0);
|
||||
DecodePredRegsRegisterClass(MI, Value, 0, nullptr);
|
||||
// op: u6
|
||||
Value = (insn >> 12) & UINT64_C(48);
|
||||
Value |= (insn >> 3) & UINT64_C(15);
|
||||
MI.addOperand(MCOperand::createImm(Value));
|
||||
// op: Nt
|
||||
Value = (insn >> 8) & UINT64_C(7);
|
||||
DecodeIntRegsRegisterClass(MI, Value, 0, 0);
|
||||
DecodeIntRegsRegisterClass(MI, Value, 0, nullptr);
|
||||
break;
|
||||
}
|
||||
|
||||
case Hexagon::S4_pstorerbf_abs:
|
||||
case Hexagon::S4_pstorerbt_abs:
|
||||
@ -948,36 +941,34 @@ static DecodeStatus decodeSpecial(MCInst &MI, uint32_t insn) {
|
||||
case Hexagon::S4_pstorerif_abs:
|
||||
case Hexagon::S4_pstorerit_abs:
|
||||
case Hexagon::S4_pstorerifnew_abs:
|
||||
case Hexagon::S4_pstoreritnew_abs: {
|
||||
case Hexagon::S4_pstoreritnew_abs:
|
||||
// op: Pv
|
||||
Value = insn & UINT64_C(3);
|
||||
DecodePredRegsRegisterClass(MI, Value, 0, 0);
|
||||
DecodePredRegsRegisterClass(MI, Value, 0, nullptr);
|
||||
// op: u6
|
||||
Value = (insn >> 12) & UINT64_C(48);
|
||||
Value |= (insn >> 3) & UINT64_C(15);
|
||||
MI.addOperand(MCOperand::createImm(Value));
|
||||
// op: Rt
|
||||
Value = (insn >> 8) & UINT64_C(31);
|
||||
DecodeIntRegsRegisterClass(MI, Value, 0, 0);
|
||||
DecodeIntRegsRegisterClass(MI, Value, 0, nullptr);
|
||||
break;
|
||||
}
|
||||
|
||||
case Hexagon::L4_ploadrdf_abs:
|
||||
case Hexagon::L4_ploadrdt_abs:
|
||||
case Hexagon::L4_ploadrdfnew_abs:
|
||||
case Hexagon::L4_ploadrdtnew_abs: {
|
||||
case Hexagon::L4_ploadrdtnew_abs:
|
||||
// op: Rdd
|
||||
Value = insn & UINT64_C(31);
|
||||
DecodeDoubleRegsRegisterClass(MI, Value, 0, 0);
|
||||
DecodeDoubleRegsRegisterClass(MI, Value, 0, nullptr);
|
||||
// op: Pt
|
||||
Value = ((insn >> 9) & UINT64_C(3));
|
||||
DecodePredRegsRegisterClass(MI, Value, 0, 0);
|
||||
DecodePredRegsRegisterClass(MI, Value, 0, nullptr);
|
||||
// op: u6
|
||||
Value = ((insn >> 15) & UINT64_C(62));
|
||||
Value |= ((insn >> 8) & UINT64_C(1));
|
||||
MI.addOperand(MCOperand::createImm(Value));
|
||||
break;
|
||||
}
|
||||
|
||||
case Hexagon::L4_ploadrbf_abs:
|
||||
case Hexagon::L4_ploadrbt_abs:
|
||||
@ -1001,10 +992,10 @@ static DecodeStatus decodeSpecial(MCInst &MI, uint32_t insn) {
|
||||
case Hexagon::L4_ploadritnew_abs:
|
||||
// op: Rd
|
||||
Value = insn & UINT64_C(31);
|
||||
DecodeIntRegsRegisterClass(MI, Value, 0, 0);
|
||||
DecodeIntRegsRegisterClass(MI, Value, 0, nullptr);
|
||||
// op: Pt
|
||||
Value = (insn >> 9) & UINT64_C(3);
|
||||
DecodePredRegsRegisterClass(MI, Value, 0, 0);
|
||||
DecodePredRegsRegisterClass(MI, Value, 0, nullptr);
|
||||
// op: u6
|
||||
Value = (insn >> 15) & UINT64_C(62);
|
||||
Value |= (insn >> 8) & UINT64_C(1);
|
||||
@ -1020,28 +1011,26 @@ static DecodeStatus decodeSpecial(MCInst &MI, uint32_t insn) {
|
||||
++shift;
|
||||
// op: g16_0
|
||||
case Hexagon::PS_loadrbabs:
|
||||
case Hexagon::PS_loadrubabs: {
|
||||
case Hexagon::PS_loadrubabs:
|
||||
// op: Rd
|
||||
Value |= insn & UINT64_C(31);
|
||||
DecodeIntRegsRegisterClass(MI, Value, 0, 0);
|
||||
DecodeIntRegsRegisterClass(MI, Value, 0, nullptr);
|
||||
Value = (insn >> 11) & UINT64_C(49152);
|
||||
Value |= (insn >> 7) & UINT64_C(15872);
|
||||
Value |= (insn >> 5) & UINT64_C(511);
|
||||
MI.addOperand(MCOperand::createImm(Value << shift));
|
||||
break;
|
||||
}
|
||||
|
||||
case Hexagon::PS_loadrdabs: {
|
||||
case Hexagon::PS_loadrdabs:
|
||||
Value = insn & UINT64_C(31);
|
||||
DecodeDoubleRegsRegisterClass(MI, Value, 0, 0);
|
||||
DecodeDoubleRegsRegisterClass(MI, Value, 0, nullptr);
|
||||
Value = (insn >> 11) & UINT64_C(49152);
|
||||
Value |= (insn >> 7) & UINT64_C(15872);
|
||||
Value |= (insn >> 5) & UINT64_C(511);
|
||||
MI.addOperand(MCOperand::createImm(Value << 3));
|
||||
break;
|
||||
}
|
||||
|
||||
case Hexagon::PS_storerdabs: {
|
||||
case Hexagon::PS_storerdabs:
|
||||
// op: g16_3
|
||||
Value = (insn >> 11) & UINT64_C(49152);
|
||||
Value |= (insn >> 7) & UINT64_C(15872);
|
||||
@ -1050,9 +1039,8 @@ static DecodeStatus decodeSpecial(MCInst &MI, uint32_t insn) {
|
||||
MI.addOperand(MCOperand::createImm(Value << 3));
|
||||
// op: Rtt
|
||||
Value = (insn >> 8) & UINT64_C(31);
|
||||
DecodeDoubleRegsRegisterClass(MI, Value, 0, 0);
|
||||
DecodeDoubleRegsRegisterClass(MI, Value, 0, nullptr);
|
||||
break;
|
||||
}
|
||||
|
||||
// op: g16_2
|
||||
case Hexagon::PS_storerinewabs:
|
||||
@ -1061,7 +1049,7 @@ static DecodeStatus decodeSpecial(MCInst &MI, uint32_t insn) {
|
||||
case Hexagon::PS_storerhnewabs:
|
||||
++shift;
|
||||
// op: g16_0
|
||||
case Hexagon::PS_storerbnewabs: {
|
||||
case Hexagon::PS_storerbnewabs:
|
||||
Value = (insn >> 11) & UINT64_C(49152);
|
||||
Value |= (insn >> 7) & UINT64_C(15872);
|
||||
Value |= (insn >> 5) & UINT64_C(256);
|
||||
@ -1069,9 +1057,8 @@ static DecodeStatus decodeSpecial(MCInst &MI, uint32_t insn) {
|
||||
MI.addOperand(MCOperand::createImm(Value << shift));
|
||||
// op: Nt
|
||||
Value = (insn >> 8) & UINT64_C(7);
|
||||
DecodeIntRegsRegisterClass(MI, Value, 0, 0);
|
||||
DecodeIntRegsRegisterClass(MI, Value, 0, nullptr);
|
||||
break;
|
||||
}
|
||||
|
||||
// op: g16_2
|
||||
case Hexagon::PS_storeriabs:
|
||||
@ -1081,7 +1068,7 @@ static DecodeStatus decodeSpecial(MCInst &MI, uint32_t insn) {
|
||||
case Hexagon::PS_storerfabs:
|
||||
++shift;
|
||||
// op: g16_0
|
||||
case Hexagon::PS_storerbabs: {
|
||||
case Hexagon::PS_storerbabs:
|
||||
Value = (insn >> 11) & UINT64_C(49152);
|
||||
Value |= (insn >> 7) & UINT64_C(15872);
|
||||
Value |= (insn >> 5) & UINT64_C(256);
|
||||
@ -1089,10 +1076,9 @@ static DecodeStatus decodeSpecial(MCInst &MI, uint32_t insn) {
|
||||
MI.addOperand(MCOperand::createImm(Value << shift));
|
||||
// op: Rt
|
||||
Value = (insn >> 8) & UINT64_C(31);
|
||||
DecodeIntRegsRegisterClass(MI, Value, 0, 0);
|
||||
DecodeIntRegsRegisterClass(MI, Value, 0, nullptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return MCDisassembler::Success;
|
||||
}
|
||||
return MCDisassembler::Fail;
|
||||
@ -1100,7 +1086,6 @@ static DecodeStatus decodeSpecial(MCInst &MI, uint32_t insn) {
|
||||
|
||||
static DecodeStatus decodeImmext(MCInst &MI, uint32_t insn,
|
||||
void const *Decoder) {
|
||||
|
||||
// Instruction Class for a constant a extender: bits 31:28 = 0x0000
|
||||
if ((~insn & 0xf0000000) == 0xf0000000) {
|
||||
unsigned Value;
|
||||
|
@ -11,16 +11,36 @@
|
||||
|
||||
#include "HexagonBitTracker.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/CodeGen/MachineDominators.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineOperand.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/IR/DebugLoc.h"
|
||||
#include "llvm/MC/MCInstrDesc.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -28,16 +48,19 @@ static cl::opt<bool> PreserveTiedOps("hexbit-keep-tied", cl::Hidden,
|
||||
cl::init(true), cl::desc("Preserve subregisters in tied operands"));
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void initializeHexagonBitSimplifyPass(PassRegistry& Registry);
|
||||
FunctionPass *createHexagonBitSimplify();
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
namespace {
|
||||
|
||||
// Set of virtual registers, based on BitVector.
|
||||
struct RegisterSet : private BitVector {
|
||||
RegisterSet() : BitVector() {}
|
||||
RegisterSet() = default;
|
||||
explicit RegisterSet(unsigned s, bool t = false) : BitVector(s, t) {}
|
||||
RegisterSet(const RegisterSet &RS) : BitVector(RS) {}
|
||||
RegisterSet(const RegisterSet &RS) = default;
|
||||
|
||||
using BitVector::clear;
|
||||
using BitVector::count;
|
||||
@ -108,20 +131,23 @@ namespace {
|
||||
if (size() <= Idx)
|
||||
resize(std::max(Idx+1, 32U));
|
||||
}
|
||||
|
||||
static inline unsigned v2x(unsigned v) {
|
||||
return TargetRegisterInfo::virtReg2Index(v);
|
||||
}
|
||||
|
||||
static inline unsigned x2v(unsigned x) {
|
||||
return TargetRegisterInfo::index2VirtReg(x);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct PrintRegSet {
|
||||
PrintRegSet(const RegisterSet &S, const TargetRegisterInfo *RI)
|
||||
: RS(S), TRI(RI) {}
|
||||
|
||||
friend raw_ostream &operator<< (raw_ostream &OS,
|
||||
const PrintRegSet &P);
|
||||
|
||||
private:
|
||||
const RegisterSet &RS;
|
||||
const TargetRegisterInfo *TRI;
|
||||
@ -136,27 +162,28 @@ namespace {
|
||||
OS << " }";
|
||||
return OS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
class Transformation;
|
||||
|
||||
class HexagonBitSimplify : public MachineFunctionPass {
|
||||
public:
|
||||
static char ID;
|
||||
HexagonBitSimplify() : MachineFunctionPass(ID), MDT(0) {
|
||||
|
||||
HexagonBitSimplify() : MachineFunctionPass(ID), MDT(nullptr) {
|
||||
initializeHexagonBitSimplifyPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
virtual StringRef getPassName() const {
|
||||
|
||||
StringRef getPassName() const override {
|
||||
return "Hexagon bit simplification";
|
||||
}
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequired<MachineDominatorTree>();
|
||||
AU.addPreserved<MachineDominatorTree>();
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
}
|
||||
virtual bool runOnMachineFunction(MachineFunction &MF);
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &MF) override;
|
||||
|
||||
static void getInstrDefs(const MachineInstr &MI, RegisterSet &Defs);
|
||||
static void getInstrUses(const MachineInstr &MI, RegisterSet &Uses);
|
||||
@ -199,18 +226,20 @@ namespace {
|
||||
char HexagonBitSimplify::ID = 0;
|
||||
typedef HexagonBitSimplify HBS;
|
||||
|
||||
|
||||
// The purpose of this class is to provide a common facility to traverse
|
||||
// the function top-down or bottom-up via the dominator tree, and keep
|
||||
// track of the available registers.
|
||||
class Transformation {
|
||||
public:
|
||||
bool TopDown;
|
||||
|
||||
Transformation(bool TD) : TopDown(TD) {}
|
||||
virtual ~Transformation() = default;
|
||||
|
||||
virtual bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) = 0;
|
||||
virtual ~Transformation() {}
|
||||
};
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
INITIALIZE_PASS_BEGIN(HexagonBitSimplify, "hexbit",
|
||||
"Hexagon bit simplification", false, false)
|
||||
@ -218,7 +247,6 @@ INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
|
||||
INITIALIZE_PASS_END(HexagonBitSimplify, "hexbit",
|
||||
"Hexagon bit simplification", false, false)
|
||||
|
||||
|
||||
bool HexagonBitSimplify::visitBlock(MachineBasicBlock &B, Transformation &T,
|
||||
RegisterSet &AVs) {
|
||||
MachineDomTreeNode *N = MDT->getNode(&B);
|
||||
@ -297,7 +325,6 @@ bool HexagonBitSimplify::isZero(const BitTracker::RegisterCell &RC,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool HexagonBitSimplify::getConst(const BitTracker::RegisterCell &RC,
|
||||
uint16_t B, uint16_t W, uint64_t &U) {
|
||||
assert(B < RC.width() && B+W <= RC.width());
|
||||
@ -314,7 +341,6 @@ bool HexagonBitSimplify::getConst(const BitTracker::RegisterCell &RC,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool HexagonBitSimplify::replaceReg(unsigned OldR, unsigned NewR,
|
||||
MachineRegisterInfo &MRI) {
|
||||
if (!TargetRegisterInfo::isVirtualRegister(OldR) ||
|
||||
@ -329,7 +355,6 @@ bool HexagonBitSimplify::replaceReg(unsigned OldR, unsigned NewR,
|
||||
return Begin != End;
|
||||
}
|
||||
|
||||
|
||||
bool HexagonBitSimplify::replaceRegWithSub(unsigned OldR, unsigned NewR,
|
||||
unsigned NewSR, MachineRegisterInfo &MRI) {
|
||||
if (!TargetRegisterInfo::isVirtualRegister(OldR) ||
|
||||
@ -347,7 +372,6 @@ bool HexagonBitSimplify::replaceRegWithSub(unsigned OldR, unsigned NewR,
|
||||
return Begin != End;
|
||||
}
|
||||
|
||||
|
||||
bool HexagonBitSimplify::replaceSubWithSub(unsigned OldR, unsigned OldSR,
|
||||
unsigned NewR, unsigned NewSR, MachineRegisterInfo &MRI) {
|
||||
if (!TargetRegisterInfo::isVirtualRegister(OldR) ||
|
||||
@ -367,7 +391,6 @@ bool HexagonBitSimplify::replaceSubWithSub(unsigned OldR, unsigned OldSR,
|
||||
return Begin != End;
|
||||
}
|
||||
|
||||
|
||||
// For a register ref (pair Reg:Sub), set Begin to the position of the LSB
|
||||
// of Sub in Reg, and set Width to the size of Sub in bits. Return true,
|
||||
// if this succeeded, otherwise return false.
|
||||
@ -423,7 +446,6 @@ bool HexagonBitSimplify::parseRegSequence(const MachineInstr &I,
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// All stores (except 64-bit stores) take a 32-bit register as the source
|
||||
// of the value to be stored. If the instruction stores into a location
|
||||
// that is shorter than 32 bits, some bits of the source register are not
|
||||
@ -581,7 +603,6 @@ bool HexagonBitSimplify::getUsedBitsInStore(unsigned Opc, BitVector &Bits,
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// For an instruction with opcode Opc, calculate the set of bits that it
|
||||
// uses in a register in operand OpN. This only calculates the set of used
|
||||
// bits for cases where it does not depend on any operands (as is the case
|
||||
@ -861,7 +882,6 @@ bool HexagonBitSimplify::getUsedBits(unsigned Opc, unsigned OpN,
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Calculate the register class that matches Reg:Sub. For example, if
|
||||
// vreg1 is a double register, then vreg1:isub_hi would match the "int"
|
||||
// register class.
|
||||
@ -894,7 +914,6 @@ const TargetRegisterClass *HexagonBitSimplify::getFinalVRegClass(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
// Check if RD could be replaced with RS at any possible use of RD.
|
||||
// For example a predicate register cannot be replaced with a integer
|
||||
// register, but a 64-bit register with a subregister can be replaced
|
||||
@ -912,21 +931,18 @@ bool HexagonBitSimplify::isTransparentCopy(const BitTracker::RegisterRef &RD,
|
||||
return DRC == getFinalVRegClass(RS, MRI);
|
||||
}
|
||||
|
||||
|
||||
bool HexagonBitSimplify::hasTiedUse(unsigned Reg, MachineRegisterInfo &MRI,
|
||||
unsigned NewSub) {
|
||||
if (!PreserveTiedOps)
|
||||
return false;
|
||||
return any_of(MRI.use_operands(Reg),
|
||||
[NewSub] (const MachineOperand &Op) -> bool {
|
||||
return Op.getSubReg() != NewSub && Op.isTied();
|
||||
});
|
||||
return llvm::any_of(MRI.use_operands(Reg),
|
||||
[NewSub] (const MachineOperand &Op) -> bool {
|
||||
return Op.getSubReg() != NewSub && Op.isTied();
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Dead code elimination
|
||||
//
|
||||
namespace {
|
||||
|
||||
class DeadCodeElimination {
|
||||
public:
|
||||
DeadCodeElimination(MachineFunction &mf, MachineDominatorTree &mdt)
|
||||
@ -946,8 +962,8 @@ namespace {
|
||||
MachineDominatorTree &MDT;
|
||||
MachineRegisterInfo &MRI;
|
||||
};
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
bool DeadCodeElimination::isDead(unsigned R) const {
|
||||
for (auto I = MRI.use_begin(R), E = MRI.use_end(); I != E; ++I) {
|
||||
@ -965,7 +981,6 @@ bool DeadCodeElimination::isDead(unsigned R) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DeadCodeElimination::runOnNode(MachineDomTreeNode *N) {
|
||||
bool Changed = false;
|
||||
typedef GraphTraits<MachineDomTreeNode*> GTN;
|
||||
@ -1015,8 +1030,8 @@ bool DeadCodeElimination::runOnNode(MachineDomTreeNode *N) {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
//
|
||||
// Eliminate redundant instructions
|
||||
//
|
||||
// This transformation will identify instructions where the output register
|
||||
@ -1027,13 +1042,14 @@ bool DeadCodeElimination::runOnNode(MachineDomTreeNode *N) {
|
||||
// registers.
|
||||
// If the output matches an input, the instruction is replaced with COPY.
|
||||
// The copies will be removed by another transformation.
|
||||
namespace {
|
||||
class RedundantInstrElimination : public Transformation {
|
||||
public:
|
||||
RedundantInstrElimination(BitTracker &bt, const HexagonInstrInfo &hii,
|
||||
MachineRegisterInfo &mri)
|
||||
: Transformation(true), HII(hii), MRI(mri), BT(bt) {}
|
||||
|
||||
bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) override;
|
||||
|
||||
private:
|
||||
bool isLossyShiftLeft(const MachineInstr &MI, unsigned OpN,
|
||||
unsigned &LostB, unsigned &LostE);
|
||||
@ -1048,8 +1064,8 @@ namespace {
|
||||
MachineRegisterInfo &MRI;
|
||||
BitTracker &BT;
|
||||
};
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
// Check if the instruction is a lossy shift left, where the input being
|
||||
// shifted is the operand OpN of MI. If true, [LostB, LostE) is the range
|
||||
@ -1057,6 +1073,7 @@ namespace {
|
||||
bool RedundantInstrElimination::isLossyShiftLeft(const MachineInstr &MI,
|
||||
unsigned OpN, unsigned &LostB, unsigned &LostE) {
|
||||
using namespace Hexagon;
|
||||
|
||||
unsigned Opc = MI.getOpcode();
|
||||
unsigned ImN, RegN, Width;
|
||||
switch (Opc) {
|
||||
@ -1110,13 +1127,13 @@ bool RedundantInstrElimination::isLossyShiftLeft(const MachineInstr &MI,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Check if the instruction is a lossy shift right, where the input being
|
||||
// shifted is the operand OpN of MI. If true, [LostB, LostE) is the range
|
||||
// of bit indices that are lost.
|
||||
bool RedundantInstrElimination::isLossyShiftRight(const MachineInstr &MI,
|
||||
unsigned OpN, unsigned &LostB, unsigned &LostE) {
|
||||
using namespace Hexagon;
|
||||
|
||||
unsigned Opc = MI.getOpcode();
|
||||
unsigned ImN, RegN;
|
||||
switch (Opc) {
|
||||
@ -1173,7 +1190,6 @@ bool RedundantInstrElimination::isLossyShiftRight(const MachineInstr &MI,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Calculate the bit vector that corresponds to the used bits of register Reg.
|
||||
// The vector Bits has the same size, as the size of Reg in bits. If the cal-
|
||||
// culation fails (i.e. the used bits are unknown), it returns false. Other-
|
||||
@ -1210,7 +1226,6 @@ bool RedundantInstrElimination::computeUsedBits(unsigned Reg, BitVector &Bits) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Calculate the bits used by instruction MI in a register in operand OpN.
|
||||
// Return true/false if the calculation succeeds/fails. If is succeeds, set
|
||||
// used bits in Bits. This function does not reset any bits in Bits, so
|
||||
@ -1251,7 +1266,6 @@ bool RedundantInstrElimination::computeUsedBits(const MachineInstr &MI,
|
||||
return GotBits;
|
||||
}
|
||||
|
||||
|
||||
// Calculates the used bits in RD ("defined register"), and checks if these
|
||||
// bits in RS ("used register") and RD are identical.
|
||||
bool RedundantInstrElimination::usedBitsEqual(BitTracker::RegisterRef RD,
|
||||
@ -1278,7 +1292,6 @@ bool RedundantInstrElimination::usedBitsEqual(BitTracker::RegisterRef RD,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool RedundantInstrElimination::processBlock(MachineBasicBlock &B,
|
||||
const RegisterSet&) {
|
||||
if (!BT.reached(&B))
|
||||
@ -1348,20 +1361,19 @@ bool RedundantInstrElimination::processBlock(MachineBasicBlock &B,
|
||||
return Changed;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
//
|
||||
// Const generation
|
||||
//
|
||||
// Recognize instructions that produce constant values known at compile-time.
|
||||
// Replace them with register definitions that load these constants directly.
|
||||
namespace {
|
||||
class ConstGeneration : public Transformation {
|
||||
public:
|
||||
ConstGeneration(BitTracker &bt, const HexagonInstrInfo &hii,
|
||||
MachineRegisterInfo &mri)
|
||||
: Transformation(true), HII(hii), MRI(mri), BT(bt) {}
|
||||
|
||||
bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) override;
|
||||
static bool isTfrConst(const MachineInstr &MI);
|
||||
|
||||
private:
|
||||
unsigned genTfrConst(const TargetRegisterClass *RC, int64_t C,
|
||||
MachineBasicBlock &B, MachineBasicBlock::iterator At, DebugLoc &DL);
|
||||
@ -1370,7 +1382,8 @@ namespace {
|
||||
MachineRegisterInfo &MRI;
|
||||
BitTracker &BT;
|
||||
};
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
bool ConstGeneration::isTfrConst(const MachineInstr &MI) {
|
||||
unsigned Opc = MI.getOpcode();
|
||||
@ -1388,7 +1401,6 @@ bool ConstGeneration::isTfrConst(const MachineInstr &MI) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Generate a transfer-immediate instruction that is appropriate for the
|
||||
// register class and the actual value being transferred.
|
||||
unsigned ConstGeneration::genTfrConst(const TargetRegisterClass *RC, int64_t C,
|
||||
@ -1437,7 +1449,6 @@ unsigned ConstGeneration::genTfrConst(const TargetRegisterClass *RC, int64_t C,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool ConstGeneration::processBlock(MachineBasicBlock &B, const RegisterSet&) {
|
||||
if (!BT.reached(&B))
|
||||
return false;
|
||||
@ -1471,25 +1482,19 @@ bool ConstGeneration::processBlock(MachineBasicBlock &B, const RegisterSet&) {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
//
|
||||
// Copy generation
|
||||
//
|
||||
// Identify pairs of available registers which hold identical values.
|
||||
// In such cases, only one of them needs to be calculated, the other one
|
||||
// will be defined as a copy of the first.
|
||||
//
|
||||
// Copy propagation
|
||||
//
|
||||
// Eliminate register copies RD = RS, by replacing the uses of RD with
|
||||
// with uses of RS.
|
||||
namespace {
|
||||
class CopyGeneration : public Transformation {
|
||||
public:
|
||||
CopyGeneration(BitTracker &bt, const HexagonInstrInfo &hii,
|
||||
const HexagonRegisterInfo &hri, MachineRegisterInfo &mri)
|
||||
: Transformation(true), HII(hii), HRI(hri), MRI(mri), BT(bt) {}
|
||||
|
||||
bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) override;
|
||||
|
||||
private:
|
||||
bool findMatch(const BitTracker::RegisterRef &Inp,
|
||||
BitTracker::RegisterRef &Out, const RegisterSet &AVs);
|
||||
@ -1501,12 +1506,17 @@ namespace {
|
||||
RegisterSet Forbidden;
|
||||
};
|
||||
|
||||
// Eliminate register copies RD = RS, by replacing the uses of RD with
|
||||
// with uses of RS.
|
||||
class CopyPropagation : public Transformation {
|
||||
public:
|
||||
CopyPropagation(const HexagonRegisterInfo &hri, MachineRegisterInfo &mri)
|
||||
: Transformation(false), HRI(hri), MRI(mri) {}
|
||||
|
||||
bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) override;
|
||||
|
||||
static bool isCopyReg(unsigned Opc, bool NoConv);
|
||||
|
||||
private:
|
||||
bool propagateRegCopy(MachineInstr &MI);
|
||||
|
||||
@ -1514,8 +1524,7 @@ namespace {
|
||||
MachineRegisterInfo &MRI;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
/// Check if there is a register in AVs that is identical to Inp. If so,
|
||||
/// set Out to the found register. The output may be a pair Reg:Sub.
|
||||
@ -1566,7 +1575,6 @@ bool CopyGeneration::findMatch(const BitTracker::RegisterRef &Inp,
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CopyGeneration::processBlock(MachineBasicBlock &B,
|
||||
const RegisterSet &AVs) {
|
||||
if (!BT.reached(&B))
|
||||
@ -1631,7 +1639,6 @@ bool CopyGeneration::processBlock(MachineBasicBlock &B,
|
||||
return Changed;
|
||||
}
|
||||
|
||||
|
||||
bool CopyPropagation::isCopyReg(unsigned Opc, bool NoConv) {
|
||||
switch (Opc) {
|
||||
case TargetOpcode::COPY:
|
||||
@ -1651,7 +1658,6 @@ bool CopyPropagation::isCopyReg(unsigned Opc, bool NoConv) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CopyPropagation::propagateRegCopy(MachineInstr &MI) {
|
||||
bool Changed = false;
|
||||
unsigned Opc = MI.getOpcode();
|
||||
@ -1706,7 +1712,6 @@ bool CopyPropagation::propagateRegCopy(MachineInstr &MI) {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
|
||||
bool CopyPropagation::processBlock(MachineBasicBlock &B, const RegisterSet&) {
|
||||
std::vector<MachineInstr*> Instrs;
|
||||
for (auto I = B.rbegin(), E = B.rend(); I != E; ++I)
|
||||
@ -1723,21 +1728,20 @@ bool CopyPropagation::processBlock(MachineBasicBlock &B, const RegisterSet&) {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
//
|
||||
// Bit simplification
|
||||
//
|
||||
// Recognize patterns that can be simplified and replace them with the
|
||||
// simpler forms.
|
||||
// This is by no means complete
|
||||
namespace {
|
||||
class BitSimplification : public Transformation {
|
||||
public:
|
||||
BitSimplification(BitTracker &bt, const HexagonInstrInfo &hii,
|
||||
const HexagonRegisterInfo &hri, MachineRegisterInfo &mri,
|
||||
MachineFunction &mf)
|
||||
: Transformation(true), HII(hii), HRI(hri), MRI(mri), MF(mf), BT(bt) {}
|
||||
|
||||
bool processBlock(MachineBasicBlock &B, const RegisterSet &AVs) override;
|
||||
|
||||
private:
|
||||
struct RegHalf : public BitTracker::RegisterRef {
|
||||
bool Low; // Low/High halfword.
|
||||
@ -1770,8 +1774,8 @@ namespace {
|
||||
MachineFunction &MF;
|
||||
BitTracker &BT;
|
||||
};
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
// Check if the bits [B..B+16) in register cell RC form a valid halfword,
|
||||
// i.e. [0..16), [16..32), etc. of some register. If so, return true and
|
||||
@ -1854,7 +1858,6 @@ bool BitSimplification::matchHalf(unsigned SelfR,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool BitSimplification::validateReg(BitTracker::RegisterRef R, unsigned Opc,
|
||||
unsigned OpNum) {
|
||||
auto *OpRC = HII.getRegClass(HII.get(Opc), OpNum, &HRI, MF);
|
||||
@ -1862,7 +1865,6 @@ bool BitSimplification::validateReg(BitTracker::RegisterRef R, unsigned Opc,
|
||||
return OpRC->hasSubClassEq(RRC);
|
||||
}
|
||||
|
||||
|
||||
// Check if RC matches the pattern of a S2_packhl. If so, return true and
|
||||
// set the inputs Rs and Rt.
|
||||
bool BitSimplification::matchPackhl(unsigned SelfR,
|
||||
@ -1886,7 +1888,6 @@ bool BitSimplification::matchPackhl(unsigned SelfR,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
unsigned BitSimplification::getCombineOpcode(bool HLow, bool LLow) {
|
||||
return HLow ? LLow ? Hexagon::A2_combine_ll
|
||||
: Hexagon::A2_combine_lh
|
||||
@ -1894,7 +1895,6 @@ unsigned BitSimplification::getCombineOpcode(bool HLow, bool LLow) {
|
||||
: Hexagon::A2_combine_hh;
|
||||
}
|
||||
|
||||
|
||||
// If MI stores the upper halfword of a register (potentially obtained via
|
||||
// shifts or extracts), replace it with a storerf instruction. This could
|
||||
// cause the "extraction" code to become dead.
|
||||
@ -1919,7 +1919,6 @@ bool BitSimplification::genStoreUpperHalf(MachineInstr *MI) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// If MI stores a value known at compile-time, and the value is within a range
|
||||
// that avoids using constant-extenders, replace it with a store-immediate.
|
||||
bool BitSimplification::genStoreImmediate(MachineInstr *MI) {
|
||||
@ -1988,7 +1987,6 @@ bool BitSimplification::genStoreImmediate(MachineInstr *MI) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// If MI is equivalent o S2_packhl, generate the S2_packhl. MI could be the
|
||||
// last instruction in a sequence that results in something equivalent to
|
||||
// the pack-halfwords. The intent is to cause the entire sequence to become
|
||||
@ -2018,7 +2016,6 @@ bool BitSimplification::genPackhl(MachineInstr *MI,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// If MI produces halfword of the input in the low half of the output,
|
||||
// replace it with zero-extend or extractu.
|
||||
bool BitSimplification::genExtractHalf(MachineInstr *MI,
|
||||
@ -2058,7 +2055,6 @@ bool BitSimplification::genExtractHalf(MachineInstr *MI,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// If MI is equivalent to a combine(.L/.H, .L/.H) replace with with the
|
||||
// combine.
|
||||
bool BitSimplification::genCombineHalf(MachineInstr *MI,
|
||||
@ -2091,7 +2087,6 @@ bool BitSimplification::genCombineHalf(MachineInstr *MI,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// If MI resets high bits of a register and keeps the lower ones, replace it
|
||||
// with zero-extend byte/half, and-immediate, or extractu, as appropriate.
|
||||
bool BitSimplification::genExtractLow(MachineInstr *MI,
|
||||
@ -2154,7 +2149,6 @@ bool BitSimplification::genExtractLow(MachineInstr *MI,
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Check for tstbit simplification opportunity, where the bit being checked
|
||||
// can be tracked back to another register. For example:
|
||||
// vreg2 = S2_lsr_i_r vreg1, 5
|
||||
@ -2184,7 +2178,7 @@ bool BitSimplification::simplifyTstbit(MachineInstr *MI,
|
||||
// Need to map V.RefI.Reg to a 32-bit register, i.e. if it is
|
||||
// a double register, need to use a subregister and adjust bit
|
||||
// number.
|
||||
unsigned P = UINT_MAX;
|
||||
unsigned P = std::numeric_limits<unsigned>::max();
|
||||
BitTracker::RegisterRef RR(V.RefI.Reg, 0);
|
||||
if (TC == &Hexagon::DoubleRegsRegClass) {
|
||||
P = V.RefI.Pos;
|
||||
@ -2196,7 +2190,7 @@ bool BitSimplification::simplifyTstbit(MachineInstr *MI,
|
||||
} else if (TC == &Hexagon::IntRegsRegClass) {
|
||||
P = V.RefI.Pos;
|
||||
}
|
||||
if (P != UINT_MAX) {
|
||||
if (P != std::numeric_limits<unsigned>::max()) {
|
||||
unsigned NewR = MRI.createVirtualRegister(&Hexagon::PredRegsRegClass);
|
||||
BuildMI(B, At, DL, HII.get(Hexagon::S2_tstbit_i), NewR)
|
||||
.addReg(RR.Reg, 0, RR.Sub)
|
||||
@ -2216,7 +2210,6 @@ bool BitSimplification::simplifyTstbit(MachineInstr *MI,
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool BitSimplification::processBlock(MachineBasicBlock &B,
|
||||
const RegisterSet &AVs) {
|
||||
if (!BT.reached(&B))
|
||||
@ -2275,7 +2268,6 @@ bool BitSimplification::processBlock(MachineBasicBlock &B,
|
||||
return Changed;
|
||||
}
|
||||
|
||||
|
||||
bool HexagonBitSimplify::runOnMachineFunction(MachineFunction &MF) {
|
||||
if (skipFunction(*MF.getFunction()))
|
||||
return false;
|
||||
@ -2335,7 +2327,6 @@ bool HexagonBitSimplify::runOnMachineFunction(MachineFunction &MF) {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
|
||||
// Recognize loops where the code at the end of the loop matches the code
|
||||
// before the entry of the loop, and the matching code is such that is can
|
||||
// be simplified. This pass relies on the bit simplification above and only
|
||||
@ -2399,16 +2390,20 @@ bool HexagonBitSimplify::runOnMachineFunction(MachineFunction &MF) {
|
||||
// }:endloop0
|
||||
|
||||
namespace llvm {
|
||||
|
||||
FunctionPass *createHexagonLoopRescheduling();
|
||||
void initializeHexagonLoopReschedulingPass(PassRegistry&);
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
namespace {
|
||||
|
||||
class HexagonLoopRescheduling : public MachineFunctionPass {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
HexagonLoopRescheduling() : MachineFunctionPass(ID),
|
||||
HII(0), HRI(0), MRI(0), BTP(0) {
|
||||
HII(nullptr), HRI(nullptr), MRI(nullptr), BTP(nullptr) {
|
||||
initializeHexagonLoopReschedulingPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
@ -2448,14 +2443,14 @@ namespace {
|
||||
MachineBasicBlock::iterator At, unsigned OldPhiR, unsigned NewPredR);
|
||||
bool processLoop(LoopCand &C);
|
||||
};
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
char HexagonLoopRescheduling::ID = 0;
|
||||
|
||||
INITIALIZE_PASS(HexagonLoopRescheduling, "hexagon-loop-resched",
|
||||
"Hexagon Loop Rescheduling", false, false)
|
||||
|
||||
|
||||
HexagonLoopRescheduling::PhiInfo::PhiInfo(MachineInstr &P,
|
||||
MachineBasicBlock &B) {
|
||||
DefR = HexagonLoopRescheduling::getDefReg(&P);
|
||||
@ -2472,7 +2467,6 @@ HexagonLoopRescheduling::PhiInfo::PhiInfo(MachineInstr &P,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned HexagonLoopRescheduling::getDefReg(const MachineInstr *MI) {
|
||||
RegisterSet Defs;
|
||||
HBS::getInstrDefs(*MI, Defs);
|
||||
@ -2481,7 +2475,6 @@ unsigned HexagonLoopRescheduling::getDefReg(const MachineInstr *MI) {
|
||||
return Defs.find_first();
|
||||
}
|
||||
|
||||
|
||||
bool HexagonLoopRescheduling::isConst(unsigned Reg) const {
|
||||
if (!BTP->has(Reg))
|
||||
return false;
|
||||
@ -2494,7 +2487,6 @@ bool HexagonLoopRescheduling::isConst(unsigned Reg) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool HexagonLoopRescheduling::isBitShuffle(const MachineInstr *MI,
|
||||
unsigned DefR) const {
|
||||
unsigned Opc = MI->getOpcode();
|
||||
@ -2525,7 +2517,6 @@ bool HexagonLoopRescheduling::isBitShuffle(const MachineInstr *MI,
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool HexagonLoopRescheduling::isStoreInput(const MachineInstr *MI,
|
||||
unsigned InpR) const {
|
||||
for (unsigned i = 0, n = MI->getNumOperands(); i < n; ++i) {
|
||||
@ -2538,7 +2529,6 @@ bool HexagonLoopRescheduling::isStoreInput(const MachineInstr *MI,
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool HexagonLoopRescheduling::isShuffleOf(unsigned OutR, unsigned InpR) const {
|
||||
if (!BTP->has(OutR) || !BTP->has(InpR))
|
||||
return false;
|
||||
@ -2553,7 +2543,6 @@ bool HexagonLoopRescheduling::isShuffleOf(unsigned OutR, unsigned InpR) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool HexagonLoopRescheduling::isSameShuffle(unsigned OutR1, unsigned InpR1,
|
||||
unsigned OutR2, unsigned &InpR2) const {
|
||||
if (!BTP->has(OutR1) || !BTP->has(InpR1) || !BTP->has(OutR2))
|
||||
@ -2585,7 +2574,6 @@ bool HexagonLoopRescheduling::isSameShuffle(unsigned OutR1, unsigned InpR1,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void HexagonLoopRescheduling::moveGroup(InstrGroup &G, MachineBasicBlock &LB,
|
||||
MachineBasicBlock &PB, MachineBasicBlock::iterator At, unsigned OldPhiR,
|
||||
unsigned NewPredR) {
|
||||
@ -2625,7 +2613,6 @@ void HexagonLoopRescheduling::moveGroup(InstrGroup &G, MachineBasicBlock &LB,
|
||||
HBS::replaceReg(OldPhiR, RegMap[G.Out.Reg], *MRI);
|
||||
}
|
||||
|
||||
|
||||
bool HexagonLoopRescheduling::processLoop(LoopCand &C) {
|
||||
DEBUG(dbgs() << "Processing loop in BB#" << C.LB->getNumber() << "\n");
|
||||
std::vector<PhiInfo> Phis;
|
||||
@ -2765,7 +2752,7 @@ bool HexagonLoopRescheduling::processLoop(LoopCand &C) {
|
||||
auto LoopInpEq = [G] (const PhiInfo &P) -> bool {
|
||||
return G.Out.Reg == P.LR.Reg;
|
||||
};
|
||||
if (find_if(Phis, LoopInpEq) == Phis.end())
|
||||
if (llvm::find_if(Phis, LoopInpEq) == Phis.end())
|
||||
continue;
|
||||
|
||||
G.Inp.Reg = Inputs.find_first();
|
||||
@ -2790,7 +2777,7 @@ bool HexagonLoopRescheduling::processLoop(LoopCand &C) {
|
||||
auto LoopInpEq = [G] (const PhiInfo &P) -> bool {
|
||||
return G.Out.Reg == P.LR.Reg;
|
||||
};
|
||||
auto F = find_if(Phis, LoopInpEq);
|
||||
auto F = llvm::find_if(Phis, LoopInpEq);
|
||||
if (F == Phis.end())
|
||||
continue;
|
||||
unsigned PrehR = 0;
|
||||
@ -2830,7 +2817,6 @@ bool HexagonLoopRescheduling::processLoop(LoopCand &C) {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
|
||||
bool HexagonLoopRescheduling::runOnMachineFunction(MachineFunction &MF) {
|
||||
if (skipFunction(*MF.getFunction()))
|
||||
return false;
|
||||
@ -2893,4 +2879,3 @@ FunctionPass *llvm::createHexagonLoopRescheduling() {
|
||||
FunctionPass *llvm::createHexagonBitSimplify() {
|
||||
return new HexagonBitSimplify();
|
||||
}
|
||||
|
||||
|
@ -12,17 +12,19 @@
|
||||
#include "HexagonBlockRanges.h"
|
||||
#include "HexagonInstrInfo.h"
|
||||
#include "HexagonSubtarget.h"
|
||||
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
|
||||
using namespace llvm;
|
||||
@ -40,7 +42,6 @@ bool HexagonBlockRanges::IndexRange::overlaps(const IndexRange &A) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool HexagonBlockRanges::IndexRange::contains(const IndexRange &A) const {
|
||||
if (start() <= A.start()) {
|
||||
// Treat "None" in the range end as equal to the range start.
|
||||
@ -52,7 +53,6 @@ bool HexagonBlockRanges::IndexRange::contains(const IndexRange &A) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void HexagonBlockRanges::IndexRange::merge(const IndexRange &A) {
|
||||
// Allow merging adjacent ranges.
|
||||
assert(end() == A.start() || overlaps(A));
|
||||
@ -70,14 +70,12 @@ void HexagonBlockRanges::IndexRange::merge(const IndexRange &A) {
|
||||
Fixed = true;
|
||||
}
|
||||
|
||||
|
||||
void HexagonBlockRanges::RangeList::include(const RangeList &RL) {
|
||||
for (auto &R : RL)
|
||||
if (!is_contained(*this, R))
|
||||
push_back(R);
|
||||
}
|
||||
|
||||
|
||||
// Merge all overlapping ranges in the list, so that all that remains
|
||||
// is a list of disjoint ranges.
|
||||
void HexagonBlockRanges::RangeList::unionize(bool MergeAdjacent) {
|
||||
@ -101,7 +99,6 @@ void HexagonBlockRanges::RangeList::unionize(bool MergeAdjacent) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Compute a range A-B and add it to the list.
|
||||
void HexagonBlockRanges::RangeList::addsub(const IndexRange &A,
|
||||
const IndexRange &B) {
|
||||
@ -138,7 +135,6 @@ void HexagonBlockRanges::RangeList::addsub(const IndexRange &A,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Subtract a given range from each element in the list.
|
||||
void HexagonBlockRanges::RangeList::subtract(const IndexRange &Range) {
|
||||
// Cannot assume that the list is unionized (i.e. contains only non-
|
||||
@ -156,7 +152,6 @@ void HexagonBlockRanges::RangeList::subtract(const IndexRange &Range) {
|
||||
include(T);
|
||||
}
|
||||
|
||||
|
||||
HexagonBlockRanges::InstrIndexMap::InstrIndexMap(MachineBasicBlock &B)
|
||||
: Block(B) {
|
||||
IndexType Idx = IndexType::First;
|
||||
@ -171,13 +166,11 @@ HexagonBlockRanges::InstrIndexMap::InstrIndexMap(MachineBasicBlock &B)
|
||||
Last = B.empty() ? IndexType::None : unsigned(Idx)-1;
|
||||
}
|
||||
|
||||
|
||||
MachineInstr *HexagonBlockRanges::InstrIndexMap::getInstr(IndexType Idx) const {
|
||||
auto F = Map.find(Idx);
|
||||
return (F != Map.end()) ? F->second : 0;
|
||||
return (F != Map.end()) ? F->second : nullptr;
|
||||
}
|
||||
|
||||
|
||||
HexagonBlockRanges::IndexType HexagonBlockRanges::InstrIndexMap::getIndex(
|
||||
MachineInstr *MI) const {
|
||||
for (auto &I : Map)
|
||||
@ -186,7 +179,6 @@ HexagonBlockRanges::IndexType HexagonBlockRanges::InstrIndexMap::getIndex(
|
||||
return IndexType::None;
|
||||
}
|
||||
|
||||
|
||||
HexagonBlockRanges::IndexType HexagonBlockRanges::InstrIndexMap::getPrevIndex(
|
||||
IndexType Idx) const {
|
||||
assert (Idx != IndexType::None);
|
||||
@ -199,7 +191,6 @@ HexagonBlockRanges::IndexType HexagonBlockRanges::InstrIndexMap::getPrevIndex(
|
||||
return unsigned(Idx)-1;
|
||||
}
|
||||
|
||||
|
||||
HexagonBlockRanges::IndexType HexagonBlockRanges::InstrIndexMap::getNextIndex(
|
||||
IndexType Idx) const {
|
||||
assert (Idx != IndexType::None);
|
||||
@ -210,7 +201,6 @@ HexagonBlockRanges::IndexType HexagonBlockRanges::InstrIndexMap::getNextIndex(
|
||||
return unsigned(Idx)+1;
|
||||
}
|
||||
|
||||
|
||||
void HexagonBlockRanges::InstrIndexMap::replaceInstr(MachineInstr *OldMI,
|
||||
MachineInstr *NewMI) {
|
||||
for (auto &I : Map) {
|
||||
@ -224,7 +214,6 @@ void HexagonBlockRanges::InstrIndexMap::replaceInstr(MachineInstr *OldMI,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HexagonBlockRanges::HexagonBlockRanges(MachineFunction &mf)
|
||||
: MF(mf), HST(mf.getSubtarget<HexagonSubtarget>()),
|
||||
TII(*HST.getInstrInfo()), TRI(*HST.getRegisterInfo()),
|
||||
@ -239,7 +228,6 @@ HexagonBlockRanges::HexagonBlockRanges(MachineFunction &mf)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
HexagonBlockRanges::RegisterSet HexagonBlockRanges::getLiveIns(
|
||||
const MachineBasicBlock &B, const MachineRegisterInfo &MRI,
|
||||
const TargetRegisterInfo &TRI) {
|
||||
@ -267,7 +255,6 @@ HexagonBlockRanges::RegisterSet HexagonBlockRanges::getLiveIns(
|
||||
return LiveIns;
|
||||
}
|
||||
|
||||
|
||||
HexagonBlockRanges::RegisterSet HexagonBlockRanges::expandToSubRegs(
|
||||
RegisterRef R, const MachineRegisterInfo &MRI,
|
||||
const TargetRegisterInfo &TRI) {
|
||||
@ -297,7 +284,6 @@ HexagonBlockRanges::RegisterSet HexagonBlockRanges::expandToSubRegs(
|
||||
return SRs;
|
||||
}
|
||||
|
||||
|
||||
void HexagonBlockRanges::computeInitialLiveRanges(InstrIndexMap &IndexMap,
|
||||
RegToRangeMap &LiveMap) {
|
||||
std::map<RegisterRef,IndexType> LastDef, LastUse;
|
||||
@ -379,7 +365,6 @@ void HexagonBlockRanges::computeInitialLiveRanges(InstrIndexMap &IndexMap,
|
||||
P.second.unionize();
|
||||
}
|
||||
|
||||
|
||||
HexagonBlockRanges::RegToRangeMap HexagonBlockRanges::computeLiveMap(
|
||||
InstrIndexMap &IndexMap) {
|
||||
RegToRangeMap LiveMap;
|
||||
@ -390,7 +375,6 @@ HexagonBlockRanges::RegToRangeMap HexagonBlockRanges::computeLiveMap(
|
||||
return LiveMap;
|
||||
}
|
||||
|
||||
|
||||
HexagonBlockRanges::RegToRangeMap HexagonBlockRanges::computeDeadMap(
|
||||
InstrIndexMap &IndexMap, RegToRangeMap &LiveMap) {
|
||||
RegToRangeMap DeadMap;
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===--- HexagonBlockRanges.h ---------------------------------------------===//
|
||||
//===--- HexagonBlockRanges.h -----------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -11,23 +11,21 @@
|
||||
|
||||
#include "llvm/ADT/BitVector.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/MC/MCRegisterInfo.h" // For MCPhysReg.
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
namespace llvm {
|
||||
class Function;
|
||||
class HexagonSubtarget;
|
||||
class MachineBasicBlock;
|
||||
class MachineFunction;
|
||||
class MachineInstr;
|
||||
class MCInstrDesc;
|
||||
class raw_ostream;
|
||||
class TargetInstrInfo;
|
||||
class TargetRegisterClass;
|
||||
class TargetRegisterInfo;
|
||||
class Type;
|
||||
|
||||
class HexagonSubtarget;
|
||||
class MachineBasicBlock;
|
||||
class MachineFunction;
|
||||
class MachineInstr;
|
||||
class raw_ostream;
|
||||
class TargetInstrInfo;
|
||||
class TargetRegisterInfo;
|
||||
|
||||
struct HexagonBlockRanges {
|
||||
HexagonBlockRanges(MachineFunction &MF);
|
||||
@ -50,10 +48,12 @@ struct HexagonBlockRanges {
|
||||
Exit = 2,
|
||||
First = 11 // 10th + 1st
|
||||
};
|
||||
static bool isInstr(IndexType X) { return X.Index >= First; }
|
||||
|
||||
IndexType() : Index(None) {}
|
||||
IndexType(unsigned Idx) : Index(Idx) {}
|
||||
|
||||
static bool isInstr(IndexType X) { return X.Index >= First; }
|
||||
|
||||
operator unsigned() const;
|
||||
bool operator== (unsigned x) const;
|
||||
bool operator== (IndexType Idx) const;
|
||||
@ -76,21 +76,23 @@ struct HexagonBlockRanges {
|
||||
// register is dead.
|
||||
class IndexRange : public std::pair<IndexType,IndexType> {
|
||||
public:
|
||||
IndexRange() : Fixed(false), TiedEnd(false) {}
|
||||
IndexRange() = default;
|
||||
IndexRange(IndexType Start, IndexType End, bool F = false, bool T = false)
|
||||
: std::pair<IndexType,IndexType>(Start, End), Fixed(F), TiedEnd(T) {}
|
||||
|
||||
IndexType start() const { return first; }
|
||||
IndexType end() const { return second; }
|
||||
|
||||
bool operator< (const IndexRange &A) const {
|
||||
return start() < A.start();
|
||||
}
|
||||
|
||||
bool overlaps(const IndexRange &A) const;
|
||||
bool contains(const IndexRange &A) const;
|
||||
void merge(const IndexRange &A);
|
||||
|
||||
bool Fixed; // Can be renamed? "Fixed" means "no".
|
||||
bool TiedEnd; // The end is not a use, but a dead def tied to a use.
|
||||
bool Fixed = false; // Can be renamed? "Fixed" means "no".
|
||||
bool TiedEnd = false; // The end is not a use, but a dead def tied to a use.
|
||||
|
||||
private:
|
||||
void setStart(const IndexType &S) { first = S; }
|
||||
@ -107,6 +109,7 @@ struct HexagonBlockRanges {
|
||||
void add(const IndexRange &Range) {
|
||||
push_back(Range);
|
||||
}
|
||||
|
||||
void include(const RangeList &RL);
|
||||
void unionize(bool MergeAdjacent = false);
|
||||
void subtract(const IndexRange &Range);
|
||||
@ -118,6 +121,7 @@ struct HexagonBlockRanges {
|
||||
class InstrIndexMap {
|
||||
public:
|
||||
InstrIndexMap(MachineBasicBlock &B);
|
||||
|
||||
MachineInstr *getInstr(IndexType Idx) const;
|
||||
IndexType getIndex(MachineInstr *MI) const;
|
||||
MachineBasicBlock &getBlock() const { return Block; }
|
||||
@ -126,6 +130,7 @@ struct HexagonBlockRanges {
|
||||
void replaceInstr(MachineInstr *OldMI, MachineInstr *NewMI);
|
||||
|
||||
friend raw_ostream &operator<< (raw_ostream &OS, const InstrIndexMap &Map);
|
||||
|
||||
IndexType First, Last;
|
||||
|
||||
private:
|
||||
@ -144,6 +149,7 @@ struct HexagonBlockRanges {
|
||||
: Map(M), TRI(I) {}
|
||||
|
||||
friend raw_ostream &operator<< (raw_ostream &OS, const PrintRangeMap &P);
|
||||
|
||||
private:
|
||||
const RegToRangeMap ⤅
|
||||
const TargetRegisterInfo &TRI;
|
||||
@ -163,7 +169,6 @@ private:
|
||||
BitVector Reserved;
|
||||
};
|
||||
|
||||
|
||||
inline HexagonBlockRanges::IndexType::operator unsigned() const {
|
||||
assert(Index >= First);
|
||||
return Index;
|
||||
@ -224,7 +229,6 @@ inline bool HexagonBlockRanges::IndexType::operator<= (IndexType Idx) const {
|
||||
return operator==(Idx) || operator<(Idx);
|
||||
}
|
||||
|
||||
|
||||
raw_ostream &operator<< (raw_ostream &OS, HexagonBlockRanges::IndexType Idx);
|
||||
raw_ostream &operator<< (raw_ostream &OS,
|
||||
const HexagonBlockRanges::IndexRange &IR);
|
||||
@ -235,6 +239,6 @@ raw_ostream &operator<< (raw_ostream &OS,
|
||||
raw_ostream &operator<< (raw_ostream &OS,
|
||||
const HexagonBlockRanges::PrintRangeMap &P);
|
||||
|
||||
} // namespace llvm
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
#endif // HEXAGON_BLOCK_RANGES_H
|
||||
|
@ -12,15 +12,23 @@
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonInstrInfo.h"
|
||||
#include "HexagonSubtarget.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineOperand.h"
|
||||
#include "llvm/CodeGen/Passes.h"
|
||||
#include "llvm/PassSupport.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -30,14 +38,18 @@ static cl::opt<uint32_t> BranchRelaxSafetyBuffer("branch-relax-safety-buffer",
|
||||
cl::init(200), cl::Hidden, cl::ZeroOrMore, cl::desc("safety buffer size"));
|
||||
|
||||
namespace llvm {
|
||||
|
||||
FunctionPass *createHexagonBranchRelaxation();
|
||||
void initializeHexagonBranchRelaxationPass(PassRegistry&);
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
namespace {
|
||||
|
||||
struct HexagonBranchRelaxation : public MachineFunctionPass {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
HexagonBranchRelaxation() : MachineFunctionPass(ID) {
|
||||
initializeHexagonBranchRelaxationPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
@ -67,6 +79,7 @@ namespace {
|
||||
};
|
||||
|
||||
char HexagonBranchRelaxation::ID = 0;
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
INITIALIZE_PASS(HexagonBranchRelaxation, "hexagon-brelax",
|
||||
@ -76,7 +89,6 @@ FunctionPass *llvm::createHexagonBranchRelaxation() {
|
||||
return new HexagonBranchRelaxation();
|
||||
}
|
||||
|
||||
|
||||
bool HexagonBranchRelaxation::runOnMachineFunction(MachineFunction &MF) {
|
||||
DEBUG(dbgs() << "****** Hexagon Branch Relaxation ******\n");
|
||||
|
||||
@ -89,7 +101,6 @@ bool HexagonBranchRelaxation::runOnMachineFunction(MachineFunction &MF) {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
|
||||
void HexagonBranchRelaxation::computeOffset(MachineFunction &MF,
|
||||
DenseMap<MachineBasicBlock*, unsigned> &OffsetMap) {
|
||||
// offset of the current instruction from the start.
|
||||
@ -108,7 +119,6 @@ void HexagonBranchRelaxation::computeOffset(MachineFunction &MF,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// relaxBranches - For Hexagon, if the jump target/loop label is too far from
|
||||
/// the jump/loop instruction then, we need to make sure that we have constant
|
||||
/// extenders set for jumps and loops.
|
||||
@ -124,7 +134,6 @@ bool HexagonBranchRelaxation::relaxBranches(MachineFunction &MF) {
|
||||
return reGenerateBranch(MF, BlockToInstOffset);
|
||||
}
|
||||
|
||||
|
||||
/// Check if a given instruction is:
|
||||
/// - a jump to a distant target
|
||||
/// - that exceeds its immediate range
|
||||
@ -144,7 +153,7 @@ bool HexagonBranchRelaxation::isJumpOutOfRange(MachineInstr &MI,
|
||||
// Number of instructions times typical instruction size.
|
||||
InstOffset += HII->nonDbgBBSize(&B) * HEXAGON_INSTR_SIZE;
|
||||
|
||||
MachineBasicBlock *TBB = NULL, *FBB = NULL;
|
||||
MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
|
||||
SmallVector<MachineOperand, 4> Cond;
|
||||
|
||||
// Try to analyze this branch.
|
||||
@ -176,7 +185,6 @@ bool HexagonBranchRelaxation::isJumpOutOfRange(MachineInstr &MI,
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool HexagonBranchRelaxation::reGenerateBranch(MachineFunction &MF,
|
||||
DenseMap<MachineBasicBlock*, unsigned> &BlockToInstOffset) {
|
||||
bool Changed = false;
|
||||
|
@ -9,29 +9,42 @@
|
||||
|
||||
#define DEBUG_TYPE "commgep"
|
||||
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/PostDominators.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
#include "llvm/IR/Constant.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/IR/Dominators.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Instruction.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/Verifier.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/IR/Use.h"
|
||||
#include "llvm/IR/User.h"
|
||||
#include "llvm/IR/Value.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Transforms/Utils/Local.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "HexagonTargetMachine.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static cl::opt<bool> OptSpeculate("commgep-speculate", cl::init(true),
|
||||
@ -44,10 +57,13 @@ static cl::opt<bool> OptEnableConst("commgep-const", cl::init(true),
|
||||
cl::Hidden, cl::ZeroOrMore);
|
||||
|
||||
namespace llvm {
|
||||
|
||||
void initializeHexagonCommonGEPPass(PassRegistry&);
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
namespace {
|
||||
|
||||
struct GepNode;
|
||||
typedef std::set<GepNode*> NodeSet;
|
||||
typedef std::map<GepNode*,Value*> NodeToValueMap;
|
||||
@ -59,7 +75,7 @@ namespace {
|
||||
// Numbering map for gep nodes. Used to keep track of ordering for
|
||||
// gep nodes.
|
||||
struct NodeOrdering {
|
||||
NodeOrdering() : LastNum(0) {}
|
||||
NodeOrdering() = default;
|
||||
|
||||
void insert(const GepNode *N) { Map.insert(std::make_pair(N, ++LastNum)); }
|
||||
void clear() { Map.clear(); }
|
||||
@ -72,19 +88,21 @@ namespace {
|
||||
|
||||
private:
|
||||
std::map<const GepNode *, unsigned> Map;
|
||||
unsigned LastNum;
|
||||
unsigned LastNum = 0;
|
||||
};
|
||||
|
||||
class HexagonCommonGEP : public FunctionPass {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
HexagonCommonGEP() : FunctionPass(ID) {
|
||||
initializeHexagonCommonGEPPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
virtual bool runOnFunction(Function &F);
|
||||
virtual StringRef getPassName() const { return "Hexagon Common GEP"; }
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
bool runOnFunction(Function &F) override;
|
||||
StringRef getPassName() const override { return "Hexagon Common GEP"; }
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
AU.addPreserved<DominatorTreeWrapperPass>();
|
||||
AU.addRequired<PostDominatorTreeWrapperPass>();
|
||||
@ -137,8 +155,8 @@ namespace {
|
||||
PostDominatorTree *PDT;
|
||||
Function *Fn;
|
||||
};
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
char HexagonCommonGEP::ID = 0;
|
||||
INITIALIZE_PASS_BEGIN(HexagonCommonGEP, "hcommgep", "Hexagon Common GEP",
|
||||
@ -150,6 +168,7 @@ INITIALIZE_PASS_END(HexagonCommonGEP, "hcommgep", "Hexagon Common GEP",
|
||||
false, false)
|
||||
|
||||
namespace {
|
||||
|
||||
struct GepNode {
|
||||
enum {
|
||||
None = 0,
|
||||
@ -166,17 +185,17 @@ namespace {
|
||||
Value *Idx;
|
||||
Type *PTy; // Type of the pointer operand.
|
||||
|
||||
GepNode() : Flags(0), Parent(0), Idx(0), PTy(0) {}
|
||||
GepNode() : Flags(0), Parent(nullptr), Idx(nullptr), PTy(nullptr) {}
|
||||
GepNode(const GepNode *N) : Flags(N->Flags), Idx(N->Idx), PTy(N->PTy) {
|
||||
if (Flags & Root)
|
||||
BaseVal = N->BaseVal;
|
||||
else
|
||||
Parent = N->Parent;
|
||||
}
|
||||
|
||||
friend raw_ostream &operator<< (raw_ostream &OS, const GepNode &GN);
|
||||
};
|
||||
|
||||
|
||||
Type *next_type(Type *Ty, Value *Idx) {
|
||||
if (auto *PTy = dyn_cast<PointerType>(Ty))
|
||||
return PTy->getElementType();
|
||||
@ -193,7 +212,6 @@ namespace {
|
||||
return NextTy;
|
||||
}
|
||||
|
||||
|
||||
raw_ostream &operator<< (raw_ostream &OS, const GepNode &GN) {
|
||||
OS << "{ {";
|
||||
bool Comma = false;
|
||||
@ -240,7 +258,6 @@ namespace {
|
||||
return OS;
|
||||
}
|
||||
|
||||
|
||||
template <typename NodeContainer>
|
||||
void dump_node_container(raw_ostream &OS, const NodeContainer &S) {
|
||||
typedef typename NodeContainer::const_iterator const_iterator;
|
||||
@ -255,7 +272,6 @@ namespace {
|
||||
return OS;
|
||||
}
|
||||
|
||||
|
||||
raw_ostream &operator<< (raw_ostream &OS,
|
||||
const NodeToUsesMap &M) LLVM_ATTRIBUTE_UNUSED;
|
||||
raw_ostream &operator<< (raw_ostream &OS, const NodeToUsesMap &M){
|
||||
@ -275,23 +291,22 @@ namespace {
|
||||
return OS;
|
||||
}
|
||||
|
||||
|
||||
struct in_set {
|
||||
in_set(const NodeSet &S) : NS(S) {}
|
||||
bool operator() (GepNode *N) const {
|
||||
return NS.find(N) != NS.end();
|
||||
}
|
||||
|
||||
private:
|
||||
const NodeSet &NS;
|
||||
};
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
inline void *operator new(size_t, SpecificBumpPtrAllocator<GepNode> &A) {
|
||||
return A.Allocate();
|
||||
}
|
||||
|
||||
|
||||
void HexagonCommonGEP::getBlockTraversalOrder(BasicBlock *Root,
|
||||
ValueVect &Order) {
|
||||
// Compute block ordering for a typical DT-based traversal of the flow
|
||||
@ -306,7 +321,6 @@ void HexagonCommonGEP::getBlockTraversalOrder(BasicBlock *Root,
|
||||
getBlockTraversalOrder((*I)->getBlock(), Order);
|
||||
}
|
||||
|
||||
|
||||
bool HexagonCommonGEP::isHandledGepForm(GetElementPtrInst *GepI) {
|
||||
// No vector GEPs.
|
||||
if (!GepI->getType()->isPointerTy())
|
||||
@ -317,7 +331,6 @@ bool HexagonCommonGEP::isHandledGepForm(GetElementPtrInst *GepI) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void HexagonCommonGEP::processGepInst(GetElementPtrInst *GepI,
|
||||
ValueToNodeMap &NM) {
|
||||
DEBUG(dbgs() << "Visiting GEP: " << *GepI << '\n');
|
||||
@ -383,7 +396,6 @@ void HexagonCommonGEP::processGepInst(GetElementPtrInst *GepI,
|
||||
NM.insert(std::make_pair(GepI, PN));
|
||||
}
|
||||
|
||||
|
||||
void HexagonCommonGEP::collect() {
|
||||
// Establish depth-first traversal order of the dominator tree.
|
||||
ValueVect BO;
|
||||
@ -407,10 +419,8 @@ void HexagonCommonGEP::collect() {
|
||||
DEBUG(dbgs() << "Gep nodes after initial collection:\n" << Nodes);
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
void invert_find_roots(const NodeVect &Nodes, NodeChildrenMap &NCM,
|
||||
NodeVect &Roots) {
|
||||
static void invert_find_roots(const NodeVect &Nodes, NodeChildrenMap &NCM,
|
||||
NodeVect &Roots) {
|
||||
typedef NodeVect::const_iterator const_iterator;
|
||||
for (const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
|
||||
GepNode *N = *I;
|
||||
@ -421,9 +431,10 @@ namespace {
|
||||
GepNode *PN = N->Parent;
|
||||
NCM[PN].push_back(N);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nodes_for_root(GepNode *Root, NodeChildrenMap &NCM, NodeSet &Nodes) {
|
||||
static void nodes_for_root(GepNode *Root, NodeChildrenMap &NCM,
|
||||
NodeSet &Nodes) {
|
||||
NodeVect Work;
|
||||
Work.push_back(Root);
|
||||
Nodes.insert(Root);
|
||||
@ -438,41 +449,43 @@ namespace {
|
||||
Nodes.insert(CF->second.begin(), CF->second.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
typedef std::set<NodeSet> NodeSymRel;
|
||||
typedef std::pair<GepNode*,GepNode*> NodePair;
|
||||
typedef std::set<NodePair> NodePairSet;
|
||||
|
||||
const NodeSet *node_class(GepNode *N, NodeSymRel &Rel) {
|
||||
} // end anonymous namespace
|
||||
|
||||
static const NodeSet *node_class(GepNode *N, NodeSymRel &Rel) {
|
||||
for (NodeSymRel::iterator I = Rel.begin(), E = Rel.end(); I != E; ++I)
|
||||
if (I->count(N))
|
||||
return &*I;
|
||||
return 0;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create an ordered pair of GepNode pointers. The pair will be used in
|
||||
// determining equality. The only purpose of the ordering is to eliminate
|
||||
// duplication due to the commutativity of equality/non-equality.
|
||||
NodePair node_pair(GepNode *N1, GepNode *N2) {
|
||||
static NodePair node_pair(GepNode *N1, GepNode *N2) {
|
||||
uintptr_t P1 = uintptr_t(N1), P2 = uintptr_t(N2);
|
||||
if (P1 <= P2)
|
||||
return std::make_pair(N1, N2);
|
||||
return std::make_pair(N2, N1);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned node_hash(GepNode *N) {
|
||||
static unsigned node_hash(GepNode *N) {
|
||||
// Include everything except flags and parent.
|
||||
FoldingSetNodeID ID;
|
||||
ID.AddPointer(N->Idx);
|
||||
ID.AddPointer(N->PTy);
|
||||
return ID.ComputeHash();
|
||||
}
|
||||
}
|
||||
|
||||
bool node_eq(GepNode *N1, GepNode *N2, NodePairSet &Eq, NodePairSet &Ne) {
|
||||
static bool node_eq(GepNode *N1, GepNode *N2, NodePairSet &Eq,
|
||||
NodePairSet &Ne) {
|
||||
// Don't cache the result for nodes with different hashes. The hash
|
||||
// comparison is fast enough.
|
||||
if (node_hash(N1) != node_hash(N2))
|
||||
@ -504,10 +517,8 @@ namespace {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HexagonCommonGEP::common() {
|
||||
// The essence of this commoning is finding gep nodes that are equal.
|
||||
// To do this we need to compare all pairs of nodes. To save time,
|
||||
@ -571,7 +582,6 @@ void HexagonCommonGEP::common() {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Create a projection from a NodeSet to the minimal element in it.
|
||||
typedef std::map<const NodeSet*,GepNode*> ProjMap;
|
||||
ProjMap PM;
|
||||
@ -644,10 +654,8 @@ void HexagonCommonGEP::common() {
|
||||
DEBUG(dbgs() << "Gep nodes after post-commoning cleanup:\n" << Nodes);
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
template <typename T>
|
||||
BasicBlock *nearest_common_dominator(DominatorTree *DT, T &Blocks) {
|
||||
template <typename T>
|
||||
static BasicBlock *nearest_common_dominator(DominatorTree *DT, T &Blocks) {
|
||||
DEBUG({
|
||||
dbgs() << "NCD of {";
|
||||
for (typename T::iterator I = Blocks.begin(), E = Blocks.end();
|
||||
@ -660,23 +668,23 @@ namespace {
|
||||
dbgs() << " }\n";
|
||||
});
|
||||
|
||||
// Allow null basic blocks in Blocks. In such cases, return 0.
|
||||
// Allow null basic blocks in Blocks. In such cases, return nullptr.
|
||||
typename T::iterator I = Blocks.begin(), E = Blocks.end();
|
||||
if (I == E || !*I)
|
||||
return 0;
|
||||
return nullptr;
|
||||
BasicBlock *Dom = cast<BasicBlock>(*I);
|
||||
while (++I != E) {
|
||||
BasicBlock *B = cast_or_null<BasicBlock>(*I);
|
||||
Dom = B ? DT->findNearestCommonDominator(Dom, B) : 0;
|
||||
Dom = B ? DT->findNearestCommonDominator(Dom, B) : nullptr;
|
||||
if (!Dom)
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
DEBUG(dbgs() << "computed:" << Dom->getName() << '\n');
|
||||
return Dom;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
BasicBlock *nearest_common_dominatee(DominatorTree *DT, T &Blocks) {
|
||||
template <typename T>
|
||||
static BasicBlock *nearest_common_dominatee(DominatorTree *DT, T &Blocks) {
|
||||
// If two blocks, A and B, dominate a block C, then A dominates B,
|
||||
// or B dominates A.
|
||||
typename T::iterator I = Blocks.begin(), E = Blocks.end();
|
||||
@ -693,16 +701,16 @@ namespace {
|
||||
if (DT->dominates(B, DomB))
|
||||
continue;
|
||||
if (!DT->dominates(DomB, B))
|
||||
return 0;
|
||||
return nullptr;
|
||||
DomB = B;
|
||||
}
|
||||
return DomB;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the first use in B of any value from Values. If no such use,
|
||||
// return B->end().
|
||||
template <typename T>
|
||||
BasicBlock::iterator first_use_of_in_block(T &Values, BasicBlock *B) {
|
||||
// Find the first use in B of any value from Values. If no such use,
|
||||
// return B->end().
|
||||
template <typename T>
|
||||
static BasicBlock::iterator first_use_of_in_block(T &Values, BasicBlock *B) {
|
||||
BasicBlock::iterator FirstUse = B->end(), BEnd = B->end();
|
||||
typedef typename T::iterator iterator;
|
||||
for (iterator I = Values.begin(), E = Values.end(); I != E; ++I) {
|
||||
@ -724,20 +732,18 @@ namespace {
|
||||
FirstUse = It;
|
||||
}
|
||||
return FirstUse;
|
||||
}
|
||||
|
||||
bool is_empty(const BasicBlock *B) {
|
||||
return B->empty() || (&*B->begin() == B->getTerminator());
|
||||
}
|
||||
}
|
||||
|
||||
static bool is_empty(const BasicBlock *B) {
|
||||
return B->empty() || (&*B->begin() == B->getTerminator());
|
||||
}
|
||||
|
||||
BasicBlock *HexagonCommonGEP::recalculatePlacement(GepNode *Node,
|
||||
NodeChildrenMap &NCM, NodeToValueMap &Loc) {
|
||||
DEBUG(dbgs() << "Loc for node:" << Node << '\n');
|
||||
// Recalculate the placement for Node, assuming that the locations of
|
||||
// its children in Loc are valid.
|
||||
// Return 0 if there is no valid placement for Node (for example, it
|
||||
// Return nullptr if there is no valid placement for Node (for example, it
|
||||
// uses an index value that is not available at the location required
|
||||
// to dominate all children, etc.).
|
||||
|
||||
@ -780,11 +786,11 @@ BasicBlock *HexagonCommonGEP::recalculatePlacement(GepNode *Node,
|
||||
|
||||
BasicBlock *DomB = nearest_common_dominator(DT, Bs);
|
||||
if (!DomB)
|
||||
return 0;
|
||||
return nullptr;
|
||||
// Check if the index used by Node dominates the computed dominator.
|
||||
Instruction *IdxI = dyn_cast<Instruction>(Node->Idx);
|
||||
if (IdxI && !DT->dominates(IdxI->getParent(), DomB))
|
||||
return 0;
|
||||
return nullptr;
|
||||
|
||||
// Avoid putting nodes into empty blocks.
|
||||
while (is_empty(DomB)) {
|
||||
@ -799,7 +805,6 @@ BasicBlock *HexagonCommonGEP::recalculatePlacement(GepNode *Node,
|
||||
return DomB;
|
||||
}
|
||||
|
||||
|
||||
BasicBlock *HexagonCommonGEP::recalculatePlacementRec(GepNode *Node,
|
||||
NodeChildrenMap &NCM, NodeToValueMap &Loc) {
|
||||
DEBUG(dbgs() << "LocRec begin for node:" << Node << '\n');
|
||||
@ -816,7 +821,6 @@ BasicBlock *HexagonCommonGEP::recalculatePlacementRec(GepNode *Node,
|
||||
return LB;
|
||||
}
|
||||
|
||||
|
||||
bool HexagonCommonGEP::isInvariantIn(Value *Val, Loop *L) {
|
||||
if (isa<Constant>(Val) || isa<Argument>(Val))
|
||||
return true;
|
||||
@ -827,7 +831,6 @@ bool HexagonCommonGEP::isInvariantIn(Value *Val, Loop *L) {
|
||||
return DT->properlyDominates(DefB, HdrB);
|
||||
}
|
||||
|
||||
|
||||
bool HexagonCommonGEP::isInvariantIn(GepNode *Node, Loop *L) {
|
||||
if (Node->Flags & GepNode::Root)
|
||||
if (!isInvariantIn(Node->BaseVal, L))
|
||||
@ -835,7 +838,6 @@ bool HexagonCommonGEP::isInvariantIn(GepNode *Node, Loop *L) {
|
||||
return isInvariantIn(Node->Idx, L);
|
||||
}
|
||||
|
||||
|
||||
bool HexagonCommonGEP::isInMainPath(BasicBlock *B, Loop *L) {
|
||||
BasicBlock *HB = L->getHeader();
|
||||
BasicBlock *LB = L->getLoopLatch();
|
||||
@ -847,21 +849,17 @@ bool HexagonCommonGEP::isInMainPath(BasicBlock *B, Loop *L) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
BasicBlock *preheader(DominatorTree *DT, Loop *L) {
|
||||
if (BasicBlock *PH = L->getLoopPreheader())
|
||||
return PH;
|
||||
if (!OptSpeculate)
|
||||
return 0;
|
||||
DomTreeNode *DN = DT->getNode(L->getHeader());
|
||||
if (!DN)
|
||||
return 0;
|
||||
return DN->getIDom()->getBlock();
|
||||
}
|
||||
static BasicBlock *preheader(DominatorTree *DT, Loop *L) {
|
||||
if (BasicBlock *PH = L->getLoopPreheader())
|
||||
return PH;
|
||||
if (!OptSpeculate)
|
||||
return nullptr;
|
||||
DomTreeNode *DN = DT->getNode(L->getHeader());
|
||||
if (!DN)
|
||||
return nullptr;
|
||||
return DN->getIDom()->getBlock();
|
||||
}
|
||||
|
||||
|
||||
BasicBlock *HexagonCommonGEP::adjustForInvariance(GepNode *Node,
|
||||
NodeChildrenMap &NCM, NodeToValueMap &Loc) {
|
||||
// Find the "topmost" location for Node: it must be dominated by both,
|
||||
@ -911,10 +909,11 @@ BasicBlock *HexagonCommonGEP::adjustForInvariance(GepNode *Node,
|
||||
return LocB;
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
struct LocationAsBlock {
|
||||
LocationAsBlock(const NodeToValueMap &L) : Map(L) {}
|
||||
|
||||
const NodeToValueMap ⤅
|
||||
};
|
||||
|
||||
@ -934,8 +933,8 @@ namespace {
|
||||
inline bool is_constant(GepNode *N) {
|
||||
return isa<ConstantInt>(N->Idx);
|
||||
}
|
||||
}
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
void HexagonCommonGEP::separateChainForNode(GepNode *Node, Use *U,
|
||||
NodeToValueMap &Loc) {
|
||||
@ -945,7 +944,7 @@ void HexagonCommonGEP::separateChainForNode(GepNode *Node, Use *U,
|
||||
BasicBlock *PB = cast<Instruction>(R)->getParent();
|
||||
|
||||
GepNode *N = Node;
|
||||
GepNode *C = 0, *NewNode = 0;
|
||||
GepNode *C = nullptr, *NewNode = nullptr;
|
||||
while (is_constant(N) && !(N->Flags & GepNode::Root)) {
|
||||
// XXX if (single-use) dont-replicate;
|
||||
GepNode *NewN = new (*Mem) GepNode(N);
|
||||
@ -989,7 +988,6 @@ void HexagonCommonGEP::separateChainForNode(GepNode *Node, Use *U,
|
||||
Uses[NewNode] = NewUs;
|
||||
}
|
||||
|
||||
|
||||
void HexagonCommonGEP::separateConstantChains(GepNode *Node,
|
||||
NodeChildrenMap &NCM, NodeToValueMap &Loc) {
|
||||
// First approximation: extract all chains.
|
||||
@ -1043,7 +1041,6 @@ void HexagonCommonGEP::separateConstantChains(GepNode *Node,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HexagonCommonGEP::computeNodePlacement(NodeToValueMap &Loc) {
|
||||
// Compute the inverse of the Node.Parent links. Also, collect the set
|
||||
// of root nodes.
|
||||
@ -1078,7 +1075,6 @@ void HexagonCommonGEP::computeNodePlacement(NodeToValueMap &Loc) {
|
||||
DEBUG(dbgs() << "Final node placement:\n" << LocationAsBlock(Loc));
|
||||
}
|
||||
|
||||
|
||||
Value *HexagonCommonGEP::fabricateGEP(NodeVect &NA, BasicBlock::iterator At,
|
||||
BasicBlock *LocB) {
|
||||
DEBUG(dbgs() << "Fabricating GEP in " << LocB->getName()
|
||||
@ -1087,7 +1083,7 @@ Value *HexagonCommonGEP::fabricateGEP(NodeVect &NA, BasicBlock::iterator At,
|
||||
GepNode *RN = NA[0];
|
||||
assert((RN->Flags & GepNode::Root) && "Creating GEP for non-root");
|
||||
|
||||
Value *NewInst = 0;
|
||||
Value *NewInst = nullptr;
|
||||
Value *Input = RN->BaseVal;
|
||||
Value **IdxList = new Value*[Num+1];
|
||||
unsigned nax = 0;
|
||||
@ -1126,7 +1122,6 @@ Value *HexagonCommonGEP::fabricateGEP(NodeVect &NA, BasicBlock::iterator At,
|
||||
return NewInst;
|
||||
}
|
||||
|
||||
|
||||
void HexagonCommonGEP::getAllUsersForNode(GepNode *Node, ValueVect &Values,
|
||||
NodeChildrenMap &NCM) {
|
||||
NodeVect Work;
|
||||
@ -1151,7 +1146,6 @@ void HexagonCommonGEP::getAllUsersForNode(GepNode *Node, ValueVect &Values,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HexagonCommonGEP::materialize(NodeToValueMap &Loc) {
|
||||
DEBUG(dbgs() << "Nodes before materialization:\n" << Nodes << '\n');
|
||||
NodeChildrenMap NCM;
|
||||
@ -1190,7 +1184,7 @@ void HexagonCommonGEP::materialize(NodeToValueMap &Loc) {
|
||||
break;
|
||||
GepNode *Child = CF->second.front();
|
||||
BasicBlock *ChildB = cast_or_null<BasicBlock>(Loc[Child]);
|
||||
if (ChildB != 0 && LastB != ChildB)
|
||||
if (ChildB != nullptr && LastB != ChildB)
|
||||
break;
|
||||
Last = Child;
|
||||
} while (true);
|
||||
@ -1234,7 +1228,6 @@ void HexagonCommonGEP::materialize(NodeToValueMap &Loc) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HexagonCommonGEP::removeDeadCode() {
|
||||
ValueVect BO;
|
||||
BO.push_back(&Fn->front());
|
||||
@ -1263,7 +1256,6 @@ void HexagonCommonGEP::removeDeadCode() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool HexagonCommonGEP::runOnFunction(Function &F) {
|
||||
if (skipFunction(F))
|
||||
return false;
|
||||
@ -1302,9 +1294,10 @@ bool HexagonCommonGEP::runOnFunction(Function &F) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
namespace llvm {
|
||||
|
||||
FunctionPass *createHexagonCommonGEP() {
|
||||
return new HexagonCommonGEP();
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
Loading…
Reference in New Issue
Block a user