Moved patch forward to ToT.

Hi rinon,

http://llvm-reviews.chandlerc.com/D1803

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D1803?vs=4935&id=6618#toc

Files:
  include/llvm/CodeGen/CommandFlags.h
  include/llvm/MC/MCRegisterInfo.h
  include/llvm/Support/RandomNumberGenerator.h
  include/llvm/Target/TargetOptions.h
  lib/CodeGen/LLVMBuild.txt
  lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
  lib/LTO/LTOCodeGenerator.cpp
  lib/LTO/LTOModule.cpp
  lib/Support/CMakeLists.txt
  lib/Support/RandomNumberGenerator.cpp
  lib/Target/X86/CMakeLists.txt
  lib/Target/X86/NOPInsertion.cpp
  lib/Target/X86/X86.h
  lib/Target/X86/X86TargetMachine.cpp
  test/CodeGen/X86/nop-insert-percentage.ll
  test/CodeGen/X86/nop-insert.ll
  test/CodeGen/X86/sched-rnd-test.ll
  tools/llc/llc.cpp
  tools/llvm-lto/llvm-lto.cpp
  tools/lto/lto.cpp
  tools/opt/opt.cpp
Index: include/llvm/CodeGen/CommandFlags.h
===================================================================
--- include/llvm/CodeGen/CommandFlags.h
+++ include/llvm/CodeGen/CommandFlags.h
@@ -210,4 +210,9 @@
                           cl::value_desc("pass-name"),
                           cl::init(""));
 
+cl::opt<bool>
+NOPInsertion("nop-insertion",
+             cl::desc("Randomly add NOPs."),
+             cl::init(false));
+
 #endif
