1 //===-- Thumb2ITBlockPass.cpp - Insert Thumb IT blocks -----------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #define DEBUG_TYPE "thumb2-it" 11 #include "ARM.h" 12 #include "ARMMachineFunctionInfo.h" 13 #include "Thumb2InstrInfo.h" 14 #include "llvm/CodeGen/MachineInstr.h" 15 #include "llvm/CodeGen/MachineInstrBuilder.h" 16 #include "llvm/CodeGen/MachineFunctionPass.h" 17 #include "llvm/Support/Compiler.h" 18 #include "llvm/ADT/Statistic.h" 19 using namespace llvm; 20 21 STATISTIC(NumITs, "Number of IT blocks inserted"); 22 23 namespace { 24 struct VISIBILITY_HIDDEN Thumb2ITBlockPass : public MachineFunctionPass { 25 static char ID; 26 Thumb2ITBlockPass() : MachineFunctionPass(&ID) {} 27 28 const Thumb2InstrInfo *TII; 29 ARMFunctionInfo *AFI; 30 31 virtual bool runOnMachineFunction(MachineFunction &Fn); 32 33 virtual const char *getPassName() const { 34 return "Thumb IT blocks insertion pass"; 35 } 36 37 private: 38 bool InsertITBlocks(MachineBasicBlock &MBB); 39 }; 40 char Thumb2ITBlockPass::ID = 0; 41 } 42 43 static ARMCC::CondCodes getPredicate(const MachineInstr *MI, 44 const Thumb2InstrInfo *TII) { 45 unsigned Opc = MI->getOpcode(); 46 if (Opc == ARM::tBcc || Opc == ARM::t2Bcc) 47 return ARMCC::AL; 48 return TII->getPredicate(MI); 49 } 50 51 bool Thumb2ITBlockPass::InsertITBlocks(MachineBasicBlock &MBB) { 52 bool Modified = false; 53 54 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 55 while (MBBI != E) { 56 MachineInstr *MI = &*MBBI; 57 ARMCC::CondCodes CC = getPredicate(MI, TII); 58 if (CC == ARMCC::AL) { 59 ++MBBI; 60 continue; 61 } 62 63 // Insert an IT instruction. 64 DebugLoc dl = MI->getDebugLoc(); 65 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT)) 66 .addImm(CC); 67 ++MBBI; 68 69 // Finalize IT mask. 70 ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC); 71 unsigned Mask = 0, Pos = 3; 72 while (MBBI != E && Pos) { 73 ARMCC::CondCodes NCC = getPredicate(&*MBBI, TII); 74 if (NCC == OCC) { 75 Mask |= (1 << Pos); 76 } else if (NCC != CC) 77 break; 78 --Pos; 79 ++MBBI; 80 } 81 Mask |= (1 << Pos); 82 MIB.addImm(Mask); 83 Modified = true; 84 ++NumITs; 85 } 86 87 return Modified; 88 } 89 90 bool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) { 91 const TargetMachine &TM = Fn.getTarget(); 92 AFI = Fn.getInfo<ARMFunctionInfo>(); 93 TII = static_cast<const Thumb2InstrInfo*>(TM.getInstrInfo()); 94 95 if (!AFI->isThumbFunction()) 96 return false; 97 98 bool Modified = false; 99 for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; 100 ++MFI) { 101 MachineBasicBlock &MBB = *MFI; 102 Modified |= InsertITBlocks(MBB); 103 } 104 105 return Modified; 106 } 107 108 /// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks 109 /// insertion pass. 110 FunctionPass *llvm::createThumb2ITBlockPass() { 111 return new Thumb2ITBlockPass(); 112 } 113