~louis/ubuntu/trusty/clamav/lp799623_fix_logrotate

« back to all changes in this revision

Viewing changes to libclamav/c++/llvm/lib/Target/ARM/Thumb2SizeReduction.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2010-03-12 11:30:04 UTC
  • mfrom: (0.41.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100312113004-b0fop4bkycszdd0z
Tags: 0.96~rc1+dfsg-0ubuntu1
* New upstream RC - FFE (LP: #537636):
  - Add OfficialDatabaseOnly option to clamav-base.postinst.in
  - Add LocalSocketGroup option to clamav-base.postinst.in
  - Add LocalSocketMode option to clamav-base.postinst.in
  - Add CrossFilesystems option to clamav-base.postinst.in
  - Add ClamukoScannerCount option to clamav-base.postinst.in
  - Add BytecodeSecurity opiton to clamav-base.postinst.in
  - Add DetectionStatsHostID option to clamav-freshclam.postinst.in
  - Add Bytecode option to clamav-freshclam.postinst.in
  - Add MilterSocketGroup option to clamav-milter.postinst.in
  - Add MilterSocketMode option to clamav-milter.postinst.in
  - Add ReportHostname option to clamav-milter.postinst.in
  - Bump libclamav SO version to 6.1.0 in libclamav6.install
  - Drop clamdmon from clamav.examples (no longer shipped by upstream)
  - Drop libclamav.a from libclamav-dev.install (not built by upstream)
  - Update SO version for lintian override for libclamav6
  - Add new Bytecode Testing Tool, usr/bin/clambc, to clamav.install
  - Add build-depends on python and python-setuptools for new test suite
  - Update debian/copyright for the embedded copy of llvm (using the system
    llvm is not currently feasible)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//===-- Thumb2SizeReduction.cpp - Thumb2 code size reduction pass -*- 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 "t2-reduce-size"
 
11
#include "ARM.h"
 
12
#include "ARMAddressingModes.h"
 
13
#include "ARMBaseRegisterInfo.h"
 
14
#include "ARMBaseInstrInfo.h"
 
15
#include "Thumb2InstrInfo.h"
 
16
#include "llvm/CodeGen/MachineInstr.h"
 
17
#include "llvm/CodeGen/MachineInstrBuilder.h"
 
18
#include "llvm/CodeGen/MachineFunctionPass.h"
 
19
#include "llvm/Support/CommandLine.h"
 
20
#include "llvm/Support/Debug.h"
 
21
#include "llvm/Support/raw_ostream.h"
 
22
#include "llvm/ADT/DenseMap.h"
 
23
#include "llvm/ADT/Statistic.h"
 
24
using namespace llvm;
 
25
 
 
26
STATISTIC(NumNarrows,  "Number of 32-bit instrs reduced to 16-bit ones");
 
27
STATISTIC(Num2Addrs,   "Number of 32-bit instrs reduced to 2addr 16-bit ones");
 
28
STATISTIC(NumLdSts,    "Number of 32-bit load / store reduced to 16-bit ones");
 
29
 
 
30
static cl::opt<int> ReduceLimit("t2-reduce-limit",
 
31
                                cl::init(-1), cl::Hidden);
 
32
static cl::opt<int> ReduceLimit2Addr("t2-reduce-limit2",
 
33
                                     cl::init(-1), cl::Hidden);
 
34
static cl::opt<int> ReduceLimitLdSt("t2-reduce-limit3",
 
35
                                     cl::init(-1), cl::Hidden);
 
36
 
 
37
namespace {
 
38
  /// ReduceTable - A static table with information on mapping from wide
 
39
  /// opcodes to narrow
 
40
  struct ReduceEntry {
 
41
    unsigned WideOpc;      // Wide opcode
 
42
    unsigned NarrowOpc1;   // Narrow opcode to transform to
 
43
    unsigned NarrowOpc2;   // Narrow opcode when it's two-address
 
44
    uint8_t  Imm1Limit;    // Limit of immediate field (bits)
 
45
    uint8_t  Imm2Limit;    // Limit of immediate field when it's two-address
 
46
    unsigned LowRegs1 : 1; // Only possible if low-registers are used
 
47
    unsigned LowRegs2 : 1; // Only possible if low-registers are used (2addr)
 
48
    unsigned PredCC1  : 2; // 0 - If predicated, cc is on and vice versa.
 
49
                           // 1 - No cc field.
 
50
                           // 2 - Always set CPSR.
 
51
    unsigned PredCC2  : 2;
 
52
    unsigned Special  : 1; // Needs to be dealt with specially
 
53
  };
 
54
 
 
55
  static const ReduceEntry ReduceTable[] = {
 
56
    // Wide,        Narrow1,      Narrow2,     imm1,imm2,  lo1, lo2, P/C, S
 
57
    { ARM::t2ADCrr, 0,            ARM::tADC,     0,   0,    0,   1,  0,0, 0 },
 
58
    { ARM::t2ADDri, ARM::tADDi3,  ARM::tADDi8,   3,   8,    1,   1,  0,0, 0 },
 
59
    { ARM::t2ADDrr, ARM::tADDrr,  ARM::tADDhirr, 0,   0,    1,   0,  0,1, 0 },
 
60
    // Note: immediate scale is 4.
 
61
    { ARM::t2ADDrSPi,ARM::tADDrSPi,0,            8,   0,    1,   0,  1,0, 0 },
 
62
    { ARM::t2ADDSri,ARM::tADDi3,  ARM::tADDi8,   3,   8,    1,   1,  2,2, 1 },
 
63
    { ARM::t2ADDSrr,ARM::tADDrr,  0,             0,   0,    1,   0,  2,0, 1 },
 
64
    { ARM::t2ANDrr, 0,            ARM::tAND,     0,   0,    0,   1,  0,0, 0 },
 
65
    { ARM::t2ASRri, ARM::tASRri,  0,             5,   0,    1,   0,  0,0, 0 },
 
66
    { ARM::t2ASRrr, 0,            ARM::tASRrr,   0,   0,    0,   1,  0,0, 0 },
 
67
    { ARM::t2BICrr, 0,            ARM::tBIC,     0,   0,    0,   1,  0,0, 0 },
 
68
    //FIXME: Disable CMN, as CCodes are backwards from compare expectations
 
69
    //{ ARM::t2CMNrr, ARM::tCMN,    0,             0,   0,    1,   0,  2,0, 0 },
 
70
    { ARM::t2CMPri, ARM::tCMPi8,  0,             8,   0,    1,   0,  2,0, 0 },
 
71
    { ARM::t2CMPrr, ARM::tCMPhir, 0,             0,   0,    0,   0,  2,0, 0 },
 
72
    { ARM::t2CMPzri,ARM::tCMPzi8, 0,             8,   0,    1,   0,  2,0, 0 },
 
73
    { ARM::t2CMPzrr,ARM::tCMPzhir,0,             0,   0,    0,   0,  2,0, 0 },
 
74
    { ARM::t2EORrr, 0,            ARM::tEOR,     0,   0,    0,   1,  0,0, 0 },
 
75
    // FIXME: adr.n immediate offset must be multiple of 4.
 
76
    //{ ARM::t2LEApcrelJT,ARM::tLEApcrelJT, 0,     0,   0,    1,   0,  1,0, 0 },
 
77
    { ARM::t2LSLri, ARM::tLSLri,  0,             5,   0,    1,   0,  0,0, 0 },
 
78
    { ARM::t2LSLrr, 0,            ARM::tLSLrr,   0,   0,    0,   1,  0,0, 0 },
 
79
    { ARM::t2LSRri, ARM::tLSRri,  0,             5,   0,    1,   0,  0,0, 0 },
 
80
    { ARM::t2LSRrr, 0,            ARM::tLSRrr,   0,   0,    0,   1,  0,0, 0 },
 
81
    { ARM::t2MOVi,  ARM::tMOVi8,  0,             8,   0,    1,   0,  0,0, 0 },
 
82
    { ARM::t2MOVi16,ARM::tMOVi8,  0,             8,   0,    1,   0,  0,0, 1 },
 
83
    // FIXME: Do we need the 16-bit 'S' variant?
 
84
    { ARM::t2MOVr,ARM::tMOVgpr2gpr,0,            0,   0,    0,   0,  1,0, 0 },
 
85
    { ARM::t2MOVCCr,0,            ARM::tMOVCCr,  0,   0,    0,   0,  0,1, 0 },
 
86
    { ARM::t2MOVCCi,0,            ARM::tMOVCCi,  0,   8,    0,   1,  0,1, 0 },
 
87
    { ARM::t2MUL,   0,            ARM::tMUL,     0,   0,    0,   1,  0,0, 0 },
 
88
    { ARM::t2MVNr,  ARM::tMVN,    0,             0,   0,    1,   0,  0,0, 0 },
 
89
    { ARM::t2ORRrr, 0,            ARM::tORR,     0,   0,    0,   1,  0,0, 0 },
 
90
    { ARM::t2REV,   ARM::tREV,    0,             0,   0,    1,   0,  1,0, 0 },
 
91
    { ARM::t2REV16, ARM::tREV16,  0,             0,   0,    1,   0,  1,0, 0 },
 
92
    { ARM::t2REVSH, ARM::tREVSH,  0,             0,   0,    1,   0,  1,0, 0 },
 
93
    { ARM::t2RORrr, 0,            ARM::tROR,     0,   0,    0,   1,  0,0, 0 },
 
94
    { ARM::t2RSBri, ARM::tRSB,    0,             0,   0,    1,   0,  0,0, 1 },
 
95
    { ARM::t2RSBSri,ARM::tRSB,    0,             0,   0,    1,   0,  2,0, 1 },
 
96
    { ARM::t2SBCrr, 0,            ARM::tSBC,     0,   0,    0,   1,  0,0, 0 },
 
97
    { ARM::t2SUBri, ARM::tSUBi3,  ARM::tSUBi8,   3,   8,    1,   1,  0,0, 0 },
 
98
    { ARM::t2SUBrr, ARM::tSUBrr,  0,             0,   0,    1,   0,  0,0, 0 },
 
99
    { ARM::t2SUBSri,ARM::tSUBi3,  ARM::tSUBi8,   3,   8,    1,   1,  2,2, 0 },
 
100
    { ARM::t2SUBSrr,ARM::tSUBrr,  0,             0,   0,    1,   0,  2,0, 0 },
 
101
    { ARM::t2SXTBr, ARM::tSXTB,   0,             0,   0,    1,   0,  1,0, 0 },
 
102
    { ARM::t2SXTHr, ARM::tSXTH,   0,             0,   0,    1,   0,  1,0, 0 },
 
103
    { ARM::t2TSTrr, ARM::tTST,    0,             0,   0,    1,   0,  2,0, 0 },
 
104
    { ARM::t2UXTBr, ARM::tUXTB,   0,             0,   0,    1,   0,  1,0, 0 },
 
105
    { ARM::t2UXTHr, ARM::tUXTH,   0,             0,   0,    1,   0,  1,0, 0 },
 
106
 
 
107
    // FIXME: Clean this up after splitting each Thumb load / store opcode
 
108
    // into multiple ones.
 
109
    { ARM::t2LDRi12,ARM::tLDR,    ARM::tLDRspi,  5,   8,    1,   0,  0,0, 1 },
 
110
    { ARM::t2LDRs,  ARM::tLDR,    0,             0,   0,    1,   0,  0,0, 1 },
 
111
    { ARM::t2LDRBi12,ARM::tLDRB,  0,             5,   0,    1,   0,  0,0, 1 },
 
112
    { ARM::t2LDRBs, ARM::tLDRB,   0,             0,   0,    1,   0,  0,0, 1 },
 
113
    { ARM::t2LDRHi12,ARM::tLDRH,  0,             5,   0,    1,   0,  0,0, 1 },
 
114
    { ARM::t2LDRHs, ARM::tLDRH,   0,             0,   0,    1,   0,  0,0, 1 },
 
115
    { ARM::t2LDRSBs,ARM::tLDRSB,  0,             0,   0,    1,   0,  0,0, 1 },
 
116
    { ARM::t2LDRSHs,ARM::tLDRSH,  0,             0,   0,    1,   0,  0,0, 1 },
 
117
    { ARM::t2STRi12,ARM::tSTR,    ARM::tSTRspi,  5,   8,    1,   0,  0,0, 1 },
 
118
    { ARM::t2STRs,  ARM::tSTR,    0,             0,   0,    1,   0,  0,0, 1 },
 
119
    { ARM::t2STRBi12,ARM::tSTRB,  0,             5,   0,    1,   0,  0,0, 1 },
 
120
    { ARM::t2STRBs, ARM::tSTRB,   0,             0,   0,    1,   0,  0,0, 1 },
 
121
    { ARM::t2STRHi12,ARM::tSTRH,  0,             5,   0,    1,   0,  0,0, 1 },
 
122
    { ARM::t2STRHs, ARM::tSTRH,   0,             0,   0,    1,   0,  0,0, 1 },
 
123
 
 
124
    { ARM::t2LDM_RET,0,           ARM::tPOP_RET, 0,   0,    1,   1,  1,1, 1 },
 
125
    { ARM::t2LDM,   ARM::tLDM,    ARM::tPOP,     0,   0,    1,   1,  1,1, 1 },
 
126
    { ARM::t2STM,   ARM::tSTM,    ARM::tPUSH,    0,   0,    1,   1,  1,1, 1 },
 
127
  };
 
128
 
 
129
  class Thumb2SizeReduce : public MachineFunctionPass {
 
130
  public:
 
131
    static char ID;
 
132
    Thumb2SizeReduce();
 
133
 
 
134
    const Thumb2InstrInfo *TII;
 
135
 
 
136
    virtual bool runOnMachineFunction(MachineFunction &MF);
 
137
 
 
138
    virtual const char *getPassName() const {
 
139
      return "Thumb2 instruction size reduction pass";
 
140
    }
 
141
 
 
142
  private:
 
143
    /// ReduceOpcodeMap - Maps wide opcode to index of entry in ReduceTable.
 
144
    DenseMap<unsigned, unsigned> ReduceOpcodeMap;
 
145
 
 
146
    bool VerifyPredAndCC(MachineInstr *MI, const ReduceEntry &Entry,
 
147
                         bool is2Addr, ARMCC::CondCodes Pred,
 
148
                         bool LiveCPSR, bool &HasCC, bool &CCDead);
 
149
 
 
150
    bool ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
 
151
                         const ReduceEntry &Entry);
 
152
 
 
153
    bool ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI,
 
154
                       const ReduceEntry &Entry, bool LiveCPSR);
 
155
 
 
156
    /// ReduceTo2Addr - Reduce a 32-bit instruction to a 16-bit two-address
 
157
    /// instruction.
 
158
    bool ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI,
 
159
                       const ReduceEntry &Entry,
 
160
                       bool LiveCPSR);
 
161
 
 
162
    /// ReduceToNarrow - Reduce a 32-bit instruction to a 16-bit
 
163
    /// non-two-address instruction.
 
164
    bool ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI,
 
165
                        const ReduceEntry &Entry,
 
166
                        bool LiveCPSR);
 