Index: include/llvm/MC/MCRegisterInfo.h
===================================================================
--- include/llvm/MC/MCRegisterInfo.h
+++ include/llvm/MC/MCRegisterInfo.h
@@ -18,6 +18,7 @@
 
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/RandomNumberGenerator.h"
 #include <cassert>
 
 namespace llvm {
Index: include/llvm/Support/RandomNumberGenerator.h
===================================================================
--- /dev/null
+++ include/llvm/Support/RandomNumberGenerator.h
@@ -0,0 +1,127 @@
+//==- llvm/Support/RandomNumberGenerator.h - RNG for diversity ---*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the crypto-secure Random Number Generator. This
+// RNG is based on HMAC_DRBG with MD5 as the hash.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_RANDOMNUMBERGENERATOR_H_
+#define LLVM_SUPPORT_RANDOMNUMBERGENERATOR_H_
+
+#include "llvm/Config/config.h"
+#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/ThreadLocal.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+#include <inttypes.h>
+
+namespace llvm {
+
+class StringRef;
+
+#define BLOCK_SIZE 16 // MD5 has a block size of 128 bits
+
+/// RandomNumberGenerator is a crypto-secure RNG which can be used to
+/// generate randomness for security uses. The RNG is based on the
+/// standard HMAC_DRBG with MD5 as the hash function.
+class RandomNumberGenerator {
+public:
+  /// Initialized by the frontend using SetSalt. Should contain
+  /// unique, deterministic data. Currently initialized to
+  /// command-line paramater string, without any randomly generated
+  /// arguments.
+  static std::string SaltData;
+
+  uint64_t Random();
+
+  static RandomNumberGenerator *Generator();
+
+  /// \brief Add additional personalization data to the RNG seed
+  ///
+  /// This function should be used to add deterministic command line
+  /// argument data to the RNG initialization, resulting in a
+  /// different stream of random numbers for each invocation during a
+  /// build. The input to this function should be unique per
+  /// compilation unit.
+  static void SetSalt(const StringRef &Salt) { SaltData = Salt; }
+
+  /// \brief Returns a random number in the range [0, Max)
+  ///
+  /// Uses sampling to make sure that the result is not biased because
+  /// Max does not divide evenly into 2^64
+  uint64_t Random(uint64_t Max) {
+    uint64_t t = Max * (((uint64_t)1 << 63) / Max);
+    uint64_t r;
+    while ((r = Random()) >= t)
+      ; /*noop */
+
+    return r % Max;
+  }
+
+  /// \brief Shuffles an *array* of type T.
+  ///
+  /// Uses the Durstenfeld version of the Fisher-Yates method (aka the Knuth
+  /// method).  See http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
+  template <typename T> void shuffle(T *array, size_t length) {
+    for (size_t i = length - 1; i > 0; i--) {
+      size_t j = Random(i + 1);
+      if (j < i)
+        std::swap(array[j], array[i]);
+    }
+  }
+
+  /// \brief Shuffles a SmallVector of type T, default size N
+  template <typename T, unsigned N> void shuffle(SmallVector<T, N> &sv) {
+    if (sv.empty())
+      return;
+    for (size_t i = sv.size() - 1; i > 0; i--) {
+      size_t j = Random(i + 1);
+      if (j < i)
+        std::swap(sv[j], sv[i]);
+    }
+  }
+
+  /// \brief Shuffles an iplist of type T
+  template <typename T> void shuffle(iplist<T> &list) {
+    if (list.empty())
+      return;
+    SmallVector<T *, 10> sv(list.begin(), list.end());
+    shuffle<T *, 10>(sv);
+    list.clear();
+    for (typename SmallVector<T *, 10>::size_type i = 0; i < sv.size(); i++) {
+      list.push_back(sv[i]);
+    }
+  }
+
+private:
+  typedef uint8_t BlockType[BLOCK_SIZE];
+
+  BlockType Value;
+  BlockType Key;
+
+  RandomNumberGenerator();
+
+  // Noncopyable.
+  RandomNumberGenerator(
+      const RandomNumberGenerator &other) LLVM_DELETED_FUNCTION;
+  RandomNumberGenerator &
+  operator=(const RandomNumberGenerator &other) LLVM_DELETED_FUNCTION;
+
+  void HMAC(BlockType Key, ArrayRef<uint8_t> Text, BlockType &Result);
+  void HMAC_DRBG_Update(ArrayRef<uint8_t> Data);
+
+  void Seed(StringRef Salt, uint64_t Seed);
+};
+}
+
+#endif
Index: include/llvm/Target/TargetOptions.h
===================================================================
--- include/llvm/Target/TargetOptions.h
+++ include/llvm/Target/TargetOptions.h
@@ -50,8 +50,9 @@
           GuaranteedTailCallOpt(false), DisableTailCalls(false),
           StackAlignmentOverride(0),
           EnableFastISel(false), PositionIndependentExecutable(false),
-          EnableSegmentedStacks(false), UseInitArray(false), TrapFuncName(""),
-          FloatABIType(FloatABI::Default), AllowFPOpFusion(FPOpFusion::Standard)
+          EnableSegmentedStacks(false), NOPInsertion(false), UseInitArray(false),
+          TrapFuncName(""), FloatABIType(FloatABI::Default),
+          AllowFPOpFusion(FPOpFusion::Standard)
     {}
 
     /// PrintMachineCode - This flag is enabled when the -print-machineinstrs
@@ -154,6 +155,9 @@
 
     unsigned EnableSegmentedStacks : 1;
 
+    /// Attempt to insert NOPs
+    unsigned NOPInsertion : 1;
+
     /// UseInitArray - Use .init_array instead of .ctors for static
     /// constructors.
     unsigned UseInitArray : 1;
Index: lib/CodeGen/LLVMBuild.txt
===================================================================
--- lib/CodeGen/LLVMBuild.txt
+++ lib/CodeGen/LLVMBuild.txt
@@ -22,4 +22,4 @@
 type = Library
 name = CodeGen
 parent = Libraries
-required_libraries = Analysis Core MC Scalar Support Target TransformUtils
+required_libraries = Analysis Core Instrumentation MC Scalar Support Target TransformUtils
Index: lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
===================================================================
--- lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
+++ lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
@@ -28,6 +28,7 @@
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/RandomNumberGenerator.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetInstrInfo.h"
 #include "llvm/Target/TargetLowering.h"
@@ -103,6 +104,17 @@
   "sched-avg-ipc", cl::Hidden, cl::init(1),
   cl::desc("Average inst/cycle whan no target itinerary exists."));
 
