llvm.org GIT mirror llvm / 74c23af
ARMLoadStoreOpt: Merge subs/adds into LDRD/STRD; Factor out common code This commit factors out common code from MergeBaseUpdateLoadStore() and MergeBaseUpdateLSMultiple() and introduces a new function MergeBaseUpdateLSDouble() which merges adds/subs preceding/following a strd/ldrd instruction into an strd/ldrd instruction with writeback where possible. Differential Revision: http://reviews.llvm.org/D10676 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241928 91177308-0d34-0410-b5e6-96231b3b80d8 Matthias Braun 5 years ago
2 changed file(s) with 243 addition(s) and 175 deletion(s). Raw diff Collapse all Expand all
117117 };
118118 BumpPtrAllocator Allocator;
119119 SmallVector Candidates;
120 SmallVector MergeBaseCandidates;
120121
121122 void moveLiveRegsBefore(const MachineBasicBlock &MBB,
122123 MachineBasicBlock::const_iterator Before);
139140 MachineBasicBlock::iterator &MBBI);
140141 bool MergeBaseUpdateLoadStore(MachineInstr *MI);
141142 bool MergeBaseUpdateLSMultiple(MachineInstr *MI);
143 bool MergeBaseUpdateLSDouble(MachineInstr &MI) const;
142144 bool LoadStoreMultipleOpti(MachineBasicBlock &MBB);
143145 bool MergeReturnIntoLDM(MachineBasicBlock &MBB);
144146 };
10091011 } while (SIndex < EIndex);
10101012 }
10111013
1012 static bool isMatchingDecrement(MachineInstr *MI, unsigned Base,
1013 unsigned Bytes, unsigned Limit,
1014 ARMCC::CondCodes Pred, unsigned PredReg) {
1015 unsigned MyPredReg = 0;
1016 if (!MI)
1017 return false;
1018
1019 bool CheckCPSRDef = false;
1020 switch (MI->getOpcode()) {
1021 default: return false;
1022 case ARM::tSUBi8:
1023 case ARM::t2SUBri:
1024 case ARM::SUBri:
1025 CheckCPSRDef = true;
1026 break;
1027 case ARM::tSUBspi:
1028 break;
1029 }
1030
1031 // Make sure the offset fits in 8 bits.
1032 if (Bytes == 0 || (Limit && Bytes >= Limit))
1033 return false;
1034
1035 unsigned Scale = (MI->getOpcode() == ARM::tSUBspi ||
1036 MI->getOpcode() == ARM::tSUBi8) ? 4 : 1; // FIXME
1037 if (!(MI->getOperand(0).getReg() == Base &&
1038 MI->getOperand(1).getReg() == Base &&
1039 (MI->getOperand(2).getImm() * Scale) == Bytes &&
1040 getInstrPredicate(MI, MyPredReg) == Pred &&
1041 MyPredReg == PredReg))
1042 return false;
1043
1044 return CheckCPSRDef ? !definesCPSR(MI) : true;
1045 }
1046
1047 static bool isMatchingIncrement(MachineInstr *MI, unsigned Base,
1048 unsigned Bytes, unsigned Limit,
1049 ARMCC::CondCodes Pred, unsigned PredReg) {
1050 unsigned MyPredReg = 0;
1051 if (!MI)
1052 return false;
1053
1054 bool CheckCPSRDef = false;
1055 switch (MI->getOpcode()) {
1056 default: return false;
1057 case ARM::tADDi8:
1058 case ARM::t2ADDri:
1059 case ARM::ADDri:
1060 CheckCPSRDef = true;
1061 break;
1062 case ARM::tADDspi:
1063 break;
1064 }
1065
1066 if (Bytes == 0 || (Limit && Bytes >= Limit))
1067 // Make sure the offset fits in 8 bits.
1068 return false;
1069
1070 unsigned Scale = (MI->getOpcode() == ARM::tADDspi ||
1071 MI->getOpcode() == ARM::tADDi8) ? 4 : 1; // FIXME
1072 if (!(MI->getOperand(0).getReg() == Base &&
1073 MI->getOperand(1).getReg() == Base &&
1074 (MI->getOperand(2).getImm() * Scale) == Bytes &&
1075 getInstrPredicate(MI, MyPredReg) == Pred &&
1076 MyPredReg == PredReg))
1077 return false;
1078
1079 return CheckCPSRDef ? !definesCPSR(MI) : true;
1080 }
1081
10821014 static unsigned getUpdatingLSMultipleOpcode(unsigned Opc,
10831015 ARM_AM::AMSubMode Mode) {
10841016 switch (Opc) {
11441076 case ARM_AM::db: return ARM::VSTMDDB_UPD;
11451077 }
11461078 }
1079 }
1080
1081 /// Check if the given instruction increments or decrements a register and
1082 /// return the amount it is incremented/decremented. Returns 0 if the CPSR flags
1083 /// generated by the instruction are possibly read as well.
1084 static int isIncrementOrDecrement(const MachineInstr &MI, unsigned Reg,
1085 ARMCC::CondCodes Pred, unsigned PredReg) {
1086 bool CheckCPSRDef;
1087 int Scale;
1088 switch (MI.getOpcode()) {
1089 case ARM::tADDi8: Scale = 4; CheckCPSRDef = true; break;
1090 case ARM::tSUBi8: Scale = -4; CheckCPSRDef = true; break;
1091 case ARM::t2SUBri:
1092 case ARM::SUBri: Scale = -1; CheckCPSRDef = true; break;
1093 case ARM::t2ADDri:
1094 case ARM::ADDri: Scale = 1; CheckCPSRDef = true; break;
1095 case ARM::tADDspi: Scale = 4; CheckCPSRDef = false; break;
1096 case ARM::tSUBspi: Scale = -4; CheckCPSRDef = false; break;
1097 default: return 0;
1098 }
1099
1100 unsigned MIPredReg;
1101 if (MI.getOperand(0).getReg() != Reg ||
1102 MI.getOperand(1).getReg() != Reg ||
1103 getInstrPredicate(&MI, MIPredReg) != Pred ||
1104 MIPredReg != PredReg)
1105 return 0;
1106
1107 if (CheckCPSRDef && definesCPSR(&MI))
1108 return 0;
1109 return MI.getOperand(2).getImm() * Scale;
1110 }
1111
1112 /// Searches for an increment or decrement of \p Reg before \p MBBI.
1113 static MachineBasicBlock::iterator
1114 findIncDecBefore(MachineBasicBlock::iterator MBBI, unsigned Reg,
1115 ARMCC::CondCodes Pred, unsigned PredReg, int &Offset) {
1116 Offset = 0;
1117 MachineBasicBlock &MBB = *MBBI->getParent();
1118 MachineBasicBlock::iterator BeginMBBI = MBB.begin();
1119 MachineBasicBlock::iterator EndMBBI = MBB.end();
1120 if (MBBI == BeginMBBI)
1121 return EndMBBI;
1122
1123 // Skip debug values.
1124 MachineBasicBlock::iterator PrevMBBI = std::prev(MBBI);
1125 while (PrevMBBI->isDebugValue() && PrevMBBI != BeginMBBI)
1126 --PrevMBBI;
1127
1128 Offset = isIncrementOrDecrement(*PrevMBBI, Reg, Pred, PredReg);
1129 return Offset == 0 ? EndMBBI : PrevMBBI;
1130 }
1131
1132 /// Searches for a increment or decrement of \p Reg after \p MBBI.
1133 static MachineBasicBlock::iterator
1134 findIncDecAfter(MachineBasicBlock::iterator MBBI, unsigned Reg,
1135 ARMCC::CondCodes Pred, unsigned PredReg, int &Offset) {
1136 Offset = 0;
1137 MachineBasicBlock &MBB = *MBBI->getParent();
1138 MachineBasicBlock::iterator EndMBBI = MBB.end();
1139 MachineBasicBlock::iterator NextMBBI = std::next(MBBI);
1140 // Skip debug values.
1141 while (NextMBBI != EndMBBI && NextMBBI->isDebugValue())
1142 ++NextMBBI;
1143 if (NextMBBI == EndMBBI)
1144 return EndMBBI;
1145
1146 Offset = isIncrementOrDecrement(*NextMBBI, Reg, Pred, PredReg);
1147 return Offset == 0 ? EndMBBI : NextMBBI;
11471148 }
11481149
11491150 /// Fold proceeding/trailing inc/dec of base register into the
11651166 const MachineOperand &BaseOP = MI->getOperand(0);
11661167 unsigned Base = BaseOP.getReg();
11671168 bool BaseKill = BaseOP.isKill();
1168 unsigned Bytes = getLSMultipleTransferSize(MI);
11691169 unsigned PredReg = 0;
11701170 ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg);
11711171 unsigned Opcode = MI->getOpcode();
11771177 if (MI->getOperand(i).getReg() == Base)
11781178 return false;
11791179
1180 bool DoMerge = false;
1180 int Bytes = getLSMultipleTransferSize(MI);
1181 MachineBasicBlock &MBB = *MI->getParent();
1182 MachineBasicBlock::iterator MBBI(MI);
1183 int Offset;
1184 MachineBasicBlock::iterator MergeInstr
1185 = findIncDecBefore(MBBI, Base, Pred, PredReg, Offset);
11811186 ARM_AM::AMSubMode Mode = getLoadStoreMultipleSubMode(Opcode);
1182
1183 // Try merging with the previous instruction.
1184 MachineBasicBlock &MBB = *MI->getParent();
1185 MachineBasicBlock::iterator BeginMBBI = MBB.begin();
1186 MachineBasicBlock::iterator MBBI(MI);
1187 if (MBBI != BeginMBBI) {
1188 MachineBasicBlock::iterator PrevMBBI = std::prev(MBBI);
1189 while (PrevMBBI != BeginMBBI && PrevMBBI->isDebugValue())
1190 --PrevMBBI;
1191 if (Mode == ARM_AM::ia &&
1192 isMatchingDecrement(PrevMBBI, Base, Bytes, 0, Pred, PredReg)) {
1193 Mode = ARM_AM::db;
1194 DoMerge = true;
1195 } else if (Mode == ARM_AM::ib &&
1196 isMatchingDecrement(PrevMBBI, Base, Bytes, 0, Pred, PredReg)) {
1197 Mode = ARM_AM::da;
1198 DoMerge = true;
1199 }
1200 if (DoMerge)
1201 MBB.erase(PrevMBBI);
1202 }
1203
1204 // Try merging with the next instruction.
1205 MachineBasicBlock::iterator EndMBBI = MBB.end();
1206 if (!DoMerge && MBBI != EndMBBI) {
1207 MachineBasicBlock::iterator NextMBBI = std::next(MBBI);
1208 while (NextMBBI != EndMBBI && NextMBBI->isDebugValue())
1209 ++NextMBBI;
1210 if ((Mode == ARM_AM::ia || Mode == ARM_AM::ib) &&
1211 isMatchingIncrement(NextMBBI, Base, Bytes, 0, Pred, PredReg)) {
1212 DoMerge = true;
1213 } else if ((Mode == ARM_AM::da || Mode == ARM_AM::db) &&
1214 isMatchingDecrement(NextMBBI, Base, Bytes, 0, Pred, PredReg)) {
1215 DoMerge = true;
1216 }
1217 if (DoMerge)
1218 MBB.erase(NextMBBI);
1219 }
1220
1221 if (!DoMerge)
1222 return false;
1187 if (Mode == ARM_AM::ia && Offset == -Bytes) {
1188 Mode = ARM_AM::db;
1189 } else if (Mode == ARM_AM::ib && Offset == -Bytes) {
1190 Mode = ARM_AM::da;
1191 } else {
1192 MergeInstr = findIncDecAfter(MBBI, Base, Pred, PredReg, Offset);
1193 if (((Mode != ARM_AM::ia && Mode != ARM_AM::ib) || Offset != Bytes) &&
1194 ((Mode != ARM_AM::da && Mode != ARM_AM::db) || Offset != -Bytes))
1195 return false;
1196 }
1197 MBB.erase(MergeInstr);
12231198
12241199 unsigned NewOpc = getUpdatingLSMultipleOpcode(Opcode, Mode);
12251200 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(NewOpc))
12971272
12981273 unsigned Base = getLoadStoreBaseOp(*MI).getReg();
12991274 bool BaseKill = getLoadStoreBaseOp(*MI).isKill();
1300 unsigned Bytes = getLSMultipleTransferSize(MI);
13011275 unsigned Opcode = MI->getOpcode();
13021276 DebugLoc DL = MI->getDebugLoc();
13031277 bool isAM5 = (Opcode == ARM::VLDRD || Opcode == ARM::VLDRS ||
13091283 if (isAM5 && ARM_AM::getAM5Offset(MI->getOperand(2).getImm()) != 0)
13101284 return false;
13111285
1312 bool isLd = isLoadSingle(Opcode);
13131286 // Can't do the merge if the destination register is the same as the would-be
13141287 // writeback register.
13151288 if (MI->getOperand(0).getReg() == Base)
13171290
13181291 unsigned PredReg = 0;
13191292 ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg);
1320 bool DoMerge = false;
1321 ARM_AM::AddrOpc AddSub = ARM_AM::add;
1322 unsigned NewOpc = 0;
1323 // AM2 - 12 bits, thumb2 - 8 bits.
1324 unsigned Limit = isAM5 ? 0 : (isAM2 ? 0x1000 : 0x100);
1325
1326 // Try merging with the previous instruction.
1293 int Bytes = getLSMultipleTransferSize(MI);
13271294 MachineBasicBlock &MBB = *MI->getParent();
1328 MachineBasicBlock::iterator BeginMBBI = MBB.begin();
13291295 MachineBasicBlock::iterator MBBI(MI);
1330 if (MBBI != BeginMBBI) {
1331 MachineBasicBlock::iterator PrevMBBI = std::prev(MBBI);
1332 while (PrevMBBI != BeginMBBI && PrevMBBI->isDebugValue())
1333 --PrevMBBI;
1334 if (isMatchingDecrement(PrevMBBI, Base, Bytes, Limit, Pred, PredReg)) {
1335 DoMerge = true;
1336 AddSub = ARM_AM::sub;
1337 } else if (!isAM5 &&
1338 isMatchingIncrement(PrevMBBI, Base, Bytes, Limit,Pred,PredReg)) {
1339 DoMerge = true;
1340 }
1341 if (DoMerge) {
1342 NewOpc = getPreIndexedLoadStoreOpcode(Opcode, AddSub);
1343 MBB.erase(PrevMBBI);
1344 }
1345 }
1346
1347 // Try merging with the next instruction.
1348 MachineBasicBlock::iterator EndMBBI = MBB.end();
1349 if (!DoMerge && MBBI != EndMBBI) {
1350 MachineBasicBlock::iterator NextMBBI = std::next(MBBI);
1351 while (NextMBBI != EndMBBI && NextMBBI->isDebugValue())
1352 ++NextMBBI;
1353 if (!isAM5 &&
1354 isMatchingDecrement(NextMBBI, Base, Bytes, Limit, Pred, PredReg)) {
1355 DoMerge = true;
1356 AddSub = ARM_AM::sub;
1357 } else if (isMatchingIncrement(NextMBBI, Base, Bytes, Limit,Pred,PredReg)) {
1358 DoMerge = true;
1359 }
1360 if (DoMerge) {
1361 NewOpc = getPostIndexedLoadStoreOpcode(Opcode, AddSub);
1362 MBB.erase(NextMBBI);
1363 }
1364 }
1365
1366 if (!DoMerge)
1367 return false;
1368
1296 int Offset;
1297 MachineBasicBlock::iterator MergeInstr
1298 = findIncDecBefore(MBBI, Base, Pred, PredReg, Offset);
1299 unsigned NewOpc;
1300 if (!isAM5 && Offset == Bytes) {
1301 NewOpc = getPreIndexedLoadStoreOpcode(Opcode, ARM_AM::add);
1302 } else if (Offset == -Bytes) {
1303 NewOpc = getPreIndexedLoadStoreOpcode(Opcode, ARM_AM::sub);
1304 } else {
1305 MergeInstr = findIncDecAfter(MBBI, Base, Pred, PredReg, Offset);
1306 if (Offset == Bytes) {
1307 NewOpc = getPostIndexedLoadStoreOpcode(Opcode, ARM_AM::add);
1308 } else if (!isAM5 && Offset == -Bytes) {
1309 NewOpc = getPostIndexedLoadStoreOpcode(Opcode, ARM_AM::sub);
1310 } else
1311 return false;
1312 }
1313 MBB.erase(MergeInstr);
1314
1315 ARM_AM::AddrOpc AddSub = Offset < 0 ? ARM_AM::sub : ARM_AM::add;
1316
1317 bool isLd = isLoadSingle(Opcode);
13691318 if (isAM5) {
13701319 // VLDM[SD]_UPD, VSTM[SD]_UPD
13711320 // (There are no base-updating versions of VLDR/VSTR instructions, but the
13821331 if (isAM2) {
13831332 // LDR_PRE, LDR_POST
13841333 if (NewOpc == ARM::LDR_PRE_IMM || NewOpc == ARM::LDRB_PRE_IMM) {
1385 int Offset = AddSub == ARM_AM::sub ? -Bytes : Bytes;
13861334 BuildMI(MBB, MBBI, DL, TII->get(NewOpc), MI->getOperand(0).getReg())
13871335 .addReg(Base, RegState::Define)
13881336 .addReg(Base).addImm(Offset).addImm(Pred).addReg(PredReg);
13891337 } else {
1390 int Offset = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift);
1338 int Imm = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift);
13911339 BuildMI(MBB, MBBI, DL, TII->get(NewOpc), MI->getOperand(0).getReg())
13921340 .addReg(Base, RegState::Define)
1393 .addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg);
1341 .addReg(Base).addReg(0).addImm(Imm).addImm(Pred).addReg(PredReg);
13941342 }
13951343 } else {
1396 int Offset = AddSub == ARM_AM::sub ? -Bytes : Bytes;
13971344 // t2LDR_PRE, t2LDR_POST
13981345 BuildMI(MBB, MBBI, DL, TII->get(NewOpc), MI->getOperand(0).getReg())
13991346 .addReg(Base, RegState::Define)
14051352 // the vestigal zero-reg offset register. When that's fixed, this clause
14061353 // can be removed entirely.
14071354 if (isAM2 && NewOpc == ARM::STR_POST_IMM) {
1408 int Offset = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift);
1355 int Imm = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift);
14091356 // STR_PRE, STR_POST
14101357 BuildMI(MBB, MBBI, DL, TII->get(NewOpc), Base)
14111358 .addReg(MO.getReg(), getKillRegState(MO.isKill()))
1412 .addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg);
1359 .addReg(Base).addReg(0).addImm(Imm).addImm(Pred).addReg(PredReg);
14131360 } else {
1414 int Offset = AddSub == ARM_AM::sub ? -Bytes : Bytes;
14151361 // t2STR_PRE, t2STR_POST
14161362 BuildMI(MBB, MBBI, DL, TII->get(NewOpc), Base)
14171363 .addReg(MO.getReg(), getKillRegState(MO.isKill()))
14201366 }
14211367 MBB.erase(MBBI);
14221368
1369 return true;
1370 }
1371
1372 bool ARMLoadStoreOpt::MergeBaseUpdateLSDouble(MachineInstr &MI) const {
1373 unsigned Opcode = MI.getOpcode();
1374 assert((Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2STRDi8) &&
1375 "Must have t2STRDi8 or t2LDRDi8");
1376 if (MI.getOperand(3).getImm() != 0)
1377 return false;
1378
1379 // Behaviour for writeback is undefined if base register is the same as one
1380 // of the others.
1381 const MachineOperand &BaseOp = MI.getOperand(2);
1382 unsigned Base = BaseOp.getReg();
1383 const MachineOperand &Reg0Op = MI.getOperand(0);
1384 const MachineOperand &Reg1Op = MI.getOperand(1);
1385 if (Reg0Op.getReg() == Base || Reg1Op.getReg() == Base)
1386 return false;
1387
1388 unsigned PredReg;
1389 ARMCC::CondCodes Pred = getInstrPredicate(&MI, PredReg);
1390 MachineBasicBlock::iterator MBBI(MI);
1391 MachineBasicBlock &MBB = *MI.getParent();
1392 int Offset;
1393 MachineBasicBlock::iterator MergeInstr = findIncDecBefore(MBBI, Base, Pred,
1394 PredReg, Offset);
1395 unsigned NewOpc;
1396 if (Offset == 8 || Offset == -8) {
1397 NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_PRE : ARM::t2STRD_PRE;
1398 } else {
1399 MergeInstr = findIncDecAfter(MBBI, Base, Pred, PredReg, Offset);
1400 if (Offset == 8 || Offset == -8) {
1401 NewOpc = Opcode == ARM::t2LDRDi8 ? ARM::t2LDRD_POST : ARM::t2STRD_POST;
1402 } else
1403 return false;
1404 }
1405 MBB.erase(MergeInstr);
1406
1407 DebugLoc DL = MI.getDebugLoc();
1408 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, TII->get(NewOpc));
1409 if (NewOpc == ARM::t2LDRD_PRE || NewOpc == ARM::t2LDRD_POST) {
1410 MIB.addOperand(Reg0Op).addOperand(Reg1Op)
1411 .addReg(BaseOp.getReg(), RegState::Define);
1412 } else {
1413 assert(NewOpc == ARM::t2STRD_PRE || NewOpc == ARM::t2STRD_POST);
1414 MIB.addReg(BaseOp.getReg(), RegState::Define)
1415 .addOperand(Reg0Op).addOperand(Reg1Op);
1416 }
1417 MIB.addReg(BaseOp.getReg(), RegState::Kill)
1418 .addImm(Offset).addImm(Pred).addReg(PredReg);
1419 assert(TII->get(Opcode).getNumOperands() == 6 &&
1420 TII->get(NewOpc).getNumOperands() == 7 &&
1421 "Unexpected number of operands in Opcode specification.");
1422
1423 // Transfer implicit operands.
1424 for (const MachineOperand &MO : MI.implicit_operands())
1425 MIB.addOperand(MO);
1426 MIB->setMemRefs(MI.memoperands_begin(), MI.memoperands_end());
1427
1428 MBB.erase(MBBI);
14231429 return true;
14241430 }
14251431
16321638 unsigned CurrPredReg = 0;
16331639 unsigned Position = 0;
16341640 assert(Candidates.size() == 0);
1641 assert(MergeBaseCandidates.size() == 0);
16351642 LiveRegsValid = false;
16361643
16371644 for (MachineBasicBlock::iterator I = MBB.end(), MBBI; I != MBB.begin();
17131720 MBBI = I;
17141721 --Position;
17151722 // Fallthrough to look into existing chain.
1716 } else if (MBBI->isDebugValue())
1723 } else if (MBBI->isDebugValue()) {
17171724 continue;
1725 } else if (MBBI->getOpcode() == ARM::t2LDRDi8 ||
1726 MBBI->getOpcode() == ARM::t2STRDi8) {
1727 // ARMPreAllocLoadStoreOpt has already formed some LDRD/STRD instructions
1728 // remember them because we may still be able to merge add/sub into them.
1729 MergeBaseCandidates.push_back(MBBI);
1730 }
1731
17181732
17191733 // If we are here then the chain is broken; Extract candidates for a merge.
17201734 if (MemOps.size() > 0) {
17471761 if (Merged) {
17481762 Changed = true;
17491763 unsigned Opcode = Merged->getOpcode();
1750 if (Opcode != ARM::t2STRDi8 && Opcode != ARM::t2LDRDi8)
1764 if (Opcode == ARM::t2STRDi8 || Opcode == ARM::t2LDRDi8)
1765 MergeBaseUpdateLSDouble(*Merged);
1766 else
17511767 MergeBaseUpdateLSMultiple(Merged);
17521768 } else {
17531769 for (MachineInstr *MI : Candidate->Instrs) {
17621778 }
17631779 }
17641780 Candidates.clear();
1781 // Try to fold add/sub into the LDRD/STRD formed by ARMPreAllocLoadStoreOpt.
1782 for (MachineInstr *MI : MergeBaseCandidates)
1783 MergeBaseUpdateLSDouble(*MI);
1784 MergeBaseCandidates.clear();
17651785
17661786 return Changed;
17671787 }
111111 }
112112
113113 ; CHECK-LABEL: strd_spill_ldrd_reload:
114 ; A8: strd r1, r0, [sp]
115 ; M3: strd r1, r0, [sp]
116 ; BASIC: strd r1, r0, [sp]
117 ; GREEDY: strd r0, r1, [sp]
114 ; A8: strd r1, r0, [sp, #-8]!
115 ; M3: strd r1, r0, [sp, #-8]!
116 ; BASIC: strd r1, r0, [sp, #-8]!
117 ; GREEDY: strd r0, r1, [sp, #-8]!
118118 ; CHECK: @ InlineAsm Start
119119 ; CHECK: @ InlineAsm End
120120 ; A8: ldrd r2, r1, [sp]
130130 ret void
131131 }
132132
133 declare void @extfunc2(i32*, i32, i32)
134
135 ; CHECK-LABEL: ldrd_postupdate_dec:
136 ; CHECK: ldrd r1, r2, [r0], #-8
137 ; CHECK-NEXT: bl{{x?}} _extfunc
138 define void @ldrd_postupdate_dec(i32* %p0) {
139 %p0.1 = getelementptr i32, i32* %p0, i32 1
140 %v0 = load i32, i32* %p0
141 %v1 = load i32, i32* %p0.1
142 %p1 = getelementptr i32, i32* %p0, i32 -2
143 call void @extfunc2(i32* %p1, i32 %v0, i32 %v1)
144 ret void
145 }
146
147 ; CHECK-LABEL: ldrd_postupdate_inc:
148 ; CHECK: ldrd r1, r2, [r0], #8
149 ; CHECK-NEXT: bl{{x?}} _extfunc
150 define void @ldrd_postupdate_inc(i32* %p0) {
151 %p0.1 = getelementptr i32, i32* %p0, i32 1
152 %v0 = load i32, i32* %p0
153 %v1 = load i32, i32* %p0.1
154 %p1 = getelementptr i32, i32* %p0, i32 2
155 call void @extfunc2(i32* %p1, i32 %v0, i32 %v1)
156 ret void
157 }
158
159 ; CHECK-LABEL: strd_postupdate_dec:
160 ; CHECK: strd r1, r2, [r0], #-8
161 ; CHECK-NEXT: bx lr
162 define i32* @strd_postupdate_dec(i32* %p0, i32 %v0, i32 %v1) {
163 %p0.1 = getelementptr i32, i32* %p0, i32 1
164 store i32 %v0, i32* %p0
165 store i32 %v1, i32* %p0.1
166 %p1 = getelementptr i32, i32* %p0, i32 -2
167 ret i32* %p1
168 }
169
170 ; CHECK-LABEL: strd_postupdate_inc:
171 ; CHECK: strd r1, r2, [r0], #8
172 ; CHECK-NEXT: bx lr
173 define i32* @strd_postupdate_inc(i32* %p0, i32 %v0, i32 %v1) {
174 %p0.1 = getelementptr i32, i32* %p0, i32 1
175 store i32 %v0, i32* %p0
176 store i32 %v1, i32* %p0.1
177 %p1 = getelementptr i32, i32* %p0, i32 2
178 ret i32* %p1
179 }
180
133181 declare void @llvm.lifetime.start(i64, i8* nocapture) nounwind
134182 declare void @llvm.lifetime.end(i64, i8* nocapture) nounwind