167
 
 
168
    /// ReduceMBB - Reduce width of instructions in the specified basic block.
 
169
    bool ReduceMBB(MachineBasicBlock &MBB);
 
170
  };
 
171
  char Thumb2SizeReduce::ID = 0;
 
172
}
 
173
 
 
174
Thumb2SizeReduce::Thumb2SizeReduce() : MachineFunctionPass(&ID) {
 
175
  for (unsigned i = 0, e = array_lengthof(ReduceTable); i != e; ++i) {
 
176
    unsigned FromOpc = ReduceTable[i].WideOpc;
 
177
    if (!ReduceOpcodeMap.insert(std::make_pair(FromOpc, i)).second)
 
178
      assert(false && "Duplicated entries?");
 
179
  }
 
180
}
 
181
 
 
182
static bool HasImplicitCPSRDef(const TargetInstrDesc &TID) {
 
183
  for (const unsigned *Regs = TID.ImplicitDefs; *Regs; ++Regs)
 
184
    if (*Regs == ARM::CPSR)
 
185
      return true;
 
186
  return false;
 
187
}
 
188
 
 
189
bool
 
190
Thumb2SizeReduce::VerifyPredAndCC(MachineInstr *MI, const ReduceEntry &Entry,
 
191
                                  bool is2Addr, ARMCC::CondCodes Pred,
 
192
                                  bool LiveCPSR, bool &HasCC, bool &CCDead) {
 
193
  if ((is2Addr  && Entry.PredCC2 == 0) ||
 
194
      (!is2Addr && Entry.PredCC1 == 0)) {
 
195
    if (Pred == ARMCC::AL) {
 
196
      // Not predicated, must set CPSR.
 
197
      if (!HasCC) {
 
198
        // Original instruction was not setting CPSR, but CPSR is not
 
199
        // currently live anyway. It's ok to set it. The CPSR def is
 
200
        // dead though.
 
201
        if (!LiveCPSR) {
 
202
          HasCC = true;
 
203
          CCDead = true;
 
204
          return true;
 
205
        }
 
206
        return false;
 
207
      }
 
208
    } else {
 
209
      // Predicated, must not set CPSR.
 
210
      if (HasCC)
 
211
        return false;
 
212
    }
 
213
  } else if ((is2Addr  && Entry.PredCC2 == 2) ||
 
214
             (!is2Addr && Entry.PredCC1 == 2)) {
 
215
    /// Old opcode has an optional def of CPSR.
 
216
    if (HasCC)
 
217
      return true;
 
218
    // If both old opcode does not implicit CPSR def, then it's not ok since
 
219
    // these new opcodes CPSR def is not meant to be thrown away. e.g. CMP.
 
220
    if (!HasImplicitCPSRDef(MI->getDesc()))
 
221
      return false;
 
222
    HasCC = true;
 
223
  } else {
 
224
    // 16-bit instruction does not set CPSR.
 
225
    if (HasCC)
 
226
      return false;
 
227
  }
 
228
 
 
229
  return true;
 
230
}
 