+static cl::opt<bool> RandomizeSchedule(
+  "sched-randomize",
+  cl::desc("Enable randomization of scheduling"),
+  cl::init(false));
+
+static cl::opt<unsigned> SchedRandPercentage(
+  "sched-randomize-percentage",
+  cl::desc("Percentage of instructions where schedule is randomized"),
+  cl::init(50));
+
+
 namespace {
 //===----------------------------------------------------------------------===//
 /// ScheduleDAGRRList - The actual register reduction list scheduler
@@ -1765,6 +1777,17 @@
 class RegReductionPriorityQueue : public RegReductionPQBase {
   SF Picker;
 
+  static SUnit *popRandom(std::vector<SUnit*> &Q) {
+    RandomNumberGenerator *randGen =
+      RandomNumberGenerator::Generator();
+    size_t randIndex = randGen->Random(Q.size());
+    SUnit *V = Q[randIndex];
+    if (randIndex < Q.size() - 1)
+      std::swap(Q[randIndex], Q.back());
+    Q.pop_back();
+    return V;
+  }
+
 public:
   RegReductionPriorityQueue(MachineFunction &mf,
                             bool tracksrp,
@@ -1785,7 +1808,19 @@
   SUnit *pop() {
     if (Queue.empty()) return NULL;
 
-    SUnit *V = popFromQueue(Queue, Picker, scheduleDAG);
+    SUnit *V;
+    if (RandomizeSchedule) {
+      RandomNumberGenerator *randGen =
+        RandomNumberGenerator::Generator();
+      unsigned int Roll = randGen->Random(100);
+      if (Roll < SchedRandPercentage) {
+        V = popRandom(Queue);
+      } else {
+        V = popFromQueue(Queue, Picker, scheduleDAG);
+      }
+    } else {
+      V = popFromQueue(Queue, Picker, scheduleDAG);
+    }
     V->NodeQueueId = 0;
     return V;
   }
Index: lib/LTO/LTOCodeGenerator.cpp
===================================================================
--- lib/LTO/LTOCodeGenerator.cpp
+++ lib/LTO/LTOCodeGenerator.cpp
@@ -39,6 +39,7 @@
 #include "llvm/Support/FormattedStream.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/RandomNumberGenerator.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/TargetRegistry.h"
@@ -143,6 +144,7 @@
   Options.PositionIndependentExecutable = options.PositionIndependentExecutable;
   Options.EnableSegmentedStacks = options.EnableSegmentedStacks;
   Options.UseInitArray = options.UseInitArray;
+  Options.NOPInsertion = options.NOPInsertion;
 }
 
 void LTOCodeGenerator::setDebugInfo(lto_debug_model debug) {
@@ -466,7 +468,12 @@
 
   Module *mergedModule = Linker.getModule();
 
-  // Mark which symbols can not be internalized
+  // if options were requested, set them
+  if ( !CodegenOptions.empty() )
+    cl::ParseCommandLineOptions(CodegenOptions.size(),
+                                const_cast<char **>(&CodegenOptions[0]));
+
+  // mark which symbols can not be internalized
   this->applyScopeRestrictions();
 
   // Instantiate the pass manager to organize the passes.
Index: lib/LTO/LTOModule.cpp
===================================================================
--- lib/LTO/LTOModule.cpp
+++ lib/LTO/LTOModule.cpp
@@ -35,6 +35,7 @@
 #include "llvm/Support/Host.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/RandomNumberGenerator.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/TargetSelect.h"
Index: lib/Support/CMakeLists.txt
===================================================================
--- lib/Support/CMakeLists.txt
+++ lib/Support/CMakeLists.txt
@@ -40,6 +40,7 @@
   MD5.cpp
   PluginLoader.cpp
   PrettyStackTrace.cpp
+  RandomNumberGenerator.cpp
   Regex.cpp
   SmallPtrSet.cpp
   SmallVector.cpp
Index: lib/Support/RandomNumberGenerator.cpp
===================================================================
--- /dev/null
+++ lib/Support/RandomNumberGenerator.cpp
@@ -0,0 +1,163 @@
+//===-- RandomNumberGenerator.cpp - Implement RNG class -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements cryptographically secure random number generation
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "rng"
+#include "llvm/Support/RandomNumberGenerator.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/Atomic.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MD5.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+// Only read by threads, so no locking
+// Needs to be available for SaltDataOpt to set by testing
+// command-line, so must be public
+std::string RandomNumberGenerator::SaltData;
+
+static cl::opt<unsigned long long>
+RandomSeed("rng-seed", cl::value_desc("seed"),
+           cl::desc("Seed for the random number generator"), cl::init(0));
+
+static cl::opt<std::string, true>
+SaltDataOpt("entropy-data",
+            cl::desc("Entropy data for the RNG (testing only, should be set "
+                     "by command line options"),
+            cl::Hidden, cl::location(RandomNumberGenerator::SaltData));
+
+static ManagedStatic<sys::ThreadLocal<const RandomNumberGenerator> > Instance;
+static unsigned InstanceCount = 0;
+
+/// This RNG is an implementation of the standard NIST SP 800-90A
+/// HMAC_DRBG random number generator, however with MD5 as the hash
+/// function. The use of MD5 does not comply with the NIST standard,
+/// which specifies SHA as the hash function instead. Since we are
+/// using HMAC-MD5, instead of plain MD5, and the random number stream
+/// is not directly revealed to an attacker, this should be
+/// sufficient.
+///
+/// Since this RNG is initialized from a 64-bit seed, it has only 64
+/// bits of entropy, rather than 128 as might be expected from
+/// MD5. This should not be a problem as long as possible attacks
+/// cannot brute-force through 2^64 possibilities.
+///
+/// Note: We do NOT perform reseeding due to constrained entropy
+/// data. Since we need reproducibility, we can only use the given
+/// 64-bit seed as entropy, and therefore have no additional entropy
+/// to reseed with. This means that we assume less than 2^48 calls to
+/// Random(). However, it is unlikely that compromise of the RNG is
+/// even possible in practice since the actual random stream is not
+/// exposed to an attacker.
+RandomNumberGenerator::RandomNumberGenerator() {
+  // Make sure each thread is seeded with a different seed
+  unsigned InstanceID = sys::AtomicIncrement(&InstanceCount);
+
+  if (RandomSeed == 0 && SaltData.empty())
+    DEBUG(errs() << "Warning! Using unseeded random number generator\n");
+
+  Seed(SaltData, RandomSeed + InstanceID);
+}
+
+void RandomNumberGenerator::HMAC(BlockType Key, ArrayRef<uint8_t> Text,
+                                 BlockType &Result) {
+  uint8_t Buffer[64];
+
+  // Set up ipad
+  memset(Buffer, 0, sizeof(Buffer));
+  memcpy(Buffer, Key, 16);
+  for (unsigned i = 0; i < 64; ++i) {
+    Buffer[i] ^= 0x36;
+  }
+
+  MD5 InnerHash;
+  MD5::MD5Result InnerResult;
+  InnerHash.update(makeArrayRef(Buffer));
+  InnerHash.update(Text);
+  InnerHash.final(InnerResult);
+
+  // Set up opad
+  memset(Buffer, 0, sizeof(Buffer));
+  memcpy(Buffer, Key, 16);
+  for (unsigned i = 0; i < 64; ++i) {
+    Buffer[i] ^= 0x5c;
+  }
+
+  MD5 OuterHash;
+  OuterHash.update(makeArrayRef(Buffer));
+  OuterHash.update(makeArrayRef(InnerResult));
+  OuterHash.final(Result);
+}
+
+void RandomNumberGenerator::HMAC_DRBG_Update(ArrayRef<uint8_t> Data =
+                                                 ArrayRef<uint8_t>()) {
+  SmallVector<uint8_t, 17> Buffer(Key, Key + 16);
+  Buffer.push_back(0x00);
+  Buffer.append(Data.begin(), Data.end());
+  HMAC(Key, Buffer, Key);
+  HMAC(Key, Value, Key);
+  if (Data.size() == 0)
+    return;
+
+  Buffer.clear();
+  Buffer.append(Key, Key + 16);
+  Buffer.push_back(0x01);
+  Buffer.append(Data.begin(), Data.end());
+  HMAC(Key, Buffer, Key);
+  HMAC(Key, Value, Value);
+}
+
+void RandomNumberGenerator::Seed(StringRef Salt, uint64_t Seed) {
+  DEBUG(dbgs() << "Re-Seeding RNG from salt and seed\n");
+  DEBUG(dbgs() << "Salt: " << Salt << "\n");
+  DEBUG(dbgs() << "Seed: " << Seed << "\n");
+
+  memset(Key, 0, sizeof(Key));
+  memset(Value, 1, sizeof(Value));
+
+  unsigned SeedSize = sizeof(Seed) + Salt.size();
+  uint8_t *SeedMaterial = new uint8_t[SeedSize];
+  memcpy(SeedMaterial, &Seed, sizeof(Seed));
+  memcpy(SeedMaterial + sizeof(Seed), Salt.data(), Salt.size());
+
+  HMAC_DRBG_Update(makeArrayRef(SeedMaterial, SeedSize));
+
+  delete[] SeedMaterial;
+}
+
+uint64_t RandomNumberGenerator::Random() {
+  HMAC(Key, Value, Value);
+  uint64_t Output = *(uint64_t *)(Value);
+
+  HMAC_DRBG_Update();
+
+  return Output;
+}
+
+RandomNumberGenerator *RandomNumberGenerator::Generator() {
+  RandomNumberGenerator *RNG =
+      const_cast<RandomNumberGenerator *>(Instance->get());
+
+  if (RNG == 0) {
+    RNG = new RandomNumberGenerator;
+    Instance->set(RNG);
+  }
+
+  return RNG;
+}
Index: lib/Target/X86/CMakeLists.txt
===================================================================
--- lib/Target/X86/CMakeLists.txt
+++ lib/Target/X86/CMakeLists.txt
@@ -13,6 +13,7 @@
 add_public_tablegen_target(X86CommonTableGen)
 
 set(sources
+  NOPInsertion.cpp
   X86AsmPrinter.cpp
   X86COFFMachineModuleInfo.cpp
   X86CodeEmitter.cpp
Index: lib/Target/X86/NOPInsertion.cpp
===================================================================
--- /dev/null
+++ lib/Target/X86/NOPInsertion.cpp
@@ -0,0 +1,144 @@
+//===- NOPInsertion.cpp - Insert NOPs between instructions ----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the NOPInsertion pass.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "nop-insertion"
+#include "X86InstrBuilder.h"
+#include "X86InstrInfo.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/RandomNumberGenerator.h"
+#include "llvm/Target/TargetInstrInfo.h"
+
+using namespace llvm;
+
+static cl::opt<unsigned>
+NOPInsertionPercentage(
+  "nop-insertion-percentage",
+  cl::desc("Percentage of instructions that have NOPs prepended"),
+  cl::init(50));
+
+static cl::opt<unsigned>
+MaxNOPsPerInstruction(
+  "max-nops-per-instruction",
+  llvm::cl::desc("Maximum number of NOPs per instruction"),
+  llvm::cl::init(1));
+
+
+STATISTIC(InsertedNOPs,
+          "Total number of noop type instructions inserted for diversity");
+
+namespace {
+class NOPInsertionPass : public MachineFunctionPass {
+
+  static char ID;
+
+  bool is64Bit;
+
+public:
+  NOPInsertionPass(bool is64Bit_) :
+      MachineFunctionPass(ID), is64Bit(is64Bit_) {
+  }
+
+  virtual bool runOnMachineFunction(MachineFunction &MF);
+
+  virtual const char *getPassName() const {
+    return "NOP insertion pass";
+  }
+
+  virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+    AU.setPreservesCFG();
+    MachineFunctionPass::getAnalysisUsage(AU);
+  }
+};
+}
+
+char NOPInsertionPass::ID = 0;
+
+enum { NOP,
+       MOV_EBP, MOV_ESP,
+       LEA_ESI, LEA_EDI,
+       MAX_NOPS };
+
+static const unsigned nopRegs[MAX_NOPS][2] = {
+    { 0, 0 },
+    { X86::EBP, X86::RBP },
+    { X86::ESP, X86::RSP },
+    { X86::ESI, X86::RSI },
+    { X86::EDI, X86::RDI },
+};
+
+bool NOPInsertionPass::runOnMachineFunction(MachineFunction &Fn) {
+  const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo();
+  for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) {
+    MachineBasicBlock::iterator FirstTerm = BB->getFirstTerminator();
+    // Insert NOPs before instruction.
+    for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ) {
+      MachineBasicBlock::iterator NextI = llvm::next(I);
+      if (I->isPseudo()) {
+        I = NextI;
+        continue;
+      }
+      // Insert random number of NOP-like instructions.
+      for (unsigned int i = 0; i < MaxNOPsPerInstruction; i++) {
+        unsigned int Roll = RandomNumberGenerator::Generator()->Random(100);
+        if (Roll >= NOPInsertionPercentage)
+          continue;
+
+        int NOPCode = RandomNumberGenerator::Generator()->Random(MAX_NOPS);
+
+        MachineInstr *NewMI = NULL;
+        unsigned reg = nopRegs[NOPCode][is64Bit];
+        switch (NOPCode) {
+        case NOP:
+          NewMI = BuildMI(*BB, I, I->getDebugLoc(), TII->get(X86::NOOP));
+          break;
+        case MOV_EBP:
+        case MOV_ESP: {
+          unsigned opc = is64Bit ? X86::MOV64rr : X86::MOV32rr;
+          NewMI = BuildMI(*BB, I, I->getDebugLoc(), TII->get(opc), reg)
+            .addReg(reg);
+          break;
+        }
+
+        case LEA_ESI:
+        case LEA_EDI: {
+          unsigned opc = is64Bit ? X86::LEA64r : X86::LEA32r;
+          NewMI = addRegOffset(BuildMI(*BB, I, I->getDebugLoc(),
+                                       TII->get(opc), reg),
+                               reg, false, 0);
+          break;
+        }
+        }
+
+        if (NewMI != NULL)
+          ++InsertedNOPs;
+      }
+      // Do not insert NOPs between terminators.
+      if (I == FirstTerm)
+        break;
+
+      I = NextI;
+    }
+  }
+  return true;
+}
+
+FunctionPass *llvm::createNOPInsertionPass(bool is64Bit) {
+  return new NOPInsertionPass(is64Bit);
+}
Index: lib/Target/X86/X86.h
===================================================================
--- lib/Target/X86/X86.h
+++ lib/Target/X86/X86.h
@@ -52,6 +52,10 @@
 /// AVX and SSE.
 FunctionPass *createX86IssueVZeroUpperPass();
 
+/// createNOPInsertionPass - This pass adds NOPs at random between
+/// instructions.
+FunctionPass *createNOPInsertionPass(bool is64Bit);
+
 /// createX86CodeEmitterPass - Return a pass that emits the collected X86 code
 /// to the specified MCE object.
 FunctionPass *createX86JITCodeEmitterPass(X86TargetMachine &TM,
Index: lib/Target/X86/X86TargetMachine.cpp
===================================================================
--- lib/Target/X86/X86TargetMachine.cpp
+++ lib/Target/X86/X86TargetMachine.cpp
@@ -225,6 +225,11 @@
     ShouldPrint = true;
   }
 
+  if (TM->Options.NOPInsertion) {
+    addPass(createNOPInsertionPass(getX86Subtarget().is64Bit()));
+    ShouldPrint = true;
+  }
+
   return ShouldPrint;
 }
 
