LLVM: lib/Target/ARM/ARMExpandPseudoInsts.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

29

30#include

31

32using namespace llvm;

33

34#define DEBUG_TYPE "arm-pseudo"

35

38 cl::desc("Verify machine code after expanding ARM pseudos"));

39

40#define ARM_EXPAND_PSEUDO_NAME "ARM pseudo instruction expansion pass"

41

42namespace {

44 public:

45 static char ID;

47

52

54

57 }

58

59 StringRef getPassName() const override {

61 }

62

63 private:

72 unsigned Opc, bool IsExt);

81 unsigned ClobberReg);

112 unsigned StrexOp, unsigned UxtOp,

114

118 };

119 char ARMExpandPseudo::ID = 0;

120}

121

123 false)

124

125namespace {

126

127

128

129

130 enum NEONRegSpacing {

131 SingleSpc,

132 SingleLowSpc ,

133 SingleHighQSpc,

134 SingleHighTSpc,

135 EvenDblSpc,

136 OddDblSpc

137 };

138

139

140

141 struct NEONLdStTableEntry {

144 bool IsLoad;

145 bool isUpdating;

146 bool hasWritebackOperand;

147 uint8_t RegSpacing;

148 uint8_t NumRegs;

149 uint8_t RegElts;

150

151

152

153

154

155 bool copyAllListRegs;

156

157

158 bool operator<(const NEONLdStTableEntry &TE) const {

159 return PseudoOpc < TE.PseudoOpc;

160 }

161 friend bool operator<(const NEONLdStTableEntry &TE, unsigned PseudoOpc) {

162 return TE.PseudoOpc < PseudoOpc;

163 }

164 [[maybe_unused]] friend bool operator<(unsigned PseudoOpc,

165 const NEONLdStTableEntry &TE) {

166 return PseudoOpc < TE.PseudoOpc;

167 }

168 };

169}

170

172{ ARM::VLD1LNq16Pseudo, ARM::VLD1LNd16, true, false, false, EvenDblSpc, 1, 4 ,true},

173{ ARM::VLD1LNq16Pseudo_UPD, ARM::VLD1LNd16_UPD, true, true, true, EvenDblSpc, 1, 4 ,true},

174{ ARM::VLD1LNq32Pseudo, ARM::VLD1LNd32, true, false, false, EvenDblSpc, 1, 2 ,true},

175{ ARM::VLD1LNq32Pseudo_UPD, ARM::VLD1LNd32_UPD, true, true, true, EvenDblSpc, 1, 2 ,true},

176{ ARM::VLD1LNq8Pseudo, ARM::VLD1LNd8, true, false, false, EvenDblSpc, 1, 8 ,true},

177{ ARM::VLD1LNq8Pseudo_UPD, ARM::VLD1LNd8_UPD, true, true, true, EvenDblSpc, 1, 8 ,true},

178

179{ ARM::VLD1d16QPseudo, ARM::VLD1d16Q, true, false, false, SingleSpc, 4, 4 ,false},

180{ ARM::VLD1d16QPseudoWB_fixed, ARM::VLD1d16Qwb_fixed, true, true, false, SingleSpc, 4, 4 ,false},

181{ ARM::VLD1d16QPseudoWB_register, ARM::VLD1d16Qwb_register, true, true, true, SingleSpc, 4, 4 ,false},

182{ ARM::VLD1d16TPseudo, ARM::VLD1d16T, true, false, false, SingleSpc, 3, 4 ,false},

183{ ARM::VLD1d16TPseudoWB_fixed, ARM::VLD1d16Twb_fixed, true, true, false, SingleSpc, 3, 4 ,false},

184{ ARM::VLD1d16TPseudoWB_register, ARM::VLD1d16Twb_register, true, true, true, SingleSpc, 3, 4 ,false},

185

186{ ARM::VLD1d32QPseudo, ARM::VLD1d32Q, true, false, false, SingleSpc, 4, 2 ,false},

187{ ARM::VLD1d32QPseudoWB_fixed, ARM::VLD1d32Qwb_fixed, true, true, false, SingleSpc, 4, 2 ,false},

188{ ARM::VLD1d32QPseudoWB_register, ARM::VLD1d32Qwb_register, true, true, true, SingleSpc, 4, 2 ,false},

189{ ARM::VLD1d32TPseudo, ARM::VLD1d32T, true, false, false, SingleSpc, 3, 2 ,false},

190{ ARM::VLD1d32TPseudoWB_fixed, ARM::VLD1d32Twb_fixed, true, true, false, SingleSpc, 3, 2 ,false},

191{ ARM::VLD1d32TPseudoWB_register, ARM::VLD1d32Twb_register, true, true, true, SingleSpc, 3, 2 ,false},

192

193{ ARM::VLD1d64QPseudo, ARM::VLD1d64Q, true, false, false, SingleSpc, 4, 1 ,false},

194{ ARM::VLD1d64QPseudoWB_fixed, ARM::VLD1d64Qwb_fixed, true, true, false, SingleSpc, 4, 1 ,false},

195{ ARM::VLD1d64QPseudoWB_register, ARM::VLD1d64Qwb_register, true, true, true, SingleSpc, 4, 1 ,false},

196{ ARM::VLD1d64TPseudo, ARM::VLD1d64T, true, false, false, SingleSpc, 3, 1 ,false},

197{ ARM::VLD1d64TPseudoWB_fixed, ARM::VLD1d64Twb_fixed, true, true, false, SingleSpc, 3, 1 ,false},

198{ ARM::VLD1d64TPseudoWB_register, ARM::VLD1d64Twb_register, true, true, true, SingleSpc, 3, 1 ,false},

199

200{ ARM::VLD1d8QPseudo, ARM::VLD1d8Q, true, false, false, SingleSpc, 4, 8 ,false},

201{ ARM::VLD1d8QPseudoWB_fixed, ARM::VLD1d8Qwb_fixed, true, true, false, SingleSpc, 4, 8 ,false},

202{ ARM::VLD1d8QPseudoWB_register, ARM::VLD1d8Qwb_register, true, true, true, SingleSpc, 4, 8 ,false},

203{ ARM::VLD1d8TPseudo, ARM::VLD1d8T, true, false, false, SingleSpc, 3, 8 ,false},

204{ ARM::VLD1d8TPseudoWB_fixed, ARM::VLD1d8Twb_fixed, true, true, false, SingleSpc, 3, 8 ,false},

205{ ARM::VLD1d8TPseudoWB_register, ARM::VLD1d8Twb_register, true, true, true, SingleSpc, 3, 8 ,false},

206

207{ ARM::VLD1q16HighQPseudo, ARM::VLD1d16Q, true, false, false, SingleHighQSpc, 4, 4 ,false},

208{ ARM::VLD1q16HighQPseudo_UPD, ARM::VLD1d16Qwb_fixed, true, true, true, SingleHighQSpc, 4, 4 ,false},

209{ ARM::VLD1q16HighTPseudo, ARM::VLD1d16T, true, false, false, SingleHighTSpc, 3, 4 ,false},

210{ ARM::VLD1q16HighTPseudo_UPD, ARM::VLD1d16Twb_fixed, true, true, true, SingleHighTSpc, 3, 4 ,false},

211{ ARM::VLD1q16LowQPseudo_UPD, ARM::VLD1d16Qwb_fixed, true, true, true, SingleLowSpc, 4, 4 ,false},

212{ ARM::VLD1q16LowTPseudo_UPD, ARM::VLD1d16Twb_fixed, true, true, true, SingleLowSpc, 3, 4 ,false},

213

214{ ARM::VLD1q32HighQPseudo, ARM::VLD1d32Q, true, false, false, SingleHighQSpc, 4, 2 ,false},

215{ ARM::VLD1q32HighQPseudo_UPD, ARM::VLD1d32Qwb_fixed, true, true, true, SingleHighQSpc, 4, 2 ,false},

216{ ARM::VLD1q32HighTPseudo, ARM::VLD1d32T, true, false, false, SingleHighTSpc, 3, 2 ,false},

217{ ARM::VLD1q32HighTPseudo_UPD, ARM::VLD1d32Twb_fixed, true, true, true, SingleHighTSpc, 3, 2 ,false},

218{ ARM::VLD1q32LowQPseudo_UPD, ARM::VLD1d32Qwb_fixed, true, true, true, SingleLowSpc, 4, 2 ,false},

219{ ARM::VLD1q32LowTPseudo_UPD, ARM::VLD1d32Twb_fixed, true, true, true, SingleLowSpc, 3, 2 ,false},

220

221{ ARM::VLD1q64HighQPseudo, ARM::VLD1d64Q, true, false, false, SingleHighQSpc, 4, 1 ,false},

222{ ARM::VLD1q64HighQPseudo_UPD, ARM::VLD1d64Qwb_fixed, true, true, true, SingleHighQSpc, 4, 1 ,false},

223{ ARM::VLD1q64HighTPseudo, ARM::VLD1d64T, true, false, false, SingleHighTSpc, 3, 1 ,false},

224{ ARM::VLD1q64HighTPseudo_UPD, ARM::VLD1d64Twb_fixed, true, true, true, SingleHighTSpc, 3, 1 ,false},

225{ ARM::VLD1q64LowQPseudo_UPD, ARM::VLD1d64Qwb_fixed, true, true, true, SingleLowSpc, 4, 1 ,false},

226{ ARM::VLD1q64LowTPseudo_UPD, ARM::VLD1d64Twb_fixed, true, true, true, SingleLowSpc, 3, 1 ,false},

227

228{ ARM::VLD1q8HighQPseudo, ARM::VLD1d8Q, true, false, false, SingleHighQSpc, 4, 8 ,false},

229{ ARM::VLD1q8HighQPseudo_UPD, ARM::VLD1d8Qwb_fixed, true, true, true, SingleHighQSpc, 4, 8 ,false},

230{ ARM::VLD1q8HighTPseudo, ARM::VLD1d8T, true, false, false, SingleHighTSpc, 3, 8 ,false},

231{ ARM::VLD1q8HighTPseudo_UPD, ARM::VLD1d8Twb_fixed, true, true, true, SingleHighTSpc, 3, 8 ,false},

232{ ARM::VLD1q8LowQPseudo_UPD, ARM::VLD1d8Qwb_fixed, true, true, true, SingleLowSpc, 4, 8 ,false},

233{ ARM::VLD1q8LowTPseudo_UPD, ARM::VLD1d8Twb_fixed, true, true, true, SingleLowSpc, 3, 8 ,false},

234

235{ ARM::VLD2DUPq16EvenPseudo, ARM::VLD2DUPd16x2, true, false, false, EvenDblSpc, 2, 4 ,false},

236{ ARM::VLD2DUPq16OddPseudo, ARM::VLD2DUPd16x2, true, false, false, OddDblSpc, 2, 4 ,false},

237{ ARM::VLD2DUPq16OddPseudoWB_fixed, ARM::VLD2DUPd16x2wb_fixed, true, true, false, OddDblSpc, 2, 4 ,false},

238{ ARM::VLD2DUPq16OddPseudoWB_register, ARM::VLD2DUPd16x2wb_register, true, true, true, OddDblSpc, 2, 4 ,false},

239{ ARM::VLD2DUPq32EvenPseudo, ARM::VLD2DUPd32x2, true, false, false, EvenDblSpc, 2, 2 ,false},

240{ ARM::VLD2DUPq32OddPseudo, ARM::VLD2DUPd32x2, true, false, false, OddDblSpc, 2, 2 ,false},

241{ ARM::VLD2DUPq32OddPseudoWB_fixed, ARM::VLD2DUPd32x2wb_fixed, true, true, false, OddDblSpc, 2, 2 ,false},

242{ ARM::VLD2DUPq32OddPseudoWB_register, ARM::VLD2DUPd32x2wb_register, true, true, true, OddDblSpc, 2, 2 ,false},

243{ ARM::VLD2DUPq8EvenPseudo, ARM::VLD2DUPd8x2, true, false, false, EvenDblSpc, 2, 8 ,false},

244{ ARM::VLD2DUPq8OddPseudo, ARM::VLD2DUPd8x2, true, false, false, OddDblSpc, 2, 8 ,false},

245{ ARM::VLD2DUPq8OddPseudoWB_fixed, ARM::VLD2DUPd8x2wb_fixed, true, true, false, OddDblSpc, 2, 8 ,false},

246{ ARM::VLD2DUPq8OddPseudoWB_register, ARM::VLD2DUPd8x2wb_register, true, true, true, OddDblSpc, 2, 8 ,false},

247

248{ ARM::VLD2LNd16Pseudo, ARM::VLD2LNd16, true, false, false, SingleSpc, 2, 4 ,true},

249{ ARM::VLD2LNd16Pseudo_UPD, ARM::VLD2LNd16_UPD, true, true, true, SingleSpc, 2, 4 ,true},

250{ ARM::VLD2LNd32Pseudo, ARM::VLD2LNd32, true, false, false, SingleSpc, 2, 2 ,true},

251{ ARM::VLD2LNd32Pseudo_UPD, ARM::VLD2LNd32_UPD, true, true, true, SingleSpc, 2, 2 ,true},

252{ ARM::VLD2LNd8Pseudo, ARM::VLD2LNd8, true, false, false, SingleSpc, 2, 8 ,true},

253{ ARM::VLD2LNd8Pseudo_UPD, ARM::VLD2LNd8_UPD, true, true, true, SingleSpc, 2, 8 ,true},

254{ ARM::VLD2LNq16Pseudo, ARM::VLD2LNq16, true, false, false, EvenDblSpc, 2, 4 ,true},

255{ ARM::VLD2LNq16Pseudo_UPD, ARM::VLD2LNq16_UPD, true, true, true, EvenDblSpc, 2, 4 ,true},

256{ ARM::VLD2LNq32Pseudo, ARM::VLD2LNq32, true, false, false, EvenDblSpc, 2, 2 ,true},

257{ ARM::VLD2LNq32Pseudo_UPD, ARM::VLD2LNq32_UPD, true, true, true, EvenDblSpc, 2, 2 ,true},

258

259{ ARM::VLD2q16Pseudo, ARM::VLD2q16, true, false, false, SingleSpc, 4, 4 ,false},

260{ ARM::VLD2q16PseudoWB_fixed, ARM::VLD2q16wb_fixed, true, true, false, SingleSpc, 4, 4 ,false},

261{ ARM::VLD2q16PseudoWB_register, ARM::VLD2q16wb_register, true, true, true, SingleSpc, 4, 4 ,false},

262{ ARM::VLD2q32Pseudo, ARM::VLD2q32, true, false, false, SingleSpc, 4, 2 ,false},

263{ ARM::VLD2q32PseudoWB_fixed, ARM::VLD2q32wb_fixed, true, true, false, SingleSpc, 4, 2 ,false},

264{ ARM::VLD2q32PseudoWB_register, ARM::VLD2q32wb_register, true, true, true, SingleSpc, 4, 2 ,false},

265{ ARM::VLD2q8Pseudo, ARM::VLD2q8, true, false, false, SingleSpc, 4, 8 ,false},

266{ ARM::VLD2q8PseudoWB_fixed, ARM::VLD2q8wb_fixed, true, true, false, SingleSpc, 4, 8 ,false},

267{ ARM::VLD2q8PseudoWB_register, ARM::VLD2q8wb_register, true, true, true, SingleSpc, 4, 8 ,false},

268

269{ ARM::VLD3DUPd16Pseudo, ARM::VLD3DUPd16, true, false, false, SingleSpc, 3, 4,true},

270{ ARM::VLD3DUPd16Pseudo_UPD, ARM::VLD3DUPd16_UPD, true, true, true, SingleSpc, 3, 4,true},

271{ ARM::VLD3DUPd32Pseudo, ARM::VLD3DUPd32, true, false, false, SingleSpc, 3, 2,true},

272{ ARM::VLD3DUPd32Pseudo_UPD, ARM::VLD3DUPd32_UPD, true, true, true, SingleSpc, 3, 2,true},

273{ ARM::VLD3DUPd8Pseudo, ARM::VLD3DUPd8, true, false, false, SingleSpc, 3, 8,true},

274{ ARM::VLD3DUPd8Pseudo_UPD, ARM::VLD3DUPd8_UPD, true, true, true, SingleSpc, 3, 8,true},

275{ ARM::VLD3DUPq16EvenPseudo, ARM::VLD3DUPq16, true, false, false, EvenDblSpc, 3, 4 ,true},

276{ ARM::VLD3DUPq16OddPseudo, ARM::VLD3DUPq16, true, false, false, OddDblSpc, 3, 4 ,true},

277{ ARM::VLD3DUPq16OddPseudo_UPD, ARM::VLD3DUPq16_UPD, true, true, true, OddDblSpc, 3, 4 ,true},

278{ ARM::VLD3DUPq32EvenPseudo, ARM::VLD3DUPq32, true, false, false, EvenDblSpc, 3, 2 ,true},

279{ ARM::VLD3DUPq32OddPseudo, ARM::VLD3DUPq32, true, false, false, OddDblSpc, 3, 2 ,true},

280{ ARM::VLD3DUPq32OddPseudo_UPD, ARM::VLD3DUPq32_UPD, true, true, true, OddDblSpc, 3, 2 ,true},

281{ ARM::VLD3DUPq8EvenPseudo, ARM::VLD3DUPq8, true, false, false, EvenDblSpc, 3, 8 ,true},

282{ ARM::VLD3DUPq8OddPseudo, ARM::VLD3DUPq8, true, false, false, OddDblSpc, 3, 8 ,true},