231
 
 
232
static bool VerifyLowRegs(MachineInstr *MI) {
 
233
  unsigned Opc = MI->getOpcode();
 
234
  bool isPCOk = (Opc == ARM::t2LDM_RET) || (Opc == ARM::t2LDM);
 
235
  bool isLROk = (Opc == ARM::t2STM);
 
236
  bool isSPOk = isPCOk || isLROk || (Opc == ARM::t2ADDrSPi);
 
237
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
 
238
    const MachineOperand &MO = MI->getOperand(i);
 
239
    if (!MO.isReg() || MO.isImplicit())
 
240
      continue;
 
241
    unsigned Reg = MO.getReg();
 
242
    if (Reg == 0 || Reg == ARM::CPSR)
 
243
      continue;
 
244
    if (isPCOk && Reg == ARM::PC)
 
245
      continue;
 
246
    if (isLROk && Reg == ARM::LR)
 
247
      continue;
 
248
    if (Reg == ARM::SP) {
 
249
      if (isSPOk)
 
250
        continue;
 
251
      if (i == 1 && (Opc == ARM::t2LDRi12 || Opc == ARM::t2STRi12))
 
252
        // Special case for these ldr / str with sp as base register.
 
253
        continue;
 
254
    }
 
255
    if (!isARMLowRegister(Reg))
 
256
      return false;
 
257
  }
 