Index: test/CodeGen/X86/nop-insert-percentage.ll
===================================================================
--- /dev/null
+++ test/CodeGen/X86/nop-insert-percentage.ll
@@ -0,0 +1,48 @@
+; RUN: llc < %s -rng-seed=1 -nop-insertion -nop-insertion-percentage=10 \
+; RUN:     | FileCheck %s --check-prefix=PERCENT10
+; RUN: llc < %s -rng-seed=1 -nop-insertion -nop-insertion-percentage=50 \
+; RUN:     | FileCheck %s --check-prefix=PERCENT50
+; RUN: llc < %s -rng-seed=1 -nop-insertion -nop-insertion-percentage=100 \
+; RUN:     | FileCheck %s --check-prefix=PERCENT100
+
+; This test case tests NOP insertion at varying percentage levels.
+
+define i32 @test(i32 %x, i32 %y, i32 %z) {
+entry:
+    %t1 = add i32 %x, %y
+    %t2 = mul i32 %t1, %z
+    %t3 = add i32 %t2, %x
+    %t4 = mul i32 %t3, %z
+    %t5 = add i32 %t4, %x
+    %t6 = mul i32 %t5, %z
+    %t7 = add i32 %t6, %x
+    %t8 = mul i32 %t7, %z
+    %t9 = add i32 %t8, %x
+    %t10 = mul i32 %t9, %z
+    %t11 = add i32 %t10, %x
+    ret i32 %t11
+}
+
+; PERCENT10: leaq	(%rdi), %rdi
+; PERCENT10: nop
+
+; PERCENT50: leaq	(%rsi), %rsi
+; PERCENT50: nop
+; PERCENT50: nop
+; PERCENT50: leaq	(%rsi), %rsi
+; PERCENT50: nop
+; PERCENT50: nop
+; PERCENT50: nop
+
+; PERCENT100: leaq	(%rsi), %rsi
+; PERCENT100: nop
+; PERCENT100: leaq	(%rdi), %rdi
+; PERCENT100: movq    %rbp, %rbp
+; PERCENT100: movq    %rsp, %rsp
+; PERCENT100: nop
+; PERCENT100: movq    %rsp, %rsp
+; PERCENT100: movq    %rsp, %rsp
+; PERCENT100: movq    %rsp, %rsp
+; PERCENT100: leaq	(%rdi), %rdi
+; PERCENT100: movq    %rsp, %rsp
+; PERCENT100: movq    %rsp, %rsp
Index: test/CodeGen/X86/nop-insert.ll
===================================================================
--- /dev/null
+++ test/CodeGen/X86/nop-insert.ll
@@ -0,0 +1,30 @@
+; RUN: llc < %s -nop-insertion | FileCheck %s
+; RUN: llc < %s -nop-insertion -entropy-data="test" -rng-seed=1 | FileCheck %s --check-prefix=SEED1
+; RUN: llc < %s -nop-insertion -entropy-data="test" -rng-seed=25 | FileCheck %s --check-prefix=SEED2
+; RUN: llc < %s -nop-insertion -entropy-data="test" -rng-seed=1534 | FileCheck %s --check-prefix=SEED3
+; RUN: llc < %s -nop-insertion -entropy-data="different entropy" -rng-seed=1 | FileCheck %s --check-prefix=ENTROPY
+
+; This test case checks that NOPs are inserted, and that the RNG seed
+; affects both the placement and choice of these NOPs.
+
+; CHECK: leaq	(%rsi), %rsi
+
+; SEED1: nop
+; SEED1-NOT: leaq	(%rsi), %rsi
+
+; SEED2: leaq	(%rdi), %rdi
+; SEED2: leaq	(%rdi), %rdi
+; SEED2-NOT: leaq	(%rsi), %rsi
+
+; SEED3: nop
+
+; ENTROPY: movq    %rbp, %rbp
+; ENTROPY: leaq	(%rdi), %rdi
+; ENTROPY-NOT: nop
+
+define i32 @test1(i32 %x, i32 %y, i32 %z) {
+entry:
+    %tmp = mul i32 %x, %y
+    %tmp2 = add i32 %tmp, %z
+    ret i32 %tmp2
+}
Index: test/CodeGen/X86/sched-rnd-test.ll
===================================================================
--- /dev/null
+++ test/CodeGen/X86/sched-rnd-test.ll
@@ -0,0 +1,36 @@
+; RUN: llc < %s -rng-seed=1 -sched-randomize -sched-randomize-percentage=100 | FileCheck %s --check-prefix=SEED1
+; RUN: llc < %s -rng-seed=5 -sched-randomize -sched-randomize-percentage=100 | FileCheck %s --check-prefix=SEED2
+; RUN: llc < %s -rng-seed=5 -sched-randomize -sched-randomize-percentage=50 | FileCheck %s --check-prefix=PERCENTAGE
+
+; This test case checks that the schedule randomization is changing
+; scheduling decisions, that different seeds result in different
+; schedules, and that the percentage alters the amount of
+; randomization
+
+define i32 @test(i32 %x, i32 %y, i32 %z) {
+entry:
+    %a = add i32 %x, %y
+    %b = add i32 %x, %z
+    %c = add i32 %y, %z
+    %d = mul i32 %a, %b
+    %e = mul i32 %d, %c
+    ret i32 %e
+}
+
+; SEED1: leal	(%rdi,%rdx), %ecx
+; SEED1-NEXT:	leal	(%rdi,%rsi), %eax
+; SEED1-NEXT:	imull	%ecx, %eax
+; SEED1-NEXT:	addl	%edx, %esi
+; SEED1-NEXT:	imull	%esi, %eax
+
+; SEED2: leal	(%rdi,%rdx), %ecx
+; SEED2-NEXT:	addl	%esi, %edx
+; SEED2-NEXT:	leal	(%rdi,%rsi), %eax
+; SEED2-NEXT:	imull	%ecx, %eax
+; SEED2-NEXT:	imull	%edx, %eax
+
+; PERCENTAGE: leal	(%rsi,%rdx), %eax
+; PERCENTAGE:	addl	%edi, %edx
+; PERCENTAGE:	addl	%edi, %esi
+; PERCENTAGE:	imull	%edx, %esi
+; PERCENTAGE:	imull	%esi, %eax
Index: tools/llc/llc.cpp
===================================================================
--- tools/llc/llc.cpp
+++ tools/llc/llc.cpp
@@ -33,6 +33,7 @@
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/PluginLoader.h"
 #include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/RandomNumberGenerator.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/TargetRegistry.h"