283{ ARM::VLD3DUPq8OddPseudo_UPD, ARM::VLD3DUPq8_UPD, true, true, true, OddDblSpc, 3, 8 ,true},

284

285{ ARM::VLD3LNd16Pseudo, ARM::VLD3LNd16, true, false, false, SingleSpc, 3, 4 ,true},

286{ ARM::VLD3LNd16Pseudo_UPD, ARM::VLD3LNd16_UPD, true, true, true, SingleSpc, 3, 4 ,true},

287{ ARM::VLD3LNd32Pseudo, ARM::VLD3LNd32, true, false, false, SingleSpc, 3, 2 ,true},

288{ ARM::VLD3LNd32Pseudo_UPD, ARM::VLD3LNd32_UPD, true, true, true, SingleSpc, 3, 2 ,true},

289{ ARM::VLD3LNd8Pseudo, ARM::VLD3LNd8, true, false, false, SingleSpc, 3, 8 ,true},

290{ ARM::VLD3LNd8Pseudo_UPD, ARM::VLD3LNd8_UPD, true, true, true, SingleSpc, 3, 8 ,true},

291{ ARM::VLD3LNq16Pseudo, ARM::VLD3LNq16, true, false, false, EvenDblSpc, 3, 4 ,true},

292{ ARM::VLD3LNq16Pseudo_UPD, ARM::VLD3LNq16_UPD, true, true, true, EvenDblSpc, 3, 4 ,true},

293{ ARM::VLD3LNq32Pseudo, ARM::VLD3LNq32, true, false, false, EvenDblSpc, 3, 2 ,true},

294{ ARM::VLD3LNq32Pseudo_UPD, ARM::VLD3LNq32_UPD, true, true, true, EvenDblSpc, 3, 2 ,true},

295

296{ ARM::VLD3d16Pseudo, ARM::VLD3d16, true, false, false, SingleSpc, 3, 4 ,true},

297{ ARM::VLD3d16Pseudo_UPD, ARM::VLD3d16_UPD, true, true, true, SingleSpc, 3, 4 ,true},

298{ ARM::VLD3d32Pseudo, ARM::VLD3d32, true, false, false, SingleSpc, 3, 2 ,true},

299{ ARM::VLD3d32Pseudo_UPD, ARM::VLD3d32_UPD, true, true, true, SingleSpc, 3, 2 ,true},

300{ ARM::VLD3d8Pseudo, ARM::VLD3d8, true, false, false, SingleSpc, 3, 8 ,true},

301{ ARM::VLD3d8Pseudo_UPD, ARM::VLD3d8_UPD, true, true, true, SingleSpc, 3, 8 ,true},

302

303{ ARM::VLD3q16Pseudo_UPD, ARM::VLD3q16_UPD, true, true, true, EvenDblSpc, 3, 4 ,true},

304{ ARM::VLD3q16oddPseudo, ARM::VLD3q16, true, false, false, OddDblSpc, 3, 4 ,true},

305{ ARM::VLD3q16oddPseudo_UPD, ARM::VLD3q16_UPD, true, true, true, OddDblSpc, 3, 4 ,true},

306{ ARM::VLD3q32Pseudo_UPD, ARM::VLD3q32_UPD, true, true, true, EvenDblSpc, 3, 2 ,true},

307{ ARM::VLD3q32oddPseudo, ARM::VLD3q32, true, false, false, OddDblSpc, 3, 2 ,true},

308{ ARM::VLD3q32oddPseudo_UPD, ARM::VLD3q32_UPD, true, true, true, OddDblSpc, 3, 2 ,true},

309{ ARM::VLD3q8Pseudo_UPD, ARM::VLD3q8_UPD, true, true, true, EvenDblSpc, 3, 8 ,true},

310{ ARM::VLD3q8oddPseudo, ARM::VLD3q8, true, false, false, OddDblSpc, 3, 8 ,true},

311{ ARM::VLD3q8oddPseudo_UPD, ARM::VLD3q8_UPD, true, true, true, OddDblSpc, 3, 8 ,true},

312

313{ ARM::VLD4DUPd16Pseudo, ARM::VLD4DUPd16, true, false, false, SingleSpc, 4, 4,true},

314{ ARM::VLD4DUPd16Pseudo_UPD, ARM::VLD4DUPd16_UPD, true, true, true, SingleSpc, 4, 4,true},

315{ ARM::VLD4DUPd32Pseudo, ARM::VLD4DUPd32, true, false, false, SingleSpc, 4, 2,true},

316{ ARM::VLD4DUPd32Pseudo_UPD, ARM::VLD4DUPd32_UPD, true, true, true, SingleSpc, 4, 2,true},

317{ ARM::VLD4DUPd8Pseudo, ARM::VLD4DUPd8, true, false, false, SingleSpc, 4, 8,true},

318{ ARM::VLD4DUPd8Pseudo_UPD, ARM::VLD4DUPd8_UPD, true, true, true, SingleSpc, 4, 8,true},

319{ ARM::VLD4DUPq16EvenPseudo, ARM::VLD4DUPq16, true, false, false, EvenDblSpc, 4, 4 ,true},

320{ ARM::VLD4DUPq16OddPseudo, ARM::VLD4DUPq16, true, false, false, OddDblSpc, 4, 4 ,true},

321{ ARM::VLD4DUPq16OddPseudo_UPD, ARM::VLD4DUPq16_UPD, true, true, true, OddDblSpc, 4, 4 ,true},

322{ ARM::VLD4DUPq32EvenPseudo, ARM::VLD4DUPq32, true, false, false, EvenDblSpc, 4, 2 ,true},

323{ ARM::VLD4DUPq32OddPseudo, ARM::VLD4DUPq32, true, false, false, OddDblSpc, 4, 2 ,true},

324{ ARM::VLD4DUPq32OddPseudo_UPD, ARM::VLD4DUPq32_UPD, true, true, true, OddDblSpc, 4, 2 ,true},

325{ ARM::VLD4DUPq8EvenPseudo, ARM::VLD4DUPq8, true, false, false, EvenDblSpc, 4, 8 ,true},

326{ ARM::VLD4DUPq8OddPseudo, ARM::VLD4DUPq8, true, false, false, OddDblSpc, 4, 8 ,true},

327{ ARM::VLD4DUPq8OddPseudo_UPD, ARM::VLD4DUPq8_UPD, true, true, true, OddDblSpc, 4, 8 ,true},

328

329{ ARM::VLD4LNd16Pseudo, ARM::VLD4LNd16, true, false, false, SingleSpc, 4, 4 ,true},

330{ ARM::VLD4LNd16Pseudo_UPD, ARM::VLD4LNd16_UPD, true, true, true, SingleSpc, 4, 4 ,true},

331{ ARM::VLD4LNd32Pseudo, ARM::VLD4LNd32, true, false, false, SingleSpc, 4, 2 ,true},

332{ ARM::VLD4LNd32Pseudo_UPD, ARM::VLD4LNd32_UPD, true, true, true, SingleSpc, 4, 2 ,true},

333{ ARM::VLD4LNd8Pseudo, ARM::VLD4LNd8, true, false, false, SingleSpc, 4, 8 ,true},

334{ ARM::VLD4LNd8Pseudo_UPD, ARM::VLD4LNd8_UPD, true, true, true, SingleSpc, 4, 8 ,true},

335{ ARM::VLD4LNq16Pseudo, ARM::VLD4LNq16, true, false, false, EvenDblSpc, 4, 4 ,true},

336{ ARM::VLD4LNq16Pseudo_UPD, ARM::VLD4LNq16_UPD, true, true, true, EvenDblSpc, 4, 4 ,true},

337{ ARM::VLD4LNq32Pseudo, ARM::VLD4LNq32, true, false, false, EvenDblSpc, 4, 2 ,true},

338{ ARM::VLD4LNq32Pseudo_UPD, ARM::VLD4LNq32_UPD, true, true, true, EvenDblSpc, 4, 2 ,true},

339

340{ ARM::VLD4d16Pseudo, ARM::VLD4d16, true, false, false, SingleSpc, 4, 4 ,true},

341{ ARM::VLD4d16Pseudo_UPD, ARM::VLD4d16_UPD, true, true, true, SingleSpc, 4, 4 ,true},

342{ ARM::VLD4d32Pseudo, ARM::VLD4d32, true, false, false, SingleSpc, 4, 2 ,true},

343{ ARM::VLD4d32Pseudo_UPD, ARM::VLD4d32_UPD, true, true, true, SingleSpc, 4, 2 ,true},

344{ ARM::VLD4d8Pseudo, ARM::VLD4d8, true, false, false, SingleSpc, 4, 8 ,true},

345{ ARM::VLD4d8Pseudo_UPD, ARM::VLD4d8_UPD, true, true, true, SingleSpc, 4, 8 ,true},

346

347{ ARM::VLD4q16Pseudo_UPD, ARM::VLD4q16_UPD, true, true, true, EvenDblSpc, 4, 4 ,true},

348{ ARM::VLD4q16oddPseudo, ARM::VLD4q16, true, false, false, OddDblSpc, 4, 4 ,true},

349{ ARM::VLD4q16oddPseudo_UPD, ARM::VLD4q16_UPD, true, true, true, OddDblSpc, 4, 4 ,true},

350{ ARM::VLD4q32Pseudo_UPD, ARM::VLD4q32_UPD, true, true, true, EvenDblSpc, 4, 2 ,true},

351{ ARM::VLD4q32oddPseudo, ARM::VLD4q32, true, false, false, OddDblSpc, 4, 2 ,true},

352{ ARM::VLD4q32oddPseudo_UPD, ARM::VLD4q32_UPD, true, true, true, OddDblSpc, 4, 2 ,true},

353{ ARM::VLD4q8Pseudo_UPD, ARM::VLD4q8_UPD, true, true, true, EvenDblSpc, 4, 8 ,true},

354{ ARM::VLD4q8oddPseudo, ARM::VLD4q8, true, false, false, OddDblSpc, 4, 8 ,true},

355{ ARM::VLD4q8oddPseudo_UPD, ARM::VLD4q8_UPD, true, true, true, OddDblSpc, 4, 8 ,true},

356

357{ ARM::VST1LNq16Pseudo, ARM::VST1LNd16, false, false, false, EvenDblSpc, 1, 4 ,true},

358{ ARM::VST1LNq16Pseudo_UPD, ARM::VST1LNd16_UPD, false, true, true, EvenDblSpc, 1, 4 ,true},

359{ ARM::VST1LNq32Pseudo, ARM::VST1LNd32, false, false, false, EvenDblSpc, 1, 2 ,true},

360{ ARM::VST1LNq32Pseudo_UPD, ARM::VST1LNd32_UPD, false, true, true, EvenDblSpc, 1, 2 ,true},

361{ ARM::VST1LNq8Pseudo, ARM::VST1LNd8, false, false, false, EvenDblSpc, 1, 8 ,true},

362{ ARM::VST1LNq8Pseudo_UPD, ARM::VST1LNd8_UPD, false, true, true, EvenDblSpc, 1, 8 ,true},

363

364{ ARM::VST1d16QPseudo, ARM::VST1d16Q, false, false, false, SingleSpc, 4, 4 ,false},

365{ ARM::VST1d16QPseudoWB_fixed, ARM::VST1d16Qwb_fixed, false, true, false, SingleSpc, 4, 4 ,false},

366{ ARM::VST1d16QPseudoWB_register, ARM::VST1d16Qwb_register, false, true, true, SingleSpc, 4, 4 ,false},

367{ ARM::VST1d16TPseudo, ARM::VST1d16T, false, false, false, SingleSpc, 3, 4 ,false},

368{ ARM::VST1d16TPseudoWB_fixed, ARM::VST1d16Twb_fixed, false, true, false, SingleSpc, 3, 4 ,false},

369{ ARM::VST1d16TPseudoWB_register, ARM::VST1d16Twb_register, false, true, true, SingleSpc, 3, 4 ,false},

370

371{ ARM::VST1d32QPseudo, ARM::VST1d32Q, false, false, false, SingleSpc, 4, 2 ,false},

372{ ARM::VST1d32QPseudoWB_fixed, ARM::VST1d32Qwb_fixed, false, true, false, SingleSpc, 4, 2 ,false},

373{ ARM::VST1d32QPseudoWB_register, ARM::VST1d32Qwb_register, false, true, true, SingleSpc, 4, 2 ,false},

374{ ARM::VST1d32TPseudo, ARM::VST1d32T, false, false, false, SingleSpc, 3, 2 ,false},

375{ ARM::VST1d32TPseudoWB_fixed, ARM::VST1d32Twb_fixed, false, true, false, SingleSpc, 3, 2 ,false},

376{ ARM::VST1d32TPseudoWB_register, ARM::VST1d32Twb_register, false, true, true, SingleSpc, 3, 2 ,false},

377

378{ ARM::VST1d64QPseudo, ARM::VST1d64Q, false, false, false, SingleSpc, 4, 1 ,false},

379{ ARM::VST1d64QPseudoWB_fixed, ARM::VST1d64Qwb_fixed, false, true, false, SingleSpc, 4, 1 ,false},

380{ ARM::VST1d64QPseudoWB_register, ARM::VST1d64Qwb_register, false, true, true, SingleSpc, 4, 1 ,false},

381{ ARM::VST1d64TPseudo, ARM::VST1d64T, false, false, false, SingleSpc, 3, 1 ,false},

382{ ARM::VST1d64TPseudoWB_fixed, ARM::VST1d64Twb_fixed, false, true, false, SingleSpc, 3, 1 ,false},

383{ ARM::VST1d64TPseudoWB_register, ARM::VST1d64Twb_register, false, true, true, SingleSpc, 3, 1 ,false},

384

385{ ARM::VST1d8QPseudo, ARM::VST1d8Q, false, false, false, SingleSpc, 4, 8 ,false},

386{ ARM::VST1d8QPseudoWB_fixed, ARM::VST1d8Qwb_fixed, false, true, false, SingleSpc, 4, 8 ,false},

387{ ARM::VST1d8QPseudoWB_register, ARM::VST1d8Qwb_register, false, true, true, SingleSpc, 4, 8 ,false},

388{ ARM::VST1d8TPseudo, ARM::VST1d8T, false, false, false, SingleSpc, 3, 8 ,false},

389{ ARM::VST1d8TPseudoWB_fixed, ARM::VST1d8Twb_fixed, false, true, false, SingleSpc, 3, 8 ,false},

390{ ARM::VST1d8TPseudoWB_register, ARM::VST1d8Twb_register, false, true, true, SingleSpc, 3, 8 ,false},

391

392{ ARM::VST1q16HighQPseudo, ARM::VST1d16Q, false, false, false, SingleHighQSpc, 4, 4 ,false},

393{ ARM::VST1q16HighQPseudo_UPD, ARM::VST1d16Qwb_fixed, false, true, true, SingleHighQSpc, 4, 8 ,false},

394{ ARM::VST1q16HighTPseudo, ARM::VST1d16T, false, false, false, SingleHighTSpc, 3, 4 ,false},

395{ ARM::VST1q16HighTPseudo_UPD, ARM::VST1d16Twb_fixed, false, true, true, SingleHighTSpc, 3, 4 ,false},

396{ ARM::VST1q16LowQPseudo_UPD, ARM::VST1d16Qwb_fixed, false, true, true, SingleLowSpc, 4, 4 ,false},

397{ ARM::VST1q16LowTPseudo_UPD, ARM::VST1d16Twb_fixed, false, true, true, SingleLowSpc, 3, 4 ,false},

398

399{ ARM::VST1q32HighQPseudo, ARM::VST1d32Q, false, false, false, SingleHighQSpc, 4, 2 ,false},

400{ ARM::VST1q32HighQPseudo_UPD, ARM::VST1d32Qwb_fixed, false, true, true, SingleHighQSpc, 4, 8 ,false},

401{ ARM::VST1q32HighTPseudo, ARM::VST1d32T, false, false, false, SingleHighTSpc, 3, 2 ,false},

402{ ARM::VST1q32HighTPseudo_UPD, ARM::VST1d32Twb_fixed, false, true, true, SingleHighTSpc, 3, 2 ,false},

403{ ARM::VST1q32LowQPseudo_UPD, ARM::VST1d32Qwb_fixed, false, true, true, SingleLowSpc, 4, 2 ,false},

404{ ARM::VST1q32LowTPseudo_UPD, ARM::VST1d32Twb_fixed, false, true, true, SingleLowSpc, 3, 2 ,false},

405

406{ ARM::VST1q64HighQPseudo, ARM::VST1d64Q, false, false, false, SingleHighQSpc, 4, 1 ,false},

407{ ARM::VST1q64HighQPseudo_UPD, ARM::VST1d64Qwb_fixed, false, true, true, SingleHighQSpc, 4, 8 ,false},

408{ ARM::VST1q64HighTPseudo, ARM::VST1d64T, false, false, false, SingleHighTSpc, 3, 1 ,false},

409{ ARM::VST1q64HighTPseudo_UPD, ARM::VST1d64Twb_fixed, false, true, true, SingleHighTSpc, 3, 1 ,false},

410{ ARM::VST1q64LowQPseudo_UPD, ARM::VST1d64Qwb_fixed, false, true, true, SingleLowSpc, 4, 1 ,false},

411{ ARM::VST1q64LowTPseudo_UPD, ARM::VST1d64Twb_fixed, false, true, true, SingleLowSpc, 3, 1 ,false},

412