258
  return true;
 
259
}
 
260
 
 
261
bool
 
262
Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
 
263
                                  const ReduceEntry &Entry) {
 
264
  if (ReduceLimitLdSt != -1 && ((int)NumLdSts >= ReduceLimitLdSt))
 
265
    return false;
 
266
 
 
267
  unsigned Scale = 1;
 
268
  bool HasImmOffset = false;
 
269
  bool HasShift = false;
 
270
  bool HasOffReg = true;
 
271
  bool isLdStMul = false;
 
272
  unsigned Opc = Entry.NarrowOpc1;
 
273
  unsigned OpNum = 3; // First 'rest' of operands.
 
274
  uint8_t  ImmLimit = Entry.Imm1Limit;
 
275
  switch (Entry.WideOpc) {
 
276
  default:
 
277
    llvm_unreachable("Unexpected Thumb2 load / store opcode!");
 
278
  case ARM::t2LDRi12:
 
279
  case ARM::t2STRi12: {
 
280
    unsigned BaseReg = MI->getOperand(1).getReg();
 
281
    if (BaseReg == ARM::SP) {
 
282
      Opc = Entry.NarrowOpc2;
 
283
      ImmLimit = Entry.Imm2Limit;
 
284
      HasOffReg = false;
 
285
    }
 
286
    Scale = 4;
 
287
    HasImmOffset = true;
 
288
    break;
 
289
  }
 
290
  case ARM::t2LDRBi12:
 
291
  case ARM::t2STRBi12:
 
292
    HasImmOffset = true;
 
293
    break;
 
294
  case ARM::t2LDRHi12:
 
295
  case ARM::t2STRHi12:
 
296
    Scale = 2;
 
297
    HasImmOffset = true;
 
298
    break;
 
299
  case ARM::t2LDRs:
 
300
  case ARM::t2LDRBs:
 
301
  case ARM::t2LDRHs:
 
302
  case ARM::t2LDRSBs:
 
303
  case ARM::t2LDRSHs:
 
304
  case ARM::t2STRs:
 
305
  case ARM::t2STRBs:
 
306
  case ARM::t2STRHs:
 
307
    HasShift = true;
 
308
    OpNum = 4;
 
309
    break;
 
310
  case ARM::t2LDM_RET:
 
311
  case ARM::t2LDM:
 
312
  case ARM::t2STM: {
 
313
    OpNum = 0;
 
314
    unsigned BaseReg = MI->getOperand(0).getReg();
 
315
    unsigned Mode = MI->getOperand(1).getImm();
 
316
    if (BaseReg == ARM::SP && ARM_AM::getAM4WBFlag(Mode)) {
 
317
      Opc = Entry.NarrowOpc2;
 
318
      OpNum = 2;
 
319
    } else if (Entry.WideOpc == ARM::t2LDM_RET ||
 
320
               !isARMLowRegister(BaseReg) ||
 
321
               !ARM_AM::getAM4WBFlag(Mode) ||
 
322
               ARM_AM::getAM4SubMode(Mode) != ARM_AM::ia) {
 
323
      return false;
 
324
    }
 
325
    isLdStMul = true;
 
326
    break;
 
327
  }
 
328
  }
 
329
 
 
330
  unsigned OffsetReg = 0;
 
331
  bool OffsetKill = false;
 
332
  if (HasShift) {
 
333
    OffsetReg  = MI->getOperand(2).getReg();
 
334
    OffsetKill = MI->getOperand(2).isKill();
 
335
    if (MI->getOperand(3).getImm())
 
336
      // Thumb1 addressing mode doesn't support shift.
 
337
      return false;
 
338
  }
 
339
 
 
340
  unsigned OffsetImm = 0;
 
341
  if (HasImmOffset) {
 
342
    OffsetImm = MI->getOperand(2).getImm();
 
343
    unsigned MaxOffset = ((1 << ImmLimit) - 1) * Scale;
 
344
    if ((OffsetImm & (Scale-1)) || OffsetImm > MaxOffset)
 
345
      // Make sure the immediate field fits.
 
346
      return false;
 
347
  }
 
348
 
 
349
  // Add the 16-bit load / store instruction.
 
350
  // FIXME: Thumb1 addressing mode encode both immediate and register offset.
 
351
  DebugLoc dl = MI->getDebugLoc();
 
352
  MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, TII->get(Opc));
 
