Skip to content

Commit dcdd5ad

Browse files
committedJan 14, 2015
Insert random noops to increase security against ROP attacks (llvm)
A pass that adds random noops to X86 binaries to introduce diversity with the goal of increasing security against most return-oriented programming attacks. Command line options: -noop-insertion // Enable noop insertion. -noop-insertion-percentage=X // X% of assembly instructions will have a noop prepended (default: 50%, requires -noop-insertion) -max-noops-per-instruction=X // Randomly generate X noops per instruction. ie. roll the dice X times with probability set above (default: 1). This doesn't guarantee X noop instructions. In addition, the following 'quick switch' in clang enables basic diversity using default settings (currently: noop insertion and schedule randomization; it is intended to be extended in the future). -fdiversify This is the llvm part of the patch. clang part: D3393 http://reviews.llvm.org/D3392 Patch by Stephen Crane (@rinon) llvm-svn: 225908
1 parent 6650268 commit dcdd5ad

17 files changed

+428
-4
lines changed
 

‎llvm/include/llvm/CodeGen/CommandFlags.h

+7
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,12 @@ FunctionSections("function-sections",
207207
cl::desc("Emit functions into separate sections"),
208208
cl::init(false));
209209

210+
cl::opt<bool>
211+
NoopInsertion("noop-insertion",
212+
cl::desc("Randomly add Noop instructions to create fine-grained "
213+
"code layout diversity."),
214+
cl::init(false));
215+
210216
cl::opt<llvm::JumpTable::JumpTableType>
211217
JTableType("jump-table-type",
212218
cl::desc("Choose the type of Jump-Instruction Table for jumptable."),
@@ -284,6 +290,7 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() {
284290
Options.UseInitArray = !UseCtors;
285291
Options.DataSections = DataSections;
286292
Options.FunctionSections = FunctionSections;
293+
Options.NoopInsertion = NoopInsertion;
287294

288295
Options.MCOptions = InitMCTargetOptionsFromFlags();
289296
Options.JTType = JTableType;
+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//===-- NoopInsertion.h - Noop Insertion ------------------------*- C++ -*-===//
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+
#ifndef LLVM_CODEGEN_NOOPINSERTION_H
16+
#define LLVM_CODEGEN_NOOPINSERTION_H
17+
18+
#include "llvm/CodeGen/MachineFunctionPass.h"
19+
#include <random>
20+
21+
namespace llvm {
22+
23+
class RandomNumberGenerator;
24+
25+
class NoopInsertion : public MachineFunctionPass {
26+
public:
27+
static char ID;
28+
29+
NoopInsertion();
30+
31+
private:
32+
bool runOnMachineFunction(MachineFunction &MF) override;
33+
34+
void getAnalysisUsage(AnalysisUsage &AU) const override;
35+
36+
std::unique_ptr<RandomNumberGenerator> RNG;
37+
38+
// Uniform real distribution from 0 to 100
39+
std::uniform_real_distribution<double> Distribution =
40+
std::uniform_real_distribution<double>(0, 100);
41+
};
42+
}
43+
44+
#endif // LLVM_CODEGEN_NOOPINSERTION_H

‎llvm/include/llvm/CodeGen/Passes.h

+4
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,10 @@ namespace llvm {
603603
/// the intrinsic for later emission to the StackMap.
604604
extern char &StackMapLivenessID;
605605

606+
/// NoopInsertion - This pass adds fine-grained diversity by displacing code
607+
/// using randomly placed (optionally target supplied) Noop instructions.
608+
extern char &NoopInsertionID;
609+
606610
/// createJumpInstrTables - This pass creates jump-instruction tables.
607611
ModulePass *createJumpInstrTablesPass();
608612

‎llvm/include/llvm/InitializePasses.h

+1
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ void initializeMetaRenamerPass(PassRegistry&);
205205
void initializeMergeFunctionsPass(PassRegistry&);
206206
void initializeModuleDebugInfoPrinterPass(PassRegistry&);
207207
void initializeNoAAPass(PassRegistry&);
208+
void initializeNoopInsertionPass(PassRegistry&);
208209
void initializeObjCARCAliasAnalysisPass(PassRegistry&);
209210
void initializeObjCARCAPElimPass(PassRegistry&);
210211
void initializeObjCARCExpandPass(PassRegistry&);

‎llvm/include/llvm/Support/RandomNumberGenerator.h

+14-2
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,20 @@ namespace llvm {
3131
/// module.
3232
class RandomNumberGenerator {
3333
public:
34+
typedef std::mt19937_64 RNG;
35+
typedef RNG::result_type result_type;
36+
3437
/// Returns a random number in the range [0, Max).
35-
uint_fast64_t operator()();
38+
result_type operator()();
39+
40+
// Must define min and max to be compatible with URNG as used by
41+
// std::uniform_*_distribution
42+
static LLVM_CONSTEXPR result_type min() {
43+
return RNG::min();
44+
}
45+
static LLVM_CONSTEXPR result_type max() {
46+
return RNG::max();
47+
}
3648

3749
private:
3850
/// Seeds and salts the underlying RNG engine.
@@ -45,7 +57,7 @@ class RandomNumberGenerator {
4557
// http://en.cppreference.com/w/cpp/numeric/random/mersenne_twister_engine
4658
// This RNG is deterministically portable across C++11
4759
// implementations.
48-
std::mt19937_64 Generator;
60+
RNG Generator;
4961

5062
// Noncopyable.
5163
RandomNumberGenerator(const RandomNumberGenerator &other)

‎llvm/include/llvm/Target/TargetInstrInfo.h

+9
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class MDNode;
3232
class MCInst;
3333
struct MCSchedModel;
3434
class MCSymbolRefExpr;
35+
class RandomNumberGenerator;
3536
class SDNode;
3637
class ScheduleHazardRecognizer;
3738
class SelectionDAG;
@@ -875,6 +876,14 @@ class TargetInstrInfo : public MCInstrInfo {
875876
virtual void insertNoop(MachineBasicBlock &MBB,
876877
MachineBasicBlock::iterator MI) const;
877878

879+
/// insertNoop - Insert a type of noop into the instruction stream at the
880+
/// specified point to introduce fine-grained diversity. A target may randomly
881+
/// choose from a pool of valid noops using the provided RNG.
882+
virtual void insertNoop(MachineBasicBlock &MBB,
883+
MachineBasicBlock::iterator MI,
884+
RandomNumberGenerator&) const {
885+
insertNoop(MBB, MI);
886+
}
878887

879888
/// Return the noop instruction to use for a noop.
880889
virtual void getNoopForMachoTarget(MCInst &NopInst) const;

‎llvm/include/llvm/Target/TargetOptions.h

+6-2
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ namespace llvm {
7878
EnableFastISel(false), PositionIndependentExecutable(false),
7979
UseInitArray(false), DisableIntegratedAS(false),
8080
CompressDebugSections(false), FunctionSections(false),
81-
DataSections(false), TrapUnreachable(false), TrapFuncName(),
82-
FloatABIType(FloatABI::Default),
81+
DataSections(false), NoopInsertion(false), TrapUnreachable(false),
82+
TrapFuncName(), FloatABIType(FloatABI::Default),
8383
AllowFPOpFusion(FPOpFusion::Standard), JTType(JumpTable::Single),
8484
FCFI(false), ThreadModel(ThreadModel::POSIX),
8585
CFIType(CFIntegrity::Sub), CFIEnforcing(false), CFIFuncName() {}
@@ -198,6 +198,10 @@ namespace llvm {
198198
/// Emit data into separate sections.
199199
unsigned DataSections : 1;
200200

201+
/// Randomly insert noop instructions to create fine-grained code
202+
/// layout diversity.
203+
unsigned NoopInsertion : 1;
204+
201205
/// Emit target-specific trap instruction for 'unreachable' IR instructions.
202206
unsigned TrapUnreachable : 1;
203207

‎llvm/lib/CodeGen/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ add_llvm_library(LLVMCodeGen
7171
MachineSink.cpp
7272
MachineTraceMetrics.cpp
7373
MachineVerifier.cpp
74+
NoopInsertion.cpp
7475
OcamlGC.cpp
7576
OptimizePHIs.cpp
7677
PHIElimination.cpp

‎llvm/lib/CodeGen/CodeGen.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
5151
initializeMachineSchedulerPass(Registry);
5252
initializeMachineSinkingPass(Registry);
5353
initializeMachineVerifierPassPass(Registry);
54+
initializeNoopInsertionPass(Registry);
5455
initializeOptimizePHIsPass(Registry);
5556
initializePHIEliminationPass(Registry);
5657
initializePeepholeOptimizerPass(Registry);

‎llvm/lib/CodeGen/NoopInsertion.cpp

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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+
}

‎llvm/lib/CodeGen/Passes.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,9 @@ void TargetPassConfig::addMachinePasses() {
583583
addPass(createGCInfoPrinter(dbgs()), false, false);
584584
}
585585

586+
if (TM->Options.NoopInsertion)
587+
addPass(&NoopInsertionID);
588+
586589
// Basic block placement.
587590
if (getOptLevel() != CodeGenOpt::None)
588591
addBlockPlacement();

‎llvm/lib/Target/X86/X86InstrInfo.cpp

+61
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "llvm/Support/CommandLine.h"
3535
#include "llvm/Support/Debug.h"
3636
#include "llvm/Support/ErrorHandling.h"
37+
#include "llvm/Support/RandomNumberGenerator.h"
3738
#include "llvm/Support/raw_ostream.h"
3839
#include "llvm/Target/TargetOptions.h"
3940
#include <limits>
@@ -5620,6 +5621,66 @@ void X86InstrInfo::setExecutionDomain(MachineInstr *MI, unsigned Domain) const {
56205621
MI->setDesc(get(table[Domain-1]));
56215622
}
56225623

5624+
/// insertNoop - Insert a noop into the instruction stream at the specified
5625+
/// point.
5626+
void X86InstrInfo::insertNoop(MachineBasicBlock &MBB,
5627+
MachineBasicBlock::iterator MI) const {
5628+
DebugLoc DL;
5629+
BuildMI(MBB, MI, DL, get(X86::NOOP));
5630+
}
5631+
5632+
/// insertNoop - Insert a randomly chosen type of noop into the instruction
5633+
/// stream at the specified point to introduce fine-grained diversity.
5634+
void X86InstrInfo::insertNoop(MachineBasicBlock &MBB,
5635+
MachineBasicBlock::iterator MI,
5636+
RandomNumberGenerator &RNG) const {
5637+
// This set of Noop instructions was carefully chosen so that
5638+
// misaligned parses of these instructions do not introduce new,
5639+
// useful ROP gadgets. The ASM instructions noted are for misaligned
5640+
// parses of the noop in 32 and 64 bits.
5641+
enum {
5642+
NOP, // 90
5643+
MOV_BP, // 89 ed, 48 89 ed -- IN EAX, IN AL (privileged)
5644+
MOV_SP, // 89 e4, 48 89 e4 -- IN AL, IN EAX (privileged)
5645+
LEA_SI, // 8d 36, 48 8d 36 -- SS segment override, NULL
5646+
// prefix (does not add new gadget)
5647+
LEA_DI, // 8d 3f, 48 8d 3f -- AAS (bcd->hex), invalid
5648+
MAX_NOPS
5649+
};
5650+
5651+
static const unsigned NopRegs[MAX_NOPS][2] = {
5652+
{0, 0},
5653+
{X86::EBP, X86::RBP},
5654+
{X86::ESP, X86::RSP},
5655+
{X86::ESI, X86::RSI},
5656+
{X86::EDI, X86::RDI},
5657+
};
5658+
5659+
std::uniform_int_distribution<unsigned> Distribution(0, MAX_NOPS - 1);
5660+
5661+
unsigned Type = Distribution(RNG);
5662+
5663+
DebugLoc DL;
5664+
bool is64Bit = Subtarget.is64Bit();
5665+
unsigned Reg = NopRegs[Type][is64Bit];
5666+
5667+
switch (Type) {
5668+
case NOP:
5669+
BuildMI(MBB, MI, DL, get(X86::NOOP));
5670+
break;
5671+
case MOV_BP:
5672+
case MOV_SP:
5673+
copyPhysReg(MBB, MI, DL, Reg, Reg, false);
5674+
break;
5675+
case LEA_SI:
5676+
case LEA_DI: {
5677+
unsigned opc = is64Bit ? X86::LEA64r : X86::LEA32r;
5678+
addRegOffset(BuildMI(MBB, MI, DL, get(opc), Reg), Reg, false, 0);
5679+
break;
5680+
}
5681+
}
5682+
}
5683+
56235684
/// getNoopForMachoTarget - Return the noop instruction to use for a noop.
56245685
void X86InstrInfo::getNoopForMachoTarget(MCInst &NopInst) const {
56255686
NopInst.setOpcode(X86::NOOP);

‎llvm/lib/Target/X86/X86InstrInfo.h

+7
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,13 @@ class X86InstrInfo final : public X86GenInstrInfo {
361361
bool shouldScheduleAdjacent(MachineInstr* First,
362362
MachineInstr *Second) const override;
363363

364+
void insertNoop(MachineBasicBlock &MBB,
365+
MachineBasicBlock::iterator MI) const override;
366+
367+
void insertNoop(MachineBasicBlock &MBB,
368+
MachineBasicBlock::iterator MI,
369+
RandomNumberGenerator &RNG) const override;
370+
364371
void getNoopForMachoTarget(MCInst &NopInst) const override;
365372

366373
bool

‎llvm/test/CodeGen/Mips/noop-insert.ll

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
; RUN: llc < %s -march=mips -noop-insertion | FileCheck %s
2+
; RUN: llc < %s -march=mips -noop-insertion -rng-seed=1 | FileCheck %s --check-prefix=SEED1
3+
; RUN: llc < %s -march=mips -noop-insertion -noop-insertion-percentage=100 | FileCheck %s --check-prefix=100PERCENT
4+
5+
; This test case checks that NOOPs are inserted correctly for MIPS.
6+
7+
; It just happens that with a default percentage of 25% and seed=0,
8+
; no NOOPs are inserted.
9+
; CHECK: mul
10+
; CHECK-NEXT: jr
11+
12+
; SEED1: nop
13+
; SEED1-NEXT: mul
14+
; SEED1-NEXT: jr
15+
16+
; 100PERCENT: nop
17+
; 100PERCENT-NEXT: mul
18+
; 100PERCENT-NEXT: nop
19+
; 100PERCENT-NEXT: jr
20+
21+
define i32 @test1(i32 %x, i32 %y, i32 %z) {
22+
entry:
23+
%tmp = mul i32 %x, %y
24+
%tmp2 = add i32 %tmp, %z
25+
ret i32 %tmp2
26+
}
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
; RUN: llc < %s -march=ppc32 -noop-insertion | FileCheck %s
2+
; RUN: llc < %s -march=ppc32 -noop-insertion -rng-seed=1 | FileCheck %s --check-prefix=SEED1
3+
; RUN: llc < %s -march=ppc32 -noop-insertion -noop-insertion-percentage=100 | FileCheck %s --check-prefix=100PERCENT
4+
5+
; This test case checks that NOOPs are inserted correctly for PowerPC.
6+
7+
; It just happens that with a default percentage of 25% and seed=0,
8+
; no NOOPs are inserted.
9+
; CHECK: mullw
10+
; CHECK-NEXT: add
11+
; CHECK-NEXT: blr
12+
13+
; SEED1: nop
14+
; SEED1-NEXT: mullw
15+
; SEED1-NEXT: add
16+
; SEED1-NEXT: nop
17+
; SEED1-NEXT: blr
18+
19+
; 100PERCENT: nop
20+
; 100PERCENT-NEXT: mullw
21+
; 100PERCENT-NEXT: nop
22+
; 100PERCENT-NEXT: add
23+
; 100PERCENT-NEXT: nop
24+
; 100PERCENT-NEXT: blr
25+
26+
define i32 @test1(i32 %x, i32 %y, i32 %z) {
27+
entry:
28+
%tmp = mul i32 %x, %y
29+
%tmp2 = add i32 %tmp, %z
30+
ret i32 %tmp2
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
; RUN: llc < %s -mtriple=x86_64-linux -rng-seed=5 -noop-insertion -noop-insertion-percentage=10 \
2+
; RUN: | FileCheck %s --check-prefix=PERCENT10
3+
; RUN: llc < %s -mtriple=x86_64-linux -rng-seed=5 -noop-insertion -noop-insertion-percentage=50 \
4+
; RUN: | FileCheck %s --check-prefix=PERCENT50
5+
; RUN: llc < %s -mtriple=x86_64-linux -rng-seed=5 -noop-insertion -noop-insertion-percentage=100 \
6+
; RUN: | FileCheck %s --check-prefix=PERCENT100
7+
8+
; RUN: llc < %s -march=x86 -rng-seed=5 -noop-insertion -noop-insertion-percentage=100 \
9+
; RUN: | FileCheck %s --check-prefix=X86-PERCENT100
10+
11+
; This test case tests NOOP insertion at varying percentage levels.
12+
13+
define i32 @test(i32 %x, i32 %y, i32 %z) {
14+
entry:
15+
%t1 = add i32 %x, %y
16+
%t2 = mul i32 %t1, %z
17+
%t3 = add i32 %t2, %x
18+
%t4 = mul i32 %t3, %z
19+
%t5 = add i32 %t4, %x
20+
%t6 = mul i32 %t5, %z
21+
%t7 = add i32 %t6, %x
22+
%t8 = mul i32 %t7, %z
23+
%t9 = add i32 %t8, %x
24+
%t10 = mul i32 %t9, %z
25+
%t11 = add i32 %t10, %x
26+
ret i32 %t11
27+
}
28+
29+
; PERCENT10: movq %rbp, %rbp
30+
; PERCENT10: retq
31+
32+
; PERCENT50: leaq (%rdi), %rdi
33+
; PERCENT50: nop
34+
; PERCENT50: movq %rbp, %rbp
35+
; PERCENT50: movq %rsp, %rsp
36+
; PERCENT50: leaq (%rsi), %rsi
37+
; PERCENT50: nop
38+
; PERCENT50: retq
39+
40+
; PERCENT100: leaq (%rdi), %rdi
41+
; PERCENT100: leaq (%rdi), %rdi
42+
; PERCENT100: nop
43+
; PERCENT100: movq %rbp, %rbp
44+
; PERCENT100: movq %rsp, %rsp
45+
; PERCENT100: nop
46+
; PERCENT100: nop
47+
; PERCENT100: leaq (%rsi), %rsi
48+
; PERCENT100: nop
49+
; PERCENT100: leaq (%rdi), %rdi
50+
; PERCENT100: leaq (%rdi), %rdi
51+
; PERCENT100: leaq (%rsi), %rsi
52+
; PERCENT100: retq
53+
54+
55+
; X86-PERCENT100: leal (%edi), %edi
56+
; X86-PERCENT100: leal (%edi), %edi
57+
; X86-PERCENT100: nop
58+
; X86-PERCENT100: movl %ebp, %ebp
59+
; X86-PERCENT100: movl %esp, %esp
60+
; X86-PERCENT100: nop
61+
; X86-PERCENT100: nop
62+
; X86-PERCENT100: leal (%esi), %esi
63+
; X86-PERCENT100: nop
64+
; X86-PERCENT100: leal (%edi), %edi
65+
; X86-PERCENT100: leal (%edi), %edi
66+
; X86-PERCENT100: leal (%esi), %esi

‎llvm/test/CodeGen/X86/noop-insert.ll

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
; RUN: llc < %s -mtriple=x86_64-linux -noop-insertion | FileCheck %s
2+
; RUN: llc < %s -mtriple=x86_64-linux -noop-insertion -rng-seed=1 | FileCheck %s --check-prefix=SEED1
3+
; RUN: llc < %s -mtriple=x86_64-linux -noop-insertion -rng-seed=20 | FileCheck %s --check-prefix=SEED2
4+
; RUN: llc < %s -mtriple=x86_64-linux -noop-insertion -rng-seed=500 | FileCheck %s --check-prefix=SEED3
5+
6+
; RUN: llc < %s -march=x86 -noop-insertion | FileCheck %s --check-prefix=x86_32
7+
8+
; This test case checks that NOOPs are inserted, and that the RNG seed
9+
; affects both the placement (position of imull) and choice of these NOOPs.
10+
11+
; It just happens that with a default percentage of 25% and seed=0,
12+
; no NOOPs are inserted.
13+
; CHECK: imull
14+
; CHECK-NEXT: leal
15+
; CHECK-NEXT: retq
16+
; CHECK-NOT: nop
17+
18+
; SEED1: leaq (%rsi), %rsi
19+
; SEED1-NEXT: imull
20+
; SEED1-NEXT: leal
21+
; SEED1-NEXT: retq
22+
23+
; SEED2: imull
24+
; SEED2-NEXT: movq %rsp, %rsp
25+
; SEED2-NEXT: leal
26+
; SEED2-NEXT: retq
27+
28+
; SEED3: imull
29+
; SEED3-NEXT: movq %rsp, %rsp
30+
; SEED3-NEXT: leal
31+
; SEED3-NEXT: leaq (%rdi), %rdi
32+
; SEED3-NEXT: retq
33+
34+
; The operand of the following is used to distinguish from a movl NOOP
35+
; x86_32: movl 4(%esp),
36+
; x86_32-NEXT: imull
37+
; x86_32-NEXT: addl
38+
; x86_32-NEXT: movl %esp, %esp
39+
; x86_32-NEXT: retl
40+
41+
define i32 @test1(i32 %x, i32 %y, i32 %z) {
42+
entry:
43+
%tmp = mul i32 %x, %y
44+
%tmp2 = add i32 %tmp, %z
45+
ret i32 %tmp2
46+
}

0 commit comments

Comments
 (0)
Please sign in to comment.