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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

58#include <assert.h>

59#include <stdint.h>

60

61using namespace llvm;

62

63#define DEBUG_TYPE "arm-fix-cortex-a57-aes-1742098"

64

65

66

67namespace {

69public:

70 static char ID;

72

74

77 }

78

79 StringRef getPassName() const override {

80 return "ARM fix for Cortex-A57 AES Erratum 1742098";

81 }

82

83 void getAnalysisUsage(AnalysisUsage &AU) const override {

87 }

88

89private:

90

91 struct AESFixupLocation {

93

96 };

97

101

102 void insertAESFixup(AESFixupLocation &FixupLoc, const ARMBaseInstrInfo *TII,

104

107};

108char ARMFixCortexA57AES1742098::ID = 0;

109

110}

111

113 "ARM fix for Cortex-A57 AES Erratum 1742098", false,

114 false)

117 "ARM fix for Cortex-A57 AES Erratum 1742098", false, false)

118

119

120

121bool ARMFixCortexA57AES1742098::isFirstAESPairInstr(MachineInstr &MI) {

122 unsigned Opc = MI.getOpcode();

123 return Opc == ARM::AESD || Opc == ARM::AESE;

124}

125

126bool ARMFixCortexA57AES1742098::isSafeAESInput(MachineInstr &MI) {

127 auto CondCodeIsAL = [](MachineInstr &MI) -> bool {

128 int CCIdx = MI.findFirstPredOperandIdx();

129 if (CCIdx == -1)

130 return false;

131 return MI.getOperand(CCIdx).getImm() == (int64_t)ARMCC::AL;

132 };

133

134 switch (MI.getOpcode()) {

135

136 default:

137 return false;

138

139 case ARM::AESD:

140 case ARM::AESE:

141 case ARM::AESMC:

142 case ARM::AESIMC:

143

144 return true;

145

146 case ARM::VANDd:

147 case ARM::VANDq:

148 case ARM::VORRd:

149 case ARM::VORRq:

150 case ARM::VEORd:

151 case ARM::VEORq:

152 case ARM::VMVNd:

153 case ARM::VMVNq:

154

155 case ARM::VMOVD:

156

157 case ARM::VMOVDRR:

158

159 case ARM::VMOVv2i64:

160 case ARM::VMOVv1i64:

161 case ARM::VMOVv2f32:

162 case ARM::VMOVv4f32:

163 case ARM::VMOVv2i32:

164 case ARM::VMOVv4i32:

165 case ARM::VMOVv4i16:

166 case ARM::VMOVv8i16:

167 case ARM::VMOVv8i8:

168 case ARM::VMOVv16i8:

169

170

171 case ARM::VLDRD:

172

173 case ARM::VLDMDDB_UPD:

174 case ARM::VLDMDIA_UPD:

175 case ARM::VLDMDIA:

176

177 case ARM::VLD1d64:

178 case ARM::VLD1q64:

179 case ARM::VLD1d32:

180 case ARM::VLD1q32:

181 case ARM::VLD2b32:

182 case ARM::VLD2d32:

183 case ARM::VLD2q32:

184 case ARM::VLD1d16:

185 case ARM::VLD1q16:

186 case ARM::VLD2d16:

187 case ARM::VLD2q16:

188 case ARM::VLD1d8:

189 case ARM::VLD1q8:

190 case ARM::VLD2b8:

191 case ARM::VLD2d8:

192 case ARM::VLD2q8:

193 case ARM::VLD3d32:

194 case ARM::VLD3q32:

195 case ARM::VLD3d16:

196 case ARM::VLD3q16:

197 case ARM::VLD3d8:

198 case ARM::VLD3q8:

199 case ARM::VLD4d32:

200 case ARM::VLD4q32:

201 case ARM::VLD4d16:

202 case ARM::VLD4q16:

203 case ARM::VLD4d8:

204 case ARM::VLD4q8:

205

206 case ARM::VLD1LNd32:

207 case ARM::VLD1LNd32_UPD:

208 case ARM::VLD1LNd8:

209 case ARM::VLD1LNd8_UPD:

210 case ARM::VLD1LNd16:

211 case ARM::VLD1LNd16_UPD:

212

213 case ARM::VLD1DUPd32:

214 case ARM::VLD1DUPd32wb_fixed:

215 case ARM::VLD1DUPd32wb_register:

216 case ARM::VLD1DUPd16:

217 case ARM::VLD1DUPd16wb_fixed:

218 case ARM::VLD1DUPd16wb_register:

219 case ARM::VLD1DUPd8:

220 case ARM::VLD1DUPd8wb_fixed:

221 case ARM::VLD1DUPd8wb_register:

222 case ARM::VLD1DUPq32:

223 case ARM::VLD1DUPq32wb_fixed:

224 case ARM::VLD1DUPq32wb_register:

225 case ARM::VLD1DUPq16:

226 case ARM::VLD1DUPq16wb_fixed:

227 case ARM::VLD1DUPq16wb_register:

228 case ARM::VLD1DUPq8:

229 case ARM::VLD1DUPq8wb_fixed:

230 case ARM::VLD1DUPq8wb_register:

231

232 case ARM::VSETLNi32:

233 case ARM::VSETLNi16:

234 case ARM::VSETLNi8:

235 return CondCodeIsAL(MI);

236 };

237

238 return false;

239}