353
  if (!isLdStMul) {
 
354
    MIB.addOperand(MI->getOperand(0)).addOperand(MI->getOperand(1));
 
355
    if (Opc != ARM::tLDRSB && Opc != ARM::tLDRSH) {
 
356
      // tLDRSB and tLDRSH do not have an immediate offset field. On the other
 
357
      // hand, it must have an offset register.
 
358
      // FIXME: Remove this special case.
 
359
      MIB.addImm(OffsetImm/Scale);
 
360
    }
 
361
    assert((!HasShift || OffsetReg) && "Invalid so_reg load / store address!");
 
362
 
 
363
    if (HasOffReg)
 
364
      MIB.addReg(OffsetReg, getKillRegState(OffsetKill));
 
365
  }
 
366
 
 
367
  // Transfer the rest of operands.
 
368
  for (unsigned e = MI->getNumOperands(); OpNum != e; ++OpNum)
 
369
    MIB.addOperand(MI->getOperand(OpNum));
 
370
 
 
371
  // Transfer memoperands.
 
372
  (*MIB).setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
 
373
 
 
374
  DEBUG(errs() << "Converted 32-bit: " << *MI << "       to 16-bit: " << *MIB);
 
375
 
 
376
  MBB.erase(MI);
 
377
  ++NumLdSts;
 
378
  return true;
 
379
}
 
380
 
 
381
bool
 
382
Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI,
 
383
                                const ReduceEntry &Entry,
 
384
                                bool LiveCPSR) {
 
385
  if (Entry.LowRegs1 && !VerifyLowRegs(MI))
 
386
    return false;
 
387
 
 
388
  const TargetInstrDesc &TID = MI->getDesc();
 
389
  if (TID.mayLoad() || TID.mayStore())
 
390
    return ReduceLoadStore(MBB, MI, Entry);
 
391
 
 
392
  unsigned Opc = MI->getOpcode();
 
393
  switch (Opc) {
 
394
  default: break;
 
395
  case ARM::t2ADDSri: 
 
396
  case ARM::t2ADDSrr: {
 
397
    unsigned PredReg = 0;
 
398
    if (getInstrPredicate(MI, PredReg) == ARMCC::AL) {
 
399
      switch (Opc) {
 
400
      default: break;
 
401
      case ARM::t2ADDSri: {
 
402
        if (ReduceTo2Addr(MBB, MI, Entry, LiveCPSR))
 
403
          return true;
 
404
        // fallthrough
 
405
      }
 
406
      case ARM::t2ADDSrr:
 
407
        return ReduceToNarrow(MBB, MI, Entry, LiveCPSR);
 
408
      }
 
409
    }
 
410
    break;
 
411
  }
 
412
  case ARM::t2RSBri:
 
413
  case ARM::t2RSBSri:
 
414
    if (MI->getOperand(2).getImm() == 0)
 
415
      return ReduceToNarrow(MBB, MI, Entry, LiveCPSR);
 
416
    break;
 
417
  case ARM::t2MOVi16:
 
418
    // Can convert only 'pure' immediate operands, not immediates obtained as
 
419
    // globals' addresses.
 
420
    if (MI->getOperand(1).isImm())
 
421
      return ReduceToNarrow(MBB, MI, Entry, LiveCPSR);
 
422
    break;
 
423
  }
 
424
  return false;
 
425
}
 
426
 
 
427
bool
 
428
Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI,
 
429
                                const ReduceEntry &Entry,
 
430
                                bool LiveCPSR) {
 
431
 
 
432
  if (ReduceLimit2Addr != -1 && ((int)Num2Addrs >= ReduceLimit2Addr))
 
433
    return false;
 
434
 
 
435
  const TargetInstrDesc &TID = MI->getDesc();
 
436
  unsigned Reg0 = MI->getOperand(0).getReg();
 
437
  unsigned Reg1 = MI->getOperand(1).getReg();
 
438
  if (Reg0 != Reg1)
 
439
    return false;
 
440
  if (Entry.LowRegs2 && !isARMLowRegister(Reg0))
 
441
    return false;
 
442
  if (Entry.Imm2Limit) {
 
443
    unsigned Imm = MI->getOperand(2).getImm();
 
444
    unsigned Limit = (1 << Entry.Imm2Limit) - 1;
 
445
    if (Imm > Limit)
 
446
      return false;
 
447
  } else {
 
448
    unsigned Reg2 = MI->getOperand(2).getReg();
 
449
    if (Entry.LowRegs2 && !isARMLowRegister(Reg2))
 
450
      return false;
 
451
  }
 
452
 
 
453
  // Check if it's possible / necessary to transfer the predicate.
 
454
  const TargetInstrDesc &NewTID = TII->get(Entry.NarrowOpc2);
 
455
  unsigned PredReg = 0;
 
456
  ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg);
 
457
  bool SkipPred = false;
 
458
  if (Pred != ARMCC::AL) {
 
459
    if (!NewTID.isPredicable())
 
460
      // Can't transfer predicate, fail.
 
461
      return false;
 
462
  } else {
 
463
    SkipPred = !NewTID.isPredicable();
 
464
  }
 
465
 
 
466
  bool HasCC = false;
 
467
  bool CCDead = false;
 
468
  if (TID.hasOptionalDef()) {
 
469
    unsigned NumOps = TID.getNumOperands();
 
470
    HasCC = (MI->getOperand(NumOps-1).getReg() == ARM::CPSR);
 
471
    if (HasCC && MI->getOperand(NumOps-1).isDead())
 
472
      CCDead = true;
 
473
  }
 
474
  if (!VerifyPredAndCC(MI, Entry, true, Pred, LiveCPSR, HasCC, CCDead))
 
475
    return false;
 
476
 
 
477
  // Add the 16-bit instruction.
 
478
  DebugLoc dl = MI->getDebugLoc();
 
479
  MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, NewTID);
 
480
  MIB.addOperand(MI->getOperand(0));
 
481
  if (NewTID.hasOptionalDef()) {
 
482
    if (HasCC)
 
483
      AddDefaultT1CC(MIB, CCDead);
 
484
    else
 
485
      AddNoT1CC(MIB);
 
486
  }
 
487
 
 
488
  // Transfer the rest of operands.
 
489
  unsigned NumOps = TID.getNumOperands();
 
490
  for (unsigned i = 1, e = MI->getNumOperands(); i != e; ++i) {
 
491
    if (i < NumOps && TID.OpInfo[i].isOptionalDef())
 
492
      continue;
 
493
    if (SkipPred && TID.OpInfo[i].isPredicate())
 
494
      continue;
 
495
    MIB.addOperand(MI->getOperand(i));
 
496
  }
 
497
 
 
498
  DEBUG(errs() << "Converted 32-bit: " << *MI << "       to 16-bit: " << *MIB);
 
499
 
 
500
  MBB.erase(MI);
 
501
  ++Num2Addrs;
 
502
  return true;
 
503
}
 
504
 
 
505
bool
 
506
Thumb2SizeReduce::ReduceToNarrow(MachineBasicBlock &MBB, MachineInstr *MI,
 
507
                                 const ReduceEntry &Entry,
 
508
                                 bool LiveCPSR) {
 
509
  if (ReduceLimit != -1 && ((int)NumNarrows >= ReduceLimit))
 
510
    return false;
 
511
 
 
512
  unsigned Limit = ~0U;
 
513
  unsigned Scale = (Entry.WideOpc == ARM::t2ADDrSPi) ? 4 : 1;
 
514
  if (Entry.Imm1Limit)
 
515
    Limit = ((1 << Entry.Imm1Limit) - 1) * Scale;
 
516
 
 
517
  const TargetInstrDesc &TID = MI->getDesc();
 
518
  for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) {
 
519
    if (TID.OpInfo[i].isPredicate())
 
520
      continue;
 
521
    const MachineOperand &MO = MI->getOperand(i);
 
522
    if (MO.isReg()) {
 
523
      unsigned Reg = MO.getReg();
 
524
      if (!Reg || Reg == ARM::CPSR)
 
525
        continue;
 
526
      if (Entry.WideOpc == ARM::t2ADDrSPi && Reg == ARM::SP)
 
527
        continue;
 
528
      if (Entry.LowRegs1 && !isARMLowRegister(Reg))
 
529
        return false;
 
530
    } else if (MO.isImm() &&
 
531
               !TID.OpInfo[i].isPredicate()) {
 
532
      if (((unsigned)MO.getImm()) > Limit || (MO.getImm() & (Scale-1)) != 0)
 
533
        return false;
 
534
    }
 
535
  }
 
536
 
 
537
  // Check if it's possible / necessary to transfer the predicate.
 
538
  const TargetInstrDesc &NewTID = TII->get(Entry.NarrowOpc1);
 
539
  unsigned PredReg = 0;
 
540
  ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg);
 
541
  bool SkipPred = false;
 
542
  if (Pred != ARMCC::AL) {
 
543
    if (!NewTID.isPredicable())
 
544
      // Can't transfer predicate, fail.
 
545
      return false;
 
546
  } else {
 
547
    SkipPred = !NewTID.isPredicable();
 
548
  }
 
549
 
 
550
  bool HasCC = false;
 
551
  bool CCDead = false;
 
552
  if (TID.hasOptionalDef()) {
 
553
    unsigned NumOps = TID.getNumOperands();
 
554
    HasCC = (MI->getOperand(NumOps-1).getReg() == ARM::CPSR);
 
555
    if (HasCC && MI->getOperand(NumOps-1).isDead())
 
556
      CCDead = true;
 
557
  }
 
558
  if (!VerifyPredAndCC(MI, Entry, false, Pred, LiveCPSR, HasCC, CCDead))
 
559
    return false;
 
560
 
 
561
  // Add the 16-bit instruction.
 
562
  DebugLoc dl = MI->getDebugLoc();
 
563
  MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, NewTID);
 
564
  MIB.addOperand(MI->getOperand(0));
 
565
  if (NewTID.hasOptionalDef()) {
 
566
    if (HasCC)
 
567
      AddDefaultT1CC(MIB, CCDead);
 
568
    else
 
569
      AddNoT1CC(MIB);
 
570
  }
 
571
 
 
572
  // Transfer the rest of operands.
 
573
  unsigned NumOps = TID.getNumOperands();
 
574
  for (unsigned i = 1, e = MI->getNumOperands(); i != e; ++i) {
 
575
    if (i < NumOps && TID.OpInfo[i].isOptionalDef())
 
576
      continue;
 
577
    if ((TID.getOpcode() == ARM::t2RSBSri ||
 
578
         TID.getOpcode() == ARM::t2RSBri) && i == 2)
 
579
      // Skip the zero immediate operand, it's now implicit.
 
580
      continue;
 
581
    bool isPred = (i < NumOps && TID.OpInfo[i].isPredicate());
 
582
    if (SkipPred && isPred)
 
583
        continue;
 
584
    const MachineOperand &MO = MI->getOperand(i);
 
585
    if (Scale > 1 && !isPred && MO.isImm())
 
586
      MIB.addImm(MO.getImm() / Scale);
 
587
    else {
 
588
      if (MO.isReg() && MO.isImplicit() && MO.getReg() == ARM::CPSR)
 
589
        // Skip implicit def of CPSR. Either it's modeled as an optional
 
590
        // def now or it's already an implicit def on the new instruction.
 
591
        continue;
 
592
      MIB.addOperand(MO);
 
593
    }
 
594
  }
 
595
  if (!TID.isPredicable() && NewTID.isPredicable())
 
