Thumb2ITBlockPass.cpp revision ed338e80f92d6efa961d9f8c29239dde1507e683
106e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng//===-- Thumb2ITBlockPass.cpp - Insert Thumb IT blocks -----------*- C++ -*-===//
206e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng//
306e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng//                     The LLVM Compiler Infrastructure
406e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng//
506e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng// This file is distributed under the University of Illinois Open Source
606e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng// License. See LICENSE.TXT for details.
706e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng//
806e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng//===----------------------------------------------------------------------===//
906e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng
1006e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng#define DEBUG_TYPE "thumb2-it"
1106e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng#include "ARM.h"
1206e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng#include "ARMMachineFunctionInfo.h"
13ed338e80f92d6efa961d9f8c29239dde1507e683Evan Cheng#include "Thumb2InstrInfo.h"
1406e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng#include "llvm/CodeGen/MachineInstr.h"
1506e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng#include "llvm/CodeGen/MachineInstrBuilder.h"
1606e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng#include "llvm/CodeGen/MachineFunctionPass.h"
1706e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng#include "llvm/Support/Compiler.h"
1806e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng#include "llvm/ADT/Statistic.h"
1906e16587ebc81e43b42157fa3afcfd806b59b296Evan Chengusing namespace llvm;
2006e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng
2106e16587ebc81e43b42157fa3afcfd806b59b296Evan ChengSTATISTIC(NumITs,     "Number of IT blocks inserted");
2206e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng
2306e16587ebc81e43b42157fa3afcfd806b59b296Evan Chengnamespace {
2406e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng  struct VISIBILITY_HIDDEN Thumb2ITBlockPass : public MachineFunctionPass {
2506e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    static char ID;
2606e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    Thumb2ITBlockPass() : MachineFunctionPass(&ID) {}
2706e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng
28ed338e80f92d6efa961d9f8c29239dde1507e683Evan Cheng    const Thumb2InstrInfo *TII;
2906e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    ARMFunctionInfo *AFI;
3006e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng
3106e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    virtual bool runOnMachineFunction(MachineFunction &Fn);
3206e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng
3306e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    virtual const char *getPassName() const {
3406e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng      return "Thumb IT blocks insertion pass";
3506e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    }
3606e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng
3706e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng  private:
3806e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    bool InsertITBlocks(MachineBasicBlock &MBB);
3906e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng  };
4006e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng  char Thumb2ITBlockPass::ID = 0;
4106e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng}
4206e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng
43ed338e80f92d6efa961d9f8c29239dde1507e683Evan ChengARMCC::CondCodes getPredicate(const MachineInstr *MI,
44ed338e80f92d6efa961d9f8c29239dde1507e683Evan Cheng                              const Thumb2InstrInfo *TII) {
45ed338e80f92d6efa961d9f8c29239dde1507e683Evan Cheng  unsigned Opc = MI->getOpcode();
46ed338e80f92d6efa961d9f8c29239dde1507e683Evan Cheng  if (Opc == ARM::tBcc || Opc == ARM::t2Bcc)
47ed338e80f92d6efa961d9f8c29239dde1507e683Evan Cheng    return ARMCC::AL;
48ed338e80f92d6efa961d9f8c29239dde1507e683Evan Cheng  return TII->getPredicate(MI);
49ed338e80f92d6efa961d9f8c29239dde1507e683Evan Cheng}
50ed338e80f92d6efa961d9f8c29239dde1507e683Evan Cheng
5106e16587ebc81e43b42157fa3afcfd806b59b296Evan Chengbool Thumb2ITBlockPass::InsertITBlocks(MachineBasicBlock &MBB) {
5206e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng  bool Modified = false;
5306e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng
5406e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng  MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
5506e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng  while (MBBI != E) {
5606e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    MachineInstr *MI = &*MBBI;
57ed338e80f92d6efa961d9f8c29239dde1507e683Evan Cheng    ARMCC::CondCodes CC = getPredicate(MI, TII);
5806e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    if (CC == ARMCC::AL) {
5906e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng      ++MBBI;
6006e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng      continue;
6106e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    }
6206e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng
6306e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    // Insert an IT instruction.
6406e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    DebugLoc dl = MI->getDebugLoc();
6506e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT))
6606e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng      .addImm(CC);
6706e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    ++MBBI;
6806e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng
6906e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    // Finalize IT mask. If the following instruction is not predicated or it's
7006e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    // predicated on a condition that's not the same or the opposite of CC, then
7106e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    // the mask is 0x8.
7206e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC);
7306e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    unsigned Mask = 0x8;
7406e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    while (MBBI != E || (Mask & 1)) {
75ed338e80f92d6efa961d9f8c29239dde1507e683Evan Cheng      ARMCC::CondCodes NCC = getPredicate(&*MBBI, TII);
7606e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng      if (NCC == CC) {
7706e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng        Mask >>= 1;
7806e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng        Mask |= 0x8;
7906e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng      } else if (NCC == OCC) {
8006e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng        Mask >>= 1;
8106e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng      } else {
8206e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng        break;
8306e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng      }
8406e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng      ++MBBI;
8506e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    }
8606e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    MIB.addImm(Mask);
8706e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    Modified = true;
8806e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    ++NumITs;
8906e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng  }
9006e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng
9106e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng  return Modified;
9206e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng}
9306e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng
9406e16587ebc81e43b42157fa3afcfd806b59b296Evan Chengbool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) {
9506e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng  const TargetMachine &TM = Fn.getTarget();
9606e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng  AFI = Fn.getInfo<ARMFunctionInfo>();
97ed338e80f92d6efa961d9f8c29239dde1507e683Evan Cheng  TII = static_cast<const Thumb2InstrInfo*>(TM.getInstrInfo());
9806e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng
9906e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng  if (!AFI->isThumbFunction())
10006e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    return false;
10106e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng
10206e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng  bool Modified = false;
10306e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng  for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E;
10406e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng       ++MFI) {
10506e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    MachineBasicBlock &MBB = *MFI;
10606e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng    Modified |= InsertITBlocks(MBB);
10706e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng  }
10806e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng
10906e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng  return Modified;
11006e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng}
11106e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng
11206e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng/// createThumb2ITBlockPass - returns and instance of the Thumb IT blocks
11306e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng/// insertion pass.
11406e16587ebc81e43b42157fa3afcfd806b59b296Evan ChengFunctionPass *llvm::createThumb2ITBlockPass() {
11506e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng  return new Thumb2ITBlockPass();
11606e16587ebc81e43b42157fa3afcfd806b59b296Evan Cheng}
117