mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-03-04 10:30:30 +00:00
Support for target dependent Hexagon VLIW packetizer.
This patch creates and optimizes packets as per Hexagon ISA rules. llvm-svn: 156109
This commit is contained in:
parent
c3352fa310
commit
253d16b1b0
@ -28,6 +28,7 @@ add_llvm_target(HexagonCodeGen
|
||||
HexagonSubtarget.cpp
|
||||
HexagonTargetMachine.cpp
|
||||
HexagonTargetObjectFile.cpp
|
||||
HexagonVLIWPacketizer.cpp
|
||||
)
|
||||
|
||||
add_subdirectory(TargetInfo)
|
||||
|
@ -40,6 +40,7 @@ namespace llvm {
|
||||
FunctionPass *createHexagonHardwareLoops();
|
||||
FunctionPass *createHexagonPeephole();
|
||||
FunctionPass *createHexagonFixupHwLoops();
|
||||
FunctionPass *createHexagonPacketizer();
|
||||
|
||||
/* TODO: object output.
|
||||
MCCodeEmitter *createHexagonMCCodeEmitter(const Target &,
|
||||
@ -47,7 +48,8 @@ namespace llvm {
|
||||
MCContext &Ctx);
|
||||
*/
|
||||
/* TODO: assembler input.
|
||||
TargetAsmBackend *createHexagonAsmBackend(const Target &, const std::string &);
|
||||
TargetAsmBackend *createHexagonAsmBackend(const Target &,
|
||||
const std::string &);
|
||||
*/
|
||||
void HexagonLowerToMC(const MachineInstr *MI, MCInst &MCI,
|
||||
HexagonAsmPrinter &AP);
|
||||
@ -67,7 +69,7 @@ namespace llvm {
|
||||
// Normal instruction size (in bytes).
|
||||
#define HEXAGON_INSTR_SIZE 4
|
||||
|
||||
// Maximum number of words in a packet (in instructions).
|
||||
// Maximum number of words and instructions in a packet.
|
||||
#define HEXAGON_PACKET_SIZE 4
|
||||
|
||||
#endif
|
||||
|
@ -13,11 +13,11 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#define DEBUG_TYPE "asm-printer"
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonAsmPrinter.h"
|
||||
#include "HexagonMachineFunctionInfo.h"
|
||||
#include "HexagonMCInst.h"
|
||||
#include "HexagonTargetMachine.h"
|
||||
#include "HexagonSubtarget.h"
|
||||
#include "InstPrinter/HexagonInstPrinter.h"
|
||||
@ -77,8 +77,7 @@ void HexagonAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||
|
||||
switch (MO.getType()) {
|
||||
default:
|
||||
assert(0 && "<unknown operand type>");
|
||||
default: llvm_unreachable ("<unknown operand type>");
|
||||
case MachineOperand::MO_Register:
|
||||
O << HexagonInstPrinter::getRegisterName(MO.getReg());
|
||||
return;
|
||||
@ -196,10 +195,45 @@ void HexagonAsmPrinter::printPredicateOperand(const MachineInstr *MI,
|
||||
/// the current output stream.
|
||||
///
|
||||
void HexagonAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
MCInst MCI;
|
||||
if (MI->isBundle()) {
|
||||
std::vector<const MachineInstr*> BundleMIs;
|
||||
|
||||
HexagonLowerToMC(MI, MCI, *this);
|
||||
OutStreamer.EmitInstruction(MCI);
|
||||
const MachineBasicBlock *MBB = MI->getParent();
|
||||
MachineBasicBlock::const_instr_iterator MII = MI;
|
||||
++MII;
|
||||
unsigned int IgnoreCount = 0;
|
||||
while (MII != MBB->end() && MII->isInsideBundle()) {
|
||||
const MachineInstr *MInst = MII;
|
||||
if (MInst->getOpcode() == TargetOpcode::DBG_VALUE ||
|
||||
MInst->getOpcode() == TargetOpcode::IMPLICIT_DEF) {
|
||||
IgnoreCount++;
|
||||
++MII;
|
||||
continue;
|
||||
}
|
||||
//BundleMIs.push_back(&*MII);
|
||||
BundleMIs.push_back(MInst);
|
||||
++MII;
|
||||
}
|
||||
unsigned Size = BundleMIs.size();
|
||||
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));
|
||||
|
||||
HexagonLowerToMC(BundleMIs[Index], MCI, *this);
|
||||
OutStreamer.EmitInstruction(MCI);
|
||||
}
|
||||
}
|
||||
else {
|
||||
HexagonMCInst MCI;
|
||||
if (MI->getOpcode() == Hexagon::ENDLOOP0) {
|
||||
MCI.setStartPacket(true);
|
||||
MCI.setEndPacket(true);
|
||||
}
|
||||
HexagonLowerToMC(MI, MCI, *this);
|
||||
OutStreamer.EmitInstruction(MCI);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -241,15 +275,15 @@ void HexagonAsmPrinter::printGlobalOperand(const MachineInstr *MI, int OpNo,
|
||||
void HexagonAsmPrinter::printJumpTable(const MachineInstr *MI, int OpNo,
|
||||
raw_ostream &O) {
|
||||
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||
assert( (MO.getType() == MachineOperand::MO_JumpTableIndex) &&
|
||||
"Expecting jump table index");
|
||||
assert( (MO.getType() == MachineOperand::MO_JumpTableIndex) &&
|
||||
"Expecting jump table index");
|
||||
|
||||
// Hexagon_TODO: Do we need name mangling?
|
||||
O << *GetJTISymbol(MO.getIndex());
|
||||
}
|
||||
|
||||
void HexagonAsmPrinter::printConstantPool(const MachineInstr *MI, int OpNo,
|
||||
raw_ostream &O) {
|
||||
raw_ostream &O) {
|
||||
const MachineOperand &MO = MI->getOperand(OpNo);
|
||||
assert( (MO.getType() == MachineOperand::MO_ConstantPoolIndex) &&
|
||||
"Expecting constant pool index");
|
||||
|
@ -7,9 +7,9 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// The Hexagon processor has no instructions that load or store predicate
|
||||
// registers directly. So, when these registers must be spilled a general
|
||||
// purpose register must be found and the value copied to/from it from/to
|
||||
// the predicate register. This code currently does not use the register
|
||||
// registers directly. So, when these registers must be spilled a general
|
||||
// purpose register must be found and the value copied to/from it from/to
|
||||
// the predicate register. This code currently does not use the register
|
||||
// scavenger mechanism available in the allocator. There are two registers
|
||||
// reserved to allow spilling/restoring predicate registers. One is used to
|
||||
// hold the predicate value. The other is used when stack frame offsets are
|
||||
@ -84,7 +84,7 @@ bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) {
|
||||
int SrcReg = MI->getOperand(2).getReg();
|
||||
assert(Hexagon::PredRegsRegClass.contains(SrcReg) &&
|
||||
"Not a predicate register");
|
||||
if (!TII->isValidOffset(Hexagon::STriw, Offset)) {
|
||||
if (!TII->isValidOffset(Hexagon::STriw_indexed, Offset)) {
|
||||
if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) {
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
||||
TII->get(Hexagon::CONST32_Int_Real),
|
||||
@ -95,7 +95,7 @@ bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) {
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd),
|
||||
HEXAGON_RESERVED_REG_2).addReg(SrcReg);
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
||||
TII->get(Hexagon::STriw))
|
||||
TII->get(Hexagon::STriw_indexed))
|
||||
.addReg(HEXAGON_RESERVED_REG_1)
|
||||
.addImm(0).addReg(HEXAGON_RESERVED_REG_2);
|
||||
} else {
|
||||
@ -103,7 +103,8 @@ bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) {
|
||||
HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset);
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd),
|
||||
HEXAGON_RESERVED_REG_2).addReg(SrcReg);
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::STriw))
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
||||
TII->get(Hexagon::STriw_indexed))
|
||||
.addReg(HEXAGON_RESERVED_REG_1)
|
||||
.addImm(0)
|
||||
.addReg(HEXAGON_RESERVED_REG_2);
|
||||
@ -111,7 +112,8 @@ bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) {
|
||||
} else {
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd),
|
||||
HEXAGON_RESERVED_REG_2).addReg(SrcReg);
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::STriw)).
|
||||
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
||||
TII->get(Hexagon::STriw_indexed)).
|
||||
addReg(FP).addImm(Offset).addReg(HEXAGON_RESERVED_REG_2);
|
||||
}
|
||||
MII = MBB->erase(MI);
|
||||
|
@ -318,7 +318,7 @@ SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl) {
|
||||
else if (LoadedVT == MVT::i32) Opcode = Hexagon::LDriw_indexed;
|
||||
else if (LoadedVT == MVT::i16) Opcode = Hexagon::LDrih_indexed;
|
||||
else if (LoadedVT == MVT::i8) Opcode = Hexagon::LDrib_indexed;
|
||||
else assert (0 && "unknown memory type");
|
||||
else llvm_unreachable("unknown memory type");
|
||||
|
||||
// Build indexed load.
|
||||
SDValue TargetConstOff = CurDAG->getTargetConstant(Offset, PointerTy);
|
||||
@ -516,7 +516,7 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl) {
|
||||
else
|
||||
Opcode = zextval ? Hexagon::LDriub : Hexagon::LDrib;
|
||||
} else
|
||||
assert (0 && "unknown memory type");
|
||||
llvm_unreachable("unknown memory type");
|
||||
|
||||
// For zero ext i64 loads, we need to add combine instructions.
|
||||
if (LD->getValueType(0) == MVT::i64 &&
|
||||
@ -613,7 +613,7 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, DebugLoc dl) {
|
||||
else if (StoredVT == MVT::i32) Opcode = Hexagon::POST_STwri;
|
||||
else if (StoredVT == MVT::i16) Opcode = Hexagon::POST_SThri;
|
||||
else if (StoredVT == MVT::i8) Opcode = Hexagon::POST_STbri;
|
||||
else assert (0 && "unknown memory type");
|
||||
else llvm_unreachable("unknown memory type");
|
||||
|
||||
// Build post increment store.
|
||||
SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
|
||||
@ -636,10 +636,10 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, DebugLoc dl) {
|
||||
|
||||
// Figure out the opcode.
|
||||
if (StoredVT == MVT::i64) Opcode = Hexagon::STrid;
|
||||
else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw;
|
||||
else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed;
|
||||
else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih;
|
||||
else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib;
|
||||
else assert (0 && "unknown memory type");
|
||||
else llvm_unreachable("unknown memory type");
|
||||
|
||||
// Build regular store.
|
||||
SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
|
||||
@ -693,7 +693,7 @@ SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST,
|
||||
else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed;
|
||||
else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih_indexed;
|
||||
else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib_indexed;
|
||||
else assert (0 && "unknown memory type");
|
||||
else llvm_unreachable("unknown memory type");
|
||||
|
||||
SDValue Ops[] = {SDValue(NewBase,0),
|
||||
CurDAG->getTargetConstant(Offset,PointerTy),
|
||||
@ -752,7 +752,7 @@ SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
|
||||
if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
|
||||
SDValue Sext0 = MulOp0.getOperand(0);
|
||||
if (Sext0.getNode()->getValueType(0) != MVT::i32) {
|
||||
SelectCode(N);
|
||||
return SelectCode(N);
|
||||
}
|
||||
|
||||
OP0 = Sext0;
|
||||
@ -761,7 +761,7 @@ SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
|
||||
if (LD->getMemoryVT() != MVT::i32 ||
|
||||
LD->getExtensionType() != ISD::SEXTLOAD ||
|
||||
LD->getAddressingMode() != ISD::UNINDEXED) {
|
||||
SelectCode(N);
|
||||
return SelectCode(N);
|
||||
}
|
||||
|
||||
SDValue Chain = LD->getChain();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -160,10 +160,20 @@ public:
|
||||
bool isS8_Immediate(const int value) const;
|
||||
bool isS6_Immediate(const int value) const;
|
||||
|
||||
bool isSaveCalleeSavedRegsCall(const MachineInstr* MI) const;
|
||||
bool isConditionalTransfer(const MachineInstr* MI) const;
|
||||
bool isConditionalALU32 (const MachineInstr* MI) const;
|
||||
bool isConditionalLoad (const MachineInstr* MI) const;
|
||||
bool isConditionalStore(const MachineInstr* MI) const;
|
||||
bool isDeallocRet(const MachineInstr *MI) const;
|
||||
unsigned getInvertedPredicatedOpcode(const int Opc) const;
|
||||
bool isExtendable(const MachineInstr* MI) const;
|
||||
bool isExtended(const MachineInstr* MI) const;
|
||||
bool isPostIncrement(const MachineInstr* MI) const;
|
||||
bool isNewValueStore(const MachineInstr* MI) const;
|
||||
bool isNewValueJump(const MachineInstr* MI) const;
|
||||
unsigned getImmExtForm(const MachineInstr* MI) const;
|
||||
unsigned getNormalBranchForm(const MachineInstr* MI) const;
|
||||
|
||||
private:
|
||||
int getMatchingCondBranchOpcode(int Opc, bool sense) const;
|
||||
|
41
lib/Target/Hexagon/HexagonMCInst.h
Normal file
41
lib/Target/Hexagon/HexagonMCInst.h
Normal file
@ -0,0 +1,41 @@
|
||||
//===- 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 annotation.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef HEXAGONMCINST_H
|
||||
#define HEXAGONMCINST_H
|
||||
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
|
||||
namespace llvm {
|
||||
class HexagonMCInst: public MCInst {
|
||||
// Packet start and end markers
|
||||
unsigned startPacket: 1, endPacket: 1;
|
||||
const MachineInstr *MachineI;
|
||||
public:
|
||||
explicit HexagonMCInst(): MCInst(),
|
||||
startPacket(0), endPacket(0) {}
|
||||
|
||||
const MachineInstr* getMI() const { return MachineI; };
|
||||
|
||||
void setMI(const MachineInstr *MI) { MachineI = MI; };
|
||||
|
||||
bool isStartPacket() const { return (startPacket); };
|
||||
bool isEndPacket() const { return (endPacket); };
|
||||
|
||||
void setStartPacket(bool yes) { startPacket = yes; };
|
||||
void setEndPacket(bool yes) { endPacket = yes; };
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -49,7 +49,7 @@ void llvm::HexagonLowerToMC(const MachineInstr* MI, MCInst& MCI,
|
||||
switch (MO.getType()) {
|
||||
default:
|
||||
MI->dump();
|
||||
assert(0 && "unknown operand type");
|
||||
llvm_unreachable("unknown operand type");
|
||||
case MachineOperand::MO_Register:
|
||||
// Ignore all implicit register operands.
|
||||
if (MO.isImplicit()) continue;
|
||||
|
@ -111,7 +111,6 @@ bool HexagonPassConfig::addPreRegAlloc() {
|
||||
if (!DisableHardwareLoops) {
|
||||
PM->add(createHexagonHardwareLoops());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -138,5 +137,8 @@ bool HexagonPassConfig::addPreEmitPass() {
|
||||
// Split up TFRcondsets into conditional transfers.
|
||||
PM->add(createHexagonSplitTFRCondSets(getHexagonTargetMachine()));
|
||||
|
||||
// Create Packets.
|
||||
PM->add(createHexagonPacketizer());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
3646
lib/Target/Hexagon/HexagonVLIWPacketizer.cpp
Normal file
3646
lib/Target/Hexagon/HexagonVLIWPacketizer.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -15,6 +15,7 @@
|
||||
#include "Hexagon.h"
|
||||
#include "HexagonAsmPrinter.h"
|
||||
#include "HexagonInstPrinter.h"
|
||||
#include "HexagonMCInst.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
@ -37,20 +38,50 @@ StringRef HexagonInstPrinter::getRegName(unsigned RegNo) const {
|
||||
|
||||
void HexagonInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
|
||||
StringRef Annot) {
|
||||
printInst((const HexagonMCInst*)(MI), O, Annot);
|
||||
}
|
||||
|
||||
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) {
|
||||
MCInst Nop;
|
||||
// Ending a harware loop is different from ending an regular packet.
|
||||
assert(MI->isEndPacket() && "Loop end must also end the packet");
|
||||
|
||||
O << packetPadding << startPacket << '\n';
|
||||
Nop.setOpcode(Hexagon::NOP);
|
||||
printInstruction(&Nop, O);
|
||||
O << packetPadding << endPacket;
|
||||
if (MI->isStartPacket()) {
|
||||
// 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());
|
||||
printInst (&Nop, O, NoAnnot);
|
||||
}
|
||||
|
||||
// Close the packet.
|
||||
if (MI->isEndPacket())
|
||||
O << packetPadding << endPacket;
|
||||
|
||||
printInstruction(MI, O);
|
||||
}
|
||||
else {
|
||||
// Prefix the insn opening the packet.
|
||||
if (MI->isStartPacket())
|
||||
O << packetPadding << startPacket << '\n';
|
||||
|
||||
printInstruction(MI, O);
|
||||
|
||||
// Suffix the insn closing the packet.
|
||||
if (MI->isEndPacket())
|
||||
// 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;
|
||||
}
|
||||
|
||||
printInstruction(MI, O);
|
||||
printAnnotation(O, Annot);
|
||||
}
|
||||
|
||||
@ -65,22 +96,22 @@ void HexagonInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
} else if(MO.isImm()) {
|
||||
printImmOperand(MI, OpNo, O);
|
||||
} else {
|
||||
assert(false && "Unknown operand");
|
||||
llvm_unreachable("Unknown operand");
|
||||
}
|
||||
}
|
||||
|
||||
void HexagonInstPrinter::printImmOperand
|
||||
(const MCInst *MI, unsigned OpNo, raw_ostream &O) const {
|
||||
void HexagonInstPrinter::printImmOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O) const {
|
||||
O << MI->getOperand(OpNo).getImm();
|
||||
}
|
||||
|
||||
void HexagonInstPrinter::printExtOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O) const {
|
||||
raw_ostream &O) const {
|
||||
O << MI->getOperand(OpNo).getImm();
|
||||
}
|
||||
|
||||
void HexagonInstPrinter::printUnsignedImmOperand
|
||||
(const MCInst *MI, unsigned OpNo, raw_ostream &O) const {
|
||||
void HexagonInstPrinter::printUnsignedImmOperand(const MCInst *MI,
|
||||
unsigned OpNo, raw_ostream &O) const {
|
||||
O << MI->getOperand(OpNo).getImm();
|
||||
}
|
||||
|
||||
@ -89,13 +120,13 @@ void HexagonInstPrinter::printNegImmOperand(const MCInst *MI, unsigned OpNo,
|
||||
O << -MI->getOperand(OpNo).getImm();
|
||||
}
|
||||
|
||||
void HexagonInstPrinter::printNOneImmOperand
|
||||
(const MCInst *MI, unsigned OpNo, raw_ostream &O) const {
|
||||
void HexagonInstPrinter::printNOneImmOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O) const {
|
||||
O << -1;
|
||||
}
|
||||
|
||||
void HexagonInstPrinter::printMEMriOperand
|
||||
(const MCInst *MI, unsigned OpNo, raw_ostream &O) const {
|
||||
void HexagonInstPrinter::printMEMriOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O) const {
|
||||
const MCOperand& MO0 = MI->getOperand(OpNo);
|
||||
const MCOperand& MO1 = MI->getOperand(OpNo + 1);
|
||||
|
||||
@ -103,8 +134,8 @@ void HexagonInstPrinter::printMEMriOperand
|
||||
O << " + #" << MO1.getImm();
|
||||
}
|
||||
|
||||
void HexagonInstPrinter::printFrameIndexOperand
|
||||
(const MCInst *MI, unsigned OpNo, raw_ostream &O) const {
|
||||
void HexagonInstPrinter::printFrameIndexOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O) const {
|
||||
const MCOperand& MO0 = MI->getOperand(OpNo);
|
||||
const MCOperand& MO1 = MI->getOperand(OpNo + 1);
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
#ifndef HEXAGONINSTPRINTER_H
|
||||
#define HEXAGONINSTPRINTER_H
|
||||
|
||||
#include "HexagonMCInst.h"
|
||||
#include "llvm/MC/MCInstPrinter.h"
|
||||
|
||||
namespace llvm {
|
||||
@ -25,6 +26,7 @@ namespace llvm {
|
||||
: MCInstPrinter(MAI, MII, MRI) {}
|
||||
|
||||
virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
|
||||
void printInst(const HexagonMCInst *MI, raw_ostream &O, StringRef Annot);
|
||||
virtual StringRef getOpcodeName(unsigned Opcode) const;
|
||||
void printInstruction(const MCInst *MI, raw_ostream &O);
|
||||
StringRef getRegName(unsigned RegNo) const;
|
||||
@ -33,16 +35,16 @@ namespace llvm {
|
||||
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) const;
|
||||
void printImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) const;
|
||||
void printExtOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) const;
|
||||
void printUnsignedImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
|
||||
const;
|
||||
void printUnsignedImmOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O) const;
|
||||
void printNegImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
|
||||
const;
|
||||
void printNOneImmOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
|
||||
const;
|
||||
void printMEMriOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
|
||||
const;
|
||||
void printFrameIndexOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
|
||||
const;
|
||||
void printFrameIndexOperand(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O) const;
|
||||
void printBranchOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
|
||||
const;
|
||||
void printCallOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O)
|
||||
@ -55,7 +57,8 @@ namespace llvm {
|
||||
const;
|
||||
void printJumpTable(const MCInst *MI, unsigned OpNo, raw_ostream &O) const;
|
||||
|
||||
void printConstantPool(const MCInst *MI, unsigned OpNo, raw_ostream &O) const;
|
||||
void printConstantPool(const MCInst *MI, unsigned OpNo,
|
||||
raw_ostream &O) const;
|
||||
|
||||
void printSymbolHi(const MCInst *MI, unsigned OpNo, raw_ostream &O) const
|
||||
{ printSymbol(MI, OpNo, O, true); }
|
||||
|
@ -23,14 +23,41 @@ namespace llvm {
|
||||
/// instruction info tracks.
|
||||
///
|
||||
namespace HexagonII {
|
||||
|
||||
// *** The code below must match HexagonInstrFormat*.td *** //
|
||||
|
||||
// Insn types.
|
||||
// *** Must match HexagonInstrFormat*.td ***
|
||||
enum Type {
|
||||
TypePSEUDO = 0,
|
||||
TypeALU32 = 1,
|
||||
TypeCR = 2,
|
||||
TypeJR = 3,
|
||||
TypeJ = 4,
|
||||
TypeLD = 5,
|
||||
TypeST = 6,
|
||||
TypeSYSTEM = 7,
|
||||
TypeXTYPE = 8,
|
||||
TypeMEMOP = 9,
|
||||
TypeNV = 10,
|
||||
TypePREFIX = 30, // Such as extenders.
|
||||
TypeMARKER = 31 // Such as end of a HW loop.
|
||||
};
|
||||
|
||||
|
||||
|
||||
// MCInstrDesc TSFlags
|
||||
// *** Must match HexagonInstrFormat*.td ***
|
||||
enum {
|
||||
// This 5-bit field describes the insn type.
|
||||
TypePos = 0,
|
||||
TypeMask = 0x1f,
|
||||
|
||||
// Solo instructions.
|
||||
SoloPos = 5,
|
||||
SoloMask = 0x1,
|
||||
|
||||
// Predicated instructions.
|
||||
PredicatedPos = 1,
|
||||
PredicatedPos = 6,
|
||||
PredicatedMask = 0x1
|
||||
};
|
||||
|
||||
|
17
test/CodeGen/Hexagon/dualstore.ll
Normal file
17
test/CodeGen/Hexagon/dualstore.ll
Normal file
@ -0,0 +1,17 @@
|
||||
; 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]+}}) = r{{[0-9]+}}
|
||||
; CHECK-NEXT: memw(r{{[0-9]+}} + #{{[0-9]+}}) = r{{[0-9]+}}
|
||||
; CHECK-NEXT: }
|
||||
|
||||
@Reg = global i32 0, align 4
|
||||
define i32 @main() nounwind {
|
||||
entry:
|
||||
%number= alloca i32, align 4
|
||||
store i32 500000, i32* %number, align 4
|
||||
%number1= alloca i32, align 4
|
||||
store i32 100000, i32* %number1, align 4
|
||||
ret i32 0
|
||||
}
|
||||
|
16
test/CodeGen/Hexagon/fusedandshift.ll
Normal file
16
test/CodeGen/Hexagon/fusedandshift.ll
Normal file
@ -0,0 +1,16 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
; Check that we generate fused logical and with shift instruction.
|
||||
|
||||
; CHECK: r{{[0-9]+}} = and(#15, lsr(r{{[0-9]+}}, #{{[0-9]+}})
|
||||
|
||||
define i32 @main(i16* %a, i16* %b) nounwind {
|
||||
entry:
|
||||
%0 = load i16* %a, align 2
|
||||
%conv1 = sext i16 %0 to i32
|
||||
%shr1 = ashr i32 %conv1, 3
|
||||
%and1 = and i32 %shr1, 15
|
||||
%conv2 = trunc i32 %and1 to i16
|
||||
store i16 %conv2, i16* %b, align 2
|
||||
ret i32 0
|
||||
}
|
||||
|
14
test/CodeGen/Hexagon/macint.ll
Normal file
14
test/CodeGen/Hexagon/macint.ll
Normal file
@ -0,0 +1,14 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
; Check that we generate integer multiply accumulate.
|
||||
|
||||
; CHECK: r{{[0-9]+}} += mpyi(r{{[0-9]+}}, r{{[0-9]+}})
|
||||
|
||||
define i32 @main(i32* %a, i32* %b) nounwind {
|
||||
entry:
|
||||
%0 = load i32* %a, align 4
|
||||
%div = udiv i32 %0, 10000
|
||||
%rem = urem i32 %div, 10
|
||||
store i32 %rem, i32* %b, align 4
|
||||
ret i32 0
|
||||
}
|
||||
|
22
test/CodeGen/Hexagon/newvaluestore.ll
Normal file
22
test/CodeGen/Hexagon/newvaluestore.ll
Normal file
@ -0,0 +1,22 @@
|
||||
; RUN: llc -march=hexagon -mcpu=hexagonv4 < %s | FileCheck %s
|
||||
; Check that we generate new value store packet in V4
|
||||
|
||||
@i = global i32 0, align 4
|
||||
@j = global i32 10, align 4
|
||||
@k = global i32 100, align 4
|
||||
|
||||
define i32 @main() nounwind {
|
||||
entry:
|
||||
; CHECK: memw(r{{[0-9]+}} + #{{[0-9]+}}) = r{{[0-9]+}}.new
|
||||
%number1 = alloca i32, align 4
|
||||
%number2 = alloca i32, align 4
|
||||
%number3 = alloca i32, align 4
|
||||
%0 = load i32 * @i, align 4
|
||||
store i32 %0, i32* %number1, align 4
|
||||
%1 = load i32 * @j, align 4
|
||||
store i32 %1, i32* %number2, align 4
|
||||
%2 = load i32 * @k, align 4
|
||||
store i32 %2, i32* %number3, align 4
|
||||
ret i32 %0
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user