Hexagon: Move HexagonMCInst.h to MCTargetDesc/HexagonMCInst.h.

Add HexagonMCInst class which adds various Hexagon VLIW annotations.
In addition, this class also includes some APIs related to the
constant extenders.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@175634 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jyotsna Verma 2013-02-20 16:13:27 +00:00
parent 6139b55222
commit d6c98ae638
12 changed files with 395 additions and 34 deletions

View File

@ -21,9 +21,10 @@
namespace llvm {
class FunctionPass;
class ModulePass;
class TargetMachine;
class MachineInstr;
class MCInst;
class HexagonMCInst;
class HexagonAsmPrinter;
class HexagonTargetMachine;
class raw_ostream;
@ -54,7 +55,7 @@ namespace llvm {
TargetAsmBackend *createHexagonAsmBackend(const Target &,
const std::string &);
*/
void HexagonLowerToMC(const MachineInstr *MI, MCInst &MCI,
void HexagonLowerToMC(const MachineInstr *MI, HexagonMCInst &MCI,
HexagonAsmPrinter &AP);
} // end namespace llvm;

View File

@ -14,12 +14,12 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "asm-printer"
#include "HexagonAsmPrinter.h"
#include "Hexagon.h"
#include "HexagonMCInst.h"
#include "HexagonAsmPrinter.h"
#include "HexagonMachineFunctionInfo.h"
#include "HexagonSubtarget.h"
#include "HexagonTargetMachine.h"
#include "HexagonSubtarget.h"
#include "MCTargetDesc/HexagonMCInst.h"
#include "InstPrinter/HexagonInstPrinter.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
@ -220,8 +220,8 @@ void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) {
assert((Size+IgnoreCount) == MI->getBundleSize() && "Corrupt Bundle!");
for (unsigned Index = 0; Index < Size; Index++) {
HexagonMCInst MCI;
MCI.setStartPacket(Index == 0);
MCI.setEndPacket(Index == (Size-1));
MCI.setPacketStart(Index == 0);
MCI.setPacketEnd(Index == (Size-1));
HexagonLowerToMC(BundleMIs[Index], MCI, *this);
OutStreamer.EmitInstruction(MCI);
@ -230,8 +230,8 @@ void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) {
else {
HexagonMCInst MCI;
if (MI->getOpcode() == Hexagon::ENDLOOP0) {
MCI.setStartPacket(true);
MCI.setEndPacket(true);
MCI.setPacketStart(true);
MCI.setPacketEnd(true);
}
HexagonLowerToMC(MI, MCI, *this);
OutStreamer.EmitInstruction(MCI);

View File

@ -15,6 +15,7 @@
#include "Hexagon.h"
#include "HexagonAsmPrinter.h"
#include "HexagonMachineFunctionInfo.h"
#include "MCTargetDesc/HexagonMCInst.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/MC/MCExpr.h"
@ -38,9 +39,10 @@ static MCOperand GetSymbolRef(const MachineOperand& MO, const MCSymbol* Symbol,
}
// Create an MCInst from a MachineInstr
void llvm::HexagonLowerToMC(const MachineInstr* MI, MCInst& MCI,
void llvm::HexagonLowerToMC(const MachineInstr* MI, HexagonMCInst& MCI,
HexagonAsmPrinter& AP) {
MCI.setOpcode(MI->getOpcode());
MCI.setDesc(MI->getDesc());
for (unsigned i = 0, e = MI->getNumOperands(); i < e; i++) {
const MachineOperand &MO = MI->getOperand(i);

View File

@ -12,14 +12,14 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "asm-printer"
#include "HexagonInstPrinter.h"
#include "Hexagon.h"
#include "HexagonAsmPrinter.h"
#include "HexagonMCInst.h"
#include "Hexagon.h"
#include "HexagonInstPrinter.h"
#include "MCTargetDesc/HexagonMCInst.h"
#include "llvm/MC/MCInst.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>
@ -28,6 +28,8 @@ using namespace llvm;
#define GET_INSTRUCTION_NAME
#include "HexagonGenAsmWriter.inc"
const char HexagonInstPrinter::PacketPadding = '\t';
StringRef HexagonInstPrinter::getOpcodeName(unsigned Opcode) const {
return MII.getName(Opcode);
}
@ -43,43 +45,42 @@ void HexagonInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
void HexagonInstPrinter::printInst(const HexagonMCInst *MI, raw_ostream &O,
StringRef Annot) {
const char packetPadding[] = " ";
const char startPacket = '{',
endPacket = '}';
// TODO: add outer HW loop when it's supported too.
if (MI->getOpcode() == Hexagon::ENDLOOP0) {
// Ending a harware loop is different from ending an regular packet.
assert(MI->isEndPacket() && "Loop end must also end the packet");
assert(MI->isPacketEnd() && "Loop-end must also end the packet");
if (MI->isStartPacket()) {
if (MI->isPacketStart()) {
// There must be a packet to end a loop.
// FIXME: when shuffling is always run, this shouldn't be needed.
HexagonMCInst Nop;
StringRef NoAnnot;
Nop.setOpcode (Hexagon::NOP);
Nop.setStartPacket (MI->isStartPacket());
Nop.setPacketStart (MI->isPacketStart());
printInst (&Nop, O, NoAnnot);
}
// Close the packet.
if (MI->isEndPacket())
O << packetPadding << endPacket;
if (MI->isPacketEnd())
O << PacketPadding << endPacket;
printInstruction(MI, O);
}
else {
// Prefix the insn opening the packet.
if (MI->isStartPacket())
O << packetPadding << startPacket << '\n';
if (MI->isPacketStart())
O << PacketPadding << startPacket << '\n';
printInstruction(MI, O);
// Suffix the insn closing the packet.
if (MI->isEndPacket())
if (MI->isPacketEnd())
// Suffix the packet in a new line always, since the GNU assembler has
// issues with a closing brace on the same line as CONST{32,64}.
O << '\n' << packetPadding << endPacket;
O << '\n' << PacketPadding << endPacket;
}
printAnnotation(O, Annot);
@ -102,12 +103,23 @@ void HexagonInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
void HexagonInstPrinter::printImmOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) const {
O << MI->getOperand(OpNo).getImm();
const MCOperand& MO = MI->getOperand(OpNo);
if(MO.isExpr()) {
O << *MO.getExpr();
} else if(MO.isImm()) {
O << MI->getOperand(OpNo).getImm();
} else {
llvm_unreachable("Unknown operand");
}
}
void HexagonInstPrinter::printExtOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) const {
O << MI->getOperand(OpNo).getImm();
const HexagonMCInst *HMCI = static_cast<const HexagonMCInst*>(MI);
if (HMCI->isConstExtended())
O << "#";
printOperand(MI, OpNo, O);
}
void HexagonInstPrinter::printUnsignedImmOperand(const MCInst *MI,

View File

@ -14,16 +14,18 @@
#ifndef HEXAGONINSTPRINTER_H
#define HEXAGONINSTPRINTER_H
#include "HexagonMCInst.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCInstrInfo.h"
namespace llvm {
class HexagonMCInst;
class HexagonInstPrinter : public MCInstPrinter {
public:
explicit HexagonInstPrinter(const MCAsmInfo &MAI,
const MCInstrInfo &MII,
const MCRegisterInfo &MRI)
: MCInstPrinter(MAI, MII, MRI) {}
: MCInstPrinter(MAI, MII, MRI), MII(MII) {}
virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
void printInst(const HexagonMCInst *MI, raw_ostream &O, StringRef Annot);
@ -65,10 +67,19 @@ namespace llvm {
void printSymbolLo(const MCInst *MI, unsigned OpNo, raw_ostream &O) const
{ printSymbol(MI, OpNo, O, false); }
bool isConstExtended(const MCInst *MI) const;
const MCInstrInfo &getMII() const {
return MII;
}
protected:
void printSymbol(const MCInst *MI, unsigned OpNo, raw_ostream &O, bool hi)
const;
static const char PacketPadding;
private:
const MCInstrInfo &MII;
};
} // end namespace llvm

View File

@ -19,5 +19,5 @@
type = Library
name = HexagonAsmPrinter
parent = Hexagon
required_libraries = MC Support
required_libraries = HexagonDesc MC Support
add_to_library_groups = Hexagon

View File

@ -1,6 +1,7 @@
add_llvm_library(LLVMHexagonDesc
HexagonMCTargetDesc.cpp
HexagonMCAsmInfo.cpp
HexagonMCInst.cpp
HexagonMCTargetDesc.cpp
)
add_dependencies(LLVMHexagonDesc HexagonCommonTableGen)

View File

@ -0,0 +1,175 @@
//===- HexagonMCInst.cpp - Hexagon sub-class of MCInst --------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class extends MCInst to allow some Hexagon VLIW annotations.
//
//===----------------------------------------------------------------------===//
#include "HexagonInstrInfo.h"
#include "MCTargetDesc/HexagonBaseInfo.h"
#include "MCTargetDesc/HexagonMCInst.h"
#include "MCTargetDesc/HexagonMCTargetDesc.h"
using namespace llvm;
// Return the slots used by the insn.
unsigned HexagonMCInst::getUnits(const HexagonTargetMachine* TM) const {
const HexagonInstrInfo* QII = TM->getInstrInfo();
const InstrItineraryData* II = TM->getInstrItineraryData();
const InstrStage*
IS = II->beginStage(QII->get(this->getOpcode()).getSchedClass());
return (IS->getUnits());
}
// Return the Hexagon ISA class for the insn.
unsigned HexagonMCInst::getType() const {
const uint64_t F = MCID->TSFlags;
return ((F >> HexagonII::TypePos) & HexagonII::TypeMask);
}
// Return whether the insn is an actual insn.
bool HexagonMCInst::isCanon() const {
return (!MCID->isPseudo() &&
!isPrefix() &&
getType() != HexagonII::TypeENDLOOP);
}
// Return whether the insn is a prefix.
bool HexagonMCInst::isPrefix() const {
return (getType() == HexagonII::TypePREFIX);
}
// Return whether the insn is solo, i.e., cannot be in a packet.
bool HexagonMCInst::isSolo() const {
const uint64_t F = MCID->TSFlags;
return ((F >> HexagonII::SoloPos) & HexagonII::SoloMask);
}
// Return whether the insn is a new-value consumer.
bool HexagonMCInst::isNewValue() const {
const uint64_t F = MCID->TSFlags;
return ((F >> HexagonII::NewValuePos) & HexagonII::NewValueMask);
}
// Return whether the instruction is a legal new-value producer.
bool HexagonMCInst::hasNewValue() const {
const uint64_t F = MCID->TSFlags;
return ((F >> HexagonII::hasNewValuePos) & HexagonII::hasNewValueMask);
}
// Return the operand that consumes or produces a new value.
const MCOperand& HexagonMCInst::getNewValue() const {
const uint64_t F = MCID->TSFlags;
const unsigned O = (F >> HexagonII::NewValueOpPos) &
HexagonII::NewValueOpMask;
const MCOperand& MCO = getOperand(O);
assert ((isNewValue() || hasNewValue()) && MCO.isReg());
return (MCO);
}
// Return whether the instruction needs to be constant extended.
// 1) Always return true if the instruction has 'isExtended' flag set.
//
// isExtendable:
// 2) For immediate extended operands, return true only if the value is
// out-of-range.
// 3) For global address, always return true.
bool HexagonMCInst::isConstExtended(void) const {
if (isExtended())
return true;
if (!isExtendable())
return false;
short ExtOpNum = getCExtOpNum();
int MinValue = getMinValue();
int MaxValue = getMaxValue();
const MCOperand& MO = getOperand(ExtOpNum);
// We could be using an instruction with an extendable immediate and shoehorn
// a global address into it. If it is a global address it will be constant
// extended. We do this for COMBINE.
// We currently only handle isGlobal() because it is the only kind of
// object we are going to end up with here for now.
// In the future we probably should add isSymbol(), etc.
if (MO.isExpr())
return true;
// If the extendable operand is not 'Immediate' type, the instruction should
// have 'isExtended' flag set.
assert(MO.isImm() && "Extendable operand must be Immediate type");
int ImmValue = MO.getImm();
return (ImmValue < MinValue || ImmValue > MaxValue);
}
// Return whether the instruction must be always extended.
bool HexagonMCInst::isExtended(void) const {
const uint64_t F = MCID->TSFlags;
return (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask;
}
// Return true if the instruction may be extended based on the operand value.
bool HexagonMCInst::isExtendable(void) const {
const uint64_t F = MCID->TSFlags;
return (F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask;
}
// Return number of bits in the constant extended operand.
unsigned HexagonMCInst::getBitCount(void) const {
const uint64_t F = MCID->TSFlags;
return ((F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask);
}
// Return constant extended operand number.
unsigned short HexagonMCInst::getCExtOpNum(void) const {
const uint64_t F = MCID->TSFlags;
return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask);
}
// Return whether the operand can be constant extended.
bool HexagonMCInst::isOperandExtended(const unsigned short OperandNum) const {
const uint64_t F = MCID->TSFlags;
return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask)
== OperandNum;
}
// Return the min value that a constant extendable operand can have
// without being extended.
int HexagonMCInst::getMinValue(void) const {
const uint64_t F = MCID->TSFlags;
unsigned isSigned = (F >> HexagonII::ExtentSignedPos)
& HexagonII::ExtentSignedMask;
unsigned bits = (F >> HexagonII::ExtentBitsPos)
& HexagonII::ExtentBitsMask;
if (isSigned) // if value is signed
return -1 << (bits - 1);
else
return 0;
}
// Return the max value that a constant extendable operand can have
// without being extended.
int HexagonMCInst::getMaxValue(void) const {
const uint64_t F = MCID->TSFlags;
unsigned isSigned = (F >> HexagonII::ExtentSignedPos)
& HexagonII::ExtentSignedMask;
unsigned bits = (F >> HexagonII::ExtentBitsPos)
& HexagonII::ExtentBitsMask;
if (isSigned) // if value is signed
return ~(-1 << (bits - 1));
else
return ~(-1 << bits);
}

View File

@ -0,0 +1,100 @@
//===- HexagonMCInst.h - Hexagon sub-class of MCInst ----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class extends MCInst to allow some VLIW annotations.
//
//===----------------------------------------------------------------------===//
#ifndef HEXAGONMCINST_H
#define HEXAGONMCINST_H
#include "HexagonTargetMachine.h"
#include "llvm/MC/MCInst.h"
namespace llvm {
class MCOperand;
class HexagonMCInst: public MCInst {
// MCID is set during instruction lowering.
// It is needed in order to access TSFlags for
// use in checking MC instruction properties.
const MCInstrDesc *MCID;
// Packet start and end markers
unsigned packetStart: 1, packetEnd: 1;
public:
explicit HexagonMCInst():
MCInst(), MCID(0), packetStart(0), packetEnd(0) {};
HexagonMCInst(const MCInstrDesc& mcid):
MCInst(), MCID(&mcid), packetStart(0), packetEnd(0) {};
bool isPacketStart() const { return (packetStart); };
bool isPacketEnd() const { return (packetEnd); };
void setPacketStart(bool Y) { packetStart = Y; };
void setPacketEnd(bool Y) { packetEnd = Y; };
void resetPacket() { setPacketStart(false); setPacketEnd(false); };
// Return the slots used by the insn.
unsigned getUnits(const HexagonTargetMachine* TM) const;
// Return the Hexagon ISA class for the insn.
unsigned getType() const;
void setDesc(const MCInstrDesc& mcid) { MCID = &mcid; };
const MCInstrDesc& getDesc(void) const { return *MCID; };
// Return whether the insn is an actual insn.
bool isCanon() const;
// Return whether the insn is a prefix.
bool isPrefix() const;
// Return whether the insn is solo, i.e., cannot be in a packet.
bool isSolo() const;
// Return whether the instruction needs to be constant extended.
bool isConstExtended() const;
// Return constant extended operand number.
unsigned short getCExtOpNum(void) const;
// Return whether the insn is a new-value consumer.
bool isNewValue() const;
// Return whether the instruction is a legal new-value producer.
bool hasNewValue() const;
// Return the operand that consumes or produces a new value.
const MCOperand& getNewValue() const;
// Return number of bits in the constant extended operand.
unsigned getBitCount(void) const;
private:
// Return whether the instruction must be always extended.
bool isExtended() const;
// Return true if the insn may be extended based on the operand value.
bool isExtendable() const;
// Return true if the operand can be constant extended.
bool isOperandExtended(const unsigned short OperandNum) const;
// Return the min value that a constant extendable operand can have
// without being extended.
int getMinValue() const;
// Return the max value that a constant extendable operand can have
// without being extended.
int getMaxValue() const;
};
}
#endif

View File

@ -13,11 +13,13 @@
#include "HexagonMCTargetDesc.h"
#include "HexagonMCAsmInfo.h"
#include "InstPrinter/HexagonInstPrinter.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"

View File

@ -0,0 +1,57 @@
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
; Check that we constant extended instructions only when necessary.
define i32 @cext_test1(i32* %a) nounwind {
; CHECK: r{{[0-9]+}}{{ *}}={{ *}}memw(r{{[0-9]+}}+##8000)
; CHECK: r{{[0-9]+}}{{ *}}={{ *}}add(r{{[0-9]+}}{{ *}},{{ *}}##300000)
; CHECK-NOT: r{{[0-9]+}}{{ *}}={{ *}}memw(r{{[0-9]+}}+##4092)
; CHECK-NOT: r{{[0-9]+}}{{ *}}={{ *}}add(r{{[0-9]+}}{{ *}},{{ *}}##300)
entry:
%0 = load i32* %a, align 4
%tobool = icmp ne i32 %0, 0
br i1 %tobool, label %if.then, label %if.end
if.then:
%arrayidx1 = getelementptr inbounds i32* %a, i32 2000
%1 = load i32* %arrayidx1, align 4
%add = add nsw i32 %1, 300000
br label %return
if.end:
%arrayidx2 = getelementptr inbounds i32* %a, i32 1023
%2 = load i32* %arrayidx2, align 4
%add3 = add nsw i32 %2, 300
br label %return
return:
%retval.0 = phi i32 [ %add, %if.then ], [ %add3, %if.end ]
ret i32 %retval.0
}
define i32 @cext_test2(i8* %a) nounwind {
; CHECK-NOT: r{{[0-9]+}}{{ *}}={{ *}}memub(r{{[0-9]+}}+##1023)
; CHECK: r{{[0-9]+}}{{ *}}={{ *}}add(r{{[0-9]+}}{{ *}},{{ *}}##300000)
; CHECK: r{{[0-9]+}}{{ *}}={{ *}}memub(r{{[0-9]+}}+##1024)
; CHECK-NOT: r{{[0-9]+}}{{ *}}={{ *}}add(r{{[0-9]+}}{{ *}},{{ *}}##6000)
entry:
%tobool = icmp ne i8* %a, null
br i1 %tobool, label %if.then, label %if.end
if.then:
%arrayidx = getelementptr inbounds i8* %a, i32 1023
%0 = load i8* %arrayidx, align 1
%conv = zext i8 %0 to i32
%add = add nsw i32 %conv, 300000
br label %return
if.end:
%arrayidx1 = getelementptr inbounds i8* %a, i32 1024
%1 = load i8* %arrayidx1, align 1
%conv2 = zext i8 %1 to i32
%add3 = add nsw i32 %conv2, 6000
br label %return
return:
%retval.0 = phi i32 [ %add, %if.then ], [ %add3, %if.end ]
ret i32 %retval.0
}

View File

@ -1,8 +1,8 @@
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
; Check that we generate dual stores in one packet in V4
; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#{{[0-9]+}}){{ *}}={{ *}}#100000
; CHECK-NEXT: memw(r{{[0-9]+}}{{ *}}+{{ *}}#{{[0-9]+}}){{ *}}={{ *}}#500000
; CHECK: memw(r{{[0-9]+}}{{ *}}+{{ *}}#{{[0-9]+}}){{ *}}={{ *}}##100000
; CHECK-NEXT: memw(r{{[0-9]+}}{{ *}}+{{ *}}#{{[0-9]+}}){{ *}}={{ *}}##500000
; CHECK-NEXT: }
@Reg = global i32 0, align 4