413{ ARM::VST1q8HighQPseudo, ARM::VST1d8Q, false, false, false, SingleHighQSpc, 4, 8 ,false},

414{ ARM::VST1q8HighQPseudo_UPD, ARM::VST1d8Qwb_fixed, false, true, true, SingleHighQSpc, 4, 8 ,false},

415{ ARM::VST1q8HighTPseudo, ARM::VST1d8T, false, false, false, SingleHighTSpc, 3, 8 ,false},

416{ ARM::VST1q8HighTPseudo_UPD, ARM::VST1d8Twb_fixed, false, true, true, SingleHighTSpc, 3, 8 ,false},

417{ ARM::VST1q8LowQPseudo_UPD, ARM::VST1d8Qwb_fixed, false, true, true, SingleLowSpc, 4, 8 ,false},

418{ ARM::VST1q8LowTPseudo_UPD, ARM::VST1d8Twb_fixed, false, true, true, SingleLowSpc, 3, 8 ,false},

419

420{ ARM::VST2LNd16Pseudo, ARM::VST2LNd16, false, false, false, SingleSpc, 2, 4 ,true},

421{ ARM::VST2LNd16Pseudo_UPD, ARM::VST2LNd16_UPD, false, true, true, SingleSpc, 2, 4 ,true},

422{ ARM::VST2LNd32Pseudo, ARM::VST2LNd32, false, false, false, SingleSpc, 2, 2 ,true},

423{ ARM::VST2LNd32Pseudo_UPD, ARM::VST2LNd32_UPD, false, true, true, SingleSpc, 2, 2 ,true},

424{ ARM::VST2LNd8Pseudo, ARM::VST2LNd8, false, false, false, SingleSpc, 2, 8 ,true},

425{ ARM::VST2LNd8Pseudo_UPD, ARM::VST2LNd8_UPD, false, true, true, SingleSpc, 2, 8 ,true},

426{ ARM::VST2LNq16Pseudo, ARM::VST2LNq16, false, false, false, EvenDblSpc, 2, 4,true},

427{ ARM::VST2LNq16Pseudo_UPD, ARM::VST2LNq16_UPD, false, true, true, EvenDblSpc, 2, 4,true},

428{ ARM::VST2LNq32Pseudo, ARM::VST2LNq32, false, false, false, EvenDblSpc, 2, 2,true},

429{ ARM::VST2LNq32Pseudo_UPD, ARM::VST2LNq32_UPD, false, true, true, EvenDblSpc, 2, 2,true},

430

431{ ARM::VST2q16Pseudo, ARM::VST2q16, false, false, false, SingleSpc, 4, 4 ,false},

432{ ARM::VST2q16PseudoWB_fixed, ARM::VST2q16wb_fixed, false, true, false, SingleSpc, 4, 4 ,false},

433{ ARM::VST2q16PseudoWB_register, ARM::VST2q16wb_register, false, true, true, SingleSpc, 4, 4 ,false},

434{ ARM::VST2q32Pseudo, ARM::VST2q32, false, false, false, SingleSpc, 4, 2 ,false},

435{ ARM::VST2q32PseudoWB_fixed, ARM::VST2q32wb_fixed, false, true, false, SingleSpc, 4, 2 ,false},

436{ ARM::VST2q32PseudoWB_register, ARM::VST2q32wb_register, false, true, true, SingleSpc, 4, 2 ,false},

437{ ARM::VST2q8Pseudo, ARM::VST2q8, false, false, false, SingleSpc, 4, 8 ,false},

438{ ARM::VST2q8PseudoWB_fixed, ARM::VST2q8wb_fixed, false, true, false, SingleSpc, 4, 8 ,false},

439{ ARM::VST2q8PseudoWB_register, ARM::VST2q8wb_register, false, true, true, SingleSpc, 4, 8 ,false},

440

441{ ARM::VST3LNd16Pseudo, ARM::VST3LNd16, false, false, false, SingleSpc, 3, 4 ,true},

442{ ARM::VST3LNd16Pseudo_UPD, ARM::VST3LNd16_UPD, false, true, true, SingleSpc, 3, 4 ,true},

443{ ARM::VST3LNd32Pseudo, ARM::VST3LNd32, false, false, false, SingleSpc, 3, 2 ,true},

444{ ARM::VST3LNd32Pseudo_UPD, ARM::VST3LNd32_UPD, false, true, true, SingleSpc, 3, 2 ,true},

445{ ARM::VST3LNd8Pseudo, ARM::VST3LNd8, false, false, false, SingleSpc, 3, 8 ,true},

446{ ARM::VST3LNd8Pseudo_UPD, ARM::VST3LNd8_UPD, false, true, true, SingleSpc, 3, 8 ,true},

447{ ARM::VST3LNq16Pseudo, ARM::VST3LNq16, false, false, false, EvenDblSpc, 3, 4,true},

448{ ARM::VST3LNq16Pseudo_UPD, ARM::VST3LNq16_UPD, false, true, true, EvenDblSpc, 3, 4,true},

449{ ARM::VST3LNq32Pseudo, ARM::VST3LNq32, false, false, false, EvenDblSpc, 3, 2,true},

450{ ARM::VST3LNq32Pseudo_UPD, ARM::VST3LNq32_UPD, false, true, true, EvenDblSpc, 3, 2,true},

451

452{ ARM::VST3d16Pseudo, ARM::VST3d16, false, false, false, SingleSpc, 3, 4 ,true},

453{ ARM::VST3d16Pseudo_UPD, ARM::VST3d16_UPD, false, true, true, SingleSpc, 3, 4 ,true},

454{ ARM::VST3d32Pseudo, ARM::VST3d32, false, false, false, SingleSpc, 3, 2 ,true},

455{ ARM::VST3d32Pseudo_UPD, ARM::VST3d32_UPD, false, true, true, SingleSpc, 3, 2 ,true},

456{ ARM::VST3d8Pseudo, ARM::VST3d8, false, false, false, SingleSpc, 3, 8 ,true},

457{ ARM::VST3d8Pseudo_UPD, ARM::VST3d8_UPD, false, true, true, SingleSpc, 3, 8 ,true},

458

459{ ARM::VST3q16Pseudo_UPD, ARM::VST3q16_UPD, false, true, true, EvenDblSpc, 3, 4 ,true},

460{ ARM::VST3q16oddPseudo, ARM::VST3q16, false, false, false, OddDblSpc, 3, 4 ,true},

461{ ARM::VST3q16oddPseudo_UPD, ARM::VST3q16_UPD, false, true, true, OddDblSpc, 3, 4 ,true},

462{ ARM::VST3q32Pseudo_UPD, ARM::VST3q32_UPD, false, true, true, EvenDblSpc, 3, 2 ,true},

463{ ARM::VST3q32oddPseudo, ARM::VST3q32, false, false, false, OddDblSpc, 3, 2 ,true},

464{ ARM::VST3q32oddPseudo_UPD, ARM::VST3q32_UPD, false, true, true, OddDblSpc, 3, 2 ,true},

465{ ARM::VST3q8Pseudo_UPD, ARM::VST3q8_UPD, false, true, true, EvenDblSpc, 3, 8 ,true},

466{ ARM::VST3q8oddPseudo, ARM::VST3q8, false, false, false, OddDblSpc, 3, 8 ,true},

467{ ARM::VST3q8oddPseudo_UPD, ARM::VST3q8_UPD, false, true, true, OddDblSpc, 3, 8 ,true},

468

469{ ARM::VST4LNd16Pseudo, ARM::VST4LNd16, false, false, false, SingleSpc, 4, 4 ,true},

470{ ARM::VST4LNd16Pseudo_UPD, ARM::VST4LNd16_UPD, false, true, true, SingleSpc, 4, 4 ,true},

471{ ARM::VST4LNd32Pseudo, ARM::VST4LNd32, false, false, false, SingleSpc, 4, 2 ,true},

472{ ARM::VST4LNd32Pseudo_UPD, ARM::VST4LNd32_UPD, false, true, true, SingleSpc, 4, 2 ,true},

473{ ARM::VST4LNd8Pseudo, ARM::VST4LNd8, false, false, false, SingleSpc, 4, 8 ,true},

474{ ARM::VST4LNd8Pseudo_UPD, ARM::VST4LNd8_UPD, false, true, true, SingleSpc, 4, 8 ,true},

475{ ARM::VST4LNq16Pseudo, ARM::VST4LNq16, false, false, false, EvenDblSpc, 4, 4,true},

476{ ARM::VST4LNq16Pseudo_UPD, ARM::VST4LNq16_UPD, false, true, true, EvenDblSpc, 4, 4,true},

477{ ARM::VST4LNq32Pseudo, ARM::VST4LNq32, false, false, false, EvenDblSpc, 4, 2,true},

478{ ARM::VST4LNq32Pseudo_UPD, ARM::VST4LNq32_UPD, false, true, true, EvenDblSpc, 4, 2,true},

479

480{ ARM::VST4d16Pseudo, ARM::VST4d16, false, false, false, SingleSpc, 4, 4 ,true},

481{ ARM::VST4d16Pseudo_UPD, ARM::VST4d16_UPD, false, true, true, SingleSpc, 4, 4 ,true},

482{ ARM::VST4d32Pseudo, ARM::VST4d32, false, false, false, SingleSpc, 4, 2 ,true},

483{ ARM::VST4d32Pseudo_UPD, ARM::VST4d32_UPD, false, true, true, SingleSpc, 4, 2 ,true},

484{ ARM::VST4d8Pseudo, ARM::VST4d8, false, false, false, SingleSpc, 4, 8 ,true},

485{ ARM::VST4d8Pseudo_UPD, ARM::VST4d8_UPD, false, true, true, SingleSpc, 4, 8 ,true},

486

487{ ARM::VST4q16Pseudo_UPD, ARM::VST4q16_UPD, false, true, true, EvenDblSpc, 4, 4 ,true},

488{ ARM::VST4q16oddPseudo, ARM::VST4q16, false, false, false, OddDblSpc, 4, 4 ,true},

489{ ARM::VST4q16oddPseudo_UPD, ARM::VST4q16_UPD, false, true, true, OddDblSpc, 4, 4 ,true},

490{ ARM::VST4q32Pseudo_UPD, ARM::VST4q32_UPD, false, true, true, EvenDblSpc, 4, 2 ,true},

491{ ARM::VST4q32oddPseudo, ARM::VST4q32, false, false, false, OddDblSpc, 4, 2 ,true},

492{ ARM::VST4q32oddPseudo_UPD, ARM::VST4q32_UPD, false, true, true, OddDblSpc, 4, 2 ,true},

493{ ARM::VST4q8Pseudo_UPD, ARM::VST4q8_UPD, false, true, true, EvenDblSpc, 4, 8 ,true},

494{ ARM::VST4q8oddPseudo, ARM::VST4q8, false, false, false, OddDblSpc, 4, 8 ,true},

495{ ARM::VST4q8oddPseudo_UPD, ARM::VST4q8_UPD, false, true, true, OddDblSpc, 4, 8 ,true}

496};

497

498

499

500static const NEONLdStTableEntry *LookupNEONLdSt(unsigned Opcode) {

501#ifndef NDEBUG

502

503 static std::atomic TableChecked(false);

504 if (!TableChecked.load(std::memory_order_relaxed)) {

506 TableChecked.store(true, std::memory_order_relaxed);

507 }

508#endif

509

511 if (I != std::end(NEONLdStTable) && I->PseudoOpc == Opcode)

512 return I;

513 return nullptr;

514}

515

516

517

518

522 if (RegSpc == SingleSpc || RegSpc == SingleLowSpc) {

523 D0 = TRI->getSubReg(Reg, ARM::dsub_0);

524 D1 = TRI->getSubReg(Reg, ARM::dsub_1);

525 D2 = TRI->getSubReg(Reg, ARM::dsub_2);

526 D3 = TRI->getSubReg(Reg, ARM::dsub_3);

527 } else if (RegSpc == SingleHighQSpc) {

528 D0 = TRI->getSubReg(Reg, ARM::dsub_4);

529 D1 = TRI->getSubReg(Reg, ARM::dsub_5);

530 D2 = TRI->getSubReg(Reg, ARM::dsub_6);

531 D3 = TRI->getSubReg(Reg, ARM::dsub_7);

532 } else if (RegSpc == SingleHighTSpc) {

533 D0 = TRI->getSubReg(Reg, ARM::dsub_3);

534 D1 = TRI->getSubReg(Reg, ARM::dsub_4);

535 D2 = TRI->getSubReg(Reg, ARM::dsub_5);

536 D3 = TRI->getSubReg(Reg, ARM::dsub_6);

537 } else if (RegSpc == EvenDblSpc) {

538 D0 = TRI->getSubReg(Reg, ARM::dsub_0);

539 D1 = TRI->getSubReg(Reg, ARM::dsub_2);

540 D2 = TRI->getSubReg(Reg, ARM::dsub_4);

541 D3 = TRI->getSubReg(Reg, ARM::dsub_6);

542 } else {

543 assert(RegSpc == OddDblSpc && "unknown register spacing");

544 D0 = TRI->getSubReg(Reg, ARM::dsub_1);

545 D1 = TRI->getSubReg(Reg, ARM::dsub_3);

546 D2 = TRI->getSubReg(Reg, ARM::dsub_5);

547 D3 = TRI->getSubReg(Reg, ARM::dsub_7);

548 }

549}

550

551

552

554 MachineInstr &MI = *MBBI;

555 MachineBasicBlock &MBB = *MI.getParent();

557

558 const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode());

559 assert(TableEntry && TableEntry->IsLoad && "NEONLdStTable lookup failed");

560 NEONRegSpacing RegSpc = (NEONRegSpacing)TableEntry->RegSpacing;

561 unsigned NumRegs = TableEntry->NumRegs;

562

563 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),

564 TII->get(TableEntry->RealOpc));

565 unsigned OpIdx = 0;

566

567 bool DstIsDead = MI.getOperand(OpIdx).isDead();

569

570 bool IsVLD2DUP = TableEntry->RealOpc == ARM::VLD2DUPd8x2 ||

571 TableEntry->RealOpc == ARM::VLD2DUPd16x2 ||

572 TableEntry->RealOpc == ARM::VLD2DUPd32x2 ||

573 TableEntry->RealOpc == ARM::VLD2DUPd8x2wb_fixed ||

574 TableEntry->RealOpc == ARM::VLD2DUPd16x2wb_fixed ||

575 TableEntry->RealOpc == ARM::VLD2DUPd32x2wb_fixed ||

576 TableEntry->RealOpc == ARM::VLD2DUPd8x2wb_register ||

577 TableEntry->RealOpc == ARM::VLD2DUPd16x2wb_register ||

578 TableEntry->RealOpc == ARM::VLD2DUPd32x2wb_register;

579

580 if (IsVLD2DUP) {

581 unsigned SubRegIndex;

582 if (RegSpc == EvenDblSpc) {

583 SubRegIndex = ARM::dsub_0;

584 } else {

585 assert(RegSpc == OddDblSpc && "Unexpected spacing!");

586 SubRegIndex = ARM::dsub_1;

587 }

589 MCRegister DstRegPair =

590 TRI->getMatchingSuperReg(SubReg, ARM::dsub_0, &ARM::DPairSpcRegClass);

592 } else {

593 MCRegister D0, D1, D2, D3;

596 if (NumRegs > 1 && TableEntry->copyAllListRegs)

598 if (NumRegs > 2 && TableEntry->copyAllListRegs)

600 if (NumRegs > 3 && TableEntry->copyAllListRegs)

602 }

603

604 if (TableEntry->isUpdating)

606

607

610

611

612 if (TableEntry->hasWritebackOperand) {

613

614

615

616

617

618

619

620 const MachineOperand &AM6Offset = MI.getOperand(OpIdx++);

621 if (TableEntry->RealOpc == ARM::VLD1d8Qwb_fixed ||

622 TableEntry->RealOpc == ARM::VLD1d16Qwb_fixed ||

623 TableEntry->RealOpc == ARM::VLD1d32Qwb_fixed ||

624 TableEntry->RealOpc == ARM::VLD1d64Qwb_fixed ||

625 TableEntry->RealOpc == ARM::VLD1d8Twb_fixed ||

626 TableEntry->RealOpc == ARM::VLD1d16Twb_fixed ||

627 TableEntry->RealOpc == ARM::VLD1d32Twb_fixed ||

628 TableEntry->RealOpc == ARM::VLD1d64Twb_fixed ||

629 TableEntry->RealOpc == ARM::VLD2DUPd8x2wb_fixed ||

630 TableEntry->RealOpc == ARM::VLD2DUPd16x2wb_fixed ||

631 TableEntry->RealOpc == ARM::VLD2DUPd32x2wb_fixed) {

633 "A fixed writing-back pseudo instruction provides an offset "

634 "register!");

635 } else {

636 MIB.add(AM6Offset);

637 }

638 }

639

640

641

642

643 unsigned SrcOpIdx = 0;

644 if (RegSpc == EvenDblSpc || RegSpc == OddDblSpc || RegSpc == SingleLowSpc ||

645 RegSpc == SingleHighQSpc || RegSpc == SingleHighTSpc)

646 SrcOpIdx = OpIdx++;

647

648

651

652

653

654 if (SrcOpIdx != 0) {

655 MachineOperand MO = MI.getOperand(SrcOpIdx);

657 MIB.add(MO);

658 }

659

662

663

665 MI.eraseFromParent();

667}

668

669

670

672 MachineInstr &MI = *MBBI;

