LLVM: lib/Target/BPF/BPFAdjustOpt.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

17#include "llvm/IR/IntrinsicsBPF.h"

25

26#define DEBUG_TYPE "bpf-adjust-opt"

27

28using namespace llvm;

30

33 cl::desc("BPF: Disable Serializing ICMP insns."),

35

37 "bpf-disable-avoid-speculation", cl::Hidden,

38 cl::desc("BPF: Disable Avoiding Speculative Code Motion."),

40

41namespace {

42class BPFAdjustOptImpl {

43 struct PassThroughInfo {

49 };

50

51public:

52 BPFAdjustOptImpl(Module *M) : M(M) {}

53

54 bool run();

55

56private:

59

60 bool adjustICmpToBuiltin();

61 void adjustBasicBlock(BasicBlock &BB);

62 bool serializeICMPCrossBB(BasicBlock &BB);

63 void adjustInst(Instruction &I);

64 bool serializeICMPInBB(Instruction &I);

65 bool avoidSpeculation(Instruction &I);

66 bool insertPassThrough();

67};

68

69}

70

71bool BPFAdjustOptImpl::run() {

72 bool Changed = adjustICmpToBuiltin();

73

74 for (Function &F : *M)

75 for (auto &BB : F) {

76 adjustBasicBlock(BB);

77 for (auto &I : BB)

78 adjustInst(I);

79 }

80 return insertPassThrough() || Changed;

81}

82

83

84

85

86

87

88

89

90

91bool BPFAdjustOptImpl::adjustICmpToBuiltin() {

93 ICmpInst *ToBeDeleted = nullptr;

94 for (Function &F : *M)

95 for (auto &BB : F)

96 for (auto &I : BB) {

97 if (ToBeDeleted) {

99 ToBeDeleted = nullptr;

100 }

101

103 if (!Icmp)

104 continue;

105

106 Value *Op0 = Icmp->getOperand(0);

108 continue;

109

111 if (!ConstOp1)

112 continue;

113

114 auto ConstOp1Val = ConstOp1->getValue().getZExtValue();

115 auto Op = Icmp->getPredicate();

116 if (Op == ICmpInst::ICMP_ULT || Op == ICmpInst::ICMP_UGE) {

117 if ((ConstOp1Val - 1) & ConstOp1Val)

118 continue;

119 } else if (Op == ICmpInst::ICMP_ULE || Op == ICmpInst::ICMP_UGT) {

120 if (ConstOp1Val & (ConstOp1Val + 1))

121 continue;

122 } else {

123 continue;

124 }

125

127 ConstantInt::get(Type::getInt32Ty(BB.getContext()), Op);

129 M, Intrinsic::bpf_compare, {Op0->getType(), ConstOp1->getType()});

130 auto *NewInst = CallInst::Create(Fn, {Opcode, Op0, ConstOp1});

132 Icmp->replaceAllUsesWith(NewInst);

134 ToBeDeleted = Icmp;

135 }

136

138}

139

140bool BPFAdjustOptImpl::insertPassThrough() {

141 for (auto &Info : PassThroughs) {

143 M, Info.UsedInst->getParent(), Info.Input, Info.UsedInst);

144 Info.UsedInst->setOperand(Info.OpIdx, CI);

145 }

146

147 return !PassThroughs.empty();

148}

149

150

151

152bool BPFAdjustOptImpl::serializeICMPInBB(Instruction &I) {

153

154

155

156

157

158

159

160

161

162 Value *Op0, *Op1;

163

165 return false;

167 if (!Icmp1)

168 return false;

170 if (!Icmp2)

171 return false;

172

173 Value *Icmp1Op0 = Icmp1->getOperand(0);

174 Value *Icmp2Op0 = Icmp2->getOperand(0);

175 if (Icmp1Op0 != Icmp2Op0)

176 return false;

177

178

179

180 PassThroughInfo Info(Icmp1, &I, 0);

181 PassThroughs.push_back(Info);

182 return true;

183}

184

185

186

187bool BPFAdjustOptImpl::serializeICMPCrossBB(BasicBlock &BB) {

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

213 if (!B2)

214 return false;

215

217 if (!B1)

218 return false;

219

222 if (!BI || !BI->isConditional())

223 return false;

226 return false;

227 Value *B2Op0 = Cond->getOperand(0);

228 auto Cond2Op = Cond->getPredicate();

229

232 if (!BI || !BI->isConditional())

233 return false;

236 return false;

237 Value *B1Op0 = Cond->getOperand(0);

238 auto Cond1Op = Cond->getPredicate();

239

240 if (B1Op0 != B2Op0)

241 return false;

242

243 if (Cond1Op == ICmpInst::ICMP_SGT || Cond1Op == ICmpInst::ICMP_SGE) {

244 if (Cond2Op != ICmpInst::ICMP_SLT && Cond2Op != ICmpInst::ICMP_SLE)

245 return false;

246 } else if (Cond1Op == ICmpInst::ICMP_SLT || Cond1Op == ICmpInst::ICMP_SLE) {

247 if (Cond2Op != ICmpInst::ICMP_SGT && Cond2Op != ICmpInst::ICMP_SGE)

248 return false;

249 } else if (Cond1Op == ICmpInst::ICMP_ULT || Cond1Op == ICmpInst::ICMP_ULE) {

250 if (Cond2Op != ICmpInst::ICMP_UGT && Cond2Op != ICmpInst::ICMP_UGE)

251 return false;

252 } else if (Cond1Op == ICmpInst::ICMP_UGT || Cond1Op == ICmpInst::ICMP_UGE) {

253 if (Cond2Op != ICmpInst::ICMP_ULT && Cond2Op != ICmpInst::ICMP_ULE)

254 return false;

255 } else {

256 return false;

257 }

258

259 PassThroughInfo Info(Cond, BI, 0);

260 PassThroughs.push_back(Info);

261

262 return true;

263}

