mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-15 20:29:48 +00:00
6d532d8860
Patch by Jyotsna Verma. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@156634 91177308-0d34-0410-b5e6-96231b3b80d8
262 lines
9.7 KiB
C++
262 lines
9.7 KiB
C++
//===---- HexagonOptimizeConstExt.cpp - Optimize Constant Extender Use ----===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This pass traverses through all the basic blocks in a functions and replaces
|
|
// constant extended instruction with their register equivalent if the same
|
|
// constant is being used by more than two instructions.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#define DEBUG_TYPE "xfer"
|
|
#include "llvm/CodeGen/MachineDominators.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/ADT/StringMap.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/ADT/SmallString.h"
|
|
#include "llvm/ADT/Twine.h"
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
#include "HexagonTargetMachine.h"
|
|
#include "HexagonConstExtInfo.h"
|
|
#include "llvm/CodeGen/MachineFunctionAnalysis.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#define DEBUG_TYPE "xfer"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
|
|
class HexagonOptimizeConstExt : public MachineFunctionPass {
|
|
HexagonTargetMachine& QTM;
|
|
const HexagonSubtarget &QST;
|
|
|
|
public:
|
|
static char ID;
|
|
HexagonOptimizeConstExt(HexagonTargetMachine& TM)
|
|
: MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) {}
|
|
|
|
const char *getPassName() const {
|
|
return "Remove sub-optimal uses of constant extenders";
|
|
}
|
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const {
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
|
AU.addRequired<MachineDominatorTree>();
|
|
AU.addPreserved<MachineDominatorTree>();
|
|
}
|
|
|
|
bool runOnMachineFunction(MachineFunction &Fn);
|
|
void removeConstExtFromMI (const HexagonInstrInfo *TII, MachineInstr* oldMI,
|
|
unsigned DestReg);
|
|
};
|
|
|
|
char HexagonOptimizeConstExt::ID = 0;
|
|
|
|
// Remove constant extended instructions with the corresponding non-extended
|
|
// instruction.
|
|
void HexagonOptimizeConstExt::removeConstExtFromMI (const HexagonInstrInfo *TII,
|
|
MachineInstr* oldMI,
|
|
unsigned DestReg) {
|
|
assert(HexagonConstExt::NonExtEquivalentExists(oldMI->getOpcode()) &&
|
|
"Non-extended equivalent instruction doesn't exist");
|
|
MachineBasicBlock *MBB = oldMI->getParent ();
|
|
int oldOpCode = oldMI->getOpcode();
|
|
unsigned short CExtOpNum = HexagonConstExt::getCExtOpNum(oldOpCode);
|
|
unsigned numOperands = oldMI->getNumOperands();
|
|
MachineInstrBuilder MIB = BuildMI(*MBB, oldMI, oldMI->getDebugLoc(),
|
|
TII->get(HexagonConstExt::getNonExtOpcode(oldMI->getOpcode())));
|
|
|
|
for (unsigned i = 0; i < numOperands; ++i) {
|
|
if (i == CExtOpNum) {
|
|
MIB.addReg(DestReg);
|
|
if (oldMI->getDesc().mayLoad()) {
|
|
// As of now, only absolute addressing mode instructions can load from
|
|
// global addresses. Other addressing modes allow only constant
|
|
// literals. Load with absolute addressing mode gets replaced with the
|
|
// corresponding base+offset load.
|
|
if (oldMI->getOperand(i).isGlobal()) {
|
|
MIB.addImm(oldMI->getOperand(i).getOffset());
|
|
}
|
|
else
|
|
MIB.addImm(0);
|
|
}
|
|
else if (oldMI->getDesc().mayStore()){
|
|
if (oldMI->getOperand(i).isGlobal()) {
|
|
// If stored value is a global address and is extended, it is required
|
|
// to have 0 offset.
|
|
if (CExtOpNum == (numOperands-1))
|
|
assert((oldMI->getOperand(i).getOffset()==0) && "Invalid Offset");
|
|
else
|
|
MIB.addImm(oldMI->getOperand(i).getOffset());
|
|
}
|
|
else if (CExtOpNum != (numOperands-1))
|
|
MIB.addImm(0);
|
|
}
|
|
}
|
|
else {
|
|
const MachineOperand &op = oldMI->getOperand(i);
|
|
MIB.addOperand(op);
|
|
}
|
|
}
|
|
DEBUG(dbgs () << "Removing old instr: " << *oldMI << "\n");
|
|
DEBUG(dbgs() << "New instr: " << (*MIB) << "\n");
|
|
oldMI->eraseFromParent();
|
|
}
|
|
|
|
// Returns false for the following instructions, since it may not be profitable
|
|
// to convert these instructions into a non-extended instruction if the offset
|
|
// is non-zero.
|
|
static bool canHaveAnyOffset(MachineInstr* MI) {
|
|
switch (MI->getOpcode()) {
|
|
case Hexagon::STriw_offset_ext_V4:
|
|
case Hexagon::STrih_offset_ext_V4:
|
|
return false;
|
|
default:
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool HexagonOptimizeConstExt::runOnMachineFunction(MachineFunction &Fn) {
|
|
|
|
const HexagonInstrInfo *TII = QTM.getInstrInfo();
|
|
MachineDominatorTree &MDT = getAnalysis<MachineDominatorTree>();
|
|
|
|
// CExtMap maintains a list of instructions for each constant extended value.
|
|
// It also keeps a flag for the value to indicate if it's a global address
|
|
// or a constant literal.
|
|
StringMap<std::pair<SmallVector<MachineInstr*, 8>, bool > > CExtMap;
|
|
|
|
// Loop over all the basic blocks
|
|
for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end();
|
|
MBBb != MBBe; ++MBBb) {
|
|
MachineBasicBlock* MBB = MBBb;
|
|
|
|
// Traverse the basic block and update a map of (ImmValue->MI)
|
|
MachineBasicBlock::iterator MII = MBB->begin();
|
|
MachineBasicBlock::iterator MIE = MBB->end ();
|
|
|
|
while (MII != MIE) {
|
|
MachineInstr *MI = MII;
|
|
// Check if the instruction has any constant extended operand and also has
|
|
// a non-extended equivalent.
|
|
if (TII->isConstExtended(MI) &&
|
|
HexagonConstExt::NonExtEquivalentExists(MI->getOpcode())) {
|
|
short ExtOpNum = HexagonConstExt::getCExtOpNum(MI->getOpcode());
|
|
SmallString<256> TmpData;
|
|
if (MI->getOperand(ExtOpNum).isImm()) {
|
|
DEBUG(dbgs() << "Selected for replacement : " << *MI << "\n");
|
|
int ImmValue = MI->getOperand(ExtOpNum).getImm();
|
|
StringRef ExtValue = Twine(ImmValue).toStringRef(TmpData);
|
|
CExtMap[ExtValue].first.push_back(MI);
|
|
CExtMap[ExtValue].second = false;
|
|
}
|
|
else if (MI->getOperand(ExtOpNum).isGlobal()) {
|
|
StringRef ExtValue = MI->getOperand(ExtOpNum).getGlobal()->getName();
|
|
// If stored value is constant extended and has an offset, it's not
|
|
// profitable to replace these instructions with the non-extended
|
|
// version.
|
|
if (MI->getOperand(ExtOpNum).getOffset() == 0
|
|
|| canHaveAnyOffset(MI)) {
|
|
DEBUG(dbgs() << "Selected for replacement : " << *MI << "\n");
|
|
CExtMap[ExtValue].first.push_back(MI);
|
|
CExtMap[ExtValue].second = true;
|
|
}
|
|
}
|
|
}
|
|
++MII;
|
|
} // While ends
|
|
}
|
|
|
|
enum OpType {imm, GlobalAddr};
|
|
// Process the constants that have been extended.
|
|
for (StringMap<std::pair<SmallVector<MachineInstr*, 8>, bool> >::iterator II=
|
|
CExtMap.begin(), IE = CExtMap.end(); II != IE; ++II) {
|
|
|
|
SmallVector<MachineInstr*, 8> &MIList = (*II).second.first;
|
|
|
|
// Replace the constant extended instructions with the non-extended
|
|
// equivalent if more than 2 instructions extend the same constant value.
|
|
if (MIList.size() <= 2)
|
|
continue;
|
|
|
|
bool ExtOpType = (*II).second.second;
|
|
StringRef ExtValue = (*II).getKeyData();
|
|
const GlobalValue *GV = NULL;
|
|
unsigned char TargetFlags=0;
|
|
int ExtOpNum = HexagonConstExt::getCExtOpNum(MIList[0]->getOpcode());
|
|
SmallVector<MachineBasicBlock*, 8> MachineBlocks;
|
|
|
|
if (ExtOpType == GlobalAddr) {
|
|
GV = MIList[0]->getOperand(ExtOpNum).getGlobal();
|
|
TargetFlags = MIList[0]->getOperand(ExtOpNum).getTargetFlags();
|
|
}
|
|
|
|
// For each instruction in the list, record the block it belongs to.
|
|
for (SmallVector<MachineInstr*, 8>::iterator LB = MIList.begin(),
|
|
LE = MIList.end(); LB != LE; ++LB) {
|
|
MachineInstr *MI = (*LB);
|
|
MachineBlocks.push_back (MI->getParent());
|
|
}
|
|
|
|
MachineBasicBlock* CommDomBlock = MachineBlocks[0];
|
|
MachineBasicBlock* oldCommDomBlock = NULL;
|
|
// replaceMIs is the list of instructions to be replaced with a
|
|
// non-extended equivalent instruction.
|
|
// The idea here is that not all the instructions in the MIList will
|
|
// be replaced with a register.
|
|
SmallVector<MachineInstr*, 8> replaceMIs;
|
|
replaceMIs.push_back(MIList[0]);
|
|
|
|
for (unsigned i= 1; i < MachineBlocks.size(); ++i) {
|
|
oldCommDomBlock = CommDomBlock;
|
|
MachineBasicBlock *BB = MachineBlocks[i];
|
|
CommDomBlock = MDT.findNearestCommonDominator(&(*CommDomBlock),
|
|
&(*BB));
|
|
if (!CommDomBlock) {
|
|
CommDomBlock = oldCommDomBlock;
|
|
break;
|
|
}
|
|
replaceMIs.push_back(MIList[i]);
|
|
}
|
|
|
|
// Insert into CommDomBlock.
|
|
if (CommDomBlock) {
|
|
unsigned DestReg = TII->createVR (CommDomBlock->getParent(), MVT::i32);
|
|
MachineInstr *firstMI = CommDomBlock->getFirstNonPHI();
|
|
if (ExtOpType == imm) {
|
|
int ImmValue = 0;
|
|
ExtValue.getAsInteger(10,ImmValue);
|
|
BuildMI (*CommDomBlock, firstMI, firstMI->getDebugLoc(),
|
|
TII->get(Hexagon::TFRI), DestReg)
|
|
.addImm(ImmValue);
|
|
}
|
|
else {
|
|
BuildMI (*CommDomBlock, firstMI, firstMI->getDebugLoc(),
|
|
TII->get(Hexagon::TFRI_V4), DestReg)
|
|
.addGlobalAddress(GV, 0, TargetFlags);
|
|
}
|
|
for (unsigned i= 0; i < replaceMIs.size(); i++) {
|
|
MachineInstr *oldMI = replaceMIs[i];
|
|
removeConstExtFromMI(TII, oldMI, DestReg);
|
|
}
|
|
replaceMIs.clear();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Public Constructor Functions
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
FunctionPass *
|
|
llvm::createHexagonOptimizeConstExt(HexagonTargetMachine &TM) {
|
|
return new HexagonOptimizeConstExt(TM);
|
|
}
|
|
|