llvm-6502/lib/Target/ARM/Thumb2ITBlockPass.cpp
Evan Cheng b9803a8fa6 - Add pseudo instructions tLDRpci_pic and t2LDRpci_pic which does a pc-relative
load of a GV from constantpool and then add pc. It allows the code sequence to
  be rematerializable so it would be hoisted by machine licm.
- Add a late pass to break these pseudo instructions into a number of real
  instructions. Also move the code in Thumb2 IT pass that breaks up t2MOVi32imm
  to this pass. This is done before post regalloc scheduling to allow the
  scheduler to proper schedule these instructions. It also allow them to be
  if-converted and shrunk by later passes.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@86304 91177308-0d34-0410-b5e6-96231b3b80d8
2009-11-06 23:52:48 +00:00

120 lines
3.3 KiB
C++

//===-- Thumb2ITBlockPass.cpp - Insert Thumb IT blocks -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "thumb2-it"
#include "ARM.h"
#include "ARMMachineFunctionInfo.h"
#include "Thumb2InstrInfo.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;
STATISTIC(NumITs, "Number of IT blocks inserted");
namespace {
struct Thumb2ITBlockPass : public MachineFunctionPass {
static char ID;
Thumb2ITBlockPass() : MachineFunctionPass(&ID) {}
const Thumb2InstrInfo *TII;
ARMFunctionInfo *AFI;
virtual bool runOnMachineFunction(MachineFunction &Fn);
virtual const char *getPassName() const {
return "Thumb IT blocks insertion pass";
}
private:
bool InsertITBlocks(MachineBasicBlock &MBB);
};
char Thumb2ITBlockPass::ID = 0;
}
static ARMCC::CondCodes getPredicate(const MachineInstr *MI, unsigned &PredReg){
unsigned Opc = MI->getOpcode();
if (Opc == ARM::tBcc || Opc == ARM::t2Bcc)
return ARMCC::AL;
return llvm::getInstrPredicate(MI, PredReg);
}
bool Thumb2ITBlockPass::InsertITBlocks(MachineBasicBlock &MBB) {
bool Modified = false;
MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
while (MBBI != E) {
MachineInstr *MI = &*MBBI;
DebugLoc dl = MI->getDebugLoc();
unsigned PredReg = 0;
ARMCC::CondCodes CC = getPredicate(MI, PredReg);
if (CC == ARMCC::AL) {
++MBBI;
continue;
}
// Insert an IT instruction.
MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT))
.addImm(CC);
++MBBI;
// Finalize IT mask.
ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC);
unsigned Mask = 0, Pos = 3;
// Branches, including tricky ones like LDM_RET, need to end an IT
// block so check the instruction we just put in the block.
while (MBBI != E && Pos &&
(!MI->getDesc().isBranch() && !MI->getDesc().isReturn())) {
MachineInstr *NMI = &*MBBI;
MI = NMI;
DebugLoc ndl = NMI->getDebugLoc();
unsigned NPredReg = 0;
ARMCC::CondCodes NCC = getPredicate(NMI, NPredReg);
if (NCC == OCC) {
Mask |= (1 << Pos);
} else if (NCC != CC)
break;
--Pos;
++MBBI;
}
Mask |= (1 << Pos);
MIB.addImm(Mask);
Modified = true;
++NumITs;
}
return Modified;
}
bool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) {
const TargetMachine &TM = Fn.getTarget();
AFI = Fn.getInfo<ARMFunctionInfo>();
TII = static_cast<const Thumb2InstrInfo*>(TM.getInstrInfo());
if (!AFI->isThumbFunction())
return false;
bool Modified = false;
for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
++MFI) {
MachineBasicBlock &MBB = *MFI;
Modified |= InsertITBlocks(MBB);
}
return Modified;
}
/// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks
/// insertion pass.
FunctionPass *llvm::createThumb2ITBlockPass() {
return new Thumb2ITBlockPass();
}