Commit aee5fa8d by Qining Lu

Use separate random number generator for each randomization pass

This removes random number generator from GlobalContext class and decouples different randomization passes 1. Add a new constructor for random number generator which merge three arguments to into one seed for the underlying implementation of random number generator. RandomNumberGenerator(uint64_t Seed, RandomizationPassesEnum RandomizationPassID, uint64_t Salt=0) param Seed: Should be the global random number seed passed through command line. param RandomizationPassID: Should be the ID for different randomization passes. param Salt: Should be an additional integer salt, default to be 0. 2. Move the creation of random number generators to the call sites of randomization passes. Each randomization pass create its own random number generator with specific salt value. Function reordering: Salt = 0 (default) Basic Block reordering: Salt = Function Sequence Number Global Variable reordering: Salt = 0 (default) Pooled Constants reordering: Salt = Constants' Kind value (return of getKind()) *Jump Tables: Salt = 0 Nop Insertion: Salt = Function Sequence Number Register Alloc Randomization: Salt = (Function Sequence Number << 1) ^ (Kind == RAK_Phi ? 0u : 1u) Constants Blinding: Salt = Function Sequence Number *Jump tables are treated as pooled constants, but without Kind value as salt. BUG= R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1300993002.
parent cfa628b5
......@@ -43,6 +43,16 @@ Cfg::Cfg(GlobalContext *Ctx, uint32_t SequenceNumber)
VMetadata(new VariablesMetadata(this)),
TargetAssembler(TargetLowering::createAssembler(
Ctx->getFlags().getTargetArch(), this)) {
assert(!Ctx->isIRGenerationDisabled() &&
"Attempt to build cfg when IR generation disabled");
if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Randomize) {
// If -randomize-pool-immediates=randomize, create a random number generator
// to generate a cookie for constant blinding.
RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(),
RPE_ConstantBlinding, SequenceNumber);
ConstantBlindingCookie =
(uint32_t)RNG.next((uint64_t)std::numeric_limits<uint32_t>::max + 1);
}
}
Cfg::~Cfg() { assert(ICE_TLS_GET_FIELD(CurrentCfg) == nullptr); }
......@@ -396,9 +406,11 @@ void Cfg::shuffleNodes() {
NodeList ReversedReachable;
NodeList Unreachable;
llvm::BitVector ToVisit(Nodes.size(), true);
// Create Random number generator for function reordering
RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(),
RPE_BasicBlockReordering, SequenceNumber);
// Traverse from entry node.
getRandomPostOrder(getEntryNode(), ToVisit, ReversedReachable,
&Ctx->getRNG());
getRandomPostOrder(getEntryNode(), ToVisit, ReversedReachable, &RNG);
// Collect the unreachable nodes.
for (CfgNode *Node : Nodes)
if (ToVisit[Node->getIndex()])
......@@ -431,8 +443,10 @@ void Cfg::doNopInsertion() {
if (!Ctx->getFlags().shouldDoNopInsertion())
return;
TimerMarker T(TimerStack::TT_doNopInsertion, this);
RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(), RPE_NopInsertion,
SequenceNumber);
for (CfgNode *Node : Nodes)
Node->doNopInsertion();
Node->doNopInsertion(RNG);
}
void Cfg::genCode() {
......
......@@ -164,6 +164,7 @@ public:
bool hasComputedFrame() const;
bool getFocusedTiming() const { return FocusedTiming; }
void setFocusedTiming() { FocusedTiming = true; }
uint32_t getConstantBlindingCookie() const { return ConstantBlindingCookie; }
/// @}
/// Returns true if Var is a global variable that is used by the profiling
......@@ -247,7 +248,8 @@ private:
void emitJumpTables();
GlobalContext *Ctx;
uint32_t SequenceNumber; /// output order for emission
uint32_t SequenceNumber; /// output order for emission
uint32_t ConstantBlindingCookie = 0; /// cookie for constant blinding
VerboseMask VMask;
IceString FunctionName = "";
Type ReturnType = IceType_void;
......
......@@ -496,7 +496,7 @@ void CfgNode::doAddressOpt() {
}
}
void CfgNode::doNopInsertion() {
void CfgNode::doNopInsertion(RandomNumberGenerator &RNG) {
TargetLowering *Target = Func->getTarget();
LoweringContext &Context = Target->getContext();
Context.init(this);
......@@ -510,7 +510,7 @@ void CfgNode::doNopInsertion() {
PauseNopInsertion = false;
}
if (!PauseNopInsertion)
Target->doNopInsertion();
Target->doNopInsertion(RNG);
// Ensure Cur=Next, so that the nops are inserted before the current
// instruction rather than after.
Context.advanceCur();
......
......@@ -91,7 +91,7 @@ public:
void deletePhis();
void advancedPhiLowering();
void doAddressOpt();
void doNopInsertion();
void doNopInsertion(RandomNumberGenerator &RNG);
void genCode();
void livenessLightweight();
bool liveness(Liveness *Liveness);
......
......@@ -279,6 +279,18 @@ llvm::iterator_range<typename T::reverse_iterator> reverse_range(T &Container) {
/// Options for pooling and randomization of immediates.
enum RandomizeAndPoolImmediatesEnum { RPI_None, RPI_Randomize, RPI_Pool };
/// Salts for Random number generator for different randomization passes.
enum RandomizationPassesEnum {
RPE_BasicBlockReordering,
RPE_ConstantBlinding,
RPE_FunctionReordering,
RPE_GlobalVariableReordering,
RPE_NopInsertion,
RPE_PooledConstantReordering,
RPE_RegAllocRandomization,
RPE_num
};
} // end of namespace Ice
#endif // SUBZERO_SRC_ICEDEFS_H
......@@ -512,11 +512,15 @@ template <typename ConstType> void ELFObjectWriter::writeConstantPool(Type Ty) {
// If the -reorder-pooled-constant option is set to true, we should shuffle
// the constants before we emit them.
auto *CtxPtr = &Ctx;
if (Ctx.getFlags().shouldReorderPooledConstants())
RandomShuffle(Pool.begin(), Pool.end(), [CtxPtr](uint64_t N) {
return (uint32_t)CtxPtr->getRNG().next(N);
});
if (Ctx.getFlags().shouldReorderPooledConstants() && !Pool.empty()) {
// Use the constant's kind value as the salt for creating random number
// generator.
Operand::OperandKind K = (*Pool.begin())->getKind();
RandomNumberGenerator RNG(Ctx.getFlags().getRandomSeed(),
RPE_PooledConstantReordering, K);
RandomShuffle(Pool.begin(), Pool.end(),
[&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
}
// Write the data.
for (Constant *C : Pool) {
if (!C->getShouldBePooled())
......
......@@ -222,8 +222,7 @@ void GlobalContext::CodeStats::dump(const IceString &Name, Ostream &Str) {
GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError,
ELFStreamer *ELFStr, const ClFlags &Flags)
: ConstPool(new ConstantPool()), ErrorStatus(), StrDump(OsDump),
StrEmit(OsEmit), StrError(OsError), Flags(Flags),
RNG(Flags.getRandomSeed()), ObjectWriter(),
StrEmit(OsEmit), StrError(OsError), Flags(Flags), ObjectWriter(),
OptQ(/*Sequential=*/Flags.isSequential(),
/*MaxSize=*/Flags.getNumTranslationThreads()),
// EmitQ is allowed unlimited size.
......@@ -273,14 +272,6 @@ GlobalContext::GlobalContext(Ostream *OsDump, Ostream *OsEmit, Ostream *OsError,
ProfileBlockInfoVarDecl->setName("__Sz_block_profile_info");
ProfileBlockInfoVarDecl->setSuppressMangling();
ProfileBlockInfoVarDecl->setLinkage(llvm::GlobalValue::ExternalLinkage);
// Initialize the randomization cookie for constant blinding only if constant
// blinding or pooling is turned on.
// TODO(stichnot): Using RNG for constant blinding will affect the random
// number to be used in nop-insertion and randomize-regalloc.
if (Flags.getRandomizeAndPoolImmediatesOption() != RPI_None)
RandomizationCookie =
(uint32_t)RNG.next((uint64_t)std::numeric_limits<uint32_t>::max + 1);
}
void GlobalContext::translateFunctions() {
......@@ -403,9 +394,11 @@ void GlobalContext::lowerGlobals(const IceString &SectionSuffix) {
addBlockInfoPtrs(Globals, ProfileBlockInfoVarDecl);
// If we need to shuffle the layout of global variables, shuffle them now.
if (getFlags().shouldReorderGlobalVariables()) {
auto *RNGPtr = &RNG;
// Create a random number generator for global variable reordering.
RandomNumberGenerator RNG(getFlags().getRandomSeed(),
RPE_GlobalVariableReordering);
RandomShuffle(Globals.begin(), Globals.end(),
[RNGPtr](int N) { return (uint32_t)RNGPtr->next(N); });
[&RNG](int N) { return (uint32_t)RNG.next(N); });
}
DataLowering->lowerGlobals(Globals, SectionSuffix);
for (VariableDeclaration *Var : Globals) {
......@@ -446,6 +439,9 @@ void GlobalContext::emitItems() {
const uint32_t ShuffleWindowSize =
std::max(1u, getFlags().getReorderFunctionsWindowSize());
bool Shuffle = Threaded && getFlags().shouldReorderFunctions();
// Create a random number generator for function reordering.
RandomNumberGenerator RNG(getFlags().getRandomSeed(), RPE_FunctionReordering);
while (!EmitQueueEmpty) {
resizePending(Pending, DesiredSequenceNumber);
// See if Pending contains DesiredSequenceNumber.
......@@ -497,7 +493,7 @@ void GlobalContext::emitItems() {
// Pending[ShuffleEndIndex].
RandomShuffle(Pending.begin() + ShuffleStartIndex,
Pending.begin() + ShuffleEndIndex,
[this](uint64_t N) { return (uint32_t)RNG.next(N); });
[&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
}
// Emit the item from ShuffleStartIndex to ShuffleEndIndex.
......@@ -879,20 +875,25 @@ ConstantList GlobalContext::getConstantExternSyms() {
JumpTableDataList GlobalContext::getJumpTables() {
JumpTableDataList JumpTables(*getJumpTableList());
// Make order deterministic by sorting into functions and then ID of the
// jump table within that function.
std::sort(JumpTables.begin(), JumpTables.end(),
[](const JumpTableData &A, const JumpTableData &B) {
if (A.getFunctionName() != B.getFunctionName())
return A.getFunctionName() < B.getFunctionName();
return A.getId() < B.getId();
});
if (getFlags().shouldReorderPooledConstants()) {
// If reorder-pooled-constants option is set to true, we need to shuffle the
// constant pool before emitting it.
// If reorder-pooled-constants option is set to true, we also shuffle the
// jump tables before emitting them.
// Create a random number generator for jump tables reordering, considering
// jump tables as pooled constants.
RandomNumberGenerator RNG(getFlags().getRandomSeed(),
RPE_PooledConstantReordering);
RandomShuffle(JumpTables.begin(), JumpTables.end(),
[this](uint64_t N) { return (uint32_t)getRNG().next(N); });
} else {
// Make order deterministic by sorting into functions and then ID of the
// jump table within that function.
std::sort(JumpTables.begin(), JumpTables.end(),
[](const JumpTableData &A, const JumpTableData &B) {
if (A.getFunctionName() != B.getFunctionName())
return A.getFunctionName() < B.getFunctionName();
return A.getId() < B.getId();
});
[&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
}
return JumpTables;
}
......
......@@ -243,10 +243,6 @@ public:
const Intrinsics &getIntrinsicsInfo() const { return IntrinsicsInfo; }
// TODO(wala,stichnot): Make the RNG play nicely with multithreaded
// translation.
RandomNumberGenerator &getRNG() { return RNG; }
ELFObjectWriter *getObjectWriter() const { return ObjectWriter.get(); }
/// Reset stats at the beginning of a function.
......@@ -440,10 +436,6 @@ public:
return Match.empty() || Match == SymbolName;
}
/// Return the randomization cookie for diversification.
/// Initialize the cookie if necessary
uint32_t getRandomizationCookie() const { return RandomizationCookie; }
private:
// Try to ensure mutexes are allocated on separate cache lines.
......@@ -496,7 +488,6 @@ private:
Intrinsics IntrinsicsInfo;
const ClFlags &Flags;
RandomNumberGenerator RNG; // TODO(stichnot): Move into Cfg.
// TODO(jpp): move to EmitterContext.
std::unique_ptr<ELFObjectWriter> ObjectWriter;
BoundedProducerConsumerQueue<Cfg> OptQ;
......@@ -557,11 +548,6 @@ private:
typedef llvm::SmallVector<char, 32> ManglerVector;
void incrementSubstitutions(ManglerVector &OldName) const;
// Randomization Cookie
// Managed by getRandomizationCookie()
GlobalLockType RandomizationCookieLock;
uint32_t RandomizationCookie = 0;
public:
static void TlsInit() { ICE_TLS_INIT_FIELD(TLS); }
};
......
......@@ -31,6 +31,16 @@ constexpr unsigned MAX = 2147483647;
RandomNumberGenerator::RandomNumberGenerator(uint64_t Seed, llvm::StringRef)
: State(Seed) {}
RandomNumberGenerator::RandomNumberGenerator(
uint64_t Seed, RandomizationPassesEnum RandomizationPassID, uint64_t Salt) {
constexpr unsigned NumBitsGlobalSeed = CHAR_BIT * sizeof(State);
constexpr unsigned NumBitsPassID = 4;
constexpr unsigned NumBitsSalt = 12;
static_assert(RPE_num < (1 << NumBitsPassID), "NumBitsPassID too small");
State = Seed ^ ((uint64_t)RandomizationPassID
<< (NumBitsGlobalSeed - NumBitsPassID)) ^
(Salt << (NumBitsGlobalSeed - NumBitsPassID - NumBitsSalt));
}
uint64_t RandomNumberGenerator::next(uint64_t Max) {
// Lewis, Goodman, and Miller (1969)
State = (16807 * State) % MAX;
......
......@@ -17,6 +17,8 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Compiler.h"
#include "IceDefs.h"
#include <cstdint>
namespace Ice {
......@@ -28,6 +30,22 @@ class RandomNumberGenerator {
public:
explicit RandomNumberGenerator(uint64_t Seed, llvm::StringRef Salt = "");
/// Create a random number generator with: global seed, randomization pass ID
/// and a salt uint64_t integer.
/// @param Seed should be a global seed.
/// @param RandomizationPassID should be one of RandomizationPassesEnum.
/// @param Salt should be an additional integer input for generating unique
/// RNG.
/// The global seed is 64 bits; since it is likely to originate from the
/// system time, the lower bits are more "valuable" than the upper bits. As
/// such, we merge the randomization pass ID and the salt into the global seed
/// by xor'ing them into high bit ranges. We expect the pass ID to fit within
/// 4 bits, so it gets shifted by 60 to merge into the upper 4 bits. We expect
/// the salt (usually the function sequence number) to fit within 12 bits, so
/// it gets shifted by 48 before merging.
explicit RandomNumberGenerator(uint64_t Seed,
RandomizationPassesEnum RandomizationPassID,
uint64_t Salt = 0);
uint64_t next(uint64_t Max);
private:
......
......@@ -250,11 +250,11 @@ void LinearScan::init(RegAllocKind Kind) {
}
auto CompareRanges = [](const Variable *L, const Variable *R) {
InstNumberT Lstart = L->getLiveRange().getStart();
InstNumberT Rstart = R->getLiveRange().getStart();
if (Lstart == Rstart)
return L->getIndex() < R->getIndex();
return Lstart < Rstart;
InstNumberT Lstart = L->getLiveRange().getStart();
InstNumberT Rstart = R->getLiveRange().getStart();
if (Lstart == Rstart)
return L->getIndex() < R->getIndex();
return Lstart < Rstart;
};
// Do a reverse sort so that erasing elements (from the end) is fast.
std::sort(Unhandled.rbegin(), Unhandled.rend(), CompareRanges);
......@@ -776,8 +776,15 @@ void LinearScan::scan(const llvm::SmallBitVector &RegMaskFull,
llvm::SmallVector<int32_t, REGS_SIZE> Permutation(NumRegisters);
if (Randomized) {
// Create a random number generator for regalloc randomization. Merge
// function's sequence and Kind value as the Salt. Because regAlloc()
// is called twice under O2, the second time with RAK_Phi, we check
// Kind == RAK_Phi to determine the lowest-order bit to make sure the
// Salt is different.
uint64_t Salt =
(Func->getSequenceNumber() << 1) ^ (Kind == RAK_Phi ? 0u : 1u);
Func->getTarget()->makeRandomRegisterPermutation(
Permutation, PreDefinedRegisters | ~RegMaskFull);
Permutation, PreDefinedRegisters | ~RegMaskFull, Salt);
}
// Finish up by assigning RegNumTmp->RegNum (or a random permutation
......
......@@ -103,7 +103,7 @@ void TargetLowering::doAddressOpt() {
Context.advanceNext();
}
void TargetLowering::doNopInsertion() {
void TargetLowering::doNopInsertion(RandomNumberGenerator &RNG) {
Inst *I = Context.getCur();
bool ShouldSkip = llvm::isa<InstFakeUse>(I) || llvm::isa<InstFakeDef>(I) ||
llvm::isa<InstFakeKill>(I) || I->isRedundantAssign() ||
......@@ -111,7 +111,7 @@ void TargetLowering::doNopInsertion() {
if (!ShouldSkip) {
int Probability = Ctx->getFlags().getNopProbabilityAsPercentage();
for (int I = 0; I < Ctx->getFlags().getMaxNopsPerInstruction(); ++I) {
randomlyInsertNop(Probability / 100.0);
randomlyInsertNop(Probability / 100.0, RNG);
}
}
}
......
......@@ -153,7 +153,7 @@ public:
/// Tries to do address mode optimization on a single instruction.
void doAddressOpt();
/// Randomly insert NOPs.
void doNopInsertion();
void doNopInsertion(RandomNumberGenerator &RNG);
/// Lowers a single non-Phi instruction.
void lower();
/// Inserts and lowers a single high-level instruction at a specific insertion
......@@ -213,9 +213,10 @@ public:
virtual const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const = 0;
void regAlloc(RegAllocKind Kind);
virtual void makeRandomRegisterPermutation(
llvm::SmallVectorImpl<int32_t> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters) const = 0;
virtual void
makeRandomRegisterPermutation(llvm::SmallVectorImpl<int32_t> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters,
uint64_t Salt) const = 0;
/// Save/restore any mutable state for the situation where code
/// emission needs multiple passes, such as sandboxing or relaxation.
......@@ -279,7 +280,8 @@ protected:
virtual void doAddressOptLoad() {}
virtual void doAddressOptStore() {}
virtual void randomlyInsertNop(float Probability) = 0;
virtual void randomlyInsertNop(float Probability,
RandomNumberGenerator &RNG) = 0;
/// This gives the target an opportunity to post-process the lowered
/// expansion before returning.
virtual void postLower() {}
......
......@@ -2505,9 +2505,10 @@ void TargetARM32::doAddressOptLoad() {
UnimplementedError(Func->getContext()->getFlags());
}
void TargetARM32::randomlyInsertNop(float Probability) {
RandomNumberGeneratorWrapper RNG(Ctx->getRNG());
if (RNG.getTrueWithProbability(Probability)) {
void TargetARM32::randomlyInsertNop(float Probability,
RandomNumberGenerator &RNG) {
RandomNumberGeneratorWrapper RNGW(RNG);
if (RNGW.getTrueWithProbability(Probability)) {
UnimplementedError(Func->getContext()->getFlags());
}
}
......@@ -2929,9 +2930,10 @@ void TargetARM32::postLower() {
void TargetARM32::makeRandomRegisterPermutation(
llvm::SmallVectorImpl<int32_t> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters) const {
const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const {
(void)Permutation;
(void)ExcludeRegisters;
(void)Salt;
UnimplementedError(Func->getContext()->getFlags());
}
......
......@@ -138,7 +138,8 @@ protected:
void prelowerPhis() override;
void doAddressOptLoad() override;
void doAddressOptStore() override;
void randomlyInsertNop(float Probability) override;
void randomlyInsertNop(float Probability,
RandomNumberGenerator &RNG) override;
enum OperandLegalization {
Legal_None = 0,
......@@ -162,9 +163,10 @@ protected:
/// Returns a vector in a register with the given constant entries.
Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister);
void makeRandomRegisterPermutation(
llvm::SmallVectorImpl<int32_t> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters) const override;
void
makeRandomRegisterPermutation(llvm::SmallVectorImpl<int32_t> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters,
uint64_t Salt) const override;
// If a divide-by-zero check is needed, inserts a:
// test; branch .LSKIP; trap; .LSKIP: <continuation>.
......
......@@ -607,9 +607,10 @@ void TargetMIPS32::doAddressOptLoad() {
UnimplementedError(Func->getContext()->getFlags());
}
void TargetMIPS32::randomlyInsertNop(float Probability) {
RandomNumberGeneratorWrapper RNG(Ctx->getRNG());
if (RNG.getTrueWithProbability(Probability)) {
void TargetMIPS32::randomlyInsertNop(float Probability,
RandomNumberGenerator &RNG) {
RandomNumberGeneratorWrapper RNGW(RNG);
if (RNGW.getTrueWithProbability(Probability)) {
UnimplementedError(Func->getContext()->getFlags());
}
}
......@@ -666,9 +667,10 @@ void TargetMIPS32::postLower() {
void TargetMIPS32::makeRandomRegisterPermutation(
llvm::SmallVectorImpl<int32_t> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters) const {
const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const {
(void)Permutation;
(void)ExcludeRegisters;
(void)Salt;
UnimplementedError(Func->getContext()->getFlags());
}
......
......@@ -116,10 +116,12 @@ protected:
void prelowerPhis() override;
void doAddressOptLoad() override;
void doAddressOptStore() override;
void randomlyInsertNop(float Probability) override;
void makeRandomRegisterPermutation(
llvm::SmallVectorImpl<int32_t> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters) const override;
void randomlyInsertNop(float Probability,
RandomNumberGenerator &RNG) override;
void
makeRandomRegisterPermutation(llvm::SmallVectorImpl<int32_t> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters,
uint64_t Salt) const override;
static Type stackSlotType();
......
......@@ -731,10 +731,16 @@ void TargetDataX8632::emitConstantPool(GlobalContext *Ctx) {
// If reorder-pooled-constants option is set to true, we need to shuffle the
// constant pool before emitting it.
if (Ctx->getFlags().shouldReorderPooledConstants())
RandomShuffle(Pool.begin(), Pool.end(), [Ctx](uint64_t N) {
return (uint32_t)Ctx->getRNG().next(N);
});
if (Ctx->getFlags().shouldReorderPooledConstants() && !Pool.empty()) {
// Use the constant's kind value as the salt for creating random number
// generator.
Operand::OperandKind K = (*Pool.begin())->getKind();
RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(),
RPE_PooledConstantReordering, K);
RandomShuffle(Pool.begin(), Pool.end(),
[&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
}
for (Constant *C : Pool) {
if (!C->getShouldBePooled())
......
......@@ -362,7 +362,8 @@ template <> struct MachineTraits<TargetX8632> {
static void
makeRandomRegisterPermutation(GlobalContext *Ctx, Cfg *Func,
llvm::SmallVectorImpl<int32_t> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters) {
const llvm::SmallBitVector &ExcludeRegisters,
uint64_t Salt) {
// TODO(stichnot): Declaring Permutation this way loses type/size
// information. Fix this in conjunction with the caller-side TODO.
assert(Permutation.size() >= RegisterSet::Reg_NUM);
......@@ -393,13 +394,16 @@ template <> struct MachineTraits<TargetX8632> {
REGX8632_TABLE
#undef X
RandomNumberGeneratorWrapper RNG(Ctx->getRNG());
// Create a random number generator for regalloc randomization.
RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(),
RPE_RegAllocRandomization, Salt);
RandomNumberGeneratorWrapper RNGW(RNG);
// Shuffle the resulting equivalence classes.
for (auto I : EquivalenceClasses) {
const RegisterList &List = I.second;
RegisterList Shuffled(List);
RandomShuffle(Shuffled.begin(), Shuffled.end(), RNG);
RandomShuffle(Shuffled.begin(), Shuffled.end(), RNGW);
for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) {
Permutation[List[SI]] = Shuffled[SI];
++NumShuffled;
......
......@@ -743,10 +743,15 @@ void TargetDataX8664::emitConstantPool(GlobalContext *Ctx) {
// If reorder-pooled-constants option is set to true, we need to shuffle the
// constant pool before emitting it.
if (Ctx->getFlags().shouldReorderPooledConstants())
RandomShuffle(Pool.begin(), Pool.end(), [Ctx](uint64_t N) {
return (uint32_t)Ctx->getRNG().next(N);
});
if (Ctx->getFlags().shouldReorderPooledConstants()) {
// Use the constant's kind value as the salt for creating random number
// generator.
Operand::OperandKind K = (*Pool.begin())->getKind();
RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(),
RPE_PooledConstantReordering, K);
RandomShuffle(Pool.begin(), Pool.end(),
[&RNG](uint64_t N) { return (uint32_t)RNG.next(N); });
}
for (Constant *C : Pool) {
if (!C->getShouldBePooled())
......
......@@ -375,7 +375,8 @@ template <> struct MachineTraits<TargetX8664> {
static void
makeRandomRegisterPermutation(GlobalContext *Ctx, Cfg *Func,
llvm::SmallVectorImpl<int32_t> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters) {
const llvm::SmallBitVector &ExcludeRegisters,
uint64_t Salt) {
// TODO(stichnot): Declaring Permutation this way loses type/size
// information. Fix this in conjunction with the caller-side TODO.
assert(Permutation.size() >= RegisterSet::Reg_NUM);
......@@ -406,13 +407,16 @@ template <> struct MachineTraits<TargetX8664> {
REGX8664_TABLE
#undef X
RandomNumberGeneratorWrapper RNG(Ctx->getRNG());
// Create a random number generator for regalloc randomization.
RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(),
RPE_RegAllocRandomization, Salt);
RandomNumberGeneratorWrapper RNGW(RNG);
// Shuffle the resulting equivalence classes.
for (auto I : EquivalenceClasses) {
const RegisterList &List = I.second;
RegisterList Shuffled(List);
RandomShuffle(Shuffled.begin(), Shuffled.end(), RNG);
RandomShuffle(Shuffled.begin(), Shuffled.end(), RNGW);
for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) {
Permutation[List[SI]] = Shuffled[SI];
++NumShuffled;
......
......@@ -180,7 +180,8 @@ protected:
void prelowerPhis() override;
void doAddressOptLoad() override;
void doAddressOptStore() override;
void randomlyInsertNop(float Probability) override;
void randomlyInsertNop(float Probability,
RandomNumberGenerator &RNG) override;
/// Naive lowering of cmpxchg.
void lowerAtomicCmpxchg(Variable *DestPrev, Operand *Ptr, Operand *Expected,
......@@ -290,9 +291,10 @@ protected:
typename Traits::X86OperandMem *
getMemoryOperandForStackSlot(Type Ty, Variable *Slot, uint32_t Offset = 0);
void makeRandomRegisterPermutation(
llvm::SmallVectorImpl<int32_t> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters) const override;
void
makeRandomRegisterPermutation(llvm::SmallVectorImpl<int32_t> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters,
uint64_t Salt) const override;
/// The following are helpers that insert lowered x86 instructions
/// with minimal syntactic overhead, so that the lowering code can
......
......@@ -4161,10 +4161,11 @@ template <class Machine> void TargetX86Base<Machine>::doAddressOptLoad() {
}
template <class Machine>
void TargetX86Base<Machine>::randomlyInsertNop(float Probability) {
RandomNumberGeneratorWrapper RNG(Ctx->getRNG());
if (RNG.getTrueWithProbability(Probability)) {
_nop(RNG(Traits::X86_NUM_NOP_VARIANTS));
void TargetX86Base<Machine>::randomlyInsertNop(float Probability,
RandomNumberGenerator &RNG) {
RandomNumberGeneratorWrapper RNGW(RNG);
if (RNGW.getTrueWithProbability(Probability)) {
_nop(RNGW(Traits::X86_NUM_NOP_VARIANTS));
}
}
......@@ -5119,9 +5120,9 @@ template <class Machine> void TargetX86Base<Machine>::postLower() {
template <class Machine>
void TargetX86Base<Machine>::makeRandomRegisterPermutation(
llvm::SmallVectorImpl<int32_t> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters) const {
const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const {
Traits::makeRandomRegisterPermutation(Ctx, Func, Permutation,
ExcludeRegisters);
ExcludeRegisters, Salt);
}
template <class Machine>
......@@ -5196,7 +5197,7 @@ Operand *TargetX86Base<Machine>::randomizeOrPoolImmediate(Constant *Immediate,
Variable *Reg = makeReg(IceType_i32, RegNum);
ConstantInteger32 *Integer = llvm::cast<ConstantInteger32>(Immediate);
uint32_t Value = Integer->getValue();
uint32_t Cookie = Ctx->getRandomizationCookie();
uint32_t Cookie = Func->getConstantBlindingCookie();
_mov(Reg, Ctx->getConstantInt(IceType_i32, Cookie + Value));
Constant *Offset = Ctx->getConstantInt(IceType_i32, 0 - Cookie);
_lea(Reg, Traits::X86OperandMem::create(Func, IceType_i32, Reg, Offset,
......@@ -5275,7 +5276,7 @@ TargetX86Base<Machine>::randomizeOrPoolImmediate(
uint32_t Value =
llvm::dyn_cast<ConstantInteger32>(MemOperand->getOffset())
->getValue();
uint32_t Cookie = Ctx->getRandomizationCookie();
uint32_t Cookie = Func->getConstantBlindingCookie();
Constant *Mask1 = Ctx->getConstantInt(
MemOperand->getOffset()->getType(), Cookie + Value);
Constant *Mask2 =
......
......@@ -25,106 +25,112 @@ entry:
ret <4 x i32> %res
; PROB50-LABEL: mul_v4i32
; PROB50: nop # variant = 4
; PROB50: nop # variant = 1
; PROB50: subl $60, %esp
; PROB50: nop # variant = 3
; PROB50: movups %xmm0, 32(%esp)
; PROB50: nop # variant = 0
; PROB50: movups %xmm1, 16(%esp)
; PROB50: nop # variant = 4
; PROB50: movups 32(%esp), %xmm0
; PROB50: nop # variant = 1
; PROB50: pshufd $49, 32(%esp), %xmm1
; PROB50: nop # variant = 4
; PROB50: pshufd $49, 16(%esp), %xmm2
; PROB50: nop # variant = 1
; PROB50: pmuludq 16(%esp), %xmm0
; PROB50: nop # variant = 0
; PROB50: pmuludq %xmm2, %xmm1
; PROB50: nop # variant = 0
; PROB50: shufps $136, %xmm1, %xmm0
; PROB50: nop # variant = 2
; PROB50: nop # variant = 3
; PROB50: pshufd $216, %xmm0, %xmm0
; PROB50: nop # variant = 1
; PROB50: movups %xmm0, (%esp)
; PROB50: movups (%esp), %xmm0
; PROB50: nop # variant = 0
; PROB50: addl $60, %esp
; PROB50: nop # variant = 3
; PROB50: ret
; PROB90-LABEL: mul_v4i32
; PROB90: nop # variant = 4
; PROB90: nop # variant = 1
; PROB90: subl $60, %esp
; PROB90: nop # variant = 3
; PROB90: movups %xmm0, 32(%esp)
; PROB90: nop # variant = 2
; PROB90: nop # variant = 4
; PROB90: movups %xmm1, 16(%esp)
; PROB90: nop # variant = 3
; PROB90: nop # variant = 1
; PROB90: movups 32(%esp), %xmm0
; PROB90: nop # variant = 4
; PROB90: pshufd $49, 32(%esp), %xmm1
; PROB90: nop # variant = 0
; PROB90: nop # variant = 1
; PROB90: pshufd $49, 16(%esp), %xmm2
; PROB90: nop # variant = 2
; PROB90: nop # variant = 4
; PROB90: pmuludq 16(%esp), %xmm0
; PROB90: nop # variant = 3
; PROB90: nop # variant = 2
; PROB90: pmuludq %xmm2, %xmm1
; PROB90: nop # variant = 4
; PROB90: shufps $136, %xmm1, %xmm0
; PROB90: nop # variant = 2
; PROB90: nop # variant = 1
; PROB90: pshufd $216, %xmm0, %xmm0
; PROB90: nop # variant = 4
; PROB90: movups %xmm0, (%esp)
; PROB90: nop # variant = 2
; PROB90: nop # variant = 1
; PROB90: movups (%esp), %xmm0
; PROB90: nop # variant = 3
; PROB90: nop # variant = 0
; PROB90: addl $60, %esp
; PROB90: nop # variant = 3
; PROB90: nop # variant = 0
; PROB90: ret
; PROB90: nop # variant = 4
; MAXNOPS2-LABEL: mul_v4i32
; MAXNOPS2: nop # variant = 4
; MAXNOPS2: nop # variant = 1
; MAXNOPS2: nop # variant = 3
; MAXNOPS2: subl $60, %esp
; MAXNOPS2: nop # variant = 0
; MAXNOPS2: nop # variant = 4
; MAXNOPS2: movups %xmm0, 32(%esp)
; MAXNOPS2: nop # variant = 1
; MAXNOPS2: nop # variant = 4
; MAXNOPS2: movups %xmm1, 16(%esp)
; MAXNOPS2: nop # variant = 0
; MAXNOPS2: nop # variant = 1
; MAXNOPS2: movups 32(%esp), %xmm0
; MAXNOPS2: nop # variant = 2
; MAXNOPS2: pshufd $49, 32(%esp), %xmm1
; MAXNOPS2: pshufd $49, 16(%esp), %xmm2
; MAXNOPS2: nop # variant = 0
; MAXNOPS2: nop # variant = 3
; MAXNOPS2: pshufd $49, 32(%esp), %xmm1
; MAXNOPS2: nop # variant = 1
; MAXNOPS2: pshufd $49, 16(%esp), %xmm2
; MAXNOPS2: pmuludq 16(%esp), %xmm0
; MAXNOPS2: pmuludq %xmm2, %xmm1
; MAXNOPS2: nop # variant = 0
; MAXNOPS2: shufps $136, %xmm1, %xmm0
; MAXNOPS2: nop # variant = 3
; MAXNOPS2: pshufd $216, %xmm0, %xmm0
; MAXNOPS2: nop # variant = 0
; MAXNOPS2: nop # variant = 0
; MAXNOPS2: pshufd $216, %xmm0, %xmm0
; MAXNOPS2: nop # variant = 1
; MAXNOPS2: nop # variant = 3
; MAXNOPS2: movups %xmm0, (%esp)
; MAXNOPS2: nop # variant = 2
; MAXNOPS2: nop # variant = 3
; MAXNOPS2: movups (%esp), %xmm0
; MAXNOPS2: nop # variant = 4
; MAXNOPS2: addl $60, %esp
; MAXNOPS2: nop # variant = 3
; MAXNOPS2: ret
; SANDBOX50-LABEL: mul_v4i32
; SANDBOX50: nop # variant = 4
; SANDBOX50: nop # variant = 1
; SANDBOX50: subl $60, %esp
; SANDBOX50: nop # variant = 3
; SANDBOX50: movups %xmm0, 32(%esp)
; SANDBOX50: nop # variant = 0
; SANDBOX50: movups %xmm1, 16(%esp)
; SANDBOX50: nop # variant = 4
; SANDBOX50: movups 32(%esp), %xmm0
; SANDBOX50: nop # variant = 1
; SANDBOX50: pshufd $49, 32(%esp), %xmm1
; SANDBOX50: nop # variant = 4
; SANDBOX50: pshufd $49, 16(%esp), %xmm2
; SANDBOX50: nop # variant = 1
; SANDBOX50: pmuludq 16(%esp), %xmm0
; SANDBOX50: nop # variant = 0
; SANDBOX50: pmuludq %xmm2, %xmm1
; SANDBOX50: nop # variant = 0
; SANDBOX50: shufps $136, %xmm1, %xmm0
; SANDBOX50: nop # variant = 2
; SANDBOX50: nop # variant = 3
; SANDBOX50: pshufd $216, %xmm0, %xmm0
; SANDBOX50: nop # variant = 1
; SANDBOX50: movups %xmm0, (%esp)
; SANDBOX50: movups (%esp), %xmm0
; SANDBOX50: nop # variant = 0
; SANDBOX50: addl $60, %esp
; SANDBOX50: nop # variant = 3
; SANDBOX50: pop %ecx
; SANDBOX50: .bundle_lock
; SANDBOX50: andl $-32, %ecx
......
......@@ -25,12 +25,12 @@ entry:
ret i32 %res
; BLINDINGO2-LABEL: add_arg_plus_200000
; BLINDINGO2: mov [[REG:e[a-z]*]],0x34ee7
; BLINDINGO2-NEXT: lea [[REG]],{{[[]}}[[REG]]-0x41a7{{[]]}}
; BLINDINGO2: mov [[REG:e[a-z]*]],0x2c8df4
; BLINDINGO2-NEXT: lea [[REG]],{{[[]}}[[REG]]-0x2980b4{{[]]}}
; BLINDINGOM1-LABEL: add_arg_plus_200000
; BLINDINGOM1: mov [[REG:e[a-z]*]],0x34ee7
; BLINDINGOM1-NEXT: lea [[REG]],{{[[]}}[[REG]]-0x41a7{{[]]}}
; BLINDINGOM1: mov [[REG:e[a-z]*]],0x2c8df4
; BLINDINGOM1-NEXT: lea [[REG]],{{[[]}}[[REG]]-0x2980b4{{[]]}}
; POOLING-LABEL: add_arg_plus_200000
; POOLING: mov e{{[a-z]*}},DWORD PTR ds:0x0 {{[0-9a-f]*}}: R_386_32 .L$i32${{[0-9]*}}
......@@ -44,10 +44,10 @@ entry:
%addr.load = load float, float* %addr.ptr, align 4
ret float %addr.load
; BLINDINGO2-LABEL: load_arg_plus_200000
; BLINDINGO2: lea [[REG:e[a-z]*]],{{[[]}}{{e[a-z]*}}+0x34ee7{{[]]}}
; BLINDINGO2: lea [[REG:e[a-z]*]],{{[[]}}{{e[a-z]*}}+0x32c814{{[]]}}
; BLINDINGOM1-LABEL: load_arg_plus_200000
; BLINDINGOM1: lea [[REG:e[a-z]*]],{{[[]}}{{e[a-z]*}}-0x41a7{{[]]}}
; BLINDINGOM1: lea [[REG:e[a-z]*]],{{[[]}}{{e[a-z]*}}-0x2fbad4{{[]]}}
; POOLING-LABEL: load_arg_plus_200000
; POOLING: mov e{{[a-z]*}},DWORD PTR ds:0x0 {{[0-9a-f]*}}: R_386_32 .L$i32${{[0-9]*}}
......@@ -61,13 +61,13 @@ entry:
; BLINDINGO2-LABEL: add_arg_plus_64bits
; BLINDINGO2: sar [[RHI:e[a-z]*]],0x1f
; BLINDINGO2: mov [[RLO:e[a-z]*]],0xf46b45a7
; BLINDINGO2-NEXT: lea [[RLO]],{{[[]}}[[RLO]]-0x41a7{{[]]}}
; BLINDINGO2: mov [[RLO:e[a-z]*]],0xf4a0f8f8
; BLINDINGO2-NEXT: lea [[RLO]],{{[[]}}[[RLO]]-0x35f4f8{{[]]}}
; BLINDINGOM1-LABEL: add_arg_plus_64bits
; BLINDINGOM1: sar [[RHI:e[a-z]*]],0x1f
; BLINDINGOM1: mov [[RLO:e[a-z]*]],0xf46b45a7
; BLINDINGOM1-NEXT: lea [[RLO]],{{[[]}}[[RLO]]-0x41a7{{[]]}}
; BLINDINGOM1: mov [[RLO:e[a-z]*]],0xf4a0f8f8
; BLINDINGOM1-NEXT: lea [[RLO]],{{[[]}}[[RLO]]-0x35f4f8{{[]]}}
; POOLING-LABEL: add_arg_plus_64bits
; POOLING: mov e{{[a-z]*}},DWORD PTR ds:0x0 {{[0-9a-f]*}}: R_386_32 .L$i32${{[0-9]*}}
......@@ -82,12 +82,12 @@ entry:
ret i64 %arg.load
; BLINDINGO2-LABEL: load_arg_plus_64bits
; BLINDINGO2: lea e{{[a-z]*}},{{[[]}}e{{[a-z]*}}+0x1a137{{[]]}}
; BLINDINGO2: mov e{{[a-z]*}},DWORD PTR {{[[]}}e{{[a-z]*}}-0x41a7{{[]]}}
; BLINDINGO2: lea e{{[a-z]*}},{{[[]}}e{{[a-z]*}}+0x3d8eac{{[]]}}
; BLINDINGO2: mov e{{[a-z]*}},DWORD PTR {{[[]}}e{{[a-z]*}}-0x3c2f1c{{[]]}}
; BLINDINGOM1-LABEL: load_arg_plus_64bits
; BLINDINGOM1: mov e{{[a-z]*}},0x1a137
; BLINDINGOM1-NEXT: lea e{{[a-z]*}},{{[[]}}e{{[a-z]*}}-0x41a7{{[]]}}
; BLINDINGOM1: mov e{{[a-z]*}},0x3d8eac
; BLINDINGOM1-NEXT: lea e{{[a-z]*}},{{[[]}}e{{[a-z]*}}-0x3c2f1c{{[]]}}
; POOLING-LABEL: load_arg_plus_64bits
; POOLING: mov e{{[a-z]x}},DWORD PTR ds:0x0 {{[0-9a-f]*}}: R_386_32 .L$i32${{[0-9]*}}
......@@ -101,12 +101,12 @@ entry:
ret i32 %ret
; BLINDINGO2-LABEL: add_const_8bits
; BLINDINGO2: mov e{{[a-z]*}},0x4222
; BLINDINGO2-NEXT: e{{[a-z]*}},{{[[]}}e{{[a-z]*}}-0x41a7{{[]]}}
; BLINDINGO2: mov e{{[a-z]*}},0x1d0aa
; BLINDINGO2-NEXT: e{{[a-z]*}},{{[[]}}e{{[a-z]*}}-0x1d02f{{[]]}}
; BLINDINGOM1-LABEL: add_const_8bits
; BLINDINGOM1: mov e{{[a-z]*}},0x4222
; BLINDINGOM1-NEXT: e{{[a-z]*}},{{[[]}}e{{[a-z]*}}-0x41a7{{[]]}}
; BLINDINGOM1: mov e{{[a-z]*}},0x1d0aa
; BLINDINGOM1-NEXT: e{{[a-z]*}},{{[[]}}e{{[a-z]*}}-0x1d02f{{[]]}}
; POOLING-LABEL: add_const_8bits
; POOLING: mov {{[a-z]l}},BYTE PTR ds:0x0 {{[0-9a-f]*}}: R_386_32 .L$i8${{[0-9]*}}
......@@ -120,12 +120,12 @@ entry:
ret i32 %ret
; BLINDINGO2-LABEL: add_const_16bits
; BLINDINGO2: mov e{{[a-z]*}},0xc1a5
; BLINDINGO2-NEXT: e{{[a-z]*}},{{[[]}}e{{[a-z]*}}-0x41a7{{[]]}}
; BLINDINGO2: mov e{{[a-z]*}},0x88a4d
; BLINDINGO2-NEXT: e{{[a-z]*}},{{[[]}}e{{[a-z]*}}-0x80a4f{{[]]}}
; BLINDINGOM1-LABEL: add_const_16bits
; BLINDINGOM1: mov e{{[a-z]*}},0xc1a5
; BLINDINGOM1-NEXT: e{{[a-z]*}},{{[[]}}e{{[a-z]*}}-0x41a7{{[]]}}
; BLINDINGOM1: mov e{{[a-z]*}},0x88a4d
; BLINDINGOM1-NEXT: e{{[a-z]*}},{{[[]}}e{{[a-z]*}}-0x80a4f{{[]]}}
; POOLING-LABEL: add_const_16bits
; POOLING: mov {{[a-z]x}},WORD PTR ds:0x0 {{[0-9a-f]*}}: R_386_32 .L$i16${{[0-9]*}}
......
......@@ -26,11 +26,11 @@ entry:
; OPTM1_1-NEXT: movups XMMWORD PTR [esp+0x20],xmm0
; OPTM1_1-NEXT: movups XMMWORD PTR [esp+0x10],xmm1
; OPTM1_1-NEXT: movups xmm0,XMMWORD PTR [esp+0x20]
; OPTM1_1-NEXT: pshufd xmm1,XMMWORD PTR [esp+0x20],0x31
; OPTM1_1-NEXT: pshufd xmm2,XMMWORD PTR [esp+0x10],0x31
; OPTM1_1-NEXT: pshufd xmm7,XMMWORD PTR [esp+0x20],0x31
; OPTM1_1-NEXT: pshufd xmm3,XMMWORD PTR [esp+0x10],0x31
; OPTM1_1-NEXT: pmuludq xmm0,XMMWORD PTR [esp+0x10]
; OPTM1_1-NEXT: pmuludq xmm1,xmm2
; OPTM1_1-NEXT: shufps xmm0,xmm1,0x88
; OPTM1_1-NEXT: pmuludq xmm7,xmm3
; OPTM1_1-NEXT: shufps xmm0,xmm7,0x88
; OPTM1_1-NEXT: pshufd xmm0,xmm0,0xd8
; OPTM1_1-NEXT: movups XMMWORD PTR [esp],xmm0
; OPTM1_1-NEXT: movups xmm0,XMMWORD PTR [esp]
......@@ -38,14 +38,14 @@ entry:
; OPTM1_1-NEXT: ret
; CHECK_1-LABEL: mul_v4i32
; CHECK_1: movups xmm5,xmm0
; CHECK_1: movups xmm7,xmm0
; CHECK_1-NEXT: pshufd xmm0,xmm0,0x31
; CHECK_1-NEXT: pshufd xmm3,xmm1,0x31
; CHECK_1-NEXT: pmuludq xmm5,xmm1
; CHECK_1-NEXT: pmuludq xmm7,xmm1
; CHECK_1-NEXT: pmuludq xmm0,xmm3
; CHECK_1-NEXT: shufps xmm5,xmm0,0x88
; CHECK_1-NEXT: pshufd xmm5,xmm5,0xd8
; CHECK_1-NEXT: movups xmm0,xmm5
; CHECK_1-NEXT: shufps xmm7,xmm0,0x88
; CHECK_1-NEXT: pshufd xmm7,xmm7,0xd8
; CHECK_1-NEXT: movups xmm0,xmm7
; CHECK_1-NEXT: ret
; OPTM1_123-LABEL: mul_v4i32
......@@ -53,11 +53,11 @@ entry:
; OPTM1_123-NEXT: movups XMMWORD PTR [esp+0x20],xmm0
; OPTM1_123-NEXT: movups XMMWORD PTR [esp+0x10],xmm1
; OPTM1_123-NEXT: movups xmm0,XMMWORD PTR [esp+0x20]
; OPTM1_123-NEXT: pshufd xmm1,XMMWORD PTR [esp+0x20],0x31
; OPTM1_123-NEXT: pshufd xmm6,XMMWORD PTR [esp+0x10],0x31
; OPTM1_123-NEXT: pshufd xmm2,XMMWORD PTR [esp+0x20],0x31
; OPTM1_123-NEXT: pshufd xmm1,XMMWORD PTR [esp+0x10],0x31
; OPTM1_123-NEXT: pmuludq xmm0,XMMWORD PTR [esp+0x10]
; OPTM1_123-NEXT: pmuludq xmm1,xmm6
; OPTM1_123-NEXT: shufps xmm0,xmm1,0x88
; OPTM1_123-NEXT: pmuludq xmm2,xmm1
; OPTM1_123-NEXT: shufps xmm0,xmm2,0x88
; OPTM1_123-NEXT: pshufd xmm0,xmm0,0xd8
; OPTM1_123-NEXT: movups XMMWORD PTR [esp],xmm0
; OPTM1_123-NEXT: movups xmm0,XMMWORD PTR [esp]
......@@ -65,14 +65,14 @@ entry:
; OPTM1_123-NEXT: ret
; CHECK_123-LABEL: mul_v4i32
; CHECK_123: movups xmm4,xmm0
; CHECK_123: movups xmm3,xmm0
; CHECK_123-NEXT: pshufd xmm0,xmm0,0x31
; CHECK_123-NEXT: pshufd xmm2,xmm1,0x31
; CHECK_123-NEXT: pmuludq xmm4,xmm1
; CHECK_123-NEXT: pmuludq xmm0,xmm2
; CHECK_123-NEXT: shufps xmm4,xmm0,0x88
; CHECK_123-NEXT: pshufd xmm4,xmm4,0xd8
; CHECK_123-NEXT: movups xmm0,xmm4
; CHECK_123-NEXT: pshufd xmm5,xmm1,0x31
; CHECK_123-NEXT: pmuludq xmm3,xmm1
; CHECK_123-NEXT: pmuludq xmm0,xmm5
; CHECK_123-NEXT: shufps xmm3,xmm0,0x88
; CHECK_123-NEXT: pshufd xmm3,xmm3,0xd8
; CHECK_123-NEXT: movups xmm0,xmm3
; CHECK_123-NEXT: ret
}
......
......@@ -29,8 +29,8 @@ BB4:
; SEED1: .Lbasic_block_reordering$entry:
; SEED1: .Lbasic_block_reordering$BB1:
; SEED1: .Lbasic_block_reordering$BB2:
; SEED1: .Lbasic_block_reordering$BB3:
; SEED1: .Lbasic_block_reordering$BB4:
; SEED1: .Lbasic_block_reordering$BB3:
; SEED2-LABEL: basic_block_reordering:
; SEED2: .Lbasic_block_reordering$entry:
......
......@@ -61,12 +61,12 @@ define void @func6() {
ret void
}
; DEFAULTWINDOWSIZE-LABEL: func4
; DEFAULTWINDOWSIZE-LABEL: func1
; DEFAULTWINDOWSIZE-LABEL: func3
; DEFAULTWINDOWSIZE-LABEL: func6
; DEFAULTWINDOWSIZE-LABEL: func4
; DEFAULTWINDOWSIZE-LABEL: func5
; DEFAULTWINDOWSIZE-LABEL: func2
; DEFAULTWINDOWSIZE-LABEL: func6
; DEFAULTWINDOWSIZE-LABEL: func3
; WINDOWSIZE1-LABEL: func1
; WINDOWSIZE1-LABEL: func2
......@@ -82,9 +82,9 @@ define void @func6() {
; SEQUENTIAL-LABEL: func5
; SEQUENTIAL-LABEL: func6
; WINDOWSIZEMAX-LABEL: func4
; WINDOWSIZEMAX-LABEL: func1
; WINDOWSIZEMAX-LABEL: func3
; WINDOWSIZEMAX-LABEL: func6
; WINDOWSIZEMAX-LABEL: func4
; WINDOWSIZEMAX-LABEL: func5
; WINDOWSIZEMAX-LABEL: func2
; WINDOWSIZEMAX-LABEL: func6
; WINDOWSIZEMAX-LABEL: func3
......@@ -54,16 +54,11 @@
@ArrayUninitConstInt = internal constant [20 x i8] zeroinitializer, align 4
;@__init_array_start = internal constant [0 x i8] zeroinitializer, align 4
;@__fini_array_start = internal constant [0 x i8] zeroinitializer, align 4
;@__tls_template_start = internal constant [0 x i8] zeroinitializer, align 8
;@__tls_template_alignment = internal constant [4 x i8] c"\01\00\00\00", align 4
; Make sure the shuffled order is correct.
; CHECK-LABEL: ArrayInitPartial
; CHECK-LABEL: PrimitiveInit
; CHECK-LABEL: ArrayInit
; CHECK-LABEL: PrimitiveInit
; CHECK-LABEL: ArrayInitPartial
; CHECK-LABEL: PrimitiveUninit
; CHECK-LABEL: ArrayUninit
; CHECK-LABEL: PrimitiveInitStatic
......
......@@ -3,11 +3,11 @@
; RUN: %p2i --assemble --disassemble --filetype=obj --dis-flags=-s \
; RUN: --target x8632 -i %s --args -sz-seed=1 -O2 -reorder-pooled-constants \
; RUN: | FileCheck %s --check-prefix=X86O2
; RUN: | FileCheck %s --check-prefix=X86
; RUN: %p2i --assemble --disassemble --filetype=obj --dis-flags=-s \
; RUN: --target x8632 -i %s --args -sz-seed=1 -Om1 -reorder-pooled-constants \
; RUN: | FileCheck %s --check-prefix=X86OM1
; RUN: | FileCheck %s --check-prefix=X86
@__init_array_start = internal constant [0 x i8] zeroinitializer, align 4
@__fini_array_start = internal constant [0 x i8] zeroinitializer, align 4
......@@ -533,38 +533,17 @@ return: ; preds = %entry, %sw.bb65, %s
}
; Make sure the constants in pools are shuffled.
; TODO(qining, stichnot): Unify the checkers for Om1 and O2 optimization levels.
; Om1 and O2 result into different sizes of i32 constant pools.
; Because the shuffling routine of constant pools is applied to integer
; constant pools first, the random number used for shuffling float and double
; constant pools will be different for Om1 and O2, so is the order of the pooled
; float and double constants. The source of this difference may includes: stack
; frame size, strength reduction, etc.
; Check for float pool
; X86O2-LABEL: .rodata.cst4
; X86O2: 00000040 0000c0ff 00000041 00000000
; X86O2: 0000003f 0000803f 00008040 0000c07f
; X86O2: 0000803e
; X86-LABEL: .rodata.cst4
; X86: 00000041 0000c0ff 0000803f 00008040
; X86: 0000c07f 00000000 0000003f 0000803e
; X86: 00000040
; Check for double pool
; X86O2-LABEL: .rodata.cst8
; X86O2: 55555555 5555d53f 00000000 0000f8ff
; X86O2: 00000000 0000f87f 00000000 0000e03f
; X86O2: 00000000 0000d03f 00000000 00000000
; X86-LABEL: .rodata.cst8
; X86: 00000000 0000f8ff 00000000 0000f87f
; X86: 00000000 0000e03f 00000000 00000000
; X86: 55555555 5555d53f 00000000 0000d03f
; X86O2-LABEL: .text
; Check for float pool
; X86OM1-LABEL: .rodata.cst4
; X86OM1: 0000803f 0000003f 00000040 0000c0ff
; X86OM1: 00000000 00008040 0000c07f 0000803e
; X86OM1: 00000041
; Check for double pool
; X86OM1-LABEL: .rodata.cst8
; X86OM1: 00000000 0000e03f 00000000 0000f87f
; X86OM1: 00000000 0000f8ff 00000000 0000d03f
; X86OM1: 00000000 00000000 55555555 5555d53f
; X86OM1-LABEL: .text
; X86-LABEL: .text
; This is a smoke test of random number generator.
; The random number generators for different randomization passes should be
; decoupled. The random number used in one randomization pass should not be
; influenced by the existence of other randomization passes.
; REQUIRES: allow_dump, target_X8632
; Command for checking constant blinding (Need to turn off nop-insertion)
; RUN: %p2i --target x8632 -i %s --filetype=obj --disassemble --args -O2 \
; RUN: -sz-seed=1 -randomize-pool-immediates=randomize \
; RUN: -randomize-pool-threshold=0x1 \
; RUN: -reorder-global-variables \
; RUN: -reorder-basic-blocks \
; RUN: -reorder-functions \
; RUN: -randomize-regalloc \
; RUN: -nop-insertion=0 \
; RUN: -reorder-pooled-constants \
; RUN: | FileCheck %s --check-prefix=BLINDINGO2
; Command for checking global variable reordering
; RUN: %p2i --target x8632 -i %s \
; RUN: --filetype=obj --disassemble --dis-flags=-rD \
; RUN: --args -O2 -sz-seed=1 \
; RUN: -randomize-pool-immediates=randomize \
; RUN: -randomize-pool-threshold=0x1 \
; RUN: -reorder-global-variables \
; RUN: -reorder-basic-blocks \
; RUN: -reorder-functions \
; RUN: -randomize-regalloc \
; RUN: -nop-insertion \
; RUN: -reorder-pooled-constants \
; RUN: | FileCheck %s --check-prefix=GLOBALVARS
; Command for checking basic block reordering
; RUN: %p2i --target x8632 -i %s --filetype=asm --args -O2 -sz-seed=1\
; RUN: -randomize-pool-immediates=randomize \
; RUN: -randomize-pool-threshold=0x1 \
; RUN: -reorder-global-variables \
; RUN: -reorder-basic-blocks \
; RUN: -reorder-functions \
; RUN: -randomize-regalloc \
; RUN: -nop-insertion \
; RUN: -reorder-pooled-constants \
; RUN: | FileCheck %s --check-prefix=BBREORDERING
; Command for checking function reordering
; RUN: %p2i --target x8632 -i %s --filetype=obj --disassemble --args -O2 \
; RUN: -sz-seed=1 -randomize-pool-immediates=randomize \
; RUN: -randomize-pool-threshold=0x1 \
; RUN: -reorder-global-variables \
; RUN: -reorder-basic-blocks \
; RUN: -reorder-functions \
; RUN: -randomize-regalloc \
; RUN: -nop-insertion \
; RUN: -reorder-pooled-constants \
; RUN: | FileCheck %s --check-prefix=FUNCREORDERING
; Command for checking regalloc randomization
; RUN: %p2i --target x8632 -i %s --filetype=obj --disassemble --args -O2 \
; RUN: -sz-seed=1 -randomize-pool-immediates=randomize \
; RUN: -randomize-pool-threshold=0x1 \
; RUN: -reorder-global-variables \
; RUN: -reorder-basic-blocks \
; RUN: -reorder-functions \
; RUN: -randomize-regalloc \
; RUN: -nop-insertion \
; RUN: -reorder-pooled-constants \
; RUN: | FileCheck %s --check-prefix=REGALLOC
; Command for checking nop insertion (Need to turn off randomize-regalloc)
; RUN: %p2i --target x8632 -i %s --filetype=asm --args \
; RUN: -sz-seed=1 -randomize-pool-immediates=randomize \
; RUN: -reorder-global-variables \
; RUN: -reorder-basic-blocks \
; RUN: -reorder-functions \
; RUN: -randomize-regalloc=0 \
; RUN: -nop-insertion -nop-insertion-percentage=50\
; RUN: -reorder-pooled-constants \
; RUN: | FileCheck %s --check-prefix=NOPINSERTION
; Command for checking pooled constants reordering
; RUN: %p2i --target x8632 -i %s --filetype=obj --disassemble --dis-flags=-s \
; RUN: --args -O2 -sz-seed=1 \
; RUN: -randomize-pool-immediates=randomize \
; RUN: -randomize-pool-threshold=0x1 \
; RUN: -reorder-global-variables \
; RUN: -reorder-basic-blocks \
; RUN: -reorder-functions \
; RUN: -randomize-regalloc \
; RUN: -nop-insertion \
; RUN: -reorder-pooled-constants \
; RUN: | FileCheck %s --check-prefix=POOLEDCONSTANTS
; Global variables copied from reorder-global-variables.ll
@PrimitiveInit = internal global [4 x i8] c"\1B\00\00\00", align 4
@PrimitiveInitConst = internal constant [4 x i8] c"\0D\00\00\00", align 4
@ArrayInit = internal global [20 x i8] c"\0A\00\00\00\14\00\00\00\1E\00\00\00(\00\00\002\00\00\00", align 4
@ArrayInitPartial = internal global [40 x i8] c"<\00\00\00F\00\00\00P\00\00\00Z\00\00\00d\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00", align 4
@PrimitiveInitStatic = internal global [4 x i8] zeroinitializer, align 4
@PrimitiveUninit = internal global [4 x i8] zeroinitializer, align 4
@ArrayUninit = internal global [20 x i8] zeroinitializer, align 4
@ArrayUninitConstDouble = internal constant [200 x i8] zeroinitializer, align 8
@ArrayUninitConstInt = internal constant [20 x i8] zeroinitializer, align 4
define <4 x i32> @func1(<4 x i32> %a, <4 x i32> %b) {
entry:
%res = mul <4 x i32> %a, %b
ret <4 x i32> %res
; NOPINSERTION-LABEL: func1
; NOPINSERTION: nop # variant = 1
; NOPINSERTION: subl $60, %esp
; NOPINSERTION: nop # variant = 3
; NOPINSERTION: movups %xmm0, 32(%esp)
; NOPINSERTION: movups %xmm1, 16(%esp)
; NOPINSERTION: movups 32(%esp), %xmm0
; NOPINSERTION: nop # variant = 1
; NOPINSERTION: pshufd $49, 32(%esp), %xmm1
; NOPINSERTION: nop # variant = 4
; NOPINSERTION: pshufd $49, 16(%esp), %xmm2
; NOPINSERTION: nop # variant = 1
; NOPINSERTION: pmuludq 16(%esp), %xmm0
; NOPINSERTION: pmuludq %xmm2, %xmm1
; NOPINSERTION: nop # variant = 0
; NOPINSERTION: shufps $136, %xmm1, %xmm0
; NOPINSERTION: nop # variant = 3
; NOPINSERTION: pshufd $216, %xmm0, %xmm0
; NOPINSERTION: nop # variant = 1
; NOPINSERTION: movups %xmm0, (%esp)
; NOPINSERTION: movups (%esp), %xmm0
; NOPINSERTION: addl $60, %esp
; NOPINSERTION: ret
}
define float @func2(float* %arg) {
entry:
%arg.int = ptrtoint float* %arg to i32
%addr.int = add i32 %arg.int, 200000
%addr.ptr = inttoptr i32 %addr.int to float*
%addr.load = load float, float* %addr.ptr, align 4
ret float %addr.load
; BLINDINGO2-LABEL: func2
; BLINDINGO2: lea [[REG:e[a-z]*]],{{[[]}}{{e[a-z]*}}+0x32c814{{[]]}}
}
define float @func3(i32 %arg, float %input) {
entry:
switch i32 %arg, label %return [
i32 0, label %sw.bb
i32 1, label %sw.bb1
i32 2, label %sw.bb2
i32 3, label %sw.bb3
i32 4, label %sw.bb4
]
sw.bb:
%rbb = fadd float %input, 1.000000e+00
br label %return
sw.bb1:
%rbb1 = fadd float %input, 2.000000e+00
br label %return
sw.bb2:
%rbb2 = fadd float %input, 4.000000e+00
br label %return
sw.bb3:
%rbb3 = fadd float %input, 5.000000e-01
br label %return
sw.bb4:
%rbb4 = fadd float %input, 2.500000e-01
br label %return
return:
%retval.0 = phi float [ %rbb, %sw.bb ], [ %rbb1, %sw.bb1 ], [ %rbb2, %sw.bb2 ], [ %rbb3, %sw.bb3 ], [ %rbb4, %sw.bb4], [ 0.000000e+00, %entry ]
ret float %retval.0
}
define <4 x i32> @func4(<4 x i32> %a, <4 x i32> %b) {
entry:
%res = mul <4 x i32> %a, %b
ret <4 x i32> %res
; REGALLOC-LABEL: func4
; REGALLOC: movups xmm3,xmm0
; REGALLOC-NEXT: pshufd xmm0,xmm0,0x31
; REGALLOC-NEXT: pshufd xmm5,xmm1,0x31
; REGALLOC-NEXT: pmuludq xmm3,xmm1
; REGALLOC-NEXT: pmuludq xmm0,xmm5
; REGALLOC-NEXT: shufps xmm3,xmm0,0x88
; REGALLOC-NEXT: pshufd xmm3,xmm3,0xd8
; REGALLOC-NEXT: movups xmm0,xmm3
; REGALLOC-NEXT: ret
}
define void @func5(i32 %foo, i32 %bar) {
entry:
%r1 = icmp eq i32 %foo, %bar
br i1 %r1, label %BB1, label %BB2
BB1:
%r2 = icmp sgt i32 %foo, %bar
br i1 %r2, label %BB3, label %BB4
BB2:
%r3 = icmp slt i32 %foo, %bar
br i1 %r3, label %BB3, label %BB4
BB3:
ret void
BB4:
ret void
; BBREORDERING-LABEL: func5:
; BBREORDERING: .Lfunc5$entry:
; BBREORDERING: .Lfunc5$BB1:
; BBREORDERING: .Lfunc5$BB2:
; BBREORDERING: .Lfunc5$BB4:
; BBREORDERING: .Lfunc5$BB3
}
define i32 @func6(i32 %arg) {
entry:
%res = add i32 200000, %arg
ret i32 %res
; BLINDINGO2-LABEL: func6
; BLINDINGO2: mov [[REG:e[a-z]*]],0xb178f
; BLINDINGO2-NEXT: lea [[REG]],{{[[]}}[[REG]]-0x80a4f{{[]]}}
}
; Check for function reordering
; FUNCREORDERING-LABEL: func1
; FUNCREORDERING-LABEL: func4
; FUNCREORDERING-LABEL: func5
; FUNCREORDERING-LABEL: func2
; FUNCREORDERING-LABEL: func6
; FUNCREORDERING-LABEL: func3
; Check for global variable reordering
; GLOBALVARS-LABEL: ArrayInit
; GLOBALVARS-LABEL: PrimitiveInit
; GLOBALVARS-LABEL: ArrayInitPartial
; GLOBALVARS-LABEL: PrimitiveUninit
; GLOBALVARS-LABEL: ArrayUninit
; GLOBALVARS-LABEL: PrimitiveInitStatic
; GLOBALVARS-LABEL: ArrayUninitConstDouble
; GLOBALVARS-LABEL: ArrayUninitConstInt
; GLOBALVARS-LABEL: PrimitiveInitConst
; Check for pooled constant reordering
; POOLEDCONSTANTS-LABEL: .rodata.cst4
; POOLEDCONSTANTS: 0000803e 0000803f 00000000 0000003f
; POOLEDCONSTANTS: 00008040 00000040
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment