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//===----------------------------------------------------------------------===//
--- 91 unchanged lines hidden (view full) ---
100 { ARM::t2SXTBr, ARM::tSXTB, 0, 0, 0, 1, 0, 1,0, 0 },
101 { ARM::t2SXTHr, ARM::tSXTH, 0, 0, 0, 1, 0, 1,0, 0 },
102 { ARM::t2TSTrr, ARM::tTST, 0, 0, 0, 1, 0, 2,0, 0 },
103 { ARM::t2UXTBr, ARM::tUXTB, 0, 0, 0, 1, 0, 1,0, 0 },
104 { ARM::t2UXTHr, ARM::tUXTH, 0, 0, 0, 1, 0, 1,0, 0 },
105
106 // FIXME: Clean this up after splitting each Thumb load / store opcode
107 // into multiple ones.
108 { ARM::t2LDRi12,ARM::tLDR, 0, 5, 0, 1, 0, 0,0, 1 },
109 { ARM::t2LDRs, ARM::tLDR, 0, 0, 0, 1, 0, 0,0, 1 },
110 { ARM::t2LDRBi12,ARM::tLDRB, 0, 5, 0, 1, 0, 0,0, 1 },
111 { ARM::t2LDRBs, ARM::tLDRB, 0, 0, 0, 1, 0, 0,0, 1 },
112 { ARM::t2LDRHi12,ARM::tLDRH, 0, 5, 0, 1, 0, 0,0, 1 },
113 { ARM::t2LDRHs, ARM::tLDRH, 0, 0, 0, 1, 0, 0,0, 1 },
114 { ARM::t2LDRSBs,ARM::tLDRSB, 0, 0, 0, 1, 0, 0,0, 1 },
115 { ARM::t2LDRSHs,ARM::tLDRSH, 0, 0, 0, 1, 0, 0,0, 1 },
116 { ARM::t2STRi12,ARM::tSTR, 0, 5, 0, 1, 0, 0,0, 1 },
117 { ARM::t2STRs, ARM::tSTR, 0, 0, 0, 1, 0, 0,0, 1 },
118 { ARM::t2STRBi12,ARM::tSTRB, 0, 5, 0, 1, 0, 0,0, 1 },
119 { ARM::t2STRBs, ARM::tSTRB, 0, 0, 0, 1, 0, 0,0, 1 },
120 { ARM::t2STRHi12,ARM::tSTRH, 0, 5, 0, 1, 0, 0,0, 1 },
121 { ARM::t2STRHs, ARM::tSTRH, 0, 0, 0, 1, 0, 0,0, 1 },
122
123 { ARM::t2LDM_RET,0, ARM::tPOP_RET, 0, 0, 1, 1, 1,1, 1 },
124 { ARM::t2LDM, ARM::tLDM, ARM::tPOP, 0, 0, 1, 1, 1,1, 1 },
--- 114 unchanged lines hidden (view full) ---
239 continue;
240 unsigned Reg = MO.getReg();
241 if (Reg == 0 || Reg == ARM::CPSR)
242 continue;
243 if (isPCOk && Reg == ARM::PC)
244 continue;
245 if (isLROk && Reg == ARM::LR)
246 continue;
247 if (isSPOk && Reg == ARM::SP)
248 continue;
249 if (!isARMLowRegister(Reg))
250 return false;
251 }
252 return true;
253}
254
255bool
256Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
257 const ReduceEntry &Entry) {
258 if (ReduceLimitLdSt != -1 && ((int)NumLdSts >= ReduceLimitLdSt))
259 return false;
260
261 unsigned Scale = 1;
262 bool HasImmOffset = false;
263 bool HasShift = false;
264 bool isLdStMul = false;
265 unsigned Opc = Entry.NarrowOpc1;
266 unsigned OpNum = 3; // First 'rest' of operands.
267 switch (Entry.WideOpc) {
268 default:
269 llvm_unreachable("Unexpected Thumb2 load / store opcode!");
270 case ARM::t2LDRi12:
271 case ARM::t2STRi12:
272 Scale = 4;
273 HasImmOffset = true;
274 break;
275 case ARM::t2LDRBi12:
276 case ARM::t2STRBi12:
277 HasImmOffset = true;
278 break;
279 case ARM::t2LDRHi12:
280 case ARM::t2STRHi12:
281 Scale = 2;
282 HasImmOffset = true;
--- 37 unchanged lines hidden (view full) ---
320 if (MI->getOperand(3).getImm())
321 // Thumb1 addressing mode doesn't support shift.
322 return false;
323 }
324
325 unsigned OffsetImm = 0;
326 if (HasImmOffset) {
327 OffsetImm = MI->getOperand(2).getImm();
328 unsigned MaxOffset = ((1 << Entry.Imm1Limit) - 1) * Scale;
329 if ((OffsetImm & (Scale-1)) || OffsetImm > MaxOffset)
330 // Make sure the immediate field fits.
331 return false;
332 }
333
334 // Add the 16-bit load / store instruction.
335 // FIXME: Thumb1 addressing mode encode both immediate and register offset.
336 DebugLoc dl = MI->getDebugLoc();
337 MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, TII->get(Opc));
338 if (!isLdStMul) {
339 MIB.addOperand(MI->getOperand(0)).addOperand(MI->getOperand(1));
340 if (Entry.NarrowOpc1 != ARM::tLDRSB && Entry.NarrowOpc1 != ARM::tLDRSH) {
341 // tLDRSB and tLDRSH do not have an immediate offset field. On the other
342 // hand, it must have an offset register.
343 // FIXME: Remove this special case.
344 MIB.addImm(OffsetImm/Scale);
345 }
346 assert((!HasShift || OffsetReg) && "Invalid so_reg load / store address!");
347
348 MIB.addReg(OffsetReg, getKillRegState(OffsetKill));
349 }
350
351 // Transfer the rest of operands.
352 for (unsigned e = MI->getNumOperands(); OpNum != e; ++OpNum)
353 MIB.addOperand(MI->getOperand(OpNum));
354
355 DEBUG(errs() << "Converted 32-bit: " << *MI << " to 16-bit: " << *MIB);
356
357 MBB.erase(MI);
358 ++NumLdSts;
359 return true;
360}
361
362bool
--- 322 unchanged lines hidden ---
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//===----------------------------------------------------------------------===//
--- 91 unchanged lines hidden (view full) ---
100 { ARM::t2SXTBr, ARM::tSXTB, 0, 0, 0, 1, 0, 1,0, 0 },
101 { ARM::t2SXTHr, ARM::tSXTH, 0, 0, 0, 1, 0, 1,0, 0 },
102 { ARM::t2TSTrr, ARM::tTST, 0, 0, 0, 1, 0, 2,0, 0 },
103 { ARM::t2UXTBr, ARM::tUXTB, 0, 0, 0, 1, 0, 1,0, 0 },
104 { ARM::t2UXTHr, ARM::tUXTH, 0, 0, 0, 1, 0, 1,0, 0 },
105
106 // FIXME: Clean this up after splitting each Thumb load / store opcode
107 // into multiple ones.
108 { ARM::t2LDRi12,ARM::tLDR, 0, 5, 0, 1, 0, 0,0, 1 },
109 { ARM::t2LDRs, ARM::tLDR, 0, 0, 0, 1, 0, 0,0, 1 },
110 { ARM::t2LDRBi12,ARM::tLDRB, 0, 5, 0, 1, 0, 0,0, 1 },
111 { ARM::t2LDRBs, ARM::tLDRB, 0, 0, 0, 1, 0, 0,0, 1 },
112 { ARM::t2LDRHi12,ARM::tLDRH, 0, 5, 0, 1, 0, 0,0, 1 },
113 { ARM::t2LDRHs, ARM::tLDRH, 0, 0, 0, 1, 0, 0,0, 1 },
114 { ARM::t2LDRSBs,ARM::tLDRSB, 0, 0, 0, 1, 0, 0,0, 1 },
115 { ARM::t2LDRSHs,ARM::tLDRSH, 0, 0, 0, 1, 0, 0,0, 1 },
116 { ARM::t2STRi12,ARM::tSTR, 0, 5, 0, 1, 0, 0,0, 1 },
117 { ARM::t2STRs, ARM::tSTR, 0, 0, 0, 1, 0, 0,0, 1 },
118 { ARM::t2STRBi12,ARM::tSTRB, 0, 5, 0, 1, 0, 0,0, 1 },
119 { ARM::t2STRBs, ARM::tSTRB, 0, 0, 0, 1, 0, 0,0, 1 },
120 { ARM::t2STRHi12,ARM::tSTRH, 0, 5, 0, 1, 0, 0,0, 1 },
121 { ARM::t2STRHs, ARM::tSTRH, 0, 0, 0, 1, 0, 0,0, 1 },
122
123 { ARM::t2LDM_RET,0, ARM::tPOP_RET, 0, 0, 1, 1, 1,1, 1 },
124 { ARM::t2LDM, ARM::tLDM, ARM::tPOP, 0, 0, 1, 1, 1,1, 1 },
--- 114 unchanged lines hidden (view full) ---
239 continue;
240 unsigned Reg = MO.getReg();
241 if (Reg == 0 || Reg == ARM::CPSR)
242 continue;
243 if (isPCOk && Reg == ARM::PC)
244 continue;
245 if (isLROk && Reg == ARM::LR)
246 continue;
247 if (isSPOk && Reg == ARM::SP)
248 continue;
249 if (!isARMLowRegister(Reg))
250 return false;
251 }
252 return true;
253}
254
255bool
256Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
257 const ReduceEntry &Entry) {
258 if (ReduceLimitLdSt != -1 && ((int)NumLdSts >= ReduceLimitLdSt))
259 return false;
260
261 unsigned Scale = 1;
262 bool HasImmOffset = false;
263 bool HasShift = false;
264 bool isLdStMul = false;
265 unsigned Opc = Entry.NarrowOpc1;
266 unsigned OpNum = 3; // First 'rest' of operands.
267 switch (Entry.WideOpc) {
268 default:
269 llvm_unreachable("Unexpected Thumb2 load / store opcode!");
270 case ARM::t2LDRi12:
271 case ARM::t2STRi12:
272 Scale = 4;
273 HasImmOffset = true;
274 break;
275 case ARM::t2LDRBi12:
276 case ARM::t2STRBi12:
277 HasImmOffset = true;
278 break;
279 case ARM::t2LDRHi12:
280 case ARM::t2STRHi12:
281 Scale = 2;
282 HasImmOffset = true;
--- 37 unchanged lines hidden (view full) ---
320 if (MI->getOperand(3).getImm())
321 // Thumb1 addressing mode doesn't support shift.
322 return false;
323 }
324
325 unsigned OffsetImm = 0;
326 if (HasImmOffset) {
327 OffsetImm = MI->getOperand(2).getImm();
328 unsigned MaxOffset = ((1 << Entry.Imm1Limit) - 1) * Scale;
329 if ((OffsetImm & (Scale-1)) || OffsetImm > MaxOffset)
330 // Make sure the immediate field fits.
331 return false;
332 }
333
334 // Add the 16-bit load / store instruction.
335 // FIXME: Thumb1 addressing mode encode both immediate and register offset.
336 DebugLoc dl = MI->getDebugLoc();
337 MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, TII->get(Opc));
338 if (!isLdStMul) {
339 MIB.addOperand(MI->getOperand(0)).addOperand(MI->getOperand(1));
340 if (Entry.NarrowOpc1 != ARM::tLDRSB && Entry.NarrowOpc1 != ARM::tLDRSH) {
341 // tLDRSB and tLDRSH do not have an immediate offset field. On the other
342 // hand, it must have an offset register.
343 // FIXME: Remove this special case.
344 MIB.addImm(OffsetImm/Scale);
345 }
346 assert((!HasShift || OffsetReg) && "Invalid so_reg load / store address!");
347
348 MIB.addReg(OffsetReg, getKillRegState(OffsetKill));
349 }
350
351 // Transfer the rest of operands.
352 for (unsigned e = MI->getNumOperands(); OpNum != e; ++OpNum)
353 MIB.addOperand(MI->getOperand(OpNum));
354
355 DEBUG(errs() << "Converted 32-bit: " << *MI << " to 16-bit: " << *MIB);
356
357 MBB.erase(MI);
358 ++NumLdSts;
359 return true;
360}
361
362bool
--- 322 unchanged lines hidden ---