673 MachineBasicBlock &MBB = *MI.getParent();

675

676 const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode());

677 assert(TableEntry && !TableEntry->IsLoad && "NEONLdStTable lookup failed");

678 NEONRegSpacing RegSpc = (NEONRegSpacing)TableEntry->RegSpacing;

679 unsigned NumRegs = TableEntry->NumRegs;

680

681 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),

682 TII->get(TableEntry->RealOpc));

683 unsigned OpIdx = 0;

684 if (TableEntry->isUpdating)

686

687

690

691 if (TableEntry->hasWritebackOperand) {

692

693

694

695

696

697

698

699 const MachineOperand &AM6Offset = MI.getOperand(OpIdx++);

700 if (TableEntry->RealOpc == ARM::VST1d8Qwb_fixed ||

701 TableEntry->RealOpc == ARM::VST1d16Qwb_fixed ||

702 TableEntry->RealOpc == ARM::VST1d32Qwb_fixed ||

703 TableEntry->RealOpc == ARM::VST1d64Qwb_fixed ||

704 TableEntry->RealOpc == ARM::VST1d8Twb_fixed ||

705 TableEntry->RealOpc == ARM::VST1d16Twb_fixed ||

706 TableEntry->RealOpc == ARM::VST1d32Twb_fixed ||

707 TableEntry->RealOpc == ARM::VST1d64Twb_fixed) {

709 "A fixed writing-back pseudo instruction provides an offset "

710 "register!");

711 } else {

712 MIB.add(AM6Offset);

713 }

714 }

715

716 bool SrcIsKill = MI.getOperand(OpIdx).isKill();

717 bool SrcIsUndef = MI.getOperand(OpIdx).isUndef();

719 MCRegister D0, D1, D2, D3;

722 if (NumRegs > 1 && TableEntry->copyAllListRegs)

724 if (NumRegs > 2 && TableEntry->copyAllListRegs)

726 if (NumRegs > 3 && TableEntry->copyAllListRegs)

728

729

732

733 if (SrcIsKill && !SrcIsUndef)

735 else if (!SrcIsUndef)

738

739

741 MI.eraseFromParent();

743}

744

745

746

748 MachineInstr &MI = *MBBI;

749 MachineBasicBlock &MBB = *MI.getParent();

751

752 const NEONLdStTableEntry *TableEntry = LookupNEONLdSt(MI.getOpcode());

753 assert(TableEntry && "NEONLdStTable lookup failed");

754 NEONRegSpacing RegSpc = (NEONRegSpacing)TableEntry->RegSpacing;

755 unsigned NumRegs = TableEntry->NumRegs;

756 unsigned RegElts = TableEntry->RegElts;

757

758 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),

759 TII->get(TableEntry->RealOpc));

760 unsigned OpIdx = 0;

761

762

763 unsigned Lane = MI.getOperand(MI.getDesc().getNumOperands() - 3).getImm();

764

765

766 assert(RegSpc != OddDblSpc && "unexpected register spacing for VLD/VST-lane");

767 if (RegSpc == EvenDblSpc && Lane >= RegElts) {

768 RegSpc = OddDblSpc;

769 Lane -= RegElts;

770 }

771 assert(Lane < RegElts && "out of range lane for VLD/VST-lane");

772

773 MCRegister D0, D1, D2, D3;

774 unsigned DstReg = 0;

775 bool DstIsDead = false;

776 if (TableEntry->IsLoad) {

777 DstIsDead = MI.getOperand(OpIdx).isDead();

778 DstReg = MI.getOperand(OpIdx++).getReg();

781 if (NumRegs > 1)

783 if (NumRegs > 2)

785 if (NumRegs > 3)

787 }

788

789 if (TableEntry->isUpdating)

791

792

795

796 if (TableEntry->hasWritebackOperand)

798

799

800 MachineOperand MO = MI.getOperand(OpIdx++);

801 if (!TableEntry->IsLoad)

803

804

807 MIB.addReg(D0, SrcFlags);

808 if (NumRegs > 1)

809 MIB.addReg(D1, SrcFlags);

810 if (NumRegs > 2)

811 MIB.addReg(D2, SrcFlags);

812 if (NumRegs > 3)

813 MIB.addReg(D3, SrcFlags);

814

815

818

819

822

823

825 MIB.add(MO);

826 if (TableEntry->IsLoad)

827

830

832 MI.eraseFromParent();

833}

834

835

836

838 unsigned Opc, bool IsExt) {

839 MachineInstr &MI = *MBBI;

840 MachineBasicBlock &MBB = *MI.getParent();

842

844 unsigned OpIdx = 0;

845

846

848 if (IsExt) {

849 MachineOperand VdSrc(MI.getOperand(OpIdx++));

850 MIB.add(VdSrc);

851 }

852

853 bool SrcIsKill = MI.getOperand(OpIdx).isKill();

855 MCRegister D0, D1, D2, D3;

858

859

860 MachineOperand VmSrc(MI.getOperand(OpIdx++));

861 MIB.add(VmSrc);

862

863

866

867

870 MI.eraseFromParent();

872}

873

875 MachineInstr &MI = *MBBI;

876 MachineBasicBlock &MBB = *MI.getParent();

877 unsigned NewOpc =

878 MI.getOpcode() == ARM::MQQPRStore || MI.getOpcode() == ARM::MQQQQPRStore

879 ? ARM::VSTMDIA

880 : ARM::VLDMDIA;

881 MachineInstrBuilder MIB =

883

886 Register SrcReg = MI.getOperand(0).getReg();

887

888

889 MIB.add(MI.getOperand(1));

891 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_0), Flags);

892 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_1), Flags);

893 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_2), Flags);

894 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_3), Flags);

895 if (MI.getOpcode() == ARM::MQQQQPRStore ||

896 MI.getOpcode() == ARM::MQQQQPRLoad) {

897 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_4), Flags);

898 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_5), Flags);

899 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_6), Flags);

900 MIB.addReg(TRI->getSubReg(SrcReg, ARM::dsub_7), Flags);

901 }

902

903 if (NewOpc == ARM::VSTMDIA)

905

908 MI.eraseFromParent();

909}

910

912

913

914

921 return false;

923 return true;

925 return false;

932 return true;

936 return false;

939 return true;

942 return false;

946 }

948}

949

955

957 unsigned TargetFlag) {

961 unsigned Imm = MO.getImm();

962 switch (TargetFlag) {

964 Imm = (Imm >> 24) & 0xff;

965 break;

967 Imm = (Imm >> 16) & 0xff;

968 break;

970 Imm = (Imm >> 8) & 0xff;

971 break;

973 Imm = Imm & 0xff;

974 break;

976 Imm = (Imm >> 16) & 0xffff;

977 break;

979 Imm = Imm & 0xffff;

980 break;

981 default:

983 }

985 }

990 default:

992 }

993}

994

995void ARMExpandPseudo::ExpandTMOV32BitImm(MachineBasicBlock &MBB,

997 MachineInstr &MI = *MBBI;

998 Register DstReg = MI.getOperand(0).getReg();

999 bool DstIsDead = MI.getOperand(0).isDead();

1000 const MachineOperand &MO = MI.getOperand(1);

1001 unsigned MIFlags = MI.getFlags();

1002

1004

1005

1006

1007

1008

1009

1010 unsigned PendingShift = 0;

1011 for (unsigned Byte = 0; Byte < 4; ++Byte) {

1016 MachineOperand Operand = getMovOperand(MO, Flag);

1017 bool ZeroImm = Operand.isImm() && Operand.getImm() == 0;

1018 unsigned Op = PendingShift ? ARM::tADDi8 : ARM::tMOVi8;

1019

1020

1021

1022 if (PendingShift && (!ZeroImm || Byte == 3)) {

1023 MachineInstr *Lsl =

1027 .addImm(PendingShift)

1030 (void)Lsl;

1032 PendingShift = 0;

1033 }

1034

1035

1036 if (!ZeroImm) {

1037 MachineInstrBuilder MIB =

1040 if (Op == ARM::tADDi8)

1042 MIB.add(Operand);

1045 LLVM_DEBUG(dbgs() << (Op == ARM::tMOVi8 ? "To: " : "And:") << " ";

1047 }

1048

1049

1050 if (PendingShift || !ZeroImm)

1051 PendingShift += 8;

1052 }

1053

1054

1055

1056 (--MBBI)->getOperand(0).setIsDead(DstIsDead);

1057

1058 MI.eraseFromParent();

1059}

1060

1061void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB,

1063 MachineInstr &MI = *MBBI;

1064 unsigned Opcode = MI.getOpcode();

1067 Register DstReg = MI.getOperand(0).getReg();

1068 bool DstIsDead = MI.getOperand(0).isDead();

1069 bool isCC = Opcode == ARM::MOVCCi32imm || Opcode == ARM::t2MOVCCi32imm;

1070 const MachineOperand &MO = MI.getOperand(isCC ? 2 : 1);

1072 MachineInstrBuilder LO16, HI16;

1074

1075 if (!STI->hasV6T2Ops() &&

1076 (Opcode == ARM::MOVi32imm || Opcode == ARM::MOVCCi32imm)) {

1077

1079

1080 assert (MO.isImm() && "MOVi32imm w/ non-immediate source operand!");

1081 unsigned ImmVal = (unsigned)MO.getImm();

1082 unsigned SOImmValV1 = 0, SOImmValV2 = 0;

1083

1091 } else {

1098 SOImmValV1 = ~(-SOImmValV1);

1099 }

1100

1101 unsigned MIFlags = MI.getFlags();

1102 LO16 = LO16.addImm(SOImmValV1);

1103 HI16 = HI16.addImm(SOImmValV2);

1110 if (isCC)

1114 MI.eraseFromParent();

1115 return;

1116 }

1117

1118 unsigned LO16Opc = 0;

1119 unsigned HI16Opc = 0;

1120 unsigned MIFlags = MI.getFlags();

1121 if (Opcode == ARM::t2MOVi32imm || Opcode == ARM::t2MOVCCi32imm) {

1122 LO16Opc = ARM::t2MOVi16;

1123 HI16Opc = ARM::t2MOVTi16;

1124 } else {

1125 LO16Opc = ARM::MOVi16;

1126 HI16Opc = ARM::MOVTi16;

1127 }

1128

1134 if (isCC)

1138

1140 if (!(HIOperand.isImm() && HIOperand.getImm() == 0)) {

1145 HI16.add(HIOperand);

1150 } else {

1152 }

1153

1154 if (RequiresBundling)

1156

1157 MI.eraseFromParent();

1158}

1159

1160

1161

1163

1165 const std::initializer_list &Regs,

1169 if (Op.isReg() || Op.isUse())

1170 continue;

1172 }

1174

1175 std::set_difference(Regs.begin(), Regs.end(), OpRegs.begin(), OpRegs.end(),

1176 std::back_inserter(ClearRegs));

1177}

1178

1179void ARMExpandPseudo::CMSEClearGPRegs(

1181 const DebugLoc &DL, const SmallVectorImpl &ClearRegs,

1182 unsigned ClobberReg) {

1183

1184 if (STI->hasV8_1MMainlineOps()) {

1185

1186 MachineInstrBuilder CLRM =

1188 for (unsigned R : ClearRegs)

1192 } else {

1193

1194

1195 for (unsigned Reg : ClearRegs) {

1196 if (Reg == ClobberReg)

1197 continue;

1201 }

1202

1204 .addImm(STI->hasDSP() ? 0xc00 : 0x800)

1207 }

1208}

1209

1210

1211

1212

1213

1216 bool DefFP = false;

1218 if (Op.isReg())

1219 continue;

1220

1222 if (Op.isDef()) {

1223 if ((Reg >= ARM::Q0 && Reg <= ARM::Q7) ||

1224 (Reg >= ARM::D0 && Reg <= ARM::D15) ||

1225 (Reg >= ARM::S0 && Reg <= ARM::S31))

1226 DefFP = true;

1227 continue;

1228 }

1229

1230 if (Reg >= ARM::Q0 && Reg <= ARM::Q7) {

1231 int R = Reg - ARM::Q0;

1232 ClearRegs.reset(R * 4, (R + 1) * 4);

1233 } else if (Reg >= ARM::D0 && Reg <= ARM::D15) {

1234 int R = Reg - ARM::D0;

1235 ClearRegs.reset(R * 2, (R + 1) * 2);

1236 } else if (Reg >= ARM::S0 && Reg <= ARM::S31) {

1237 ClearRegs[Reg - ARM::S0] = false;

1238 }

1239 }

1240 return DefFP;

1241}

1242

1243MachineBasicBlock &

1244ARMExpandPseudo::CMSEClearFPRegs(MachineBasicBlock &MBB,

1246 BitVector ClearRegs(16, true);

1248

1249 if (STI->hasV8_1MMainlineOps())

1250 return CMSEClearFPRegsV81(MBB, MBBI, ClearRegs);

1251 else

1252 return CMSEClearFPRegsV8(MBB, MBBI, ClearRegs);

1253}

1254

1255

1256

1257MachineBasicBlock &

1258ARMExpandPseudo::CMSEClearFPRegsV8(MachineBasicBlock &MBB,

1260 const BitVector &ClearRegs) {

1261 if (!STI->hasFPRegs())

1262 return MBB;

1263

1264 auto &RetI = *MBBI;

1265 const DebugLoc &DL = RetI.getDebugLoc();

1266

1267

1268

1269

1270 MachineBasicBlock *ClearBB, *DoneBB;

1272 ClearBB = DoneBB = &MBB;

1273 } else {

1277

1280

1286

1287

1288

1289 for (const MachineOperand &Op : RetI.operands()) {

1290 if (Op.isReg())

1291 continue;

1293 if (Reg == ARM::NoRegister || Reg == ARM::LR)

1294 continue;

1298 }

1301

1302

1306

1311

1316 }

1317

1318

1319 for (unsigned D = 0; D < 8; D++) {

1320

1321 if (ClearRegs[D * 2 + 0] && ClearRegs[D * 2 + 1]) {

1322 unsigned Reg = ARM::D0 + D;

1327 } else {

1328

1329 if (ClearRegs[D * 2 + 0]) {

1330 unsigned Reg = ARM::S0 + D * 2;

1334 }

1335

1336 if (ClearRegs[D * 2 + 1]) {

1337 unsigned Reg = ARM::S0 + D * 2 + 1;

1341 }

1342 }

1343 }

1344

1345

1346

1362

1363 return *DoneBB;

1364}

1365

1366MachineBasicBlock &

1367ARMExpandPseudo::CMSEClearFPRegsV81(MachineBasicBlock &MBB,

1369 const BitVector &ClearRegs) {

1370 auto &RetI = *MBBI;

1371

1372

1373

1374 int Start = -1, End = -1;

1375 for (int S = 0, E = ClearRegs.size(); S != E; ++S) {

1376 if (ClearRegs[S] && S == End + 1) {

1377 End = S;

1378 continue;

1379 }

1380

1381 if (Start < End) {

1382 MachineInstrBuilder VSCCLRM =

1385 while (++Start <= End)

1388 }

1389 Start = End = S;

1390 }

1391

1392 if (Start < End) {

1393 MachineInstrBuilder VSCCLRM =

1396 while (++Start <= End)

1399 }

1400

1401 return MBB;

1402}

1403

1404void ARMExpandPseudo::CMSESaveClearFPRegs(

1406 const LivePhysRegs &LiveRegs, SmallVectorImpl &ScratchRegs) {

1407 if (STI->hasV8_1MMainlineOps())

1408 CMSESaveClearFPRegsV81(MBB, MBBI, DL, LiveRegs);

1409 else if (STI->hasV8MMainlineOps())

1410 CMSESaveClearFPRegsV8(MBB, MBBI, DL, LiveRegs, ScratchRegs);

1411}

1412

1413

1414void ARMExpandPseudo::CMSESaveClearFPRegsV8(

1416 const LivePhysRegs &LiveRegs, SmallVectorImpl &ScratchRegs) {

1417

1418

1420 unsigned SpareReg = ScratchRegs.front();

1421

1422

1427

1428

1429 std::vector<std::tuple<unsigned, unsigned, unsigned>> ClearedFPRegs;

1430 std::vector NonclearedFPRegs;

1431 bool ReturnsFPReg = false;

1432 for (const MachineOperand &Op : MBBI->operands()) {

1433 if (Op.isReg() && Op.isUse()) {

1438 if (ARM::DPR_VFP2RegClass.contains(Reg)) {

1439 if (ScratchRegs.size() >= 2) {

1440 unsigned SaveReg2 = ScratchRegs.pop_back_val();

1441 unsigned SaveReg1 = ScratchRegs.pop_back_val();

1442 ClearedFPRegs.emplace_back(Reg, SaveReg1, SaveReg2);

1443

1444

1450 } else {

1451 NonclearedFPRegs.push_back(Reg);

1452 }

1453 } else if (ARM::SPRRegClass.contains(Reg)) {

1454 if (ScratchRegs.size() >= 1) {

1455 unsigned SaveReg = ScratchRegs.pop_back_val();

1456 ClearedFPRegs.emplace_back(Reg, SaveReg, 0);

1457

1458

1462 } else {

1463 NonclearedFPRegs.push_back(Reg);

1464 }

1465 }

1466 } else if (Op.isReg() && Op.isDef()) {

1470 ReturnsFPReg = true;

1471 }

1472 }

1473

1474 bool PassesFPReg = (!NonclearedFPRegs.empty() || !ClearedFPRegs.empty());

1475

1476 if (PassesFPReg || ReturnsFPReg)

1477 assert(STI->hasFPRegs() && "Subtarget needs fpregs");

1478

1479

1480

1481

1482

1483

1484

1485

1486

1487

1488

1489

1490

1491

1492

1493

1494

1495

1496

1497

1498

1499

1500

1501

1502

1503 if (ReturnsFPReg && !PassesFPReg) {

1504 bool S0Dead = !LiveRegs.contains(ARM::S0);

1509 }

1510

1511

1512

1513 MachineInstrBuilder VLSTM =

1517 .addImm(0);

1518

1519

1524 }