264

265

266

267bool BPFAdjustOptImpl::avoidSpeculation(Instruction &I) {

272 return false;

273 }

274 }

275

277 return false;

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

300 for (User *U : I.users()) {

302 if (!Inst)

303 continue;

304

305

306

308 Value *Icmp1Op1 = Icmp1->getOperand(1);

310 return false;

312 continue;

313 }

314

315

316 if (Inst->getParent() == I.getParent())

317 continue;

318

319

320

321

322 for (auto &I2 : *Inst->getParent()) {

324 return false;

326 return false;

327 if (&I2 == Inst)

328 break;

329 }

330

331

332

333 if (Inst->getOpcode() == Instruction::ZExt ||

334 Inst->getOpcode() == Instruction::SExt) {

335 PassThroughInfo Info(&I, Inst, 0);

338

339 unsigned i, e;

340 for (i = 1, e = GI->getNumOperands(); i != e; ++i) {

341 Value *V = GI->getOperand(i);

342 if (V == &I)

343 break;

344 }

345 if (i == e)

346 continue;

347

348 PassThroughInfo Info(&I, GI, i);

350 }

351 }

352

354 return false;

355

357 return true;

358}

359

360void BPFAdjustOptImpl::adjustBasicBlock(BasicBlock &BB) {

362 return;

363}

364

365void BPFAdjustOptImpl::adjustInst(Instruction &I) {

367 return;

369 return;

370}

371

static cl::opt< bool > DisableBPFserializeICMP("bpf-disable-serialize-icmp", cl::Hidden, cl::desc("BPF: Disable Serializing ICMP insns."), cl::init(false))

static cl::opt< bool > DisableBPFavoidSpeculation("bpf-disable-avoid-speculation", cl::Hidden, cl::desc("BPF: Disable Avoiding Speculative Code Motion."), cl::init(false))

Analysis containing CSE Info

Module.h This file contains the declarations for the Module class.

Machine Check Debug Module

static bool isCandidate(const MachineInstr *MI, Register &DefedReg, Register FrameReg)

MachineInstr unsigned OpIdx

const SmallVectorImpl< MachineOperand > & Cond

The Input class is used to parse a yaml document into in-memory structs and vectors.

PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)

Definition BPFAdjustOpt.cpp:372

LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const

Returns an iterator to the first instruction in this block that is not a PHINode instruction.

LLVM_ABI const BasicBlock * getSinglePredecessor() const

Return the predecessor of this block if it has a single predecessor block.

const Instruction * getTerminator() const LLVM_READONLY

Returns the terminator instruction if the block is well formed or null if the block is not well forme...

static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)

LLVM_ABI void insertBefore(InstListType::iterator InsertPos)

Insert an unlinked instruction into a basic block immediately before the specified position.

LLVM_ABI InstListType::iterator eraseFromParent()

This method unlinks 'this' from the containing basic block and deletes it.

unsigned getOpcode() const

Returns a member of one of the enums like Instruction::Add.

A Module instance is used to store all the information related to an LLVM module.

A set of analyses that are preserved following a run of a transformation pass.

static PreservedAnalyses none()

Convenience factory function for the empty preserved set.

static PreservedAnalyses all()

Construct a special preserved set that preserves all passes.

void push_back(const T &Elt)

Type * getType() const

All values are typed, get the type of this value.

const ParentTy * getParent() const

@ BasicBlock

Various leaf nodes.

LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})

Look up the Function declaration of the intrinsic id in the Module M.

bool match(Val *V, const Pattern &P)

auto m_LogicalOr()

Matches L || R where L and R are arbitrary values.

class_match< Value > m_Value()

Match an arbitrary value and ignore it.

initializer< Ty > init(const Ty &Val)

PointerTypeMap run(const Module &M)

Compute the PointerTypeMap for the module M.

friend class Instruction

Iterator for Instructions in a `BasicBlock.

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

void append_range(Container &C, Range &&R)

Wrapper function to append range R to container C.

class LLVM_GSL_OWNER SmallVector

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

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

DWARFExpression::Operation Op

AnalysisManager< Module > ModuleAnalysisManager

Convenience typedef for the Module analysis manager.