Chromium Code Reviews| Index: src/IceTargetLoweringX8632.cpp |
| diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp |
| index 506b315079909210d3b1f7c9dc1fbee21e0e53ea..36f1ed386b126fdc6983d83683da7ea47ae1226a 100644 |
| --- a/src/IceTargetLoweringX8632.cpp |
| +++ b/src/IceTargetLoweringX8632.cpp |
| @@ -438,6 +438,16 @@ TargetX8632::TargetX8632(Cfg *Func) |
| TypeToRegisterSet[IceType_v8i16] = VectorRegisters; |
| TypeToRegisterSet[IceType_v4i32] = VectorRegisters; |
| TypeToRegisterSet[IceType_v4f32] = VectorRegisters; |
| + |
| + // qining: initialize the assistant pause flag |
|
Jim Stichnoth
2015/06/12 23:48:18
"qining:"? (here and below)
What does "assistant
qining
2015/06/17 04:28:53
Done. Removed
|
| + // for constant blinding and pooling. |
| + // When this is set to true, all constant blinding |
| + // and pooling will be disabled. This should be set to |
| + // true for doLoadOpt() and advancedPhiLowering(). |
| + // Note, when a physical regs are available for the Dest |
|
Jim Stichnoth
2015/06/12 23:48:18
I'm not 100% sure what this part of the comment me
|
| + // of Phi lowering assignment, we should set this flag to |
| + // false to enable blinding/pooling for that instruction. |
| + RandomizationPoolingPaused = false; |
|
Jim Stichnoth
2015/06/12 23:48:17
Do this simple initialization in the initializer l
qining
2015/06/13 00:41:26
Agree, but should we still leave the comments (may
qining
2015/06/17 04:28:54
Done.
|
| } |
| void TargetX8632::translateO2() { |
| @@ -482,7 +492,12 @@ void TargetX8632::translateO2() { |
| return; |
| Func->dump("After x86 address mode opt"); |
| + // qining: disable constant blinding or pooling for load optimization |
| + bool RPLatchForDoLoadOpt = RandomizationPoolingPaused; |
|
Jim Stichnoth
2015/06/12 23:48:17
You are using this pattern enough times (5?) that
qining
2015/06/17 04:28:54
Done.
|
| + RandomizationPoolingPaused = true; |
| doLoadOpt(); |
| + // qining: Resume constant blinding and pooling |
| + RandomizationPoolingPaused = RPLatchForDoLoadOpt; |
| Func->genCode(); |
| if (Func->hasError()) |
| return; |
| @@ -509,7 +524,14 @@ void TargetX8632::translateO2() { |
| Func->dump("After linear scan regalloc"); |
| if (Ctx->getFlags().getPhiEdgeSplit()) { |
| + // : In general we need to pause constant blinding or pooling |
|
Jim Stichnoth
2015/06/12 23:48:18
":" ?
qining
2015/06/17 04:28:53
Done. Should I remove this comment?
|
| + // advanced phi lowering, unless the lowering assignment has a |
|
Jim Stichnoth
2015/06/12 23:48:17
during advanced phi lowering
qining
2015/06/17 04:28:54
Done.
|
| + // physical register for the Dest Variable |
| + bool RPLatchAdvancedPhiLowering = RandomizationPoolingPaused; |
| + RandomizationPoolingPaused = true; |
| Func->advancedPhiLowering(); |
| + // qining: recover the pause flag; |
| + RandomizationPoolingPaused = RPLatchAdvancedPhiLowering; |
| Func->dump("After advanced Phi lowering"); |
| } |
| @@ -762,8 +784,9 @@ void TargetX8632::emitVariable(const Variable *Var) const { |
| Str << "%" << getRegName(Var->getRegNum(), Var->getType()); |
| return; |
| } |
| - if (Var->getWeight().isInf()) |
| + if (Var->getWeight().isInf()) { |
| llvm_unreachable("Infinite-weight Variable has no register assigned"); |
| + } |
| int32_t Offset = Var->getStackOffset(); |
| if (!hasFramePointer()) |
| Offset += getStackAdjustment(); |
| @@ -776,8 +799,9 @@ void TargetX8632::emitVariable(const Variable *Var) const { |
| X8632::Address TargetX8632::stackVarToAsmOperand(const Variable *Var) const { |
| if (Var->hasReg()) |
| llvm_unreachable("Stack Variable has a register assigned"); |
| - if (Var->getWeight().isInf()) |
| + if (Var->getWeight().isInf()) { |
| llvm_unreachable("Infinite-weight Variable has no register assigned"); |
| + } |
| int32_t Offset = Var->getStackOffset(); |
| if (!hasFramePointer()) |
| Offset += getStackAdjustment(); |
| @@ -1168,12 +1192,19 @@ Operand *TargetX8632::loOperand(Operand *Operand) { |
| return Var->getLo(); |
| } |
| if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
| - return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue())); |
| + ConstantInteger32 *ConstInt = llvm::dyn_cast<ConstantInteger32>( |
|
Jim Stichnoth
2015/06/12 23:48:18
Use cast<> instead of dyn_cast<>.
qining
2015/06/17 04:28:54
Done
|
| + Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue()))); |
|
Jim Stichnoth
2015/06/12 23:48:18
I think you should use int32_t instead of uint32_t
qining
2015/06/17 04:28:54
Done
|
| + // check if we need to blind/pool the constant |
| + return randomizeOrPoolImmediate(ConstInt); |
| } |
| if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { |
| - return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(), |
| - Mem->getOffset(), Mem->getIndex(), |
| - Mem->getShift(), Mem->getSegmentRegister()); |
| + OperandX8632Mem *MemOperand = OperandX8632Mem::create( |
| + Func, IceType_i32, Mem->getBase(), Mem->getOffset(), Mem->getIndex(), |
| + Mem->getShift(), Mem->getSegmentRegister()); |
| + // Test if we should randomize or pool the offset, if so randomize it or |
| + // pool it then create mem operand with the blinded/pooled constant. |
| + // Otherwise, return the mem operand as ordinary mem operand. |
| + return randomizeOrPoolImmediate(MemOperand); |
| } |
| llvm_unreachable("Unsupported operand type"); |
| return nullptr; |
| @@ -1189,8 +1220,10 @@ Operand *TargetX8632::hiOperand(Operand *Operand) { |
| return Var->getHi(); |
| } |
| if (ConstantInteger64 *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
| - return Ctx->getConstantInt32( |
| - static_cast<uint32_t>(Const->getValue() >> 32)); |
| + ConstantInteger32 *ConstInt = llvm::dyn_cast<ConstantInteger32>( |
|
Jim Stichnoth
2015/06/12 23:48:18
cast<>
qining
2015/06/17 04:28:54
Done
|
| + Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue() >> 32))); |
|
Jim Stichnoth
2015/06/12 23:48:17
int32_t
qining
2015/06/17 04:28:54
Done
|
| + // check if we need to blind/pool the constant |
| + return randomizeOrPoolImmediate(ConstInt); |
| } |
| if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) { |
| Constant *Offset = Mem->getOffset(); |
| @@ -1206,9 +1239,13 @@ Operand *TargetX8632::hiOperand(Operand *Operand) { |
| Ctx->getConstantSym(4 + SymOffset->getOffset(), SymOffset->getName(), |
| SymOffset->getSuppressMangling()); |
| } |
| - return OperandX8632Mem::create(Func, IceType_i32, Mem->getBase(), Offset, |
| - Mem->getIndex(), Mem->getShift(), |
| - Mem->getSegmentRegister()); |
| + OperandX8632Mem *MemOperand = OperandX8632Mem::create( |
| + Func, IceType_i32, Mem->getBase(), Offset, Mem->getIndex(), |
| + Mem->getShift(), Mem->getSegmentRegister()); |
| + // Test if the Offset is an eligible i32 constants for randomization and |
| + // pooling. Blind/pool it if it is. Otherwise return as oridinary mem |
| + // operand. |
| + return randomizeOrPoolImmediate(MemOperand); |
| } |
| llvm_unreachable("Unsupported operand type"); |
| return nullptr; |
| @@ -1839,18 +1876,30 @@ void TargetX8632::lowerAssign(const InstAssign *Inst) { |
| _mov(DestHi, T_Hi); |
| } else { |
| Operand *RI; |
| - if (Dest->hasReg()) |
| + if (Dest->hasReg()) { |
| // If Dest already has a physical register, then legalize the |
| // Src operand into a Variable with the same register |
| // assignment. This is mostly a workaround for advanced phi |
| // lowering's ad-hoc register allocation which assumes no |
| // register allocation is needed when at least one of the |
| // operands is non-memory. |
| + |
| + // qining: if we have a physical register for the dest variable, |
| + // we can enable our constant blinding or pooling again. Note |
| + // this is only for advancedPhiLowering(), the flag flip should |
| + // leave no other side effect. |
| + bool RPLatchInLowerAssign = RandomizationPoolingPaused; |
| + RandomizationPoolingPaused = false; |
| + |
| RI = legalize(Src0, Legal_Reg, Dest->getRegNum()); |
| - else |
| + |
| + // qining: Resume constant blinding and pooling |
| + RandomizationPoolingPaused = RPLatchInLowerAssign; |
| + } else { |
| // If Dest could be a stack operand, then RI must be a physical |
| // register or a scalar integer immediate. |
| RI = legalize(Src0, Legal_Reg | Legal_Imm); |
| + } |
| if (isVectorType(Dest->getType())) |
| _movp(Dest, RI); |
| else |
| @@ -3119,10 +3168,11 @@ void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { |
| Func->setError("Unexpected memory ordering for AtomicRMW"); |
| return; |
| } |
| - lowerAtomicRMW(Instr->getDest(), |
| - static_cast<uint32_t>(llvm::cast<ConstantInteger32>( |
| - Instr->getArg(0))->getValue()), |
| - Instr->getArg(1), Instr->getArg(2)); |
| + lowerAtomicRMW( |
| + Instr->getDest(), |
| + static_cast<uint32_t>( |
| + llvm::cast<ConstantInteger32>(Instr->getArg(0))->getValue()), |
| + Instr->getArg(1), Instr->getArg(2)); |
| return; |
| case Intrinsics::AtomicStore: { |
| if (!Intrinsics::isMemoryOrderValid( |
| @@ -4325,6 +4375,10 @@ void TargetX8632::lowerUnreachable(const InstUnreachable * /*Inst*/) { _ud2(); } |
| // turned into zeroes, since loOperand() and hiOperand() don't expect |
| // Undef input. |
| void TargetX8632::prelowerPhis() { |
| + // Pause constant blinding or pooling, blinding or pooling will be done later |
| + // during phi lowering assignments |
| + RandomizationPoolingPaused = true; |
| + |
| CfgNode *Node = Context.getNode(); |
| for (Inst &I : Node->getPhis()) { |
| auto Phi = llvm::dyn_cast<InstPhi>(&I); |
| @@ -4349,6 +4403,9 @@ void TargetX8632::prelowerPhis() { |
| Phi->setDeleted(); |
| } |
| } |
| + |
| + // Recover the constant blinding/pooling state |
| + RandomizationPoolingPaused = false; |
| } |
| namespace { |
| @@ -4619,6 +4676,9 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed, |
| Mem->getShift(), Mem->getSegmentRegister()); |
| } |
| + // qining: For all Memory Operands, we do randomization/pooling from here |
| + From = randomizeOrPoolImmediate(llvm::dyn_cast<OperandX8632Mem>(From)); |
|
Jim Stichnoth
2015/06/12 23:48:17
You've already done a dyn_cast<>(From) in the encl
qining
2015/06/17 04:28:53
Done
|
| + |
| if (!(Allowed & Legal_Mem)) { |
| From = copyToReg(From, RegNum); |
| } |
| @@ -4643,6 +4703,16 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed, |
| } |
| // There should be no constants of vector type (other than undef). |
| assert(!isVectorType(Ty)); |
| + |
| + // If the operand is an 32 bit constant integer, we should check |
| + // whether we need to randomize it or pool it. |
| + if (From && llvm::isa<ConstantInteger32>(From)) { |
|
Jim Stichnoth
2015/06/12 23:48:18
"From" must be non-null, so no need to test that.
qining
2015/06/17 04:28:54
Done
|
| + Operand *NewFrom = |
| + randomizeOrPoolImmediate(llvm::cast<Constant>(From), RegNum); |
|
Jim Stichnoth
2015/06/12 23:48:17
You can avoid the cast<> and the earlier isa<> che
qining
2015/06/17 04:28:54
Done
|
| + if (NewFrom != From) |
| + return NewFrom; |
| + } |
| + |
| // Convert a scalar floating point constant into an explicit |
| // memory operand. |
| if (isScalarFloatingType(Ty)) { |
| @@ -4706,25 +4776,40 @@ Operand *TargetX8632::legalizeSrc0ForCmp(Operand *Src0, Operand *Src1) { |
| return legalize(Src0, IsSrc1ImmOrReg ? (Legal_Reg | Legal_Mem) : Legal_Reg); |
| } |
| -OperandX8632Mem *TargetX8632::formMemoryOperand(Operand *Operand, Type Ty, |
| +OperandX8632Mem *TargetX8632::formMemoryOperand(Operand *operand, Type Ty, |
|
Jim Stichnoth
2015/06/12 23:48:17
Variable names should be capitalized, so maybe Opn
qining
2015/06/17 04:28:54
Done, replaced with Opnd.
|
| bool DoLegalize) { |
| - OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand); |
| + OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(operand); |
| // It may be the case that address mode optimization already creates |
| // an OperandX8632Mem, so in that case it wouldn't need another level |
| // of transformation. |
| if (!Mem) { |
| - Variable *Base = llvm::dyn_cast<Variable>(Operand); |
| - Constant *Offset = llvm::dyn_cast<Constant>(Operand); |
| + Variable *Base = llvm::dyn_cast<Variable>(operand); |
| + Constant *Offset = llvm::dyn_cast<Constant>(operand); |
| assert(Base || Offset); |
| if (Offset) { |
| - // Make sure Offset is not undef. |
| + // qining: during memory operand building, we do not |
| + // blind or pool the constant offset, we will work on |
| + // the whole memory operand later as one entity later, |
| + // this save one instruction. By turning blinding and |
| + // pooling off, we guarantee legalize(Offset) will return |
| + // a constant* |
| + bool RPLatchForMemOperandBuilding = RandomizationPoolingPaused; |
| + RandomizationPoolingPaused = true; |
| + |
| Offset = llvm::cast<Constant>(legalize(Offset)); |
| + |
| assert(llvm::isa<ConstantInteger32>(Offset) || |
| llvm::isa<ConstantRelocatable>(Offset)); |
| + |
| + // qining: Resume constant blinding and pooling |
| + RandomizationPoolingPaused = RPLatchForMemOperandBuilding; |
| } |
| Mem = OperandX8632Mem::create(Func, Ty, Base, Offset); |
| } |
| - return llvm::cast<OperandX8632Mem>(DoLegalize ? legalize(Mem) : Mem); |
| + // qining: do legalization, which contains randomization/pooling |
| + // or do randomization/pooling. |
| + return llvm::cast<OperandX8632Mem>( |
| + DoLegalize ? legalize(Mem) : randomizeOrPoolImmediate(Mem)); |
| } |
| Variable *TargetX8632::makeReg(Type Type, int32_t RegNum) { |
| @@ -4965,6 +5050,19 @@ const char *PoolTypeConverter<double>::TypeName = "double"; |
| const char *PoolTypeConverter<double>::AsmTag = ".quad"; |
| const char *PoolTypeConverter<double>::PrintfString = "0x%llx"; |
| +// Add converter for int type constant pooling |
| +template <> struct PoolTypeConverter<int> { |
| + typedef uint32_t PrimitiveIntType; |
| + typedef ConstantInteger32 IceType; |
| + static const Type Ty = IceType_i32; |
| + static const char *TypeName; |
| + static const char *AsmTag; |
| + static const char *PrintfString; |
| +}; |
| +const char *PoolTypeConverter<int>::TypeName = "i32"; |
| +const char *PoolTypeConverter<int>::AsmTag = ".long"; |
| +const char *PoolTypeConverter<int>::PrintfString = "0x%x"; |
| + |
| template <typename T> |
| void TargetDataX8632::emitConstantPool(GlobalContext *Ctx) { |
| if (!ALLOW_DUMP) |
| @@ -4979,6 +5077,12 @@ void TargetDataX8632::emitConstantPool(GlobalContext *Ctx) { |
| Str << "\t.align\t" << Align << "\n"; |
| for (Constant *C : Pool) { |
| typename T::IceType *Const = llvm::cast<typename T::IceType>(C); |
| + // When constant pooling turned on, only emit labels for eligible constants |
| + // If C is i32 constant and not large enough, we should ignore it here. |
| + if (llvm::isa<ConstantInteger32>(C) && |
| + llvm::dyn_cast_or_null<ConstantInteger32>(C) |
|
Jim Stichnoth
2015/06/12 23:48:18
Same comments here as in IceELFObjectWriter.cpp
qining
2015/06/17 04:28:54
Done. shouldBePooled will be checked before poolin
|
| + ->shouldBeRandomizedOrPooled(Ctx) == false) |
| + continue; |
| typename T::IceType::PrimType Value = Const->getValue(); |
| // Use memcpy() to copy bits from Value into RawValue in a way |
| // that avoids breaking strict-aliasing rules. |
| @@ -5004,12 +5108,22 @@ void TargetDataX8632::lowerConstants() const { |
| switch (Ctx->getFlags().getOutFileType()) { |
| case FT_Elf: { |
| ELFObjectWriter *Writer = Ctx->getObjectWriter(); |
| + |
| + // If immediates pooling turned on, pool the integer constants |
| + if (Ctx->getFlags().shouldPoolImmediates()) |
| + Writer->writeConstantPool<ConstantInteger32>(IceType_i32); |
| + |
| Writer->writeConstantPool<ConstantFloat>(IceType_f32); |
| Writer->writeConstantPool<ConstantDouble>(IceType_f64); |
| } break; |
| case FT_Asm: |
| case FT_Iasm: { |
| OstreamLocker L(Ctx); |
| + |
| + // If immediates pooling turned on, pool the integer constants |
| + if (Ctx->getFlags().shouldPoolImmediates()) |
| + emitConstantPool<PoolTypeConverter<int>>(Ctx); |
| + |
| emitConstantPool<PoolTypeConverter<float>>(Ctx); |
| emitConstantPool<PoolTypeConverter<double>>(Ctx); |
| } break; |
| @@ -5019,4 +5133,186 @@ void TargetDataX8632::lowerConstants() const { |
| TargetHeaderX8632::TargetHeaderX8632(GlobalContext *Ctx) |
| : TargetHeaderLowering(Ctx) {} |
| +uint32_t TargetX8632::getRandomizationCookie() { |
| + static uint64_t cookie = 0; |
|
Jim Stichnoth
2015/06/12 23:48:18
Don't use static non-const variables, as they are
qining
2015/06/17 04:28:54
Done. Moved getRandomizationCookie() and the cooki
|
| + static bool cookie_initialized = false; |
| + if (!cookie_initialized) { |
| + RandomNumberGenerator &RNG = Ctx->getRNG(); |
| + cookie = |
| + (uint32_t)RNG.next((uint64_t)std::numeric_limits<uint32_t>::max() + 1); |
| + cookie_initialized = true; |
| + } |
| + return cookie; |
| +} |
| + |
| +// Blind/pool an immediate value |
| +Operand *TargetX8632::randomizeOrPoolImmediate(Constant *immediate, |
|
Jim Stichnoth
2015/06/12 23:48:18
Capitalize "immediate" arg name.
qining
2015/06/17 04:28:53
Done
|
| + int32_t RegNum) { |
| + assert(llvm::isa<ConstantInteger32>(immediate) || |
| + llvm::isa<ConstantRelocatable>(immediate)); |
| + if (Ctx->getFlags().shouldNotRandomizeOrPoolImmediates() == true || |
| + RandomizationPoolingPaused == true) { |
| + // immediates randomization/pool turned off |
| + return immediate; |
| + } |
| + if (llvm::isa<ConstantInteger32>(immediate) && |
| + llvm::dyn_cast<ConstantInteger32>(immediate) |
| + ->shouldBeRandomizedOrPooled(Ctx)) { |
|
Jim Stichnoth
2015/06/12 23:48:18
Call immediate->shouldBeRandomizedOrPooled(Ctx) di
qining
2015/06/17 04:28:54
Done. Changed to:
if(Constant *C = dyn_cast_or_nul
|
| + Ctx->statsUpdateRPImms(); |
| + if (Ctx->getFlags().shouldRandomizeImmediates() == true) { |
| + // blind the constant |
| + // FROM: |
| + // imm |
| + // TO: |
| + // insert: mov imm+cookie, Reg |
| + // insert: lea -cookie[Reg], Reg |
| + // => Reg |
| + // if we have already assigned a phy register, we must come from |
| + // andvancedPhiLowering()=>lowerAssign(). In this case we should reuse |
|
Jim Stichnoth
2015/06/12 23:48:18
advancedPhiLowering
qining
2015/06/17 04:28:54
Done.
|
| + // the assigned register as this assignment is that start of its use-def |
| + // chain. So we add RegNum argument here. |
| + Variable *Reg = makeReg(immediate->getType(), RegNum); |
| + ConstantInteger32 *integer = llvm::cast<ConstantInteger32>(immediate); |
|
Jim Stichnoth
2015/06/12 23:48:18
Capitalize variable names
qining
2015/06/17 04:28:53
Done.
|
| + uint32_t value = integer->getValue(); |
| + uint64_t cookie = getRandomizationCookie(); |
|
Jim Stichnoth
2015/06/12 23:48:18
uint32_t
qining
2015/06/17 04:28:54
Done.
|
| + _mov(Reg, Ctx->getConstantInt(IceType_i32, cookie + value)); |
| + Constant *offset = Ctx->getConstantInt(IceType_i32, 0 - cookie); |
| + _lea(Reg, OperandX8632Mem::create(Func, offset->getType(), Reg, offset, |
| + NULL, 0)); |
| + // make sure liveness analysis won't kill this variable, otherwise a |
| + // liveness |
| + // assertion will be triggered. |
| + _set_dest_nonkillable(); |
| + return Reg; |
| + } else { |
|
Jim Stichnoth
2015/06/12 23:48:18
Don't use this pattern:
if (abc) {
def;
qining
2015/06/17 04:28:54
Done. Changed to:
if (abc) {
return xyz;
}
if
|
| + // pool the constant |
| + // FROM: |
| + // imm |
| + // TO: |
| + // insert: mov $label, Reg |
| + // => Reg |
| + assert(Ctx->getFlags().shouldPoolImmediates() == true); |
| + // if we have already assigned a phy register, we must come from |
| + // andvancedPhiLowering()=>lowerAssign(). In this case we should reuse |
|
Jim Stichnoth
2015/06/12 23:48:17
advancedPhiLowering
qining
2015/06/17 04:28:53
Done.
|
| + // the assigned register as this assignment is that start of its use-def |
| + // chain. So we add RegNum argument here. |
| + Variable *Reg = makeReg(immediate->getType(), RegNum); |
| + IceString label; |
| + llvm::raw_string_ostream label_stream(label); |
| + immediate->emitPoolLabel(label_stream); |
| + Constant *symbol = Ctx->getConstantSym(0, label_stream.str(), true); |
|
Jim Stichnoth
2015/06/12 23:48:17
Try to avoid using non-obvious constants as argume
qining
2015/06/17 04:28:54
Done.
|
| + OperandX8632Mem *MemOperand = |
| + OperandX8632Mem::create(Func, immediate->getType(), NULL, symbol); |
| + _mov(Reg, MemOperand); |
| + return Reg; |
| + } |
| + } else { |
| + // the constant immediate is not eligible for blinding/pooling |
| + return immediate; |
| + } |
| +} |
| + |
| +OperandX8632Mem * |
| +TargetX8632::randomizeOrPoolImmediate(OperandX8632Mem *MemOperand, |
| + int32_t RegNum) { |
| + assert(llvm::isa<OperandX8632Mem>(MemOperand)); |
|
Jim Stichnoth
2015/06/12 23:48:18
This assert isn't very useful and should always su
qining
2015/06/17 04:28:53
Done. Changed to assert(MemOperand).
|
| + if (Ctx->getFlags().shouldNotRandomizeOrPoolImmediates() == true || |
| + RandomizationPoolingPaused == true) { |
| + // immediates randomization/pooling is turned off |
| + return MemOperand; |
| + } |
| + |
| + if (MemOperand->getOffset() && |
|
Jim Stichnoth
2015/06/12 23:48:18
Something like this might be more compact:
if (au
qining
2015/06/17 04:28:53
Done.
|
| + llvm::isa<ConstantInteger32>(MemOperand->getOffset()) && |
| + llvm::dyn_cast<ConstantInteger32>(MemOperand->getOffset()) |
| + ->shouldBeRandomizedOrPooled(Ctx)) { |
| + // The offset of this mem operand should be blinded or pooled |
| + Ctx->statsUpdateRPImms(); |
| + if (Ctx->getFlags().shouldRandomizeImmediates() == true) { |
| + // blind the constant offset |
| + // FROM: |
| + // offset[base, index, shift] |
| + // TO: |
| + // insert: lea offset+cookie[base], RegTemp |
| + // => -cookie[RegTemp, index, shift] |
| + uint32_t value = |
| + llvm::dyn_cast<ConstantInteger32>(MemOperand->getOffset()) |
| + ->getValue(); |
| + uint64_t cookie = getRandomizationCookie(); |
| + Constant *mask1 = Ctx->getConstantInt(IceType_i32, cookie + value); |
| + Constant *mask2 = Ctx->getConstantInt(IceType_i32, 0 - cookie); |
| + // qining: We need to make sure the MemOperand->getBase() has a physical |
| + // register, if it is a variable! |
| + if (MemOperand->getBase() != NULL) |
|
Jim Stichnoth
2015/06/12 23:48:18
nullptr, or just leave out the != part
qining
2015/06/17 04:28:54
Done.
|
| + MemOperand->getBase()->setWeightInfinite(); |
|
Jim Stichnoth
2015/06/12 23:48:17
This will get you into trouble. The base variable
|
| + OperandX8632Mem *TempMemOperand = OperandX8632Mem::create( |
| + Func, MemOperand->getType(), MemOperand->getBase(), mask1); |
| + // if we have already assigned a phy register, we must come from |
| + // andvancedPhiLowering()=>lowerAssign(). In this case we should reuse |
| + // the assigned register as this assignment is that start of its use-def |
| + // chain. So we add RegNum argument here. |
| + |
| + Variable *RegTemp = makeReg(MemOperand->getOffset()->getType(), RegNum); |
| + _lea(RegTemp, TempMemOperand); |
| + // as srcreg doesn't include dstreg, we don't need to add |
| + // _set_dest_nonkillable() |
| + // qining: but if we use the same Dest Reg, that is, with RegNum |
| + // assigned, we should add this _set_dest_nonkillable() |
| + if (RegNum != Variable::NoRegister) |
| + _set_dest_nonkillable(); |
| + |
| + OperandX8632Mem *NewMemOperand = OperandX8632Mem::create( |
| + Func, MemOperand->getType(), RegTemp, mask2, MemOperand->getIndex(), |
| + MemOperand->getShift(), MemOperand->getSegmentRegister()); |
| + |
| + return NewMemOperand; |
| + |
| + } else { |
| + // pool the constant offset |
| + // FROM: |
| + // offset[base, index, shift] |
| + // TO: |
| + // insert: mov $label, RegTemp |
| + // insert: lea [base, RegTemp], RegTemp |
| + // =>[RegTemp, index, shift] |
| + assert(Ctx->getFlags().shouldPoolImmediates() == true); |
| + // qining: Mem operand should never exist as source operands in phi |
| + // lowering |
| + // assignments, so there is no need to reuse any registers here. |
| + // However, for phi lowering, we should not ask for new physical |
| + // registers in general. |
| + // However, if we do meet MemOperand during phi lowering, we should not |
| + // blind or pool the immediates for now |
| + if (RegNum != Variable::NoRegister) |
| + return MemOperand; |
| + Variable *RegTemp = makeReg(MemOperand->getOffset()->getType()); |
| + IceString label; |
| + llvm::raw_string_ostream label_stream(label); |
| + MemOperand->getOffset()->emitPoolLabel(label_stream); |
| + Constant *symbol = Ctx->getConstantSym(0, label_stream.str(), true); |
| + OperandX8632Mem *SymbolOperand = OperandX8632Mem::create( |
| + Func, MemOperand->getOffset()->getType(), NULL, symbol); |
| + _mov(RegTemp, SymbolOperand); |
| + // qining: We need to make sure the MemOperand->getBase() has a physical |
| + // register! If we do not have base register here, we won't need an |
| + // extra lea instruction anymore. |
| + if (MemOperand->getBase() != NULL) { |
| + MemOperand->getBase()->setWeightInfinite(); |
| + OperandX8632Mem *CalculateOperand = OperandX8632Mem::create( |
| + Func, MemOperand->getType(), MemOperand->getBase(), NULL, RegTemp, |
| + 0, MemOperand->getSegmentRegister()); |
| + _lea(RegTemp, CalculateOperand); |
| + _set_dest_nonkillable(); |
| + } |
| + OperandX8632Mem *NewMemOperand = OperandX8632Mem::create( |
| + Func, MemOperand->getType(), RegTemp, NULL, MemOperand->getIndex(), |
| + MemOperand->getShift(), MemOperand->getSegmentRegister()); |
| + return NewMemOperand; |
| + } |
| + } else { |
| + // the offset is not eligible for blinding or pooling, return the original |
| + // mem operand |
| + return MemOperand; |
| + } |
| +} |
| } // end of namespace Ice |