1525 }

1526

1527

1528 for (const auto &Regs : ClearedFPRegs) {

1529 unsigned Reg, SaveReg1, SaveReg2;

1530 std::tie(Reg, SaveReg1, SaveReg2) = Regs;

1531 if (ARM::DPR_VFP2RegClass.contains(Reg))

1536 else if (ARM::SPRRegClass.contains(Reg))

1540 }

1541

1542 for (unsigned Reg : NonclearedFPRegs) {

1543 if (ARM::DPR_VFP2RegClass.contains(Reg)) {

1549 } else {

1550

1551

1552 MCRegister SReg0 = TRI->getSubReg(Reg, ARM::ssub_0);

1559 .addImm((Reg - ARM::D0) * 2 + 1)

1561 }

1562 } else if (ARM::SPRRegClass.contains(Reg)) {

1567 }

1568 }

1569

1570

1571 if (PassesFPReg) {

1589

1590

1592 }

1593}

1594

1595void ARMExpandPseudo::CMSESaveClearFPRegsV81(MachineBasicBlock &MBB,

1598 const LivePhysRegs &LiveRegs) {

1599 BitVector ClearRegs(32, true);

1601

1602

1603

1604

1605 if (!DefFP && ClearRegs.count() == ClearRegs.size()) {

1606

1611

1612

1613 MachineInstrBuilder VLSTM =

1617 .addImm(0);

1618

1619

1624 }

1625 }

1626 } else {

1627

1628 MachineInstrBuilder VPUSH =

1632 for (unsigned Reg = ARM::S16; Reg <= ARM::S31; ++Reg)

1634

1635

1636 (void)CMSEClearFPRegsV81(MBB, MBBI, ClearRegs);

1637

1638

1643 }

1644}

1645

1646

1647void ARMExpandPseudo::CMSERestoreFPRegs(

1649 SmallVectorImpl &AvailableRegs) {

1650 if (STI->hasV8_1MMainlineOps())

1651 CMSERestoreFPRegsV81(MBB, MBBI, DL, AvailableRegs);

1652 else if (STI->hasV8MMainlineOps())

1653 CMSERestoreFPRegsV8(MBB, MBBI, DL, AvailableRegs);

1654}

1655

1656void ARMExpandPseudo::CMSERestoreFPRegsV8(

1658 SmallVectorImpl &AvailableRegs) {

1659

1660

1661 unsigned ScratchReg = ARM::NoRegister;

1662 if (STI->fixCMSE_CVE_2021_35465())

1664

1665

1666 std::vector<std::tuple<unsigned, unsigned, unsigned>> ClearedFPRegs;

1667 std::vector NonclearedFPRegs;

1668 for (const MachineOperand &Op : MBBI->operands()) {

1669 if (Op.isReg() && Op.isDef()) {

1674 if (ARM::DPR_VFP2RegClass.contains(Reg)) {

1675 if (AvailableRegs.size() >= 2) {

1676 unsigned SaveReg2 = AvailableRegs.pop_back_val();

1677 unsigned SaveReg1 = AvailableRegs.pop_back_val();

1678 ClearedFPRegs.emplace_back(Reg, SaveReg1, SaveReg2);

1679

1680

1686 } else {

1687 NonclearedFPRegs.push_back(Reg);

1688 }

1689 } else if (ARM::SPRRegClass.contains(Reg)) {

1690 if (AvailableRegs.size() >= 1) {

1691 unsigned SaveReg = AvailableRegs.pop_back_val();

1692 ClearedFPRegs.emplace_back(Reg, SaveReg, 0);

1693

1694

1698 } else {

1699 NonclearedFPRegs.push_back(Reg);

1700 }

1701 }

1702 }

1703 }

1704

1705 bool returnsFPReg = (!NonclearedFPRegs.empty() || !ClearedFPRegs.empty());

1706

1707 if (returnsFPReg)

1708 assert(STI->hasFPRegs() && "Subtarget needs fpregs");

1709

1710

1711 for (unsigned Reg : NonclearedFPRegs) {

1712 if (ARM::DPR_VFP2RegClass.contains(Reg))

1718 else if (ARM::SPRRegClass.contains(Reg))

1724 }

1725

1726

1727

1728 MachineInstrBuilder VLLDM =

1732 .addImm(0);

1733

1734

1735 if (STI->fixCMSE_CVE_2021_35465()) {

1736 auto Bundler = MIBundleBuilder(MBB, VLLDM);

1737

1742

1747

1751

1752

1753

1754

1755 if (STI->hasFPRegs())

1760 else

1765 }

1766

1767

1768 for (const auto &Regs : ClearedFPRegs) {

1769 unsigned Reg, SaveReg1, SaveReg2;

1770 std::tie(Reg, SaveReg1, SaveReg2) = Regs;

1771 if (ARM::DPR_VFP2RegClass.contains(Reg))

1776 else if (ARM::SPRRegClass.contains(Reg))

1780 }

1781

1782

1787}

1788

1791 if (Op.isReg())

1792 continue;

1794 if ((Reg >= ARM::Q0 && Reg <= ARM::Q7) ||

1795 (Reg >= ARM::D0 && Reg <= ARM::D15) ||

1796 (Reg >= ARM::S0 && Reg <= ARM::S31))

1797 return true;

1798 }

1799 return false;

1800}

1801

1802void ARMExpandPseudo::CMSERestoreFPRegsV81(

1804 SmallVectorImpl &AvailableRegs) {

1806 if (STI->fixCMSE_CVE_2021_35465()) {

1810 }

1811

1812

1816 .addImm(0);

1817

1818

1819

1824 } else {

1825

1827 ARM::SP)

1831

1832

1833 MachineInstrBuilder VPOP =

1837 for (unsigned Reg = ARM::S16; Reg <= ARM::S31; ++Reg)

1839 }

1840}

1841

1842

1843

1844

1845bool ARMExpandPseudo::ExpandCMP_SWAP(MachineBasicBlock &MBB,

1847 unsigned LdrexOp, unsigned StrexOp,

1848 unsigned UxtOp,

1850 bool IsThumb = STI->isThumb();

1852 MachineInstr &MI = *MBBI;

1854 const MachineOperand &Dest = MI.getOperand(0);

1855 Register TempReg = MI.getOperand(1).getReg();

1856

1857

1858 assert(MI.getOperand(2).isUndef() && "cannot handle undef");

1859 Register AddrReg = MI.getOperand(2).getReg();

1860 Register DesiredReg = MI.getOperand(3).getReg();

1861 Register NewReg = MI.getOperand(4).getReg();

1862

1863 if (IsThumb) {

1864 assert(STI->hasV8MBaselineOps() &&

1865 "CMP_SWAP not expected to be custom expanded for Thumb1");

1866 assert((UxtOp == 0 || UxtOp == ARM::tUXTB || UxtOp == ARM::tUXTH) &&

1867 "ARMv8-M.baseline does not have t2UXTB/t2UXTH");

1868 assert((UxtOp == 0 || ARM::tGPRRegClass.contains(DesiredReg)) &&

1869 "DesiredReg used for UXT op must be tGPR");

1870 }

1871

1876

1878 MF->insert(++LoadCmpBB->getIterator(), StoreBB);

1879 MF->insert(++StoreBB->getIterator(), DoneBB);

1880

1881 if (UxtOp) {

1882 MachineInstrBuilder MIB =

1885 if (!IsThumb)

1888 }

1889

1890

1891

1892

1893

1894

1895 MachineInstrBuilder MIB;

1897 MIB.addReg(AddrReg);

1898 if (LdrexOp == ARM::t2LDREX)

1899 MIB.addImm(0);

1901

1902 unsigned CMPrr = IsThumb ? ARM::tCMPhir : ARM::CMPrr;

1907 unsigned Bcc = IsThumb ? ARM::tBcc : ARM::Bcc;

1912 LoadCmpBB->addSuccessor(DoneBB);

1913 LoadCmpBB->addSuccessor(StoreBB);

1914

1915

1916

1917

1918

1922 if (StrexOp == ARM::t2STREX)

1923 MIB.addImm(0);

1925

1926 unsigned CMPri =

1927 IsThumb ? (IsThumb1Only ? ARM::tCMPi8 : ARM::t2CMPri) : ARM::CMPri;

1936 StoreBB->addSuccessor(LoadCmpBB);

1937 StoreBB->addSuccessor(DoneBB);

1938

1941

1943

1944 NextMBBI = MBB.end();

1945 MI.eraseFromParent();

1946

1947

1948 LivePhysRegs LiveRegs;

1952

1953 StoreBB->clearLiveIns();

1955 LoadCmpBB->clearLiveIns();

1957

1958 return true;

1959}

1960

1961

1962

1963

1965 unsigned Flags, bool IsThumb,

1967 if (IsThumb) {

1968 Register RegLo = TRI->getSubReg(Reg.getReg(), ARM::gsub_0);

1969 Register RegHi = TRI->getSubReg(Reg.getReg(), ARM::gsub_1);

1970 MIB.addReg(RegLo, Flags);

1971 MIB.addReg(RegHi, Flags);

1972 } else

1973 MIB.addReg(Reg.getReg(), Flags);

1974}

1975

1976

1977bool ARMExpandPseudo::ExpandCMP_SWAP_64(MachineBasicBlock &MBB,

1980 bool IsThumb = STI->isThumb();

1981 assert(!STI->isThumb1Only() && "CMP_SWAP_64 unsupported under Thumb1!");

1982 MachineInstr &MI = *MBBI;

1984 MachineOperand &Dest = MI.getOperand(0);

1985

1986

1987 assert(MI.getOperand(1).isUndef() && "cannot handle undef");

1988 Register AddrAndTempReg = MI.getOperand(1).getReg();

1989 Register AddrReg = TRI->getSubReg(AddrAndTempReg, ARM::gsub_0);

1990 Register TempReg = TRI->getSubReg(AddrAndTempReg, ARM::gsub_1);

1991 assert(MI.getOperand(1).getReg() == MI.getOperand(2).getReg() &&

1992 "tied operands have different registers");

1993 Register DesiredReg = MI.getOperand(3).getReg();

1994 MachineOperand New = MI.getOperand(4);

1995 New.setIsKill(false);

1996

1999 Register DesiredLo = TRI->getSubReg(DesiredReg, ARM::gsub_0);

2000 Register DesiredHi = TRI->getSubReg(DesiredReg, ARM::gsub_1);

2001

2006

2008 MF->insert(++LoadCmpBB->getIterator(), StoreBB);

2009 MF->insert(++StoreBB->getIterator(), DoneBB);

2010

2011

2012

2013

2014

2015

2016 unsigned LDREXD = IsThumb ? ARM::t2LDREXD : ARM::LDREXD;

2017 MachineInstrBuilder MIB;

2021

2022 unsigned CMPrr = IsThumb ? ARM::tCMPhir : ARM::CMPrr;

2027

2032

2033 unsigned Bcc = IsThumb ? ARM::tBcc : ARM::Bcc;

2038 LoadCmpBB->addSuccessor(DoneBB);

2039 LoadCmpBB->addSuccessor(StoreBB);

2040

2041

2042

2043

2044

2045 unsigned STREXD = IsThumb ? ARM::t2STREXD : ARM::STREXD;

2050

2051 unsigned CMPri = IsThumb ? ARM::t2CMPri : ARM::CMPri;

2060 StoreBB->addSuccessor(LoadCmpBB);

2061 StoreBB->addSuccessor(DoneBB);

2062

2065

2067

2068 NextMBBI = MBB.end();

2069 MI.eraseFromParent();

2070

2071

2072 LivePhysRegs LiveRegs;

2076

2077 StoreBB->clearLiveIns();

2079 LoadCmpBB->clearLiveIns();

2081

2082 return true;

2083}

2084

2089 bool Thumb1Only) {

2091 if (Thumb1Only) {

2094 for (unsigned Reg = ARM::R4; Reg < ARM::R8; ++Reg) {

2097 }

2098

2099

2100

2101

2102

2103

2104

2105

2106 for (unsigned LoReg = ARM::R7, HiReg = ARM::R11; LoReg >= ARM::R4;

2107 --LoReg) {

2108 if (JumpReg == LoReg)

2109 continue;

2113 --HiReg;

2114 }

2117 for (unsigned Reg = ARM::R4; Reg < ARM::R8; ++Reg) {

2118 if (Reg == JumpReg)

2119 continue;

2121 }

2122

2123

2124

2125

2126 if (JumpReg >= ARM::R4 && JumpReg <= ARM::R7) {

2127 Register LoReg = JumpReg == ARM::R4 ? ARM::R5 : ARM::R4;

2134 }

2135 } else {

2140 for (unsigned Reg = ARM::R4; Reg < ARM::R12; ++Reg) {

2143 }

2144 }

2145}

2146

2150 bool Thumb1Only) {

2152 if (Thumb1Only) {

2155 for (int R = 0; R < 4; ++R) {

2160 }

2163 for (int R = 0; R < 4; ++R)

2165 } else {

2170 for (unsigned Reg = ARM::R4; Reg < ARM::R12; ++Reg)

2172 }

2173}

2174

2175bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,

2178 MachineInstr &MI = *MBBI;

2179 unsigned Opcode = MI.getOpcode();

2180 switch (Opcode) {

2181 default:

2182 return false;

2183

2184 case ARM::VBSPd:

2185 case ARM::VBSPq: {

2186 Register DstReg = MI.getOperand(0).getReg();

2187 if (DstReg == MI.getOperand(3).getReg()) {

2188

2189 unsigned NewOpc = Opcode == ARM::VBSPd ? ARM::VBITd : ARM::VBITq;

2191 .add(MI.getOperand(0))

2192 .add(MI.getOperand(3))

2193 .add(MI.getOperand(2))

2194 .add(MI.getOperand(1))

2195 .addImm(MI.getOperand(4).getImm())

2196 .add(MI.getOperand(5));

2197 } else if (DstReg == MI.getOperand(2).getReg()) {

2198

2199 unsigned NewOpc = Opcode == ARM::VBSPd ? ARM::VBIFd : ARM::VBIFq;

2201 .add(MI.getOperand(0))

2202 .add(MI.getOperand(2))

2203 .add(MI.getOperand(3))

2204 .add(MI.getOperand(1))

2205 .addImm(MI.getOperand(4).getImm())

2206 .add(MI.getOperand(5));

2207 } else {

2208

2209 unsigned NewOpc = Opcode == ARM::VBSPd ? ARM::VBSLd : ARM::VBSLq;

2210 if (DstReg == MI.getOperand(1).getReg()) {

2212 .add(MI.getOperand(0))

2213 .add(MI.getOperand(1))

2214 .add(MI.getOperand(2))

2215 .add(MI.getOperand(3))

2216 .addImm(MI.getOperand(4).getImm())

2217 .add(MI.getOperand(5));

2218 } else {

2219

2220 unsigned MoveOpc = Opcode == ARM::VBSPd ? ARM::VORRd : ARM::VORRq;

2221 unsigned MO1Flags = getRegState(MI.getOperand(1)) & ~RegState::Kill;

2226 .addReg(MI.getOperand(1).getReg(), MO1Flags)

2227 .addReg(MI.getOperand(1).getReg(), MO1Flags)

2228 .addImm(MI.getOperand(4).getImm())

2229 .add(MI.getOperand(5));

2231 .add(MI.getOperand(0))

2235 .add(MI.getOperand(2))

2236 .add(MI.getOperand(3))

2237 .addImm(MI.getOperand(4).getImm())

2238 .add(MI.getOperand(5));

2239 }

2240 }

2241 MI.eraseFromParent();

2242 return true;

2243 }

2244

2245 case ARM::TCRETURNdi:

2246 case ARM::TCRETURNri:

2247 case ARM::TCRETURNrinotr12: {

2249 if (MBBI->getOpcode() == ARM::SEH_EpilogEnd)

2251 if (MBBI->getOpcode() == ARM::SEH_Nop_Ret)

2254 "Can only insert epilog into returning blocks");

2255 unsigned RetOpcode = MBBI->getOpcode();

2257 const ARMBaseInstrInfo &TII = *static_cast<const ARMBaseInstrInfo *>(

2258 MBB.getParent()->getSubtarget().getInstrInfo());

2259

2260

2262 if (MBBI->getOpcode() == ARM::SEH_EpilogEnd)

2264 if (MBBI->getOpcode() == ARM::SEH_Nop_Ret)

2266 MachineOperand &JumpTarget = MBBI->getOperand(0);

2267

2268

2269 if (RetOpcode == ARM::TCRETURNdi) {

2273 unsigned TCOpcode =

2274 STI->isThumb()

2275 ? ((STI->isTargetMachO() || NeedsWinCFI) ? ARM::tTAILJMPd

2276 : ARM::tTAILJMPdND)

2277 : ARM::TAILJMPd;

2282 else {

2286 }

2287

2288

2289 if (STI->isThumb())

2291 } else if (RetOpcode == ARM::TCRETURNri ||

2292 RetOpcode == ARM::TCRETURNrinotr12) {

2293 unsigned Opcode =

2294 STI->isThumb() ? ARM::tTAILJMPr

2295 : (STI->hasV4TOps() ? ARM::TAILJMPr : ARM::TAILJMPr4);

2299 }

2300

2301 auto NewMI = std::prev(MBBI);

2302 for (unsigned i = 2, e = MBBI->getNumOperands(); i != e; ++i)

2303 NewMI->addOperand(MBBI->getOperand(i));

2304

2305 NewMI->setCFIType(*MBB.getParent(), MI.getCFIType());

2306

2307

2308 if (MI.isCandidateForAdditionalCallInfo())

2309 MI.getMF()->moveAdditionalCallInfo(&MI, &*NewMI);

2310

2314

2315 MBBI = NewMI;

2316 return true;

2317 }

