llvm.org GIT mirror llvm / b53cc01
Fix frame index elimination to correctly handle thumb-2 addressing modes that don't allow negative offsets. During frame elimination convert *i12 opcode to a *i8 when necessary due to a negative offset. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@76883 91177308-0d34-0410-b5e6-96231b3b80d8 David Goodwin 11 years ago
10 changed file(s) with 125 addition(s) and 19 deletion(s). Raw diff Collapse all Expand all
214214 // Return the opcode that implements 'Op', or 0 if no opcode
215215 virtual unsigned getOpcode(ARMII::Op Op) const =0;
216216
217 // If 'opcode' is an instruction with an unsigned offset that also
218 // has a version with a signed offset, return the opcode for the
219 // version with the signed offset. In 'NumBits' return the number of
220 // bits for the signed offset.
221 virtual unsigned unsignedOffsetOpcodeToSigned(unsigned opcode,
222 unsigned *NumBits) const = 0;
223
217224 // Return true if the block does not fall through.
218225 virtual bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const =0;
219226
139139 unsigned ARMBaseRegisterInfo::
140140 getOpcode(int Op) const {
141141 return TII.getOpcode((ARMII::Op)Op);
142 }
143
144 unsigned ARMBaseRegisterInfo::
145 unsignedOffsetOpcodeToSigned(unsigned opcode, unsigned *NumBits) const {
146 return TII.unsignedOffsetOpcodeToSigned(opcode, NumBits);
142147 }
143148
144149 const unsigned*
11081113 int InstrOffs = 0;
11091114 unsigned NumBits = 0;
11101115 unsigned Scale = 1;
1116 bool encodedOffset = true;
1117 bool HandlesNeg = true;
11111118 switch (AddrMode) {
11121119 case ARMII::AddrMode2: {
11131120 ImmIdx = i+2;
11381145 ImmIdx = i+1;
11391146 InstrOffs = MI.getOperand(ImmIdx).getImm();
11401147 NumBits = 12;
1148 encodedOffset = false;
1149 HandlesNeg = false;
11411150 break;
11421151 }
11431152 case ARMII::AddrModeT2_i8: {
11441153 ImmIdx = i+1;
11451154 InstrOffs = MI.getOperand(ImmIdx).getImm();
11461155 NumBits = 8;
1156 encodedOffset = false;
11471157 break;
11481158 }
11491159 case ARMII::AddrModeT2_so: {
11501160 ImmIdx = i+2;
11511161 InstrOffs = MI.getOperand(ImmIdx).getImm();
1162 encodedOffset = false;
11521163 break;
11531164 }
11541165 default:
11591170 Offset += InstrOffs * Scale;
11601171 assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!");
11611172 if (Offset < 0) {
1173 // For addrmodes that cannot handle negative offsets, convert to
1174 // an opcode that can, or set NumBits == 0 to avoid folding
1175 // address computation
1176 if (!HandlesNeg) {
1177 unsigned usop = unsignedOffsetOpcodeToSigned(Opcode, &NumBits);
1178 if (usop != 0) {
1179 MI.setDesc(TII.get(usop));
1180 HandlesNeg = true;
1181 Opcode = usop;
1182 }
1183 else {
1184 NumBits = 0;
1185 }
1186 }
1187
11621188 Offset = -Offset;
11631189 isSub = true;
11641190 }
11651191
1166 // Common case: small offset, fits into instruction.
1167 MachineOperand &ImmOp = MI.getOperand(ImmIdx);
1168 int ImmedOffset = Offset / Scale;
1169 unsigned Mask = (1 << NumBits) - 1;
1170 if ((unsigned)Offset <= Mask * Scale) {
1171 // Replace the FrameIndex with sp
1172 MI.getOperand(i).ChangeToRegister(FrameReg, false);
1173 if (isSub)
1174 ImmedOffset |= 1 << NumBits;
1192 // Attempt to fold address comp. if opcode has offset bits
1193 if (NumBits > 0) {
1194 // Common case: small offset, fits into instruction.
1195 MachineOperand &ImmOp = MI.getOperand(ImmIdx);
1196 int ImmedOffset = Offset / Scale;
1197 unsigned Mask = (1 << NumBits) - 1;
1198 if ((unsigned)Offset <= Mask * Scale) {
1199 // Replace the FrameIndex with sp
1200 MI.getOperand(i).ChangeToRegister(FrameReg, false);
1201 if (isSub) {
1202 if (encodedOffset)
1203 ImmedOffset |= 1 << NumBits;
1204 else
1205 ImmedOffset = -ImmedOffset;
1206 }
1207 ImmOp.ChangeToImmediate(ImmedOffset);
1208 return;
1209 }
1210
1211 // Otherwise, it didn't fit. Pull in what we can to simplify the immed.
1212 ImmedOffset = ImmedOffset & Mask;
1213 if (isSub) {
1214 if (encodedOffset)
1215 ImmedOffset |= 1 << NumBits;
1216 else
1217 ImmedOffset = -ImmedOffset;
1218 }
11751219 ImmOp.ChangeToImmediate(ImmedOffset);
1176 return;
1177 }
1178
1179 // Otherwise, it didn't fit. Pull in what we can to simplify the immed.
1180 ImmedOffset = ImmedOffset & Mask;
1181 if (isSub)
1182 ImmedOffset |= 1 << NumBits;
1183 ImmOp.ChangeToImmediate(ImmedOffset);
1184 Offset &= ~(Mask*Scale);
1220 Offset &= ~(Mask*Scale);
1221 }
11851222 }
11861223
11871224 // If we get here, the immediate doesn't fit into the instruction. We folded
5757
5858 // Return the opcode that implements 'Op', or 0 if no opcode
5959 unsigned getOpcode(int Op) const;
60
61 // If 'opcode' is an instruction with an unsigned offset that also
62 // has a version with a signed offset, return the opcode for the
63 // version with the signed offset. In 'NumBits' return the number of
64 // bits for the signed offset.
65 unsigned unsignedOffsetOpcodeToSigned(unsigned opcode,
66 unsigned *NumBits) const;
6067
6168 public:
6269 /// getRegisterNumbering - Given the enum value for some register, e.g.
2626
2727 ARMInstrInfo::ARMInstrInfo(const ARMSubtarget &STI)
2828 : ARMBaseInstrInfo(STI), RI(*this, STI) {
29 }
30
31 unsigned ARMInstrInfo::
32 unsignedOffsetOpcodeToSigned(unsigned opcode, unsigned *NumBits) const {
33 return 0;
2934 }
3035
3136 unsigned ARMInstrInfo::
3434 // Return the opcode that implements 'Op', or 0 if no opcode
3535 unsigned getOpcode(ARMII::Op Op) const;
3636
37 // If 'opcode' is an instruction with an unsigned offset that also
38 // has a version with a signed offset, return the opcode for the
39 // version with the signed offset. In 'NumBits' return the number of
40 // bits for the signed offset.
41 unsigned unsignedOffsetOpcodeToSigned(unsigned opcode,
42 unsigned *NumBits) const;
43
3744 // Return true if the block does not fall through.
3845 bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const;
3946
108108 let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
109109 }
110110
111 // t2addrmode_imm8 := reg - imm8
111 // t2addrmode_imm8 := reg +/- imm8
112112 def t2addrmode_imm8 : Operand,
113113 ComplexPattern {
114114 let PrintMethod = "printT2AddrModeImm8Operand";
2626 }
2727
2828 unsigned Thumb1InstrInfo::getUnindexedOpcode(unsigned Opc) const {
29 return 0;
30 }
31
32 unsigned
33 Thumb1InstrInfo::unsignedOffsetOpcodeToSigned(unsigned opcode,
34 unsigned *NumBits) const {
2935 return 0;
3036 }
3137
3232
3333 // Return the opcode that implements 'Op', or 0 if no opcode
3434 unsigned getOpcode(ARMII::Op Op) const;
35
36 // If 'opcode' is an instruction with an unsigned offset that also
37 // has a version with a signed offset, return the opcode for the
38 // version with the signed offset. In 'NumBits' return the number of
39 // bits for the signed offset.
40 unsigned unsignedOffsetOpcodeToSigned(unsigned opcode,
41 unsigned *NumBits) const;
3542
3643 // Return true if the block does not fall through.
3744 bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const;
8787 return false;
8888 }
8989
90 unsigned
91 Thumb2InstrInfo::unsignedOffsetOpcodeToSigned(unsigned opcode,
92 unsigned *NumBits) const
93 {
94 if (NumBits != NULL)
95 *NumBits = 8;
96
97 switch (opcode) {
98 case ARM::t2LDRi12: return ARM::t2LDRi8;
99 case ARM::t2LDRHi12: return ARM::t2LDRHi8;
100 case ARM::t2LDRBi12: return ARM::t2LDRBi8;
101 case ARM::t2LDRSHi12: return ARM::t2LDRSHi8;
102 case ARM::t2LDRSBi12: return ARM::t2LDRSBi8;
103 case ARM::t2STRi12: return ARM::t2STRi8;
104 case ARM::t2STRBi12: return ARM::t2STRBi8;
105 case ARM::t2STRHi12: return ARM::t2STRHi8;
106 default:
107 break;
108 }
109
110 return 0;
111 }
112
90113 bool
91114 Thumb2InstrInfo::copyRegToReg(MachineBasicBlock &MBB,
92115 MachineBasicBlock::iterator I,
3333 // Return the opcode that implements 'Op', or 0 if no opcode
3434 unsigned getOpcode(ARMII::Op Op) const;
3535
36 // If 'opcode' is an instruction with an unsigned offset that also
37 // has a version with a signed offset, return the opcode for the
38 // version with the signed offset. In 'NumBits' return the number of
39 // bits for the signed offset.
40 unsigned unsignedOffsetOpcodeToSigned(unsigned opcode,
41 unsigned *NumBits) const;
42
3643 // Return true if the block does not fall through.
3744 bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const;
3845