fix PR4984 by ensuring that fastisel adds properly sign extended GEP displacement
[oota-llvm.git] / lib / Target / ARM / Thumb2ITBlockPass.cpp
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 }