240

241bool ARMFixCortexA57AES1742098::runOnMachineFunction(MachineFunction &F) {

242 LLVM_DEBUG(dbgs() << "***** ARMFixCortexA57AES1742098 *****\n");

243 auto &STI = F.getSubtarget();

244

245

246 if (!STI.hasAES() || !STI.fixCortexA57AES1742098())

247 return false;

248

249 const ARMBaseRegisterInfo *TRI = STI.getRegisterInfo();

250 const ARMBaseInstrInfo *TII = STI.getInstrInfo();

251

252 auto &RDI = getAnalysis().getRDI();

253

254

256 analyzeMF(F, RDI, TRI, FixupLocsForFn);

257

258

260 LLVM_DEBUG(dbgs() << "Inserting " << FixupLocsForFn.size() << " fixup(s)\n");

261 for (AESFixupLocation &FixupLoc : FixupLocsForFn) {

262 insertAESFixup(FixupLoc, TII, TRI);

264 }

265

267}

268

269void ARMFixCortexA57AES1742098::analyzeMF(

270 MachineFunction &MF, ReachingDefInfo &RDI, const ARMBaseRegisterInfo *TRI,

271 SmallVectorImpl &FixupLocsForFn) const {

272 unsigned MaxAllowedFixups = 0;

273

274 for (MachineBasicBlock &MBB : MF) {

275 for (MachineInstr &MI : MBB) {

276 if (!isFirstAESPairInstr(MI))

277 continue;

278

279

281 assert(MI.getNumExplicitOperands() == 3 && MI.getNumExplicitDefs() == 1 &&

282 "Unknown AES Instruction Format. Expected 1 def, 2 uses.");

283

284

285

286 MaxAllowedFixups += 2;

287

288

289 for (MachineOperand &MOp : MI.uses()) {

290 SmallPtrSet<MachineInstr *, 1> AllDefs{};

292

293

294 AESFixupLocation NewLoc{&MBB, &MI, &MOp};

295

296

297

298 bool IsLiveIn = MF.front().isLiveIn(MOp.getReg());

299

300

301

302

303 if (!IsLiveIn && AllDefs.size() == 0) {

305 << "Fixup Planned: No Defining Instrs found, not live-in: "

308 continue;

309 }

310

311 auto IsUnsafe = [](MachineInstr *MI) -> bool {

312 return !isSafeAESInput(*MI);

313 };

314 size_t UnsafeCount = llvm::count_if(AllDefs, IsUnsafe);

315

316

317 if (UnsafeCount == 0) {

318

319 if (!IsLiveIn) {

320

321 LLVM_DEBUG(dbgs() << "No Fixup: Defining instrs are all safe: "

323 continue;

324 }

325

326

327

329 << "Fixup Planned: Live-In (with safe defining instrs): "

331 NewLoc.Block = &MF.front();

332 NewLoc.InsertionPt = &*NewLoc.Block->begin();

333 LLVM_DEBUG(dbgs() << "Moving Fixup for Live-In to immediately before "

334 << *NewLoc.InsertionPt);

336 continue;

337 }

338

339

340

341

342

343

344

345 if (IsLiveIn || UnsafeCount > 1) {

346 LLVM_DEBUG(dbgs() << "Fixup Planned: Multiple unsafe defining instrs "

347 "(including live-ins): "

350 continue;

351 }

352

353 assert(UnsafeCount == 1 && !IsLiveIn &&

354 "At this point, there should be one unsafe defining instrs "

355 "and the defined register should not be a live-in.");

356 SmallPtrSetIterator<MachineInstr *> It =

359 "UnsafeCount == 1 but No Unsafe MachineInstr found.");

360 MachineInstr *DefMI = *It;

361

363 dbgs() << "Fixup Planned: Found single unsafe defining instrs for "

365

366

367

368

369

370

372 ++DefIt;

375 << "And immediately before " << *DefIt);

376 NewLoc.Block = DefIt->getParent();

377 NewLoc.InsertionPt = &*DefIt;

378 }

379

381 }

382 }

383 }

