llvm.org GIT mirror llvm / 3a21425
Fix Thumb2 load / store addressing mode matching code. Do not use so_reg form to match base only address, i.e. [r] since Thumb2 requires a offset register field. For those, use [r + imm12] where the immediate is zero. Note the generated assembly code does not look any different after the patch. But the bug would have broken the JIT (if there is Thumb2 support) and it can break later passes which expect the address mode to be well-formed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78658 91177308-0d34-0410-b5e6-96231b3b80d8 Evan Cheng 11 years ago
3 changed file(s) with 180 addition(s) and 50 deletion(s). Raw diff Collapse all Expand all
606606 SDValue &Base, SDValue &OffImm) {
607607 // Match simple R + imm12 operands.
608608
609 // Match frame index...
610 if ((N.getOpcode() != ISD::ADD) && (N.getOpcode() != ISD::SUB)) {
609 // Base only.
610 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) {
611611 if (N.getOpcode() == ISD::FrameIndex) {
612 // Match frame index...
612613 int FI = cast(N)->getIndex();
613614 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
614615 OffImm = CurDAG->getTargetConstant(0, EVT::i32);
615616 return true;
616 }
617 return false;
617 } else if (N.getOpcode() == ARMISD::Wrapper) {
618 Base = N.getOperand(0);
619 if (Base.getOpcode() == ISD::TargetConstantPool)
620 return false; // We want to select t2LDRpci instead.
621 } else
622 Base = N;
623 OffImm = CurDAG->getTargetConstant(0, EVT::i32);
624 return true;
618625 }
619626
620627 if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) {
628 if (SelectT2AddrModeImm8(Op, N, Base, OffImm))
629 // Let t2LDRi8 handle (R - imm8).
630 return false;
631
621632 int RHSC = (int)RHS->getZExtValue();
622633 if (N.getOpcode() == ISD::SUB)
623634 RHSC = -RHSC;
633644 }
634645 }
635646
636 return false;
647 // Base only.
648 Base = N;
649 OffImm = CurDAG->getTargetConstant(0, EVT::i32);
650 return true;
637651 }
638652
639653 bool ARMDAGToDAGISel::SelectT2AddrModeImm8(SDValue Op, SDValue N,
640654 SDValue &Base, SDValue &OffImm) {
641655 // Match simple R - imm8 operands.
642 if ((N.getOpcode() == ISD::ADD) || (N.getOpcode() == ISD::SUB)) {
656 if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::SUB) {
643657 if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) {
644658 int RHSC = (int)RHS->getSExtValue();
645659 if (N.getOpcode() == ISD::SUB)
646660 RHSC = -RHSC;
647661
648 if ((RHSC >= -255) && (RHSC <= 0)) { // 8 bits (always negative)
649 Base = N.getOperand(0);
662 if ((RHSC >= -255) && (RHSC < 0)) { // 8 bits (always negative)
663 Base = N.getOperand(0);
650664 if (Base.getOpcode() == ISD::FrameIndex) {
651665 int FI = cast(Base)->getIndex();
652666 Base = CurDAG->getTargetFrameIndex(FI, TLI.getPointerTy());
708722 bool ARMDAGToDAGISel::SelectT2AddrModeSoReg(SDValue Op, SDValue N,
709723 SDValue &Base,
710724 SDValue &OffReg, SDValue &ShImm) {
711 // Base only.
712 if (N.getOpcode() != ISD::ADD && N.getOpcode() != ISD::SUB) {
713 Base = N;
714 if (N.getOpcode() == ISD::FrameIndex) {
715 return false; // we want to select t2LDRri12 instead
716 } else if (N.getOpcode() == ARMISD::Wrapper) {
717 Base = N.getOperand(0);
718 if (Base.getOpcode() == ISD::TargetConstantPool)
719 return false; // We want to select t2LDRpci instead.
720 }
721 OffReg = CurDAG->getRegister(0, EVT::i32);
722 ShImm = CurDAG->getTargetConstant(0, EVT::i32);
723 return true;
724 }
725
726 // Leave (R +/- imm) for other address modes... unless they can't
727 // handle them
728 if (dyn_cast(N.getOperand(1)) != NULL) {
729 SDValue OffImm;
730 if (SelectT2AddrModeImm12(Op, N, Base, OffImm) ||
731 SelectT2AddrModeImm8 (Op, N, Base, OffImm))
725 // (R - imm8) should be handled by t2LDRi8. The rest are handled by t2LDRi12.
726 if (N.getOpcode() != ISD::ADD)
727 return false;
728
729 // Leave (R + imm12) for t2LDRi12, (R - imm8) for t2LDRi8.
730 if (ConstantSDNode *RHS = dyn_cast(N.getOperand(1))) {
731 int RHSC = (int)RHS->getZExtValue();
732 if (RHSC >= 0 && RHSC < 0x1000) // 12 bits (unsigned)
732733 return false;
733 }
734
735 // Thumb2 does not support (R - R) or (R - (R << [1,2,3])).
736 if (N.getOpcode() == ISD::SUB) {
737 Base = N;
738 OffReg = CurDAG->getRegister(0, EVT::i32);
739 ShImm = CurDAG->getTargetConstant(0, EVT::i32);
740 return true;
741 }
742
743 assert(N.getOpcode() == ISD::ADD);
734 else if (RHSC < 0 && RHSC >= -255) // 8 bits
735 return false;
736 }
744737
745738 // Look for (R + R) or (R + (R << [1,2,3])).
746739 unsigned ShAmt = 0;
848848
849849 O << "[" << TRI->getAsmName(MO1.getReg());
850850
851 if (MO2.getReg()) {
852 O << ", +" << TRI->getAsmName(MO2.getReg());
853
854 unsigned ShAmt = MO3.getImm();
855 if (ShAmt) {
856 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
857 O << ", lsl #" << ShAmt;
858 }
851 assert(MO2.getReg() && "Invalid so_reg load / store address!");
852 O << ", +" << TRI->getAsmName(MO2.getReg());
853
854 unsigned ShAmt = MO3.getImm();
855 if (ShAmt) {
856 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
857 O << ", lsl #" << ShAmt;
859858 }
860859 O << "]";
861860 }
2323
2424 STATISTIC(NumNarrows, "Number of 32-bit instrs reduced to 16-bit ones");
2525 STATISTIC(Num2Addrs, "Number of 32-bit instrs reduced to 2addr 16-bit ones");
26 STATISTIC(NumLdSts, "Number of 32-bit load / store reduced to 16-bit ones");
2627
2728 static cl::opt ReduceLimit("t2-reduce-limit", cl::init(-1), cl::Hidden);
2829
8283 { ARM::t2SXTHr, ARM::tSXTH, 0, 0, 0, 1, 0, 1,0, 0 },
8384 { ARM::t2TSTrr, ARM::tTST, 0, 0, 0, 1, 0, 1,0, 0 },
8485 { ARM::t2UXTBr, ARM::tUXTB, 0, 0, 0, 1, 0, 1,0, 0 },
85 { ARM::t2UXTHr, ARM::tUXTH, 0, 0, 0, 1, 0, 1,0, 0 }
86 { ARM::t2UXTHr, ARM::tUXTH, 0, 0, 0, 1, 0, 1,0, 0 },
87
88 // FIXME: Clean this up after splitting each Thumb load / store opcode
89 // into multiple ones.
90 { ARM::t2LDRi12,ARM::tLDR, 0, 5, 0, 1, 0, 0,0, 1 },
91 { ARM::t2LDRs, ARM::tLDR, 0, 0, 0, 1, 0, 0,0, 1 },
92 { ARM::t2LDRBi12,ARM::tLDRB, 0, 5, 0, 1, 0, 0,0, 1 },
93 { ARM::t2LDRBs, ARM::tLDRB, 0, 0, 0, 1, 0, 0,0, 1 },
94 { ARM::t2LDRHi12,ARM::tLDRH, 0, 5, 0, 1, 0, 0,0, 1 },
95 { ARM::t2LDRHs, ARM::tLDRH, 0, 0, 0, 1, 0, 0,0, 1 },
96 { ARM::t2LDRSBs,ARM::tLDR, 0, 0, 0, 1, 0, 0,0, 1 },
97 { ARM::t2LDRSHs,ARM::tLDRSH, 0, 0, 0, 1, 0, 0,0, 1 },
98 { ARM::t2STRi12,ARM::tSTR, 0, 5, 0, 1, 0, 0,0, 1 },
99 { ARM::t2STRs, ARM::tSTR, 0, 0, 0, 1, 0, 0,0, 1 },
100 { ARM::t2STRBi12,ARM::tSTRB, 0, 5, 0, 1, 0, 0,0, 1 },
101 { ARM::t2STRBs, ARM::tSTRB, 0, 0, 0, 1, 0, 0,0, 1 },
102 { ARM::t2STRHi12,ARM::tSTRH, 0, 5, 0, 1, 0, 0,0, 1 },
103 { ARM::t2STRHs, ARM::tSTRH, 0, 0, 0, 1, 0, 0,0, 1 }
86104 };
87105
88106 class VISIBILITY_HIDDEN Thumb2SizeReduce : public MachineFunctionPass {
101119 private:
102120 /// ReduceOpcodeMap - Maps wide opcode to index of entry in ReduceTable.
103121 DenseMap ReduceOpcodeMap;
122
123 bool ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
124 const ReduceEntry &Entry);
125
126 bool ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI,
127 const ReduceEntry &Entry, bool LiveCPSR);
104128
105129 /// ReduceTo2Addr - Reduce a 32-bit instruction to a 16-bit two-address
106130 /// instruction.
161185 }
162186
163187 bool
188 Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI,
189 const ReduceEntry &Entry) {
190 unsigned Scale = 1;
191 bool HasImmOffset = false;
192 bool HasShift = false;
193 switch (Entry.WideOpc) {
194 default:
195 llvm_unreachable("Unexpected Thumb2 load / store opcode!");
196 case ARM::t2LDRi12:
197 case ARM::t2STRi12:
198 Scale = 4;
199 HasImmOffset = true;
200 break;
201 case ARM::t2LDRBi12:
202 case ARM::t2STRBi12:
203 HasImmOffset = true;
204 break;
205 case ARM::t2LDRHi12:
206 case ARM::t2STRHi12:
207 Scale = 2;
208 HasImmOffset = true;
209 break;
210 case ARM::t2LDRs:
211 case ARM::t2LDRBs:
212 case ARM::t2LDRHs:
213 case ARM::t2LDRSBs:
214 case ARM::t2LDRSHs:
215 case ARM::t2STRs:
216 case ARM::t2STRBs:
217 case ARM::t2STRHs:
218 HasShift = true;
219 break;
220 }
221
222 unsigned OffsetReg = 0;
223 bool OffsetKill = false;
224 if (HasShift) {
225 OffsetReg = MI->getOperand(2).getReg();
226 OffsetKill = MI->getOperand(2).isKill();
227 if (MI->getOperand(3).getImm())
228 // Thumb1 addressing mode doesn't support shift.
229 return false;
230 }
231
232 unsigned OffsetImm = 0;
233 if (HasImmOffset) {
234 OffsetImm = MI->getOperand(2).getImm();
235 unsigned MaxOffset = ((1 << Entry.Imm1Limit) - 1) * Scale;
236 if ((OffsetImm & (Scale-1)) || OffsetImm > MaxOffset)
237 // Make sure the immediate field fits.
238 return false;
239 }
240
241 // Add the 16-bit load / store instruction.
242 // FIXME: Thumb1 addressing mode encode both immediate and register offset.
243 DebugLoc dl = MI->getDebugLoc();
244 MachineInstrBuilder MIB = BuildMI(MBB, *MI, dl, TII->get(Entry.NarrowOpc1))
245 .addOperand(MI->getOperand(0))
246 .addOperand(MI->getOperand(1));
247 if (Entry.NarrowOpc1 != ARM::tLDRSB && Entry.NarrowOpc1 != ARM::tLDRSH) {
248 // tLDRSB and tLDRSH do not have an immediate offset field. On the other
249 // hand, it must have an offset register.
250 assert(OffsetReg && "Invalid so_reg load / store address!");
251 // FIXME: Remove this special case.
252 MIB.addImm(OffsetImm/Scale);
253 }
254 MIB.addReg(OffsetReg, getKillRegState(OffsetKill));
255
256 // Transfer the rest of operands.
257 unsigned OpNum = HasShift ? 4 : 3;
258 for (unsigned e = MI->getNumOperands(); OpNum != e; ++OpNum)
259 MIB.addOperand(MI->getOperand(OpNum));
260
261 DOUT << "Converted 32-bit: " << *MI << " to 16-bit: " << *MIB;
262
263 MBB.erase(MI);
264 ++NumLdSts;
265 return true;
266 }
267
268 static bool VerifyLowRegs(MachineInstr *MI, const TargetInstrDesc &TID) {
269 for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) {
270 const MachineOperand &MO = MI->getOperand(i);
271 if (!MO.isReg())
272 continue;
273 unsigned Reg = MO.getReg();
274 if (Reg == 0 || Reg == ARM::CPSR)
275 continue;
276 if (!isARMLowRegister(Reg))
277 return false;
278 }
279 return true;
280 }
281
282 bool
283 Thumb2SizeReduce::ReduceSpecial(MachineBasicBlock &MBB, MachineInstr *MI,
284 const ReduceEntry &Entry,
285 bool LiveCPSR) {
286 const TargetInstrDesc &TID = MI->getDesc();
287 if (Entry.LowRegs1 && !VerifyLowRegs(MI, TID))
288 return false;
289
290 if (TID.mayLoad() || TID.mayStore())
291 return ReduceLoadStore(MBB, MI, Entry);
292 return false;
293 }
294
295 bool
164296 Thumb2SizeReduce::ReduceTo2Addr(MachineBasicBlock &MBB, MachineInstr *MI,
165297 const ReduceEntry &Entry,
166298 bool LiveCPSR) {
352484 if (OPI != ReduceOpcodeMap.end()) {
353485 const ReduceEntry &Entry = ReduceTable[OPI->second];
354486 // Ignore "special" cases for now.
355 if (Entry.Special)
487 if (Entry.Special) {
488 if (ReduceSpecial(MBB, MI, Entry, LiveCPSR)) {
489 Modified = true;
490 MachineBasicBlock::iterator I = prior(NextMII);
491 MI = &*I;
492 }
356493 goto ProcessNext;
494 }
357495
358496 // Try to transform to a 16-bit two-address instruction.
359497 if (Entry.NarrowOpc2 && ReduceTo2Addr(MBB, MI, Entry, LiveCPSR)) {