2318 case ARM::tBXNS_RET: {

2319

2320

2323

2324 MachineBasicBlock &AfterBB = CMSEClearFPRegs(MBB, MBBI);

2325

2326 if (STI->hasV8_1MMainlineOps()) {

2327

2329 TII->get(ARM::VLDR_FPCXTNS_post), ARM::SP)

2333

2336 }

2337

2338

2340 return !Op.isReg() || Op.getReg() != ARM::R12;

2341 }));

2344 *MBBI, {ARM::R0, ARM::R1, ARM::R2, ARM::R3, ARM::R12}, ClearRegs);

2345 CMSEClearGPRegs(AfterBB, AfterBB.end(), MBBI->getDebugLoc(), ClearRegs,

2346 ARM::LR);

2347

2348 MachineInstrBuilder NewMI =

2349 BuildMI(AfterBB, AfterBB.end(), MBBI->getDebugLoc(),

2350 TII->get(ARM::tBXNS))

2353 for (const MachineOperand &Op : MI.operands())

2355 MI.eraseFromParent();

2356 return true;

2357 }

2358 case ARM::tBLXNS_CALL: {

2360 Register JumpReg = MBBI->getOperand(0).getReg();

2361

2362

2363

2364

2365

2366 LivePhysRegs LiveRegs(*TRI);

2367 LiveRegs.addLiveOuts(MBB);

2369 LiveRegs.stepBackward(MI);

2370 LiveRegs.stepBackward(*MBBI);

2371

2374

2375 SmallVector<unsigned, 16> ClearRegs;

2377 {ARM::R0, ARM::R1, ARM::R2, ARM::R3, ARM::R4,

2378 ARM::R5, ARM::R6, ARM::R7, ARM::R8, ARM::R9,

2379 ARM::R10, ARM::R11, ARM::R12},

2380 ClearRegs);

2381 auto OriginalClearRegs = ClearRegs;

2382

2383

2384

2385 unsigned ScratchReg = ClearRegs.front();

2386

2387

2394 } else {

2395

2396

2397

2407 }

2408

2409 CMSESaveClearFPRegs(MBB, MBBI, DL, LiveRegs,

2410 ClearRegs);

2411 CMSEClearGPRegs(MBB, MBBI, DL, ClearRegs, JumpReg);

2412

2413 const MachineInstrBuilder NewCall =

2417

2420 if (MI.isCandidateForAdditionalCallInfo())

2421 MI.getMF()->moveAdditionalCallInfo(&MI, NewCall.getInstr());

2422

2423 CMSERestoreFPRegs(MBB, MBBI, DL, OriginalClearRegs);

2424

2426

2427 MI.eraseFromParent();

2428 return true;

2429 }

2430 case ARM::VMOVHcc:

2431 case ARM::VMOVScc:

2432 case ARM::VMOVDcc: {

2433 unsigned newOpc = Opcode != ARM::VMOVDcc ? ARM::VMOVS : ARM::VMOVD;

2435 MI.getOperand(1).getReg())

2436 .add(MI.getOperand(2))

2437 .addImm(MI.getOperand(3).getImm())

2438 .add(MI.getOperand(4))

2440

2441 MI.eraseFromParent();

2442 return true;

2443 }

2444 case ARM::t2MOVCCr:

2445 case ARM::MOVCCr: {

2448 MI.getOperand(1).getReg())

2449 .add(MI.getOperand(2))

2450 .addImm(MI.getOperand(3).getImm())

2451 .add(MI.getOperand(4))

2454

2455 MI.eraseFromParent();

2456 return true;

2457 }

2458 case ARM::MOVCCsi: {

2460 (MI.getOperand(1).getReg()))

2461 .add(MI.getOperand(2))

2462 .addImm(MI.getOperand(3).getImm())

2463 .addImm(MI.getOperand(4).getImm())

2464 .add(MI.getOperand(5))

2467

2468 MI.eraseFromParent();

2469 return true;

2470 }

2471 case ARM::MOVCCsr: {

2473 (MI.getOperand(1).getReg()))

2474 .add(MI.getOperand(2))

2475 .add(MI.getOperand(3))

2476 .addImm(MI.getOperand(4).getImm())

2477 .addImm(MI.getOperand(5).getImm())

2478 .add(MI.getOperand(6))

2481

2482 MI.eraseFromParent();

2483 return true;

2484 }

2485 case ARM::t2MOVCCi16:

2486 case ARM::MOVCCi16: {

2487 unsigned NewOpc = AFI->isThumbFunction() ? ARM::t2MOVi16 : ARM::MOVi16;

2489 MI.getOperand(1).getReg())

2490 .addImm(MI.getOperand(2).getImm())

2491 .addImm(MI.getOperand(3).getImm())

2492 .add(MI.getOperand(4))

2494 MI.eraseFromParent();

2495 return true;

2496 }

2497 case ARM::t2MOVCCi:

2498 case ARM::MOVCCi: {

2501 MI.getOperand(1).getReg())

2502 .addImm(MI.getOperand(2).getImm())

2503 .addImm(MI.getOperand(3).getImm())

2504 .add(MI.getOperand(4))

2507

2508 MI.eraseFromParent();

2509 return true;

2510 }

2511 case ARM::t2MVNCCi:

2512 case ARM::MVNCCi: {

2515 MI.getOperand(1).getReg())

2516 .addImm(MI.getOperand(2).getImm())

2517 .addImm(MI.getOperand(3).getImm())

2518 .add(MI.getOperand(4))

2521

2522 MI.eraseFromParent();

2523 return true;

2524 }

2525 case ARM::t2MOVCClsl:

2526 case ARM::t2MOVCClsr:

2527 case ARM::t2MOVCCasr:

2528 case ARM::t2MOVCCror: {

2529 unsigned NewOpc;

2530 switch (Opcode) {

2531 case ARM::t2MOVCClsl: NewOpc = ARM::t2LSLri; break;

2532 case ARM::t2MOVCClsr: NewOpc = ARM::t2LSRri; break;

2533 case ARM::t2MOVCCasr: NewOpc = ARM::t2ASRri; break;

2534 case ARM::t2MOVCCror: NewOpc = ARM::t2RORri; break;

2536 }

2538 MI.getOperand(1).getReg())

2539 .add(MI.getOperand(2))

2540 .addImm(MI.getOperand(3).getImm())

2541 .addImm(MI.getOperand(4).getImm())

2542 .add(MI.getOperand(5))

2545 MI.eraseFromParent();

2546 return true;

2547 }

2548 case ARM::Int_eh_sjlj_dispatchsetup: {

2549 MachineFunction &MF = *MI.getParent()->getParent();

2551

2552

2553

2558 "base pointer without frame pointer?");

2559

2566 } else {

2570 }

2571

2572 if (RI.hasStackRealignment(MF)) {

2576

2578 "The BIC instruction cannot encode "

2579 "immediates larger than 256 with all lower "

2580 "bits set.");

2582 ARM::t2BICri : ARM::BICri;

2588 }

2589 }

2590 MI.eraseFromParent();

2591 return true;

2592 }

2593

2594 case ARM::LSRs1:

2595 case ARM::ASRs1: {

2596

2598 MI.getOperand(0).getReg())

2599 .add(MI.getOperand(1))

2604 MI.eraseFromParent();

2605 return true;

2606 }

2607 case ARM::RRX: {

2608

2610 MI.getOperand(0).getReg())

2611 .add(MI.getOperand(1))

2616 MI.eraseFromParent();

2617 return true;

2618 }

2619 case ARM::tTPsoft:

2620 case ARM::TPsoft: {

2621 const bool Thumb = Opcode == ARM::tTPsoft;

2622

2623 MachineInstrBuilder MIB;

2625 if (STI->genLongCalls()) {

2628 MachineConstantPoolValue *CPV =

2630 "__aeabi_read_tp", PCLabelID, 0);

2632 MIB =

2634 TII->get(Thumb ? ARM::tLDRpci : ARM::LDRi12), Reg)

2636 if (!Thumb)

2639

2640 MIB =

2643 if (Thumb)

2646 } else {

2648 TII->get(Thumb ? ARM::tBL : ARM::BL));

2649 if (Thumb)

2652 }

2653

2656

2657 if (MI.isCandidateForAdditionalCallInfo())

2659 MI.eraseFromParent();

2660 return true;

2661 }

2662 case ARM::tLDRpci_pic:

2663 case ARM::t2LDRpci_pic: {

2664 unsigned NewLdOpc = (Opcode == ARM::tLDRpci_pic)

2665 ? ARM::tLDRpci : ARM::t2LDRpci;

2666 Register DstReg = MI.getOperand(0).getReg();

2667 bool DstIsDead = MI.getOperand(0).isDead();

2669 .add(MI.getOperand(1))

2676 .add(MI.getOperand(2))

2678 MI.eraseFromParent();

2679 return true;

2680 }

2681

2682 case ARM::LDRLIT_ga_abs:

2683 case ARM::LDRLIT_ga_pcrel:

2684 case ARM::LDRLIT_ga_pcrel_ldr:

2685 case ARM::tLDRLIT_ga_abs:

2686 case ARM::t2LDRLIT_ga_pcrel:

2687 case ARM::tLDRLIT_ga_pcrel: {

2688 Register DstReg = MI.getOperand(0).getReg();

2689 bool DstIsDead = MI.getOperand(0).isDead();

2690 const MachineOperand &MO1 = MI.getOperand(1);

2692 const GlobalValue *GV = MO1.getGlobal();

2693 bool IsARM = Opcode != ARM::tLDRLIT_ga_pcrel &&

2694 Opcode != ARM::tLDRLIT_ga_abs &&

2695 Opcode != ARM::t2LDRLIT_ga_pcrel;

2696 bool IsPIC =

2697 Opcode != ARM::LDRLIT_ga_abs && Opcode != ARM::tLDRLIT_ga_abs;

2698 unsigned LDRLITOpc = IsARM ? ARM::LDRi12 : ARM::tLDRpci;

2699 if (Opcode == ARM::t2LDRLIT_ga_pcrel)

2700 LDRLITOpc = ARM::t2LDRpci;

2701 unsigned PICAddOpc =

2702 IsARM

2703 ? (Opcode == ARM::LDRLIT_ga_pcrel_ldr ? ARM::PICLDR : ARM::PICADD)

2704 : ARM::tPICADD;

2705

2706

2708 unsigned ARMPCLabelIndex = 0;

2709 MachineConstantPoolValue *CPV;

2710

2711 if (IsPIC) {

2712 unsigned PCAdj = IsARM ? 8 : 4;

2718 GV, ARMPCLabelIndex, ARMCP::CPValue, PCAdj, Modifier,

2720 } else

2722

2723 MachineInstrBuilder MIB =

2726 if (IsARM)

2729

2730 if (IsPIC) {

2731 MachineInstrBuilder MIB =

2735 .addImm(ARMPCLabelIndex);

2736

2737 if (IsARM)

2739 }

2740

2741 MI.eraseFromParent();

2742 return true;

2743 }

2744 case ARM::MOV_ga_pcrel:

2745 case ARM::MOV_ga_pcrel_ldr:

2746 case ARM::t2MOV_ga_pcrel: {

2747

2749 Register DstReg = MI.getOperand(0).getReg();

2750 bool DstIsDead = MI.getOperand(0).isDead();

2751 const MachineOperand &MO1 = MI.getOperand(1);

2752 const GlobalValue *GV = MO1.getGlobal();

2754 bool isARM = Opcode != ARM::t2MOV_ga_pcrel;

2755 unsigned LO16Opc = isARM ? ARM::MOVi16_ga_pcrel : ARM::t2MOVi16_ga_pcrel;

2756 unsigned HI16Opc = isARM ? ARM::MOVTi16_ga_pcrel :ARM::t2MOVTi16_ga_pcrel;

2759 unsigned PICAddOpc = isARM

2760 ? (Opcode == ARM::MOV_ga_pcrel_ldr ? ARM::PICLDR : ARM::PICADD)

2761 : ARM::tPICADD;

2766

2772

2773 MachineInstrBuilder MIB3 = BuildMI(MBB, MBBI, MI.getDebugLoc(),

2774 TII->get(PICAddOpc))

2777 if (isARM) {

2779 if (Opcode == ARM::MOV_ga_pcrel_ldr)

2781 }

2783 MI.eraseFromParent();

2784 return true;

2785 }

2786

2787 case ARM::MOVi32imm:

2788 case ARM::MOVCCi32imm:

2789 case ARM::t2MOVi32imm:

2790 case ARM::t2MOVCCi32imm:

2791 ExpandMOV32BitImm(MBB, MBBI);

2792 return true;

2793

2794 case ARM::tMOVi32imm:

2795 ExpandTMOV32BitImm(MBB, MBBI);

2796 return true;

2797

2798 case ARM::tLEApcrelJT:

2799