384

385 assert(FixupLocsForFn.size() <= MaxAllowedFixups &&

386 "Inserted too many fixups for this function.");

387 (void)MaxAllowedFixups;

388}

389

390void ARMFixCortexA57AES1742098::insertAESFixup(

391 AESFixupLocation &FixupLoc, const ARMBaseInstrInfo *TII,

392 const ARMBaseRegisterInfo *TRI) const {

393 MachineOperand *OperandToFixup = FixupLoc.MOp;

394

395 assert(OperandToFixup->isReg() && "OperandToFixup must be a register");

397

399 << " before: " << *FixupLoc.InsertionPt);

400

401

402

403

404

405

406

407

408

409

410

412 BuildMI(*FixupLoc.Block, FixupLoc.InsertionPt, DebugLoc(),

413 TII->get(ARM::VORRq))

418 .addReg(ARM::NoRegister);

419}

420

421

422

424 return new ARMFixCortexA57AES1742098();

425}

MachineInstrBuilder MachineInstrBuilder & DefMI

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

const HexagonInstrInfo * TII

Register const TargetRegisterInfo * TRI

Promote Memory to Register

#define INITIALIZE_PASS_DEPENDENCY(depName)

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

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

This file defines the SmallPtrSet class.

This file defines the SmallVector class.

Represent the analysis usage information of a pass.

AnalysisUsage & addRequired()

LLVM_ABI void setPreservesCFG()

This function should be called by the pass, iff they do not:

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

MachineInstrBundleIterator< MachineInstr > iterator

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

void getAnalysisUsage(AnalysisUsage &AU) const override

getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.

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

const MachineInstrBuilder & addImm(int64_t Val) const

Add a new immediate operand.

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

Add a new virtual register operand.

Representation of each machine instruction.

const MachineBasicBlock * getParent() const

MachineOperand class - Representation of each machine instruction operand.

bool isReg() const

isReg - Tests if this is a MO_Register operand.

LLVM_ABI bool isRenamable() const

isRenamable - Returns true if this register may be renamed, i.e.

Register getReg() const

getReg - Returns the register number.

This class provides the reaching def analysis.

void getGlobalReachingDefs(MachineInstr *MI, Register Reg, InstSet &Defs) const

Collect all possible definitions of the value stored in Reg, which is used by MI.

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

reference emplace_back(ArgTypes &&... Args)

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

unsigned ID

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

@ Renamable

Register that may be renamed.

@ Define

Register definition.

@ Kill

The last use of a register.

This is an optimization pass for GlobalISel generic memory operations.

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

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

LLVM_ABI raw_ostream & dbgs()

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

class LLVM_GSL_OWNER SmallVector

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

auto count_if(R &&Range, UnaryPredicate P)

Wrapper function around std::count_if to count the number of times an element satisfying a given pred...

auto find_if(R &&Range, UnaryPredicate P)

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

FunctionPass * createARMFixCortexA57AES1742098Pass()

Definition ARMFixCortexA57AES1742098Pass.cpp:423

LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)

Prints virtual and physical registers with or without a TRI instance.