diff options
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/CodeGen/CodeGen.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/CodeGen/NoopInsertion.cpp | 101 | ||||
-rw-r--r-- | llvm/lib/CodeGen/Passes.cpp | 3 |
4 files changed, 106 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt index 48bf3545e73..672b6bae2dd 100644 --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -71,6 +71,7 @@ add_llvm_library(LLVMCodeGen MachineSink.cpp MachineTraceMetrics.cpp MachineVerifier.cpp + NoopInsertion.cpp OcamlGC.cpp OptimizePHIs.cpp PHIElimination.cpp diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp index 307dec548fc..fdb89438115 100644 --- a/llvm/lib/CodeGen/CodeGen.cpp +++ b/llvm/lib/CodeGen/CodeGen.cpp @@ -51,6 +51,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) { initializeMachineSchedulerPass(Registry); initializeMachineSinkingPass(Registry); initializeMachineVerifierPassPass(Registry); + initializeNoopInsertionPass(Registry); initializeOptimizePHIsPass(Registry); initializePHIEliminationPass(Registry); initializePeepholeOptimizerPass(Registry); diff --git a/llvm/lib/CodeGen/NoopInsertion.cpp b/llvm/lib/CodeGen/NoopInsertion.cpp new file mode 100644 index 00000000000..f2291b8e99c --- /dev/null +++ b/llvm/lib/CodeGen/NoopInsertion.cpp @@ -0,0 +1,101 @@ +//===- NoopInsertion.cpp - Noop Insertion ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass adds fine-grained diversity by displacing code using randomly +// placed (optionally target supplied) Noop instructions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/NoopInsertion.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/RandomNumberGenerator.h" +#include "llvm/Target/TargetInstrInfo.h" +using namespace llvm; + +#define DEBUG_TYPE "noop-insertion" + +static cl::opt<unsigned> NoopInsertionPercentage( + "noop-insertion-percentage", + cl::desc("Percentage of instructions that have Noops prepended"), + cl::init(25)); // Default is a good balance between entropy and + // performance impact + +static cl::opt<unsigned> MaxNoopsPerInstruction( + "max-noops-per-instruction", + llvm::cl::desc("Maximum number of Noops per instruction"), + llvm::cl::init(1)); + +STATISTIC(InsertedNoops, + "Total number of noop type instructions inserted for diversity"); + +char NoopInsertion::ID = 0; +char &llvm::NoopInsertionID = NoopInsertion::ID; +INITIALIZE_PASS(NoopInsertion, "noop-insertion", + "Noop Insertion for fine-grained code randomization", false, + false) + +NoopInsertion::NoopInsertion() : MachineFunctionPass(ID) { + initializeNoopInsertionPass(*PassRegistry::getPassRegistry()); + + // clamp percentage to 100 + if (NoopInsertionPercentage > 100) + NoopInsertionPercentage = 100; +} + +void NoopInsertion::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool NoopInsertion::runOnMachineFunction(MachineFunction &Fn) { + // The RNG must be initialized on first use so we have a Module to + // construct it from + if (!RNG) + RNG.reset(Fn.getFunction()->getParent()->createRNG(this)); + + const TargetInstrInfo *TII = Fn.getSubtarget().getInstrInfo(); + + unsigned FnInsertedNoopCount = 0; + + for (auto &BB : Fn) { + MachineBasicBlock::iterator FirstTerm = BB.getFirstTerminator(); + + for (MachineBasicBlock::iterator I = BB.begin(), E = BB.end(); I != E; + ++I) { + if (I->isPseudo()) + continue; + + // Insert random number of Noop-like instructions. + for (unsigned i = 0; i < MaxNoopsPerInstruction; i++) { + if (Distribution(*RNG) >= NoopInsertionPercentage) + continue; + + TII->insertNoop(BB, I, *RNG); + + ++FnInsertedNoopCount; + } + + if (I == FirstTerm) + break; + } + } + + InsertedNoops += FnInsertedNoopCount; + + return FnInsertedNoopCount > 0; +} diff --git a/llvm/lib/CodeGen/Passes.cpp b/llvm/lib/CodeGen/Passes.cpp index 28e9f847a9d..a5d32103d7c 100644 --- a/llvm/lib/CodeGen/Passes.cpp +++ b/llvm/lib/CodeGen/Passes.cpp @@ -583,6 +583,9 @@ void TargetPassConfig::addMachinePasses() { addPass(createGCInfoPrinter(dbgs()), false, false); } + if (TM->Options.NoopInsertion) + addPass(&NoopInsertionID); + // Basic block placement. if (getOptLevel() != CodeGenOpt::None) addBlockPlacement(); |