2800 if (MI.getMF()->getJumpTableInfo()->getEntryKind() ==

2802 return false;

2803

2804

2805 assert(STI->isThumb() && "Non-inline jump tables expected only in thumb");

2806 ExpandTMOV32BitImm(MBB, MBBI);

2807 return true;

2808

2809 case ARM::SUBS_PC_LR: {

2812 .add(MI.getOperand(0))

2813 .add(MI.getOperand(1))

2814 .add(MI.getOperand(2))

2817 MI.eraseFromParent();

2818 return true;

2819 }

2820 case ARM::VLDMQIA: {

2821 unsigned NewOpc = ARM::VLDMDIA;

2822 MachineInstrBuilder MIB =

2824 unsigned OpIdx = 0;

2825

2826

2827 bool DstIsDead = MI.getOperand(OpIdx).isDead();

2829

2830

2832

2833

2836

2837

2838 Register D0 = TRI->getSubReg(DstReg, ARM::dsub_0);

2839 Register D1 = TRI->getSubReg(DstReg, ARM::dsub_1);

2842

2843

2847 MI.eraseFromParent();

2848 return true;

2849 }

2850

2851 case ARM::VSTMQIA: {

2852 unsigned NewOpc = ARM::VSTMDIA;

2853 MachineInstrBuilder MIB =

2855 unsigned OpIdx = 0;

2856

2857

2858 bool SrcIsKill = MI.getOperand(OpIdx).isKill();

2860

2861

2862 MachineOperand Dst(MI.getOperand(OpIdx++));

2863 MIB.add(Dst);

2864

2865

2868

2869

2870 Register D0 = TRI->getSubReg(SrcReg, ARM::dsub_0);

2871 Register D1 = TRI->getSubReg(SrcReg, ARM::dsub_1);

2874

2875 if (SrcIsKill)

2877

2880 MI.eraseFromParent();

2881 return true;

2882 }

2883

2884 case ARM::VLD2q8Pseudo:

2885 case ARM::VLD2q16Pseudo:

2886 case ARM::VLD2q32Pseudo:

2887 case ARM::VLD2q8PseudoWB_fixed:

2888 case ARM::VLD2q16PseudoWB_fixed:

2889 case ARM::VLD2q32PseudoWB_fixed:

2890 case ARM::VLD2q8PseudoWB_register:

2891 case ARM::VLD2q16PseudoWB_register:

2892 case ARM::VLD2q32PseudoWB_register:

2893 case ARM::VLD3d8Pseudo:

2894 case ARM::VLD3d16Pseudo:

2895 case ARM::VLD3d32Pseudo:

2896 case ARM::VLD1d8TPseudo:

2897 case ARM::VLD1d8TPseudoWB_fixed:

2898 case ARM::VLD1d8TPseudoWB_register:

2899 case ARM::VLD1d16TPseudo:

2900 case ARM::VLD1d16TPseudoWB_fixed:

2901 case ARM::VLD1d16TPseudoWB_register:

2902 case ARM::VLD1d32TPseudo:

2903 case ARM::VLD1d32TPseudoWB_fixed:

2904 case ARM::VLD1d32TPseudoWB_register:

2905 case ARM::VLD1d64TPseudo:

2906 case ARM::VLD1d64TPseudoWB_fixed:

2907 case ARM::VLD1d64TPseudoWB_register:

2908 case ARM::VLD3d8Pseudo_UPD:

2909 case ARM::VLD3d16Pseudo_UPD:

2910 case ARM::VLD3d32Pseudo_UPD:

2911 case ARM::VLD3q8Pseudo_UPD:

2912 case ARM::VLD3q16Pseudo_UPD:

2913 case ARM::VLD3q32Pseudo_UPD:

2914 case ARM::VLD3q8oddPseudo:

2915 case ARM::VLD3q16oddPseudo:

2916 case ARM::VLD3q32oddPseudo:

2917 case ARM::VLD3q8oddPseudo_UPD:

2918 case ARM::VLD3q16oddPseudo_UPD:

2919 case ARM::VLD3q32oddPseudo_UPD:

2920 case ARM::VLD4d8Pseudo:

2921 case ARM::VLD4d16Pseudo:

2922 case ARM::VLD4d32Pseudo:

2923 case ARM::VLD1d8QPseudo:

2924 case ARM::VLD1d8QPseudoWB_fixed:

2925 case ARM::VLD1d8QPseudoWB_register:

2926 case ARM::VLD1d16QPseudo:

2927 case ARM::VLD1d16QPseudoWB_fixed:

2928 case ARM::VLD1d16QPseudoWB_register:

2929 case ARM::VLD1d32QPseudo:

2930 case ARM::VLD1d32QPseudoWB_fixed:

2931 case ARM::VLD1d32QPseudoWB_register:

2932 case ARM::VLD1d64QPseudo:

2933 case ARM::VLD1d64QPseudoWB_fixed:

2934 case ARM::VLD1d64QPseudoWB_register:

2935 case ARM::VLD1q8HighQPseudo:

2936 case ARM::VLD1q8HighQPseudo_UPD:

2937 case ARM::VLD1q8LowQPseudo_UPD:

2938 case ARM::VLD1q8HighTPseudo:

2939 case ARM::VLD1q8HighTPseudo_UPD:

2940 case ARM::VLD1q8LowTPseudo_UPD:

2941 case ARM::VLD1q16HighQPseudo:

2942 case ARM::VLD1q16HighQPseudo_UPD:

2943 case ARM::VLD1q16LowQPseudo_UPD:

2944 case ARM::VLD1q16HighTPseudo:

2945 case ARM::VLD1q16HighTPseudo_UPD:

2946 case ARM::VLD1q16LowTPseudo_UPD:

2947 case ARM::VLD1q32HighQPseudo:

2948 case ARM::VLD1q32HighQPseudo_UPD:

2949 case ARM::VLD1q32LowQPseudo_UPD:

2950 case ARM::VLD1q32HighTPseudo:

2951 case ARM::VLD1q32HighTPseudo_UPD:

2952 case ARM::VLD1q32LowTPseudo_UPD:

2953 case ARM::VLD1q64HighQPseudo:

2954 case ARM::VLD1q64HighQPseudo_UPD:

2955 case ARM::VLD1q64LowQPseudo_UPD:

2956 case ARM::VLD1q64HighTPseudo:

2957 case ARM::VLD1q64HighTPseudo_UPD:

2958 case ARM::VLD1q64LowTPseudo_UPD:

2959 case ARM::VLD4d8Pseudo_UPD:

2960 case ARM::VLD4d16Pseudo_UPD:

2961 case ARM::VLD4d32Pseudo_UPD:

2962 case ARM::VLD4q8Pseudo_UPD:

2963 case ARM::VLD4q16Pseudo_UPD:

2964 case ARM::VLD4q32Pseudo_UPD:

2965 case ARM::VLD4q8oddPseudo:

2966 case ARM::VLD4q16oddPseudo:

2967 case ARM::VLD4q32oddPseudo:

2968 case ARM::VLD4q8oddPseudo_UPD:

2969 case ARM::VLD4q16oddPseudo_UPD:

2970 case ARM::VLD4q32oddPseudo_UPD:

2971 case ARM::VLD3DUPd8Pseudo:

2972 case ARM::VLD3DUPd16Pseudo:

2973 case ARM::VLD3DUPd32Pseudo:

2974 case ARM::VLD3DUPd8Pseudo_UPD:

2975 case ARM::VLD3DUPd16Pseudo_UPD:

2976 case ARM::VLD3DUPd32Pseudo_UPD:

2977 case ARM::VLD4DUPd8Pseudo:

2978 case ARM::VLD4DUPd16Pseudo:

2979 case ARM::VLD4DUPd32Pseudo:

2980 case ARM::VLD4DUPd8Pseudo_UPD:

2981 case ARM::VLD4DUPd16Pseudo_UPD:

2982 case ARM::VLD4DUPd32Pseudo_UPD:

2983 case ARM::VLD2DUPq8EvenPseudo:

2984 case ARM::VLD2DUPq8OddPseudo:

2985 case ARM::VLD2DUPq16EvenPseudo:

2986 case ARM::VLD2DUPq16OddPseudo:

2987 case ARM::VLD2DUPq32EvenPseudo:

2988 case ARM::VLD2DUPq32OddPseudo:

2989 case ARM::VLD2DUPq8OddPseudoWB_fixed:

2990 case ARM::VLD2DUPq8OddPseudoWB_register:

2991 case ARM::VLD2DUPq16OddPseudoWB_fixed:

2992 case ARM::VLD2DUPq16OddPseudoWB_register:

2993 case ARM::VLD2DUPq32OddPseudoWB_fixed:

2994 case ARM::VLD2DUPq32OddPseudoWB_register:

2995 case ARM::VLD3DUPq8EvenPseudo:

2996 case ARM::VLD3DUPq8OddPseudo:

2997 case ARM::VLD3DUPq16EvenPseudo:

2998 case ARM::VLD3DUPq16OddPseudo:

2999 case ARM::VLD3DUPq32EvenPseudo:

3000 case ARM::VLD3DUPq32OddPseudo:

3001 case ARM::VLD3DUPq8OddPseudo_UPD:

3002 case ARM::VLD3DUPq16OddPseudo_UPD:

3003 case ARM::VLD3DUPq32OddPseudo_UPD:

3004 case ARM::VLD4DUPq8EvenPseudo:

3005 case ARM::VLD4DUPq8OddPseudo:

3006 case ARM::VLD4DUPq16EvenPseudo:

3007 case ARM::VLD4DUPq16OddPseudo:

3008 case ARM::VLD4DUPq32EvenPseudo:

3009 case ARM::VLD4DUPq32OddPseudo:

3010 case ARM::VLD4DUPq8OddPseudo_UPD:

3011 case ARM::VLD4DUPq16OddPseudo_UPD:

3012 case ARM::VLD4DUPq32OddPseudo_UPD:

3013 ExpandVLD(MBBI);

3014 return true;

3015

3016 case ARM::VST2q8Pseudo:

3017 case ARM::VST2q16Pseudo:

3018 case ARM::VST2q32Pseudo:

3019 case ARM::VST2q8PseudoWB_fixed:

3020 case ARM::VST2q16PseudoWB_fixed:

3021 case ARM::VST2q32PseudoWB_fixed:

3022 case ARM::VST2q8PseudoWB_register:

3023 case ARM::VST2q16PseudoWB_register:

3024 case ARM::VST2q32PseudoWB_register:

3025 case ARM::VST3d8Pseudo:

3026 case ARM::VST3d16Pseudo:

3027 case ARM::VST3d32Pseudo:

3028 case ARM::VST1d8TPseudo:

3029 case ARM::VST1d8TPseudoWB_fixed:

3030 case ARM::VST1d8TPseudoWB_register:

3031 case ARM::VST1d16TPseudo:

3032 case ARM::VST1d16TPseudoWB_fixed:

3033 case ARM::VST1d16TPseudoWB_register:

3034 case ARM::VST1d32TPseudo:

3035 case ARM::VST1d32TPseudoWB_fixed:

3036 case ARM::VST1d32TPseudoWB_register:

3037 case ARM::VST1d64TPseudo:

3038 case ARM::VST1d64TPseudoWB_fixed:

3039 case ARM::VST1d64TPseudoWB_register:

3040 case ARM::VST3d8Pseudo_UPD:

3041 case ARM::VST3d16Pseudo_UPD:

3042 case ARM::VST3d32Pseudo_UPD:

3043 case ARM::VST3q8Pseudo_UPD:

3044 case ARM::VST3q16Pseudo_UPD:

3045 case ARM::VST3q32Pseudo_UPD:

3046 case ARM::VST3q8oddPseudo:

3047 case ARM::VST3q16oddPseudo:

3048 case ARM::VST3q32oddPseudo:

3049 case ARM::VST3q8oddPseudo_UPD:

3050 case ARM::VST3q16oddPseudo_UPD:

3051 case ARM::VST3q32oddPseudo_UPD:

3052 case ARM::VST4d8Pseudo:

3053 case ARM::VST4d16Pseudo:

3054 case ARM::VST4d32Pseudo:

3055 case ARM::VST1d8QPseudo:

3056 case ARM::VST1d8QPseudoWB_fixed:

3057 case ARM::VST1d8QPseudoWB_register:

3058 case ARM::VST1d16QPseudo:

3059 case ARM::VST1d16QPseudoWB_fixed:

3060 case ARM::VST1d16QPseudoWB_register:

3061 case ARM::VST1d32QPseudo:

3062 case ARM::VST1d32QPseudoWB_fixed:

3063 case ARM::VST1d32QPseudoWB_register:

3064 case ARM::VST1d64QPseudo:

3065 case ARM::VST1d64QPseudoWB_fixed:

3066 case ARM::VST1d64QPseudoWB_register:

3067 case ARM::VST4d8Pseudo_UPD:

3068 case ARM::VST4d16Pseudo_UPD:

3069 case ARM::VST4d32Pseudo_UPD:

3070 case ARM::VST1q8HighQPseudo:

3071 case ARM::VST1q8LowQPseudo_UPD:

3072 case ARM::VST1q8HighTPseudo:

3073 case ARM::VST1q8LowTPseudo_UPD:

3074 case ARM::VST1q16HighQPseudo:

3075 case ARM::VST1q16LowQPseudo_UPD:

3076 case ARM::VST1q16HighTPseudo:

3077 case ARM::VST1q16LowTPseudo_UPD:

3078 case ARM::VST1q32HighQPseudo:

3079 case ARM::VST1q32LowQPseudo_UPD:

3080 case ARM::VST1q32HighTPseudo:

3081 case ARM::VST1q32LowTPseudo_UPD:

3082 case ARM::VST1q64HighQPseudo:

3083 case ARM::VST1q64LowQPseudo_UPD:

3084 case ARM::VST1q64HighTPseudo:

3085 case ARM::VST1q64LowTPseudo_UPD:

3086 case ARM::VST1q8HighTPseudo_UPD:

3087 case ARM::VST1q16HighTPseudo_UPD:

3088 case ARM::VST1q32HighTPseudo_UPD:

3089 case ARM::VST1q64HighTPseudo_UPD:

3090 case ARM::VST1q8HighQPseudo_UPD:

3091 case ARM::VST1q16HighQPseudo_UPD:

3092 case ARM::VST1q32HighQPseudo_UPD:

3093 case ARM::VST1q64HighQPseudo_UPD:

3094 case ARM::VST4q8Pseudo_UPD:

3095 case ARM::VST4q16Pseudo_UPD:

3096 case ARM::VST4q32Pseudo_UPD:

3097 case ARM::VST4q8oddPseudo:

3098 case ARM::VST4q16oddPseudo:

3099 case ARM::VST4q32oddPseudo:

3100 case ARM::VST4q8oddPseudo_UPD:

3101 case ARM::VST4q16oddPseudo_UPD:

3102 case ARM::VST4q32oddPseudo_UPD:

3103 ExpandVST(MBBI);

3104 return true;

3105

3106 case ARM::VLD1LNq8Pseudo:

3107 case ARM::VLD1LNq16Pseudo:

3108 case ARM::VLD1LNq32Pseudo:

3109 case ARM::VLD1LNq8Pseudo_UPD:

3110 case ARM::VLD1LNq16Pseudo_UPD:

3111 case ARM::VLD1LNq32Pseudo_UPD:

3112 case ARM::VLD2LNd8Pseudo:

3113 case ARM::VLD2LNd16Pseudo:

3114 case ARM::VLD2LNd32Pseudo:

3115 case ARM::VLD2LNq16Pseudo:

3116 case ARM::VLD2LNq32Pseudo:

3117 case ARM::VLD2LNd8Pseudo_UPD:

3118 case ARM::VLD2LNd16Pseudo_UPD:

3119 case ARM::VLD2LNd32Pseudo_UPD:

3120 case ARM::VLD2LNq16Pseudo_UPD:

3121 case ARM::VLD2LNq32Pseudo_UPD:

3122 case ARM::VLD3LNd8Pseudo:

3123 case ARM::VLD3LNd16Pseudo:

3124 case ARM::VLD3LNd32Pseudo:

3125 case ARM::VLD3LNq16Pseudo:

3126 case ARM::VLD3LNq32Pseudo:

3127 case ARM::VLD3LNd8Pseudo_UPD:

3128 case ARM::VLD3LNd16Pseudo_UPD:

3129 case ARM::VLD3LNd32Pseudo_UPD:

3130 case ARM::VLD3LNq16Pseudo_UPD:

3131 case ARM::VLD3LNq32Pseudo_UPD:

3132 case ARM::VLD4LNd8Pseudo:

3133 case ARM::VLD4LNd16Pseudo:

3134 case ARM::VLD4LNd32Pseudo:

3135 case ARM::VLD4LNq16Pseudo:

3136 case ARM::VLD4LNq32Pseudo:

3137 case ARM::VLD4LNd8Pseudo_UPD:

3138 case ARM::VLD4LNd16Pseudo_UPD:

3139 case ARM::VLD4LNd32Pseudo_UPD:

3140 case ARM::VLD4LNq16Pseudo_UPD:

3141 case ARM::VLD4LNq32Pseudo_UPD:

3142 case ARM::VST1LNq8Pseudo:

3143 case ARM::VST1LNq16Pseudo:

3144 case ARM::VST1LNq32Pseudo:

3145 case ARM::VST1LNq8Pseudo_UPD:

3146 case ARM::VST1LNq16Pseudo_UPD:

3147 case ARM::VST1LNq32Pseudo_UPD:

3148 case ARM::VST2LNd8Pseudo:

3149 case ARM::VST2LNd16Pseudo:

3150 case ARM::VST2LNd32Pseudo:

3151 case ARM::VST2LNq16Pseudo:

3152 case ARM::VST2LNq32Pseudo:

3153 case ARM::VST2LNd8Pseudo_UPD:

3154 case ARM::VST2LNd16Pseudo_UPD:

3155 case ARM::VST2LNd32Pseudo_UPD:

3156 case ARM::VST2LNq16Pseudo_UPD:

3157 case ARM::VST2LNq32Pseudo_UPD:

3158 case ARM::VST3LNd8Pseudo:

3159 case ARM::VST3LNd16Pseudo:

3160 case ARM::VST3LNd32Pseudo:

3161 case ARM::VST3LNq16Pseudo:

3162 case ARM::VST3LNq32Pseudo:

3163 case ARM::VST3LNd8Pseudo_UPD:

3164 case ARM::VST3LNd16Pseudo_UPD:

3165 case ARM::VST3LNd32Pseudo_UPD:

3166 case ARM::VST3LNq16Pseudo_UPD:

3167 case ARM::VST3LNq32Pseudo_UPD:

3168 case ARM::VST4LNd8Pseudo:

3169 case ARM::VST4LNd16Pseudo:

3170 case ARM::VST4LNd32Pseudo:

3171 case ARM::VST4LNq16Pseudo:

3172 case ARM::VST4LNq32Pseudo:

3173 case ARM::VST4LNd8Pseudo_UPD:

3174 case ARM::VST4LNd16Pseudo_UPD:

3175 case ARM::VST4LNd32Pseudo_UPD:

3176 case ARM::VST4LNq16Pseudo_UPD:

3177 case ARM::VST4LNq32Pseudo_UPD:

3178 ExpandLaneOp(MBBI);

3179 return true;

3180

3181 case ARM::VTBL3Pseudo: ExpandVTBL(MBBI, ARM::VTBL3, false); return true;

3182 case ARM::VTBL4Pseudo: ExpandVTBL(MBBI, ARM::VTBL4, false); return true;

3183 case ARM::VTBX3Pseudo: ExpandVTBL(MBBI, ARM::VTBX3, true); return true;

3184 case ARM::VTBX4Pseudo: ExpandVTBL(MBBI, ARM::VTBX4, true); return true;

3185

3186 case ARM::MQQPRLoad:

3187 case ARM::MQQPRStore:

3188 case ARM::MQQQQPRLoad:

3189 case ARM::MQQQQPRStore:

3190 ExpandMQQPRLoadStore(MBBI);

3191 return true;

3192

3193 case ARM::tCMP_SWAP_8:

3194 assert(STI->isThumb());

3195 return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREXB, ARM::t2STREXB, ARM::tUXTB,

3196 NextMBBI);

3197 case ARM::tCMP_SWAP_16:

3198 assert(STI->isThumb());

3199 return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREXH, ARM::t2STREXH, ARM::tUXTH,

3200 NextMBBI);

3201 case ARM::tCMP_SWAP_32:

3202 assert(STI->isThumb());

3203 return ExpandCMP_SWAP(MBB, MBBI, ARM::t2LDREX, ARM::t2STREX, 0, NextMBBI);

3204

3205 case ARM::CMP_SWAP_8:

3206 assert(!STI->isThumb());

3207 return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREXB, ARM::STREXB, ARM::UXTB,

3208 NextMBBI);

3209 case ARM::CMP_SWAP_16:

3210 assert(!STI->isThumb());

3211 return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREXH, ARM::STREXH, ARM::UXTH,

3212 NextMBBI);

3213 case ARM::CMP_SWAP_32:

3214 assert(!STI->isThumb());

3215 return ExpandCMP_SWAP(MBB, MBBI, ARM::LDREX, ARM::STREX, 0, NextMBBI);

