NVPTX: Use MapMetadata() instead of custom/stale/untested logic
[oota-llvm.git] / lib / CodeGen / NoopInsertion.cpp
1 //===- NoopInsertion.cpp - Noop Insertion ---------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This pass adds fine-grained diversity by displacing code using randomly
11 // placed (optionally target supplied) Noop instructions.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/CodeGen/NoopInsertion.h"
16 #include "llvm/ADT/Statistic.h"
17 #include "llvm/CodeGen/MachineInstrBuilder.h"
18 #include "llvm/CodeGen/MachineModuleInfo.h"
19 #include "llvm/CodeGen/MachineRegisterInfo.h"
20 #include "llvm/CodeGen/Passes.h"
21 #include "llvm/IR/BasicBlock.h"
22 #include "llvm/IR/Function.h"
23 #include "llvm/IR/Module.h"
24 #include "llvm/Support/Allocator.h"
25 #include "llvm/Support/CommandLine.h"
26 #include "llvm/Support/RandomNumberGenerator.h"
27 #include "llvm/Target/TargetInstrInfo.h"
28 using namespace llvm;
29
30 #define DEBUG_TYPE "noop-insertion"
31
32 static cl::opt<unsigned> NoopInsertionPercentage(
33     "noop-insertion-percentage",
34     cl::desc("Percentage of instructions that have Noops prepended"),
35     cl::init(25)); // Default is a good balance between entropy and
36                    // performance impact
37
38 static cl::opt<unsigned> MaxNoopsPerInstruction(
39     "max-noops-per-instruction",
40     llvm::cl::desc("Maximum number of Noops per instruction"),
41     llvm::cl::init(1));
42
43 STATISTIC(InsertedNoops,
44           "Total number of noop type instructions inserted for diversity");
45
46 char NoopInsertion::ID = 0;
47 char &llvm::NoopInsertionID = NoopInsertion::ID;
48 INITIALIZE_PASS(NoopInsertion, "noop-insertion",
49                 "Noop Insertion for fine-grained code randomization", false,
50                 false)
51
52 NoopInsertion::NoopInsertion() : MachineFunctionPass(ID) {
53   initializeNoopInsertionPass(*PassRegistry::getPassRegistry());
54
55   // clamp percentage to 100
56   if (NoopInsertionPercentage > 100)
57     NoopInsertionPercentage = 100;
58 }
59
60 void NoopInsertion::getAnalysisUsage(AnalysisUsage &AU) const {
61   AU.setPreservesCFG();
62   MachineFunctionPass::getAnalysisUsage(AU);
63 }
64
65 bool NoopInsertion::runOnMachineFunction(MachineFunction &Fn) {
66   // The RNG must be initialized on first use so we have a Module to
67   // construct it from
68   if (!RNG)
69     RNG.reset(Fn.getFunction()->getParent()->createRNG(this));
70
71   const TargetInstrInfo *TII = Fn.getSubtarget().getInstrInfo();
72
73   unsigned FnInsertedNoopCount = 0;
74
75   for (auto &BB : Fn) {
76     MachineBasicBlock::iterator FirstTerm = BB.getFirstTerminator();
77
78     for (MachineBasicBlock::iterator I = BB.begin(), E = BB.end(); I != E;
79          ++I) {
80       if (I->isPseudo())
81         continue;
82
83       // Insert random number of Noop-like instructions.
84       for (unsigned i = 0; i < MaxNoopsPerInstruction; i++) {
85         if (Distribution(*RNG) >= NoopInsertionPercentage)
86           continue;
87
88         TII->insertNoop(BB, I, *RNG);
89
90         ++FnInsertedNoopCount;
91       }
92
93       if (I == FirstTerm)
94         break;
95     }
96   }
97
98   InsertedNoops += FnInsertedNoopCount;
99
100   return FnInsertedNoopCount > 0;
101 }