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, ARM::tLDRspi, 5, 8, 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, ARM::tSTRspi, 5, 8, 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 (Reg == ARM::SP) { 248 if (isSPOk) 249 continue; 250 if (i == 1 && (Opc == ARM::t2LDRi12 || Opc == ARM::t2STRi12)) 251 // Special case for these ldr / str with sp as base register. 252 continue; 253 } |
254 if (!isARMLowRegister(Reg)) 255 return false; 256 } 257 return true; 258} 259 260bool 261Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI, 262 const ReduceEntry &Entry) { 263 if (ReduceLimitLdSt != -1 && ((int)NumLdSts >= ReduceLimitLdSt)) 264 return false; 265 266 unsigned Scale = 1; 267 bool HasImmOffset = false; 268 bool HasShift = false; |
269 bool HasOffReg = true; |
270 bool isLdStMul = false; 271 unsigned Opc = Entry.NarrowOpc1; 272 unsigned OpNum = 3; // First 'rest' of operands. |
273 uint8_t ImmLimit = Entry.Imm1Limit; |
274 switch (Entry.WideOpc) { 275 default: 276 llvm_unreachable("Unexpected Thumb2 load / store opcode!"); 277 case ARM::t2LDRi12: |
278 case ARM::t2STRi12: { 279 unsigned BaseReg = MI->getOperand(1).getReg(); 280 if (BaseReg == ARM::SP) { 281 Opc = Entry.NarrowOpc2; 282 ImmLimit = Entry.Imm2Limit; 283 HasOffReg = false; 284 } |
285 Scale = 4; 286 HasImmOffset = true; 287 break; |
288 } |
289 case ARM::t2LDRBi12: 290 case ARM::t2STRBi12: 291 HasImmOffset = true; 292 break; 293 case ARM::t2LDRHi12: 294 case ARM::t2STRHi12: 295 Scale = 2; 296 HasImmOffset = true; --- 37 unchanged lines hidden (view full) --- 334 if (MI->getOperand(3).getImm()) 335 // Thumb1 addressing mode doesn't support shift. 336 return false; 337 } 338 339 unsigned OffsetImm = 0; 340 if (HasImmOffset) { 341 OffsetImm = MI->getOperand(2).getImm(); |
342 unsigned MaxOffset = ((1 << ImmLimit) - 1) * Scale; |
343 if ((OffsetImm & (Scale-1)) || OffsetImm > MaxOffset) 344 // Make sure the immediate field fits. 345 return false; 346 } 347 348 // Add the 16-bit load / store instruction. 349 // FIXME: Thumb1 addressing mode encode both immediate and register offset. 350 DebugLoc dl = MI->getDebugLoc(); 351 MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, TII->get(Opc)); 352 if (!isLdStMul) { 353 MIB.addOperand(MI->getOperand(0)).addOperand(MI->getOperand(1)); |
354 if (Opc != ARM::tLDRSB && Opc != ARM::tLDRSH) { |
355 // tLDRSB and tLDRSH do not have an immediate offset field. On the other 356 // hand, it must have an offset register. 357 // FIXME: Remove this special case. 358 MIB.addImm(OffsetImm/Scale); 359 } 360 assert((!HasShift || OffsetReg) && "Invalid so_reg load / store address!"); 361 |
362 if (HasOffReg) 363 MIB.addReg(OffsetReg, getKillRegState(OffsetKill)); |
364 } 365 366 // Transfer the rest of operands. 367 for (unsigned e = MI->getNumOperands(); OpNum != e; ++OpNum) 368 MIB.addOperand(MI->getOperand(OpNum)); 369 |
370 // Transfer memoperands. 371 (*MIB).setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); 372 |
373 DEBUG(errs() << "Converted 32-bit: " << *MI << " to 16-bit: " << *MIB); 374 375 MBB.erase(MI); 376 ++NumLdSts; 377 return true; 378} 379 380bool --- 322 unchanged lines hidden --- |