3216

3217 case ARM::CMP_SWAP_64:

3218 return ExpandCMP_SWAP_64(MBB, MBBI, NextMBBI);

3219

3220 case ARM::tBL_PUSHLR:

3221 case ARM::BL_PUSHLR: {

3222 const bool Thumb = Opcode == ARM::tBL_PUSHLR;

3224 assert(Reg == ARM::LR && "expect LR register!");

3225 MachineInstrBuilder MIB;

3226 if (Thumb) {

3227

3231

3232

3234 } else {

3235

3241

3242

3244 }

3247 MIB.add(MO);

3248 MI.eraseFromParent();

3249 return true;

3250 }

3251 case ARM::t2CALL_BTI: {

3252 MachineFunction &MF = *MI.getMF();

3253 MachineInstrBuilder MIB =

3256 for (unsigned i = 0; i < MI.getNumOperands(); ++i)

3257 MIB.add(MI.getOperand(i));

3258 if (MI.isCandidateForAdditionalCallInfo())

3260 MIBundleBuilder Bundler(MBB, MI);

3261 Bundler.append(MIB);

3262 Bundler.append(BuildMI(MF, MI.getDebugLoc(), TII->get(ARM::t2BTI)));

3264 MI.eraseFromParent();

3265 return true;

3266 }

3267 case ARM::LOADDUAL:

3268 case ARM::STOREDUAL: {

3269 Register PairReg = MI.getOperand(0).getReg();

3270

3271 MachineInstrBuilder MIB =

3273 TII->get(Opcode == ARM::LOADDUAL ? ARM::LDRD : ARM::STRD))

3274 .addReg(TRI->getSubReg(PairReg, ARM::gsub_0),

3276 .addReg(TRI->getSubReg(PairReg, ARM::gsub_1),

3279 MIB.add(MO);

3282 MI.eraseFromParent();

3283 return true;

3284 }

3285 }

3286}

3287

3288bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) {

3290

3292 while (MBBI != E) {

3295 MBBI = NMBBI;

3296 }

3297

3299}

3300

3301bool ARMExpandPseudo::runOnMachineFunction(MachineFunction &MF) {

3305 AFI = MF.getInfo();

3306

3307 LLVM_DEBUG(dbgs() << "********** ARM EXPAND PSEUDO INSTRUCTIONS **********\n"

3308 << "********** Function: " << MF.getName() << '\n');

3309

3311 for (MachineBasicBlock &MBB : MF)

3314 MF.verify(this, "After expanding ARM pseudo instructions.");

3315

3316 LLVM_DEBUG(dbgs() << "***************************************************\n");

3318}

3319

3320

3321

3323 return new ARMExpandPseudo();

3324}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

const TargetInstrInfo & TII

static bool determineFPRegsToClear(const MachineInstr &MI, BitVector &ClearRegs)

Definition ARMExpandPseudoInsts.cpp:1214

static void CMSEPopCalleeSaves(const TargetInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, bool Thumb1Only)

Definition ARMExpandPseudoInsts.cpp:2147

static void GetDSubRegs(unsigned Reg, NEONRegSpacing RegSpc, const TargetRegisterInfo *TRI, MCRegister &D0, MCRegister &D1, MCRegister &D2, MCRegister &D3)

GetDSubRegs - Get 4 D subregisters of a Q, QQ, or QQQQ register, corresponding to the specified regis...

Definition ARMExpandPseudoInsts.cpp:519

static MachineOperand getMovOperand(const MachineOperand &MO, unsigned TargetFlag)

Definition ARMExpandPseudoInsts.cpp:956

static MachineOperand makeImplicit(const MachineOperand &MO)

Definition ARMExpandPseudoInsts.cpp:950

static void addExclusiveRegPair(MachineInstrBuilder &MIB, MachineOperand &Reg, unsigned Flags, bool IsThumb, const TargetRegisterInfo *TRI)

ARM's ldrexd/strexd take a consecutive register pair (represented as a single GPRPair register),...

Definition ARMExpandPseudoInsts.cpp:1964

static cl::opt< bool > VerifyARMPseudo("verify-arm-pseudo-expand", cl::Hidden, cl::desc("Verify machine code after expanding ARM pseudos"))

static bool definesOrUsesFPReg(const MachineInstr &MI)

Definition ARMExpandPseudoInsts.cpp:1789

static void determineGPRegsToClear(const MachineInstr &MI, const std::initializer_list< unsigned > &Regs, SmallVectorImpl< unsigned > &ClearRegs)

Definition ARMExpandPseudoInsts.cpp:1164

static void CMSEPushCalleeSaves(const TargetInstrInfo &TII, MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register JumpReg, const LivePhysRegs &LiveRegs, bool Thumb1Only)

Definition ARMExpandPseudoInsts.cpp:2085

static bool IsAnAddressOperand(const MachineOperand &MO)

Definition ARMExpandPseudoInsts.cpp:911

#define ARM_EXPAND_PSEUDO_NAME

Definition ARMExpandPseudoInsts.cpp:40

static const int CMSE_FP_SAVE_SIZE

Definition ARMExpandPseudoInsts.cpp:1162

static const NEONLdStTableEntry * LookupNEONLdSt(unsigned Opcode)

LookupNEONLdSt - Search the NEONLdStTable for information about a NEON load or store pseudo instructi...

Definition ARMExpandPseudoInsts.cpp:500

static const NEONLdStTableEntry NEONLdStTable[]

Definition ARMExpandPseudoInsts.cpp:171

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

MachineBasicBlock MachineBasicBlock::iterator MBBI

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

This file implements the LivePhysRegs utility for tracking liveness of physical registers.

Register const TargetRegisterInfo * TRI

Promote Memory to Register

MachineInstr unsigned OpIdx

#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)

static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)

static const unsigned FramePtr

bool hasBasePointer(const MachineFunction &MF) const

Register getFrameRegister(const MachineFunction &MF) const override

static ARMConstantPoolConstant * Create(const Constant *C, unsigned ID)

static ARMConstantPoolSymbol * Create(LLVMContext &C, StringRef s, unsigned ID, unsigned char PCAdj)

ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...

bool isThumb2Function() const

unsigned createPICLabelUId()

bool isThumb1OnlyFunction() const

bool isThumbFunction() const

bool shouldSignReturnAddress() const

unsigned getFramePtrSpillOffset() const

bool isTargetMachO() const

const ARMBaseInstrInfo * getInstrInfo() const override

bool isThumb1Only() const

bool isTargetWindows() const

const ARMBaseRegisterInfo * getRegisterInfo() const override

size_type count() const

count - Returns the number of bits which are set.

size_type size() const

size - Returns the number of bits in this bitvector.

FunctionPass class - This class is used to implement most global optimizations.

LLVMContext & getContext() const

getContext - Return a reference to the LLVMContext associated with this function.

bool needsUnwindTableEntry() const

True if this function needs an unwind table.

A set of physical registers with utility functions to track liveness when walking backward/forward th...

bool usesWindowsCFI() const

const MCInstrDesc & get(unsigned Opcode) const

Return the machine instruction descriptor that corresponds to the specified instruction opcode.

Wrapper class representing physical registers. Should be passed by value.

LLVM_ABI void transferSuccessors(MachineBasicBlock *FromMBB)

Transfers all the successors from MBB to this machine basic block (i.e., copies all the successors Fr...

const BasicBlock * getBasicBlock() const

Return the LLVM basic block that this instance corresponded to originally.

LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())

Add Succ as a successor of this MachineBasicBlock.

LLVM_ABI iterator getLastNonDebugInstr(bool SkipPseudoOp=true)

Returns an iterator to the last non-debug instruction in the basic block, or end().

void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())

Adds the specified register as a live in.

const MachineFunction * getParent() const

Return the MachineFunction containing this basic block.

LLVM_ABI instr_iterator erase(instr_iterator I)

Remove an instruction from the instruction list and delete it.

reverse_iterator rbegin()

void splice(iterator Where, MachineBasicBlock *Other, iterator From)

Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...

MachineInstrBundleIterator< MachineInstr > iterator

unsigned getConstantPoolIndex(const Constant *C, Align Alignment)

getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.

Align getMaxAlign() const

Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...

MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...

Properties which a MachineFunction may have at a given point in time.

void moveAdditionalCallInfo(const MachineInstr *Old, const MachineInstr *New)

Move the call site info from Old to \New call site info.

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

StringRef getName() const

getName - Return the name of the corresponding LLVM function.

MachineFrameInfo & getFrameInfo()

getFrameInfo - Return the frame info object for the current function.

Function & getFunction()

Return the LLVM function that this machine code represents.

Ty * getInfo()

getInfo - Keep track of various per-function pieces of information for backends that would like to do...

MachineConstantPool * getConstantPool()

getConstantPool - Return the constant pool object for the current function.

MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)

CreateMachineInstr - Allocate a new MachineInstr.

void insert(iterator MBBI, MachineBasicBlock *MBB)

const TargetMachine & getTarget() const

getTarget - Return the target machine this machine code is compiled with

const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

const MachineInstrBuilder & add(const MachineOperand &MO) const

const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const

const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const

const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const

Add a new virtual register operand.

const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const

const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const

const MachineInstrBuilder & setMIFlags(unsigned Flags) const

const MachineInstrBuilder & copyImplicitOps(const MachineInstr &OtherMI) const

Copy all the implicit operands from OtherMI onto this one.

MachineInstr * getInstr() const

If conversion operators fail, use this method to get the MachineInstr explicitly.

Representation of each machine instruction.

LLVM_ABI void addOperand(MachineFunction &MF, const MachineOperand &Op)

Add the specified operand to the instruction.

mop_range implicit_operands()

LLVM_ABI bool addRegisterKilled(Register IncomingReg, const TargetRegisterInfo *RegInfo, bool AddIfNotFound=false)

We have determined MI kills a register.

LLVM_ABI void dump() const

const MachineOperand & getOperand(unsigned i) const

@ EK_Inline

EK_Inline - Jump table entries are emitted inline at their point of use.

MachineOperand class - Representation of each machine instruction operand.

const GlobalValue * getGlobal() const

void setImplicit(bool Val=true)

static MachineOperand CreateES(const char *SymName, unsigned TargetFlags=0)

bool isReg() const

isReg - Tests if this is a MO_Register operand.

void setIsDead(bool Val=true)

bool isImm() const

isImm - Tests if this is a MO_Immediate operand.

bool isSymbol() const

isSymbol - Tests if this is a MO_ExternalSymbol operand.

unsigned getTargetFlags() const

static MachineOperand CreateImm(int64_t Val)

bool isGlobal() const

isGlobal - Tests if this is a MO_GlobalAddress operand.

MachineOperandType getType() const

getType - Returns the MachineOperandType for this operand.

static MachineOperand CreateJTI(unsigned Idx, unsigned TargetFlags=0)

const char * getSymbolName() const

void setIsUndef(bool Val=true)

Register getReg() const

getReg - Returns the register number.

static MachineOperand CreateGA(const GlobalValue *GV, int64_t Offset, unsigned TargetFlags=0)

@ MO_CFIIndex

MCCFIInstruction index.

@ MO_Immediate

Immediate operand.

@ MO_ConstantPoolIndex

Address of indexed Constant in Constant Pool.

@ MO_MCSymbol

MCSymbol reference (for debug/eh info)

@ MO_Predicate

Generic predicate for ISel.

@ MO_GlobalAddress

Address of a global value.

@ MO_RegisterMask

Mask of preserved registers.

@ MO_ShuffleMask

Other IR Constant for ISel (shuffle masks)

@ MO_CImmediate

Immediate >64bit operand.

@ MO_BlockAddress

Address of a basic block.

@ MO_DbgInstrRef

Integer indices referring to an instruction+operand.

@ MO_MachineBasicBlock

MachineBasicBlock reference.

@ MO_LaneMask

Mask to represent active parts of registers.

@ MO_FrameIndex

Abstract Stack Frame Index.

@ MO_Register

Register operand.

@ MO_ExternalSymbol

Name of external global symbol.

@ MO_IntrinsicID

Intrinsic ID for ISel.

@ MO_JumpTableIndex

Address of indexed Jump Table for switch.

@ MO_TargetIndex

Target-dependent index+offset operand.

@ MO_Metadata

Metadata reference (for debug info)

@ MO_FPImmediate

Floating-point immediate operand.

@ MO_RegisterLiveOut

Mask of live-out registers.

int64_t getOffset() const

Return the offset from the symbol in this operand.

Wrapper class representing virtual and physical registers.

constexpr bool isPhysical() const

Return true if the specified register number is in the physical register namespace.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

bool hasFP(const MachineFunction &MF) const

hasFP - Return true if the specified function should have a dedicated frame pointer register.

TargetInstrInfo - Interface to description of machine instruction set.

const TargetRegisterInfo & getRegisterInfo() const

const MCAsmInfo * getMCAsmInfo() const

Return target specific asm information.

TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...

virtual const TargetFrameLowering * getFrameLowering() const

self_iterator getIterator()

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

constexpr char Align[]

Key for Kernel::Arg::Metadata::mAlign.

@ GOT_PREL

Thread Local Storage (General Dynamic Mode)

@ MO_LO16

MO_LO16 - On a symbol operand, this represents a relocation containing lower 16 bit of the address.

@ MO_LO_0_7

MO_LO_0_7 - On a symbol operand, this represents a relocation containing bits 0 through 7 of the addr...

@ MO_LO_8_15

MO_LO_8_15 - On a symbol operand, this represents a relocation containing bits 8 through 15 of the ad...

@ MO_HI_8_15

MO_HI_8_15 - On a symbol operand, this represents a relocation containing bits 24 through 31 of the a...

@ MO_HI16

MO_HI16 - On a symbol operand, this represents a relocation containing higher 16 bit of the address.

@ MO_HI_0_7

MO_HI_0_7 - On a symbol operand, this represents a relocation containing bits 16 through 23 of the ad...

@ MO_GOT

MO_GOT - On a symbol operand, this represents a GOT relative relocation.

unsigned getSOImmTwoPartSecond(unsigned V)

getSOImmTwoPartSecond - If V is a value that satisfies isSOImmTwoPartVal, return the second chunk of ...

bool isSOImmTwoPartVal(unsigned V)

isSOImmTwoPartVal - Return true if the specified value can be obtained by or'ing together two SOImmVa...

unsigned getSORegOpc(ShiftOpc ShOp, unsigned Imm)

unsigned getSOImmTwoPartFirst(unsigned V)

getSOImmTwoPartFirst - If V is a value that satisfies isSOImmTwoPartVal, return the first chunk of it...

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

Flag

These should be considered private to the implementation of the MCInstrDesc class.

@ Implicit

Not emitted register (e.g. carry, or temporary result).

@ Define

Register definition.

@ Kill

The last use of a register.

@ Undef

Value of the register doesn't matter.

This is an optimization pass for GlobalISel generic memory operations.

auto drop_begin(T &&RangeOrContainer, size_t N=1)

Return a range covering RangeOrContainer with the first N elements excluded.

void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)

bool operator<(int64_t V1, const APSInt &V2)

LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)

finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...

bool all_of(R &&range, UnaryPredicate P)

Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.

MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)

Builder interface. Specify how to create the initial instruction itself.

iterator_range< T > make_range(T x, T y)

Convenience function for iterating over sub-ranges.

unsigned getDeadRegState(bool B)

static std::array< MachineOperand, 2 > predOps(ARMCC::CondCodes Pred, unsigned PredReg=0)

Get the operands corresponding to the given Pred value.

void sort(IteratorTy Start, IteratorTy End)

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

bool is_sorted(R &&Range, Compare C)

Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

unsigned getUndefRegState(bool B)

unsigned getRegState(const MachineOperand &RegOp)

Get all register state flags from machine operand RegOp.

unsigned getDefRegState(bool B)

auto lower_bound(R &&Range, T &&Value)

Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...

unsigned getKillRegState(bool B)

void emitThumbRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, const TargetInstrInfo &TII, const ARMBaseRegisterInfo &MRI, unsigned MIFlags=0)

emitThumbRegPlusImmediate - Emits a series of instructions to materialize a destreg = basereg + immed...

ARMCC::CondCodes getInstrPredicate(const MachineInstr &MI, Register &PredReg)

getInstrPredicate - If instruction is predicated, returns its predicate condition,...

unsigned getRenamableRegState(bool B)

DWARFExpression::Operation Op

static MachineOperand t1CondCodeOp(bool isDead=false)

Get the operand corresponding to the conditional code result for Thumb1.

void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB)

Convenience function combining computeLiveIns() and addLiveIns().

static MachineOperand condCodeOp(unsigned CCReg=0)

Get the operand corresponding to the conditional code result.

FunctionPass * createARMExpandPseudoPass()

createARMExpandPseudoPass - returns an instance of the pseudo instruction expansion pass.

Definition ARMExpandPseudoInsts.cpp:3322

unsigned gettBLXrOpcode(const MachineFunction &MF)

unsigned getBLXOpcode(const MachineFunction &MF)

void emitARMRegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, ARMCC::CondCodes Pred, Register PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)

emitARMRegPlusImmediate / emitT2RegPlusImmediate - Emits a series of instructions to materializea des...

void emitT2RegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, const DebugLoc &dl, Register DestReg, Register BaseReg, int NumBytes, ARMCC::CondCodes Pred, Register PredReg, const ARMBaseInstrInfo &TII, unsigned MIFlags=0)

constexpr uint64_t value() const

This is a hole in the type system and should not be abused.