| Index: src/IceTargetLoweringX8632.cpp
|
| diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp
|
| index 94ab396ccaffdbb52390180d8791bbab315095ab..13af9d76906ee49914652707226c53490b6b2326 100644
|
| --- a/src/IceTargetLoweringX8632.cpp
|
| +++ b/src/IceTargetLoweringX8632.cpp
|
| @@ -246,6 +246,22 @@ ICETYPE_TABLE
|
| #undef X
|
| } // end of namespace dummy3
|
|
|
| +// A helper class to ease the settings of RandomizationPoolingPause
|
| +// to disable constant blinding or pooling for some translation phases.
|
| +class BoolFlagSaver {
|
| + BoolFlagSaver() = delete;
|
| + BoolFlagSaver(const BoolFlagSaver &) = delete;
|
| + BoolFlagSaver &operator=(const BoolFlagSaver &) = delete;
|
| +
|
| +public:
|
| + BoolFlagSaver(bool &F, bool NewValue) : OldValue(F), Flag(F) { F = NewValue; }
|
| + ~BoolFlagSaver() { Flag = OldValue; }
|
| +
|
| +private:
|
| + const bool OldValue;
|
| + bool &Flag;
|
| +};
|
| +
|
| } // end of anonymous namespace
|
|
|
| BoolFoldingEntry::BoolFoldingEntry(Inst *I)
|
| @@ -396,8 +412,8 @@ void TargetX8632::initNodeForLowering(CfgNode *Node) {
|
|
|
| TargetX8632::TargetX8632(Cfg *Func)
|
| : TargetLowering(Func), InstructionSet(X86InstructionSet::Begin),
|
| - IsEbpBasedFrame(false), NeedsStackAlignment(false),
|
| - SpillAreaSizeBytes(0) {
|
| + IsEbpBasedFrame(false), NeedsStackAlignment(false), SpillAreaSizeBytes(0),
|
| + RandomizationPoolingPaused(false) {
|
| static_assert((X86InstructionSet::End - X86InstructionSet::Begin) ==
|
| (TargetInstructionSet::X86InstructionSet_End -
|
| TargetInstructionSet::X86InstructionSet_Begin),
|
| @@ -492,7 +508,11 @@ void TargetX8632::translateO2() {
|
| return;
|
| Func->dump("After x86 address mode opt");
|
|
|
| - doLoadOpt();
|
| + // Disable constant blinding or pooling for load optimization.
|
| + {
|
| + BoolFlagSaver B(RandomizationPoolingPaused, true);
|
| + doLoadOpt();
|
| + }
|
| Func->genCode();
|
| if (Func->hasError())
|
| return;
|
| @@ -519,7 +539,13 @@ void TargetX8632::translateO2() {
|
| Func->dump("After linear scan regalloc");
|
|
|
| if (Ctx->getFlags().getPhiEdgeSplit()) {
|
| - Func->advancedPhiLowering();
|
| + // We need to pause constant blinding or pooling during advanced
|
| + // phi lowering, unless the lowering assignment has a physical
|
| + // register for the dest Variable.
|
| + {
|
| + BoolFlagSaver B(RandomizationPoolingPaused, true);
|
| + Func->advancedPhiLowering();
|
| + }
|
| Func->dump("After advanced Phi lowering");
|
| }
|
|
|
| @@ -911,8 +937,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();
|
| @@ -925,8 +952,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();
|
| @@ -1317,12 +1345,18 @@ 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>(
|
| + Ctx->getConstantInt32(static_cast<int32_t>(Const->getValue())));
|
| + return legalize(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 legalize(MemOperand);
|
| }
|
| llvm_unreachable("Unsupported operand type");
|
| return nullptr;
|
| @@ -1338,8 +1372,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>(
|
| + Ctx->getConstantInt32(static_cast<int32_t>(Const->getValue() >> 32)));
|
| + // check if we need to blind/pool the constant
|
| + return legalize(ConstInt);
|
| }
|
| if (OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand)) {
|
| Constant *Offset = Mem->getOffset();
|
| @@ -1355,9 +1391,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 legalize(MemOperand);
|
| }
|
| llvm_unreachable("Unsupported operand type");
|
| return nullptr;
|
| @@ -1543,6 +1583,49 @@ void TargetX8632::lowerArithmetic(const InstArithmetic *Inst) {
|
| std::swap(Src0, Src1);
|
| }
|
| if (Dest->getType() == IceType_i64) {
|
| + // These helper-call-involved instructions are lowered in this
|
| + // separate switch. This is because loOperand() and hiOperand()
|
| + // may insert redundant instructions for constant blinding and
|
| + // pooling. Such redundant instructions will fail liveness analysis
|
| + // under -Om1 setting. And, actually these arguments do not need
|
| + // to be processed with loOperand() and hiOperand() to be used.
|
| + switch (Inst->getOp()) {
|
| + case InstArithmetic::Udiv: {
|
| + const SizeT MaxSrcs = 2;
|
| + InstCall *Call = makeHelperCall(H_udiv_i64, Dest, MaxSrcs);
|
| + Call->addArg(Inst->getSrc(0));
|
| + Call->addArg(Inst->getSrc(1));
|
| + lowerCall(Call);
|
| + return;
|
| + }
|
| + case InstArithmetic::Sdiv: {
|
| + const SizeT MaxSrcs = 2;
|
| + InstCall *Call = makeHelperCall(H_sdiv_i64, Dest, MaxSrcs);
|
| + Call->addArg(Inst->getSrc(0));
|
| + Call->addArg(Inst->getSrc(1));
|
| + lowerCall(Call);
|
| + return;
|
| + }
|
| + case InstArithmetic::Urem: {
|
| + const SizeT MaxSrcs = 2;
|
| + InstCall *Call = makeHelperCall(H_urem_i64, Dest, MaxSrcs);
|
| + Call->addArg(Inst->getSrc(0));
|
| + Call->addArg(Inst->getSrc(1));
|
| + lowerCall(Call);
|
| + return;
|
| + }
|
| + case InstArithmetic::Srem: {
|
| + const SizeT MaxSrcs = 2;
|
| + InstCall *Call = makeHelperCall(H_srem_i64, Dest, MaxSrcs);
|
| + Call->addArg(Inst->getSrc(0));
|
| + Call->addArg(Inst->getSrc(1));
|
| + lowerCall(Call);
|
| + return;
|
| + }
|
| + default:
|
| + break;
|
| + }
|
| +
|
| Variable *DestLo = llvm::cast<Variable>(loOperand(Dest));
|
| Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest));
|
| Operand *Src0Lo = loOperand(Src0);
|
| @@ -1732,34 +1815,6 @@ void TargetX8632::lowerArithmetic(const InstArithmetic *Inst) {
|
| _mov(DestLo, T_2);
|
| _mov(DestHi, T_3);
|
| } break;
|
| - case InstArithmetic::Udiv: {
|
| - const SizeT MaxSrcs = 2;
|
| - InstCall *Call = makeHelperCall(H_udiv_i64, Dest, MaxSrcs);
|
| - Call->addArg(Inst->getSrc(0));
|
| - Call->addArg(Inst->getSrc(1));
|
| - lowerCall(Call);
|
| - } break;
|
| - case InstArithmetic::Sdiv: {
|
| - const SizeT MaxSrcs = 2;
|
| - InstCall *Call = makeHelperCall(H_sdiv_i64, Dest, MaxSrcs);
|
| - Call->addArg(Inst->getSrc(0));
|
| - Call->addArg(Inst->getSrc(1));
|
| - lowerCall(Call);
|
| - } break;
|
| - case InstArithmetic::Urem: {
|
| - const SizeT MaxSrcs = 2;
|
| - InstCall *Call = makeHelperCall(H_urem_i64, Dest, MaxSrcs);
|
| - Call->addArg(Inst->getSrc(0));
|
| - Call->addArg(Inst->getSrc(1));
|
| - lowerCall(Call);
|
| - } break;
|
| - case InstArithmetic::Srem: {
|
| - const SizeT MaxSrcs = 2;
|
| - InstCall *Call = makeHelperCall(H_srem_i64, Dest, MaxSrcs);
|
| - Call->addArg(Inst->getSrc(0));
|
| - Call->addArg(Inst->getSrc(1));
|
| - lowerCall(Call);
|
| - } break;
|
| case InstArithmetic::Fadd:
|
| case InstArithmetic::Fsub:
|
| case InstArithmetic::Fmul:
|
| @@ -1767,6 +1822,13 @@ void TargetX8632::lowerArithmetic(const InstArithmetic *Inst) {
|
| case InstArithmetic::Frem:
|
| llvm_unreachable("FP instruction with i64 type");
|
| break;
|
| + case InstArithmetic::Udiv:
|
| + case InstArithmetic::Sdiv:
|
| + case InstArithmetic::Urem:
|
| + case InstArithmetic::Srem:
|
| + llvm_unreachable("Call-helper-involved instruction for i64 type \
|
| + should have already been handled before");
|
| + break;
|
| }
|
| return;
|
| }
|
| @@ -2161,18 +2223,27 @@ 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.
|
| - RI = legalize(Src0, Legal_Reg, Dest->getRegNum());
|
| - else
|
| +
|
| + // 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.
|
| + {
|
| + BoolFlagSaver B(RandomizationPoolingPaused, false);
|
| + RI = legalize(Src0, Legal_Reg, Dest->getRegNum());
|
| + }
|
| + } 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
|
| @@ -4733,6 +4804,10 @@ void TargetX8632::lowerOther(const Inst *Instr) {
|
| // 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
|
| + BoolFlagSaver B(RandomizationPoolingPaused, true);
|
| +
|
| CfgNode *Node = Context.getNode();
|
| for (Inst &I : Node->getPhis()) {
|
| auto Phi = llvm::dyn_cast<InstPhi>(&I);
|
| @@ -4832,7 +4907,28 @@ void TargetX8632::lowerPhiAssignments(CfgNode *Node,
|
| Context.rewind();
|
| auto Assign = llvm::dyn_cast<InstAssign>(&I);
|
| Variable *Dest = Assign->getDest();
|
| +
|
| + // If the source operand is ConstantUndef, do not legalize it.
|
| + // In function test_split_undef_int_vec, the advanced phi
|
| + // lowering process will find an assignment of undefined
|
| + // vector. This vector, as the Src here, will crash if it
|
| + // go through legalize(). legalize() will create new variable
|
| + // with makeVectorOfZeros(), but this new variable will be
|
| + // assigned a stack slot. This will fail the assertion in
|
| + // IceInstX8632.cpp:789, as XmmEmitterRegOp() complain:
|
| + // Var->hasReg() fails. Note this failure is irrelevant to
|
| + // randomization or pooling of constants.
|
| + // So, we do not call legalize() to add pool label for the
|
| + // src operands of phi assignment instructions.
|
| + // Instead, we manually add pool label for constant float and
|
| + // constant double values here.
|
| + // Note going through legalize() does not affect the testing
|
| + // results of SPEC2K and xtests.
|
| Operand *Src = Assign->getSrc(0);
|
| + if (!llvm::isa<ConstantUndef>(Assign->getSrc(0))) {
|
| + Src = legalize(Src);
|
| + }
|
| +
|
| Variable *SrcVar = llvm::dyn_cast<Variable>(Src);
|
| // Use normal assignment lowering, except lower mem=mem specially
|
| // so we can register-allocate at the same time.
|
| @@ -5008,6 +5104,7 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
|
| // work, e.g. allow the shl shift amount to be either an immediate
|
| // or in ecx.)
|
| assert(RegNum == Variable::NoRegister || Allowed == Legal_Reg);
|
| +
|
| if (auto Mem = llvm::dyn_cast<OperandX8632Mem>(From)) {
|
| // Before doing anything with a Mem operand, we need to ensure
|
| // that the Base and Index components are in physical registers.
|
| @@ -5022,18 +5119,21 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
|
| RegIndex = legalizeToVar(Index);
|
| }
|
| if (Base != RegBase || Index != RegIndex) {
|
| - From =
|
| + Mem =
|
| OperandX8632Mem::create(Func, Ty, RegBase, Mem->getOffset(), RegIndex,
|
| Mem->getShift(), Mem->getSegmentRegister());
|
| }
|
|
|
| + // For all Memory Operands, we do randomization/pooling here
|
| + From = randomizeOrPoolImmediate(Mem);
|
| +
|
| if (!(Allowed & Legal_Mem)) {
|
| From = copyToReg(From, RegNum);
|
| }
|
| return From;
|
| }
|
| - if (llvm::isa<Constant>(From)) {
|
| - if (llvm::isa<ConstantUndef>(From)) {
|
| + if (auto *Const = llvm::dyn_cast<Constant>(From)) {
|
| + if (llvm::isa<ConstantUndef>(Const)) {
|
| // Lower undefs to zero. Another option is to lower undefs to an
|
| // uninitialized register; however, using an uninitialized register
|
| // results in less predictable code.
|
| @@ -5047,10 +5147,21 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
|
| // need to go in uninitialized registers.
|
| if (isVectorType(Ty))
|
| return makeVectorOfZeros(Ty, RegNum);
|
| - From = Ctx->getConstantZero(Ty);
|
| + Const = Ctx->getConstantZero(Ty);
|
| + From = Const;
|
| }
|
| // 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 (ConstantInteger32 *C = llvm::dyn_cast<ConstantInteger32>(Const)) {
|
| + Operand *NewConst = randomizeOrPoolImmediate(C, RegNum);
|
| + if (NewConst != Const) {
|
| + return NewConst;
|
| + }
|
| + }
|
| +
|
| // Convert a scalar floating point constant into an explicit
|
| // memory operand.
|
| if (isScalarFloatingType(Ty)) {
|
| @@ -5058,6 +5169,7 @@ Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed,
|
| std::string Buffer;
|
| llvm::raw_string_ostream StrBuf(Buffer);
|
| llvm::cast<Constant>(From)->emitPoolLabel(StrBuf);
|
| + llvm::cast<Constant>(From)->setShouldBePooled(true);
|
| Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true);
|
| From = OperandX8632Mem::create(Func, Ty, Base, Offset);
|
| }
|
| @@ -5114,25 +5226,37 @@ 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 *Opnd, Type Ty,
|
| bool DoLegalize) {
|
| - OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand);
|
| + OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Opnd);
|
| // 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>(Opnd);
|
| + Constant *Offset = llvm::dyn_cast<Constant>(Opnd);
|
| assert(Base || Offset);
|
| if (Offset) {
|
| - // Make sure Offset is not undef.
|
| - Offset = llvm::cast<Constant>(legalize(Offset));
|
| + // 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*.
|
| + {
|
| + BoolFlagSaver B(RandomizationPoolingPaused, true);
|
| +
|
| + Offset = llvm::cast<Constant>(legalize(Offset));
|
| + }
|
| +
|
| assert(llvm::isa<ConstantInteger32>(Offset) ||
|
| llvm::isa<ConstantRelocatable>(Offset));
|
| }
|
| Mem = OperandX8632Mem::create(Func, Ty, Base, Offset);
|
| }
|
| - return llvm::cast<OperandX8632Mem>(DoLegalize ? legalize(Mem) : Mem);
|
| + // 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) {
|
| @@ -5297,6 +5421,45 @@ 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<uint32_t> {
|
| + 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<uint32_t>::TypeName = "i32";
|
| +const char *PoolTypeConverter<uint32_t>::AsmTag = ".long";
|
| +const char *PoolTypeConverter<uint32_t>::PrintfString = "0x%x";
|
| +
|
| +// Add converter for int type constant pooling
|
| +template <> struct PoolTypeConverter<uint16_t> {
|
| + typedef uint32_t PrimitiveIntType;
|
| + typedef ConstantInteger32 IceType;
|
| + static const Type Ty = IceType_i16;
|
| + static const char *TypeName;
|
| + static const char *AsmTag;
|
| + static const char *PrintfString;
|
| +};
|
| +const char *PoolTypeConverter<uint16_t>::TypeName = "i16";
|
| +const char *PoolTypeConverter<uint16_t>::AsmTag = ".short";
|
| +const char *PoolTypeConverter<uint16_t>::PrintfString = "0x%x";
|
| +
|
| +// Add converter for int type constant pooling
|
| +template <> struct PoolTypeConverter<uint8_t> {
|
| + typedef uint32_t PrimitiveIntType;
|
| + typedef ConstantInteger32 IceType;
|
| + static const Type Ty = IceType_i8;
|
| + static const char *TypeName;
|
| + static const char *AsmTag;
|
| + static const char *PrintfString;
|
| +};
|
| +const char *PoolTypeConverter<uint8_t>::TypeName = "i8";
|
| +const char *PoolTypeConverter<uint8_t>::AsmTag = ".byte";
|
| +const char *PoolTypeConverter<uint8_t>::PrintfString = "0x%x";
|
| +
|
| template <typename T>
|
| void TargetDataX8632::emitConstantPool(GlobalContext *Ctx) {
|
| if (!ALLOW_DUMP)
|
| @@ -5310,6 +5473,8 @@ void TargetDataX8632::emitConstantPool(GlobalContext *Ctx) {
|
| << "\n";
|
| Str << "\t.align\t" << Align << "\n";
|
| for (Constant *C : Pool) {
|
| + if (!C->getShouldBePooled())
|
| + continue;
|
| typename T::IceType *Const = llvm::cast<typename T::IceType>(C);
|
| typename T::IceType::PrimType Value = Const->getValue();
|
| // Use memcpy() to copy bits from Value into RawValue in a way
|
| @@ -5336,12 +5501,22 @@ void TargetDataX8632::lowerConstants() {
|
| switch (Ctx->getFlags().getOutFileType()) {
|
| case FT_Elf: {
|
| ELFObjectWriter *Writer = Ctx->getObjectWriter();
|
| +
|
| + Writer->writeConstantPool<ConstantInteger32>(IceType_i8);
|
| + Writer->writeConstantPool<ConstantInteger32>(IceType_i16);
|
| + 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);
|
| +
|
| + emitConstantPool<PoolTypeConverter<uint8_t>>(Ctx);
|
| + emitConstantPool<PoolTypeConverter<uint16_t>>(Ctx);
|
| + emitConstantPool<PoolTypeConverter<uint32_t>>(Ctx);
|
| +
|
| emitConstantPool<PoolTypeConverter<float>>(Ctx);
|
| emitConstantPool<PoolTypeConverter<double>>(Ctx);
|
| } break;
|
| @@ -5351,4 +5526,197 @@ void TargetDataX8632::lowerConstants() {
|
| TargetHeaderX8632::TargetHeaderX8632(GlobalContext *Ctx)
|
| : TargetHeaderLowering(Ctx) {}
|
|
|
| +// Randomize or pool an Immediate.
|
| +Operand *TargetX8632::randomizeOrPoolImmediate(Constant *Immediate,
|
| + int32_t RegNum) {
|
| + assert(llvm::isa<ConstantInteger32>(Immediate) ||
|
| + llvm::isa<ConstantRelocatable>(Immediate));
|
| + if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None ||
|
| + RandomizationPoolingPaused == true) {
|
| + // Immediates randomization/pooling off or paused
|
| + return Immediate;
|
| + }
|
| + if (Immediate->shouldBeRandomizedOrPooled(Ctx)) {
|
| + Ctx->statsUpdateRPImms();
|
| + if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() ==
|
| + RPI_Randomize) {
|
| + // 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
|
| + // the assigned register as this assignment is that start of its use-def
|
| + // chain. So we add RegNum argument here.
|
| + // Note we use 'lea' instruction instead of 'xor' to avoid affecting
|
| + // the flags.
|
| + Variable *Reg = makeReg(IceType_i32, RegNum);
|
| + ConstantInteger32 *Integer = llvm::cast<ConstantInteger32>(Immediate);
|
| + uint32_t Value = Integer->getValue();
|
| + uint32_t Cookie = Ctx->getRandomizationCookie();
|
| + _mov(Reg, Ctx->getConstantInt(IceType_i32, Cookie + Value));
|
| + Constant *Offset = Ctx->getConstantInt(IceType_i32, 0 - Cookie);
|
| + _lea(Reg,
|
| + OperandX8632Mem::create(Func, IceType_i32, Reg, Offset, nullptr, 0));
|
| + // make sure liveness analysis won't kill this variable, otherwise a
|
| + // liveness
|
| + // assertion will be triggered.
|
| + _set_dest_nonkillable();
|
| + if (Immediate->getType() != IceType_i32) {
|
| + Variable *TruncReg = makeReg(Immediate->getType(), RegNum);
|
| + _mov(TruncReg, Reg);
|
| + return TruncReg;
|
| + }
|
| + return Reg;
|
| + }
|
| + if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool) {
|
| + // pool the constant
|
| + // FROM:
|
| + // imm
|
| + // TO:
|
| + // insert: mov $label, Reg
|
| + // => Reg
|
| + assert(Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool);
|
| + Immediate->setShouldBePooled(true);
|
| + // 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 *Reg = makeReg(Immediate->getType(), RegNum);
|
| + IceString Label;
|
| + llvm::raw_string_ostream Label_stream(Label);
|
| + Immediate->emitPoolLabel(Label_stream);
|
| + const RelocOffsetT Offset = 0;
|
| + const bool SuppressMangling = true;
|
| + Constant *Symbol =
|
| + Ctx->getConstantSym(Offset, Label_stream.str(), SuppressMangling);
|
| + OperandX8632Mem *MemOperand =
|
| + OperandX8632Mem::create(Func, Immediate->getType(), nullptr, Symbol);
|
| + _mov(Reg, MemOperand);
|
| + return Reg;
|
| + }
|
| + assert("Unsupported -randomize-pool-immediates option" && false);
|
| + }
|
| + // the constant Immediate is not eligible for blinding/pooling
|
| + return Immediate;
|
| +}
|
| +
|
| +OperandX8632Mem *
|
| +TargetX8632::randomizeOrPoolImmediate(OperandX8632Mem *MemOperand,
|
| + int32_t RegNum) {
|
| + assert(MemOperand);
|
| + if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None ||
|
| + RandomizationPoolingPaused == true) {
|
| + // immediates randomization/pooling is turned off
|
| + return MemOperand;
|
| + }
|
| +
|
| + // If this memory operand is already a randommized one, we do
|
| + // not randomize it again.
|
| + if (MemOperand->getRandomized())
|
| + return MemOperand;
|
| +
|
| + if (Constant *C = llvm::dyn_cast_or_null<Constant>(MemOperand->getOffset())) {
|
| + if (C->shouldBeRandomizedOrPooled(Ctx)) {
|
| + // The offset of this mem operand should be blinded or pooled
|
| + Ctx->statsUpdateRPImms();
|
| + if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() ==
|
| + RPI_Randomize) {
|
| + // 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();
|
| + uint32_t Cookie = Ctx->getRandomizationCookie();
|
| + Constant *Mask1 = Ctx->getConstantInt(
|
| + MemOperand->getOffset()->getType(), Cookie + Value);
|
| + Constant *Mask2 =
|
| + Ctx->getConstantInt(MemOperand->getOffset()->getType(), 0 - Cookie);
|
| +
|
| + OperandX8632Mem *TempMemOperand = OperandX8632Mem::create(
|
| + Func, MemOperand->getType(), MemOperand->getBase(), Mask1);
|
| + // If we have already assigned a physical register, we must come from
|
| + // advancedPhiLowering()=>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 source operand doesn't use the dstreg, we don't need to add
|
| + // _set_dest_nonkillable().
|
| + // 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());
|
| +
|
| + // Label this memory operand as randomize, so we won't randomize it
|
| + // again in case we call legalize() mutiple times on this memory
|
| + // operand.
|
| + NewMemOperand->setRandomized(true);
|
| + return NewMemOperand;
|
| + }
|
| + if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool) {
|
| + // 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().getRandomizeAndPoolImmediatesOption() ==
|
| + RPI_Pool);
|
| + // Memory operand should never exist as source operands in phi
|
| + // lowering assignments, so there is no need to reuse any registers
|
| + // here. For phi lowering, we should not ask for new physical
|
| + // registers in general.
|
| + // However, if we do meet Memory Operand during phi lowering, we
|
| + // should not blind or pool the immediates for now.
|
| + if (RegNum != Variable::NoRegister)
|
| + return MemOperand;
|
| + Variable *RegTemp = makeReg(IceType_i32);
|
| + IceString Label;
|
| + llvm::raw_string_ostream Label_stream(Label);
|
| + MemOperand->getOffset()->emitPoolLabel(Label_stream);
|
| + MemOperand->getOffset()->setShouldBePooled(true);
|
| + const RelocOffsetT SymOffset = 0;
|
| + bool SuppressMangling = true;
|
| + Constant *Symbol = Ctx->getConstantSym(SymOffset, Label_stream.str(),
|
| + SuppressMangling);
|
| + OperandX8632Mem *SymbolOperand = OperandX8632Mem::create(
|
| + Func, MemOperand->getOffset()->getType(), nullptr, Symbol);
|
| + _mov(RegTemp, SymbolOperand);
|
| + // If we have a base variable here, we should add the lea instruction
|
| + // to add the value of the base variable to RegTemp. If there is no
|
| + // base variable, we won't need this lea instruction.
|
| + if (MemOperand->getBase()) {
|
| + OperandX8632Mem *CalculateOperand = OperandX8632Mem::create(
|
| + Func, MemOperand->getType(), MemOperand->getBase(), nullptr,
|
| + RegTemp, 0, MemOperand->getSegmentRegister());
|
| + _lea(RegTemp, CalculateOperand);
|
| + _set_dest_nonkillable();
|
| + }
|
| + OperandX8632Mem *NewMemOperand = OperandX8632Mem::create(
|
| + Func, MemOperand->getType(), RegTemp, nullptr,
|
| + MemOperand->getIndex(), MemOperand->getShift(),
|
| + MemOperand->getSegmentRegister());
|
| + return NewMemOperand;
|
| + }
|
| + assert("Unsupported -randomize-pool-immediates option" && false);
|
| + }
|
| + }
|
| + // the offset is not eligible for blinding or pooling, return the original
|
| + // mem operand
|
| + return MemOperand;
|
| +}
|
| +
|
| } // end of namespace Ice
|
|
|