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 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. If the following instruction is not predicated or it's 70 // predicated on a condition that's not the same or the opposite of CC, then 71 // the mask is 0x8. 72 ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC); 73 unsigned Mask = 0x8; 74 while (MBBI != E || (Mask & 1)) { 75 ARMCC::CondCodes NCC = getPredicate(&*MBBI, TII); 76 if (NCC == CC) { 77 Mask >>= 1; 78 Mask |= 0x8; 79 } else if (NCC == OCC) { 80 Mask >>= 1; 81 } else { 82 break; 83 } 84 ++MBBI; 85 } 86 MIB.addImm(Mask); 87 Modified = true; 88 ++NumITs; 89 } 90 91 return Modified; 92 } 93 94 bool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) { 95 const TargetMachine &TM = Fn.getTarget(); 96 AFI = Fn.getInfo<ARMFunctionInfo>(); 97 TII = static_cast<const Thumb2InstrInfo*>(TM.getInstrInfo()); 98 99 if (!AFI->isThumbFunction()) 100 return false; 101 102 bool Modified = false; 103 for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; 104 ++MFI) { 105 MachineBasicBlock &MBB = *MFI; 106 Modified |= InsertITBlocks(MBB); 107 } 108 109 return Modified; 110 } 111 112 /// createThumb2ITBlockPass - returns and instance of the Thumb IT blocks 113 /// insertion pass. 114 FunctionPass *llvm::createThumb2ITBlockPass() { 115 return new Thumb2ITBlockPass(); 116 } 117