@@ -279,6 +280,7 @@
   Options.PositionIndependentExecutable = EnablePIE;
   Options.EnableSegmentedStacks = SegmentedStacks;
   Options.UseInitArray = UseInitArray;
+  Options.NOPInsertion = NOPInsertion;
 
   OwningPtr<TargetMachine>
     target(TheTarget->createTargetMachine(TheTriple.getTriple(),
Index: tools/llvm-lto/llvm-lto.cpp
===================================================================
--- tools/llvm-lto/llvm-lto.cpp
+++ tools/llvm-lto/llvm-lto.cpp
@@ -97,6 +97,7 @@
   Options.PositionIndependentExecutable = EnablePIE;
   Options.EnableSegmentedStacks = SegmentedStacks;
   Options.UseInitArray = UseInitArray;
+  Options.NOPInsertion = NOPInsertion;
 
   unsigned BaseArg = 0;
 
Index: tools/lto/lto.cpp
===================================================================
--- tools/lto/lto.cpp
+++ tools/lto/lto.cpp
@@ -75,6 +75,7 @@
   Options.TrapFuncName = TrapFuncName;
   Options.PositionIndependentExecutable = EnablePIE;
   Options.EnableSegmentedStacks = SegmentedStacks;
+  Options.NOPInsertion = NOPInsertion;
   Options.UseInitArray = UseInitArray;
 }
 
Index: tools/opt/opt.cpp
===================================================================
--- tools/opt/opt.cpp
+++ tools/opt/opt.cpp
@@ -37,6 +37,7 @@
 #include "llvm/Support/PassNameParser.h"
 #include "llvm/Support/PluginLoader.h"
 #include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/RandomNumberGenerator.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/SystemUtils.h"
@@ -552,6 +553,7 @@
   Options.PositionIndependentExecutable = EnablePIE;
   Options.EnableSegmentedStacks = SegmentedStacks;
   Options.UseInitArray = UseInitArray;
+  Options.NOPInsertion = NOPInsertion;
   return Options;
 }
 
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to