596
    AddDefaultPred(MIB);
 
597
 
 
598
  DEBUG(errs() << "Converted 32-bit: " << *MI << "       to 16-bit: " << *MIB);
 
599
 
 
600
  MBB.erase(MI);
 
601
  ++NumNarrows;
 
602
  return true;
 
603
}
 
604
 
 
605
static bool UpdateCPSRDef(MachineInstr &MI, bool LiveCPSR) {
 
606
  bool HasDef = false;
 
607
  for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
 
608
    const MachineOperand &MO = MI.getOperand(i);
 
609
    if (!MO.isReg() || MO.isUndef() || MO.isUse())
 
610
      continue;
 
611
    if (MO.getReg() != ARM::CPSR)
 
612
      continue;
 
613
    if (!MO.isDead())
 
614
      HasDef = true;
 
615
  }
 
616
 
 
617
  return HasDef || LiveCPSR;
 
618
}
 
619
 
 
620
static bool UpdateCPSRUse(MachineInstr &MI, bool LiveCPSR) {
 
621
  for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
 
622
    const MachineOperand &MO = MI.getOperand(i);
 
623
    if (!MO.isReg() || MO.isUndef() || MO.isDef())
 
624
      continue;
 
625
    if (MO.getReg() != ARM::CPSR)
 
626
      continue;
 
627
    assert(LiveCPSR && "CPSR liveness tracking is wrong!");
 
628
    if (MO.isKill()) {
 
629
      LiveCPSR = false;
 
630
      break;
 
631
    }
 
632
  }
 
633
 
 
634
  return LiveCPSR;
 
635
}
 
636
 
 
637
bool Thumb2SizeReduce::ReduceMBB(MachineBasicBlock &MBB) {
 
638
  bool Modified = false;
 
639
 
 
640
  bool LiveCPSR = false;
 
641
  // Yes, CPSR could be livein.
 
642
  for (MachineBasicBlock::const_livein_iterator I = MBB.livein_begin(),
 
643
         E = MBB.livein_end(); I != E; ++I) {
 
644
    if (*I == ARM::CPSR) {
 
645
      LiveCPSR = true;
 
646
      break;
 
647
    }
 
648
  }
 
649
 
 
650
  MachineBasicBlock::iterator MII = MBB.begin(), E = MBB.end();
 
651
  MachineBasicBlock::iterator NextMII;
 
652
  for (; MII != E; MII = NextMII) {
 
653
    NextMII = llvm::next(MII);
 
654
 
 
655
    MachineInstr *MI = &*MII;
 
656
    LiveCPSR = UpdateCPSRUse(*MI, LiveCPSR);
 
657
 
 
658
    unsigned Opcode = MI->getOpcode();
 
659
    DenseMap<unsigned, unsigned>::iterator OPI = ReduceOpcodeMap.find(Opcode);
 
660
    if (OPI != ReduceOpcodeMap.end()) {
 
661
      const ReduceEntry &Entry = ReduceTable[OPI->second];
 
662
      // Ignore "special" cases for now.
 
663
      if (Entry.Special) {
 
664
        if (ReduceSpecial(MBB, MI, Entry, LiveCPSR)) {
 
665
          Modified = true;
 
666
          MachineBasicBlock::iterator I = prior(NextMII);
 
667
          MI = &*I;
 
668
        }
 
669
        goto ProcessNext;
 
670
      }
 
671
 
 
672
      // Try to transform to a 16-bit two-address instruction.
 
673
      if (Entry.NarrowOpc2 && ReduceTo2Addr(MBB, MI, Entry, LiveCPSR)) {
 
674
        Modified = true;
 
675
        MachineBasicBlock::iterator I = prior(NextMII);
 
676
        MI = &*I;
 
677
        goto ProcessNext;
 
678
      }
 
679
 
 
680
      // Try to transform ro a 16-bit non-two-address instruction.
 
681
      if (Entry.NarrowOpc1 && ReduceToNarrow(MBB, MI, Entry, LiveCPSR)) {
 
682
        Modified = true;
 
683
        MachineBasicBlock::iterator I = prior(NextMII);
 
684
        MI = &*I;
 
685
      }
 
686
    }
 
687
 
 
688
  ProcessNext:
 
689
    LiveCPSR = UpdateCPSRDef(*MI, LiveCPSR);
 
690
  }
 
691
 
 
692
  return Modified;
 
693
}
 
694
 
 
695
bool Thumb2SizeReduce::runOnMachineFunction(MachineFunction &MF) {
 
696
  const TargetMachine &TM = MF.getTarget();
 
697
  TII = static_cast<const Thumb2InstrInfo*>(TM.getInstrInfo());
 
698
 
 
699
  bool Modified = false;
 
700
  for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
 
701
    Modified |= ReduceMBB(*I);
 
702
  return Modified;
 
703
}
 
704
 
 
705
/// createThumb2SizeReductionPass - Returns an instance of the Thumb2 size
 
706
/// reduction pass.
 
707
FunctionPass *llvm::createThumb2SizeReductionPass() {
 
708
  return new Thumb2SizeReduce();
 
709
}