OLD | NEW |
1 //===- subzero/src/IceTargetLoweringX86BaseImpl.h - x86 lowering -*- C++ -*-==// | 1 //===- subzero/src/IceTargetLoweringX86BaseImpl.h - x86 lowering -*- C++ -*-==// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 /// | 9 /// |
10 /// \file | 10 /// \file |
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 // Look for: | 518 // Look for: |
519 // a = Load addr | 519 // a = Load addr |
520 // b = <op> a, other | 520 // b = <op> a, other |
521 // Store b, addr | 521 // Store b, addr |
522 // Change to: | 522 // Change to: |
523 // a = Load addr | 523 // a = Load addr |
524 // b = <op> a, other | 524 // b = <op> a, other |
525 // x = FakeDef | 525 // x = FakeDef |
526 // RMW <op>, addr, other, x | 526 // RMW <op>, addr, other, x |
527 // b = Store b, addr, x | 527 // b = Store b, addr, x |
528 // Note that inferTwoAddress() makes sure setDestNonKillable() gets | 528 // Note that inferTwoAddress() makes sure setDestRedefined() gets called |
529 // called on the updated Store instruction, to avoid liveness problems | 529 // on the updated Store instruction, to avoid liveness problems later. |
530 // later. | |
531 // | 530 // |
532 // With this transformation, the Store instruction acquires a Dest | 531 // With this transformation, the Store instruction acquires a Dest |
533 // variable and is now subject to dead code elimination if there are no | 532 // variable and is now subject to dead code elimination if there are no |
534 // more uses of "b". Variable "x" is a beacon for determining whether | 533 // more uses of "b". Variable "x" is a beacon for determining whether the |
535 // the Store instruction gets dead-code eliminated. If the Store | 534 // Store instruction gets dead-code eliminated. If the Store instruction |
536 // instruction is eliminated, then it must be the case that the RMW | 535 // is eliminated, then it must be the case that the RMW instruction ends |
537 // instruction ends x's live range, and therefore the RMW instruction | 536 // x's live range, and therefore the RMW instruction will be retained and |
538 // will be retained and later lowered. On the other hand, if the RMW | 537 // later lowered. On the other hand, if the RMW instruction does not end |
539 // instruction does not end x's live range, then the Store instruction | 538 // x's live range, then the Store instruction must still be present, and |
540 // must still be present, and therefore the RMW instruction is ignored | 539 // therefore the RMW instruction is ignored during lowering because it is |
541 // during lowering because it is redundant with the Store instruction. | 540 // redundant with the Store instruction. |
542 // | 541 // |
543 // Note that if "a" has further uses, the RMW transformation may still | 542 // Note that if "a" has further uses, the RMW transformation may still |
544 // trigger, resulting in two loads and one store, which is worse than the | 543 // trigger, resulting in two loads and one store, which is worse than the |
545 // original one load and one store. However, this is probably rare, and | 544 // original one load and one store. However, this is probably rare, and |
546 // caching probably keeps it just as fast. | 545 // caching probably keeps it just as fast. |
547 if (!isSameMemAddressOperand<Machine>(Load->getSourceAddress(), | 546 if (!isSameMemAddressOperand<Machine>(Load->getSourceAddress(), |
548 Store->getAddr())) | 547 Store->getAddr())) |
549 continue; | 548 continue; |
550 Operand *ArithSrcFromLoad = Arith->getSrc(0); | 549 Operand *ArithSrcFromLoad = Arith->getSrc(0); |
551 Operand *ArithSrcOther = Arith->getSrc(1); | 550 Operand *ArithSrcOther = Arith->getSrc(1); |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1027 // somewhat arbitrary choice of 3. | 1026 // somewhat arbitrary choice of 3. |
1028 const uint32_t MaxOpsForOptimizedMul = 3; | 1027 const uint32_t MaxOpsForOptimizedMul = 3; |
1029 if (CountOps > MaxOpsForOptimizedMul) | 1028 if (CountOps > MaxOpsForOptimizedMul) |
1030 return false; | 1029 return false; |
1031 _mov(T, Src0); | 1030 _mov(T, Src0); |
1032 Constant *Zero = Ctx->getConstantZero(IceType_i32); | 1031 Constant *Zero = Ctx->getConstantZero(IceType_i32); |
1033 for (uint32_t i = 0; i < Count9; ++i) { | 1032 for (uint32_t i = 0; i < Count9; ++i) { |
1034 const uint16_t Shift = 3; // log2(9-1) | 1033 const uint16_t Shift = 3; // log2(9-1) |
1035 _lea(T, | 1034 _lea(T, |
1036 Traits::X86OperandMem::create(Func, IceType_void, T, Zero, T, Shift)); | 1035 Traits::X86OperandMem::create(Func, IceType_void, T, Zero, T, Shift)); |
1037 _set_dest_nonkillable(); | |
1038 } | 1036 } |
1039 for (uint32_t i = 0; i < Count5; ++i) { | 1037 for (uint32_t i = 0; i < Count5; ++i) { |
1040 const uint16_t Shift = 2; // log2(5-1) | 1038 const uint16_t Shift = 2; // log2(5-1) |
1041 _lea(T, | 1039 _lea(T, |
1042 Traits::X86OperandMem::create(Func, IceType_void, T, Zero, T, Shift)); | 1040 Traits::X86OperandMem::create(Func, IceType_void, T, Zero, T, Shift)); |
1043 _set_dest_nonkillable(); | |
1044 } | 1041 } |
1045 for (uint32_t i = 0; i < Count3; ++i) { | 1042 for (uint32_t i = 0; i < Count3; ++i) { |
1046 const uint16_t Shift = 1; // log2(3-1) | 1043 const uint16_t Shift = 1; // log2(3-1) |
1047 _lea(T, | 1044 _lea(T, |
1048 Traits::X86OperandMem::create(Func, IceType_void, T, Zero, T, Shift)); | 1045 Traits::X86OperandMem::create(Func, IceType_void, T, Zero, T, Shift)); |
1049 _set_dest_nonkillable(); | |
1050 } | 1046 } |
1051 if (Count2) { | 1047 if (Count2) { |
1052 _shl(T, Ctx->getConstantInt(Ty, Count2)); | 1048 _shl(T, Ctx->getConstantInt(Ty, Count2)); |
1053 } | 1049 } |
1054 if (Src1IsNegative) | 1050 if (Src1IsNegative) |
1055 _neg(T); | 1051 _neg(T); |
1056 _mov(Dest, T); | 1052 _mov(Dest, T); |
1057 return true; | 1053 return true; |
1058 } | 1054 } |
1059 | 1055 |
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1209 // t2 = shl t2, t1 | 1205 // t2 = shl t2, t1 |
1210 // test t1, 0x20 | 1206 // test t1, 0x20 |
1211 // je L1 | 1207 // je L1 |
1212 // use(t3) | 1208 // use(t3) |
1213 // t3 = t2 | 1209 // t3 = t2 |
1214 // t2 = 0 | 1210 // t2 = 0 |
1215 _shld(T_3, T_2, T_1); | 1211 _shld(T_3, T_2, T_1); |
1216 _shl(T_2, T_1); | 1212 _shl(T_2, T_1); |
1217 _test(T_1, BitTest); | 1213 _test(T_1, BitTest); |
1218 _br(Traits::Cond::Br_e, Label); | 1214 _br(Traits::Cond::Br_e, Label); |
1219 // T_2 and T_3 are being assigned again because of the intra-block | 1215 // T_2 and T_3 are being assigned again because of the intra-block control |
1220 // control flow, so we need the _mov_nonkillable variant to avoid | 1216 // flow, so we need the _mov_redefined variant to avoid liveness problems. |
1221 // liveness problems. | 1217 _mov_redefined(T_3, T_2); |
1222 _mov_nonkillable(T_3, T_2); | 1218 _mov_redefined(T_2, Zero); |
1223 _mov_nonkillable(T_2, Zero); | |
1224 } break; | 1219 } break; |
1225 case InstArithmetic::Lshr: { | 1220 case InstArithmetic::Lshr: { |
1226 // a=b>>c (unsigned) ==> | 1221 // a=b>>c (unsigned) ==> |
1227 // t2 = shrd t2, t3, t1 | 1222 // t2 = shrd t2, t3, t1 |
1228 // t3 = shr t3, t1 | 1223 // t3 = shr t3, t1 |
1229 // test t1, 0x20 | 1224 // test t1, 0x20 |
1230 // je L1 | 1225 // je L1 |
1231 // use(t2) | 1226 // use(t2) |
1232 // t2 = t3 | 1227 // t2 = t3 |
1233 // t3 = 0 | 1228 // t3 = 0 |
1234 _shrd(T_2, T_3, T_1); | 1229 _shrd(T_2, T_3, T_1); |
1235 _shr(T_3, T_1); | 1230 _shr(T_3, T_1); |
1236 _test(T_1, BitTest); | 1231 _test(T_1, BitTest); |
1237 _br(Traits::Cond::Br_e, Label); | 1232 _br(Traits::Cond::Br_e, Label); |
1238 // T_2 and T_3 are being assigned again because of the intra-block | 1233 // T_2 and T_3 are being assigned again because of the intra-block control |
1239 // control flow, so we need the _mov_nonkillable variant to avoid | 1234 // flow, so we need the _mov_redefined variant to avoid liveness problems. |
1240 // liveness problems. | 1235 _mov_redefined(T_2, T_3); |
1241 _mov_nonkillable(T_2, T_3); | 1236 _mov_redefined(T_3, Zero); |
1242 _mov_nonkillable(T_3, Zero); | |
1243 } break; | 1237 } break; |
1244 case InstArithmetic::Ashr: { | 1238 case InstArithmetic::Ashr: { |
1245 // a=b>>c (signed) ==> | 1239 // a=b>>c (signed) ==> |
1246 // t2 = shrd t2, t3, t1 | 1240 // t2 = shrd t2, t3, t1 |
1247 // t3 = sar t3, t1 | 1241 // t3 = sar t3, t1 |
1248 // test t1, 0x20 | 1242 // test t1, 0x20 |
1249 // je L1 | 1243 // je L1 |
1250 // use(t2) | 1244 // use(t2) |
1251 // t2 = t3 | 1245 // t2 = t3 |
1252 // t3 = sar t3, 0x1f | 1246 // t3 = sar t3, 0x1f |
1253 Constant *SignExtend = Ctx->getConstantInt32(0x1f); | 1247 Constant *SignExtend = Ctx->getConstantInt32(0x1f); |
1254 _shrd(T_2, T_3, T_1); | 1248 _shrd(T_2, T_3, T_1); |
1255 _sar(T_3, T_1); | 1249 _sar(T_3, T_1); |
1256 _test(T_1, BitTest); | 1250 _test(T_1, BitTest); |
1257 _br(Traits::Cond::Br_e, Label); | 1251 _br(Traits::Cond::Br_e, Label); |
1258 // T_2 and T_3 are being assigned again because of the intra-block | 1252 // T_2 and T_3 are being assigned again because of the intra-block control |
1259 // control flow, so T_2 needs the _mov_nonkillable variant to avoid | 1253 // flow, so T_2 needs the _mov_redefined variant to avoid liveness |
1260 // liveness problems. T_3 doesn't need special treatment because it is | 1254 // problems. T_3 doesn't need special treatment because it is reassigned |
1261 // reassigned via _sar instead of _mov. | 1255 // via _sar instead of _mov. |
1262 _mov_nonkillable(T_2, T_3); | 1256 _mov_redefined(T_2, T_3); |
1263 _sar(T_3, SignExtend); | 1257 _sar(T_3, SignExtend); |
1264 } break; | 1258 } break; |
1265 } | 1259 } |
1266 // COMMON SUFFIX OF: a=b SHIFT_OP c ==> | 1260 // COMMON SUFFIX OF: a=b SHIFT_OP c ==> |
1267 // L1: | 1261 // L1: |
1268 // a.lo = t2 | 1262 // a.lo = t2 |
1269 // a.hi = t3 | 1263 // a.hi = t3 |
1270 Context.insert(Label); | 1264 Context.insert(Label); |
1271 _mov(DestLo, T_2); | 1265 _mov(DestLo, T_2); |
1272 _mov(DestHi, T_3); | 1266 _mov(DestHi, T_3); |
(...skipping 1335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2608 _mov(Dest, Default); | 2602 _mov(Dest, Default); |
2609 if (HasC1) { | 2603 if (HasC1) { |
2610 typename Traits::Insts::Label *Label = | 2604 typename Traits::Insts::Label *Label = |
2611 Traits::Insts::Label::create(Func, this); | 2605 Traits::Insts::Label::create(Func, this); |
2612 _br(Traits::TableFcmp[Index].C1, Label); | 2606 _br(Traits::TableFcmp[Index].C1, Label); |
2613 if (HasC2) { | 2607 if (HasC2) { |
2614 _br(Traits::TableFcmp[Index].C2, Label); | 2608 _br(Traits::TableFcmp[Index].C2, Label); |
2615 } | 2609 } |
2616 Constant *NonDefault = | 2610 Constant *NonDefault = |
2617 Ctx->getConstantInt32(!Traits::TableFcmp[Index].Default); | 2611 Ctx->getConstantInt32(!Traits::TableFcmp[Index].Default); |
2618 _mov_nonkillable(Dest, NonDefault); | 2612 _mov_redefined(Dest, NonDefault); |
2619 Context.insert(Label); | 2613 Context.insert(Label); |
2620 } | 2614 } |
2621 } | 2615 } |
2622 | 2616 |
2623 template <class Machine> | 2617 template <class Machine> |
2624 void TargetX86Base<Machine>::lowerIcmp(const InstIcmp *Inst) { | 2618 void TargetX86Base<Machine>::lowerIcmp(const InstIcmp *Inst) { |
2625 Operand *Src0 = legalize(Inst->getSrc(0)); | 2619 Operand *Src0 = legalize(Inst->getSrc(0)); |
2626 Operand *Src1 = legalize(Inst->getSrc(1)); | 2620 Operand *Src1 = legalize(Inst->getSrc(1)); |
2627 Variable *Dest = Inst->getDest(); | 2621 Variable *Dest = Inst->getDest(); |
2628 | 2622 |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2769 Traits::Insts::Label::create(Func, this); | 2763 Traits::Insts::Label::create(Func, this); |
2770 _mov(Dest, One); | 2764 _mov(Dest, One); |
2771 _cmp(Src0HiRM, Src1HiRI); | 2765 _cmp(Src0HiRM, Src1HiRI); |
2772 if (Traits::TableIcmp64[Index].C1 != Traits::Cond::Br_None) | 2766 if (Traits::TableIcmp64[Index].C1 != Traits::Cond::Br_None) |
2773 _br(Traits::TableIcmp64[Index].C1, LabelTrue); | 2767 _br(Traits::TableIcmp64[Index].C1, LabelTrue); |
2774 if (Traits::TableIcmp64[Index].C2 != Traits::Cond::Br_None) | 2768 if (Traits::TableIcmp64[Index].C2 != Traits::Cond::Br_None) |
2775 _br(Traits::TableIcmp64[Index].C2, LabelFalse); | 2769 _br(Traits::TableIcmp64[Index].C2, LabelFalse); |
2776 _cmp(Src0LoRM, Src1LoRI); | 2770 _cmp(Src0LoRM, Src1LoRI); |
2777 _br(Traits::TableIcmp64[Index].C3, LabelTrue); | 2771 _br(Traits::TableIcmp64[Index].C3, LabelTrue); |
2778 Context.insert(LabelFalse); | 2772 Context.insert(LabelFalse); |
2779 _mov_nonkillable(Dest, Zero); | 2773 _mov_redefined(Dest, Zero); |
2780 Context.insert(LabelTrue); | 2774 Context.insert(LabelTrue); |
2781 } | 2775 } |
2782 | 2776 |
2783 template <class Machine> | 2777 template <class Machine> |
2784 void TargetX86Base<Machine>::lowerInsertElement(const InstInsertElement *Inst) { | 2778 void TargetX86Base<Machine>::lowerInsertElement(const InstInsertElement *Inst) { |
2785 Operand *SourceVectNotLegalized = Inst->getSrc(0); | 2779 Operand *SourceVectNotLegalized = Inst->getSrc(0); |
2786 Operand *ElementToInsertNotLegalized = Inst->getSrc(1); | 2780 Operand *ElementToInsertNotLegalized = Inst->getSrc(1); |
2787 ConstantInteger32 *ElementIndex = | 2781 ConstantInteger32 *ElementIndex = |
2788 llvm::dyn_cast<ConstantInteger32>(Inst->getSrc(2)); | 2782 llvm::dyn_cast<ConstantInteger32>(Inst->getSrc(2)); |
2789 // Only constant indices are allowed in PNaCl IR. | 2783 // Only constant indices are allowed in PNaCl IR. |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3242 case Intrinsics::Stacksave: { | 3236 case Intrinsics::Stacksave: { |
3243 Variable *esp = | 3237 Variable *esp = |
3244 Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp); | 3238 Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
3245 Variable *Dest = Instr->getDest(); | 3239 Variable *Dest = Instr->getDest(); |
3246 _mov(Dest, esp); | 3240 _mov(Dest, esp); |
3247 return; | 3241 return; |
3248 } | 3242 } |
3249 case Intrinsics::Stackrestore: { | 3243 case Intrinsics::Stackrestore: { |
3250 Variable *esp = | 3244 Variable *esp = |
3251 Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp); | 3245 Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
3252 _mov_nonkillable(esp, Instr->getArg(0)); | 3246 _mov_redefined(esp, Instr->getArg(0)); |
3253 return; | 3247 return; |
3254 } | 3248 } |
3255 case Intrinsics::Trap: | 3249 case Intrinsics::Trap: |
3256 _ud2(); | 3250 _ud2(); |
3257 return; | 3251 return; |
3258 case Intrinsics::UnknownIntrinsic: | 3252 case Intrinsics::UnknownIntrinsic: |
3259 Func->setError("Should not be lowering UnknownIntrinsic"); | 3253 Func->setError("Should not be lowering UnknownIntrinsic"); |
3260 return; | 3254 return; |
3261 } | 3255 } |
3262 return; | 3256 return; |
(...skipping 1118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4381 if (typeWidthInBytes(DestTy) == 1 || isFloatingType(DestTy)) { | 4375 if (typeWidthInBytes(DestTy) == 1 || isFloatingType(DestTy)) { |
4382 // The cmov instruction doesn't allow 8-bit or FP operands, so we need | 4376 // The cmov instruction doesn't allow 8-bit or FP operands, so we need |
4383 // explicit control flow. | 4377 // explicit control flow. |
4384 // d=cmp e,f; a=d?b:c ==> cmp e,f; a=b; jne L1; a=c; L1: | 4378 // d=cmp e,f; a=d?b:c ==> cmp e,f; a=b; jne L1; a=c; L1: |
4385 typename Traits::Insts::Label *Label = | 4379 typename Traits::Insts::Label *Label = |
4386 Traits::Insts::Label::create(Func, this); | 4380 Traits::Insts::Label::create(Func, this); |
4387 SrcT = legalize(SrcT, Legal_Reg | Legal_Imm); | 4381 SrcT = legalize(SrcT, Legal_Reg | Legal_Imm); |
4388 _mov(Dest, SrcT); | 4382 _mov(Dest, SrcT); |
4389 _br(Cond, Label); | 4383 _br(Cond, Label); |
4390 SrcF = legalize(SrcF, Legal_Reg | Legal_Imm); | 4384 SrcF = legalize(SrcF, Legal_Reg | Legal_Imm); |
4391 _mov_nonkillable(Dest, SrcF); | 4385 _mov_redefined(Dest, SrcF); |
4392 Context.insert(Label); | 4386 Context.insert(Label); |
4393 return; | 4387 return; |
4394 } | 4388 } |
4395 // mov t, SrcF; cmov_cond t, SrcT; mov dest, t | 4389 // mov t, SrcF; cmov_cond t, SrcT; mov dest, t |
4396 // But if SrcT is immediate, we might be able to do better, as the cmov | 4390 // But if SrcT is immediate, we might be able to do better, as the cmov |
4397 // instruction doesn't allow an immediate operand: | 4391 // instruction doesn't allow an immediate operand: |
4398 // mov t, SrcT; cmov_!cond t, SrcF; mov dest, t | 4392 // mov t, SrcT; cmov_!cond t, SrcF; mov dest, t |
4399 if (llvm::isa<Constant>(SrcT) && !llvm::isa<Constant>(SrcF)) { | 4393 if (llvm::isa<Constant>(SrcT) && !llvm::isa<Constant>(SrcF)) { |
4400 std::swap(SrcT, SrcF); | 4394 std::swap(SrcT, SrcF); |
4401 Cond = InstX86Base<Machine>::getOppositeCondition(Cond); | 4395 Cond = InstX86Base<Machine>::getOppositeCondition(Cond); |
(...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5217 ++TyIndex; | 5211 ++TyIndex; |
5218 uint32_t MaxIndex = MaxSize == NoSizeLimit | 5212 uint32_t MaxIndex = MaxSize == NoSizeLimit |
5219 ? llvm::array_lengthof(TypeForSize) - 1 | 5213 ? llvm::array_lengthof(TypeForSize) - 1 |
5220 : llvm::findLastSet(MaxSize, llvm::ZB_Undefined); | 5214 : llvm::findLastSet(MaxSize, llvm::ZB_Undefined); |
5221 return TypeForSize[std::min(TyIndex, MaxIndex)]; | 5215 return TypeForSize[std::min(TyIndex, MaxIndex)]; |
5222 } | 5216 } |
5223 | 5217 |
5224 template <class Machine> void TargetX86Base<Machine>::postLower() { | 5218 template <class Machine> void TargetX86Base<Machine>::postLower() { |
5225 if (Ctx->getFlags().getOptLevel() == Opt_m1) | 5219 if (Ctx->getFlags().getOptLevel() == Opt_m1) |
5226 return; | 5220 return; |
5227 inferTwoAddress(); | 5221 markRedefinitions(); |
5228 } | 5222 } |
5229 | 5223 |
5230 template <class Machine> | 5224 template <class Machine> |
5231 void TargetX86Base<Machine>::makeRandomRegisterPermutation( | 5225 void TargetX86Base<Machine>::makeRandomRegisterPermutation( |
5232 llvm::SmallVectorImpl<int32_t> &Permutation, | 5226 llvm::SmallVectorImpl<int32_t> &Permutation, |
5233 const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const { | 5227 const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const { |
5234 Traits::makeRandomRegisterPermutation(Ctx, Func, Permutation, | 5228 Traits::makeRandomRegisterPermutation(Ctx, Func, Permutation, |
5235 ExcludeRegisters, Salt); | 5229 ExcludeRegisters, Salt); |
5236 } | 5230 } |
5237 | 5231 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5304 // chain. So we add RegNum argument here. Note we use 'lea' instruction | 5298 // chain. So we add RegNum argument here. Note we use 'lea' instruction |
5305 // instead of 'xor' to avoid affecting the flags. | 5299 // instead of 'xor' to avoid affecting the flags. |
5306 Variable *Reg = makeReg(IceType_i32, RegNum); | 5300 Variable *Reg = makeReg(IceType_i32, RegNum); |
5307 ConstantInteger32 *Integer = llvm::cast<ConstantInteger32>(Immediate); | 5301 ConstantInteger32 *Integer = llvm::cast<ConstantInteger32>(Immediate); |
5308 uint32_t Value = Integer->getValue(); | 5302 uint32_t Value = Integer->getValue(); |
5309 uint32_t Cookie = Func->getConstantBlindingCookie(); | 5303 uint32_t Cookie = Func->getConstantBlindingCookie(); |
5310 _mov(Reg, Ctx->getConstantInt(IceType_i32, Cookie + Value)); | 5304 _mov(Reg, Ctx->getConstantInt(IceType_i32, Cookie + Value)); |
5311 Constant *Offset = Ctx->getConstantInt(IceType_i32, 0 - Cookie); | 5305 Constant *Offset = Ctx->getConstantInt(IceType_i32, 0 - Cookie); |
5312 _lea(Reg, Traits::X86OperandMem::create(Func, IceType_i32, Reg, Offset, | 5306 _lea(Reg, Traits::X86OperandMem::create(Func, IceType_i32, Reg, Offset, |
5313 nullptr, 0)); | 5307 nullptr, 0)); |
5314 // make sure liveness analysis won't kill this variable, otherwise a | |
5315 // liveness assertion will be triggered. | |
5316 _set_dest_nonkillable(); | |
5317 if (Immediate->getType() != IceType_i32) { | 5308 if (Immediate->getType() != IceType_i32) { |
5318 Variable *TruncReg = makeReg(Immediate->getType(), RegNum); | 5309 Variable *TruncReg = makeReg(Immediate->getType(), RegNum); |
5319 _mov(TruncReg, Reg); | 5310 _mov(TruncReg, Reg); |
5320 return TruncReg; | 5311 return TruncReg; |
5321 } | 5312 } |
5322 return Reg; | 5313 return Reg; |
5323 } | 5314 } |
5324 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool) { | 5315 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_Pool) { |
5325 // pool the constant | 5316 // pool the constant |
5326 // FROM: | 5317 // FROM: |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5393 | 5384 |
5394 typename Traits::X86OperandMem *TempMemOperand = | 5385 typename Traits::X86OperandMem *TempMemOperand = |
5395 Traits::X86OperandMem::create(Func, MemOperand->getType(), | 5386 Traits::X86OperandMem::create(Func, MemOperand->getType(), |
5396 MemOperand->getBase(), Mask1); | 5387 MemOperand->getBase(), Mask1); |
5397 // If we have already assigned a physical register, we must come from | 5388 // If we have already assigned a physical register, we must come from |
5398 // advancedPhiLowering()=>lowerAssign(). In this case we should reuse | 5389 // advancedPhiLowering()=>lowerAssign(). In this case we should reuse |
5399 // the assigned register as this assignment is that start of its | 5390 // the assigned register as this assignment is that start of its |
5400 // use-def chain. So we add RegNum argument here. | 5391 // use-def chain. So we add RegNum argument here. |
5401 Variable *RegTemp = makeReg(MemOperand->getOffset()->getType(), RegNum); | 5392 Variable *RegTemp = makeReg(MemOperand->getOffset()->getType(), RegNum); |
5402 _lea(RegTemp, TempMemOperand); | 5393 _lea(RegTemp, TempMemOperand); |
5403 // As source operand doesn't use the dstreg, we don't need to add | |
5404 // _set_dest_nonkillable(). But if we use the same Dest Reg, that is, | |
5405 // with RegNum assigned, we should add this _set_dest_nonkillable() | |
5406 if (RegNum != Variable::NoRegister) | |
5407 _set_dest_nonkillable(); | |
5408 | 5394 |
5409 typename Traits::X86OperandMem *NewMemOperand = | 5395 typename Traits::X86OperandMem *NewMemOperand = |
5410 Traits::X86OperandMem::create(Func, MemOperand->getType(), RegTemp, | 5396 Traits::X86OperandMem::create(Func, MemOperand->getType(), RegTemp, |
5411 Mask2, MemOperand->getIndex(), | 5397 Mask2, MemOperand->getIndex(), |
5412 MemOperand->getShift(), | 5398 MemOperand->getShift(), |
5413 MemOperand->getSegmentRegister()); | 5399 MemOperand->getSegmentRegister()); |
5414 | 5400 |
5415 // Label this memory operand as randomized, so we won't randomize it | 5401 // Label this memory operand as randomized, so we won't randomize it |
5416 // again in case we call legalize() multiple times on this memory | 5402 // again in case we call legalize() multiple times on this memory |
5417 // operand. | 5403 // operand. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5450 _mov(RegTemp, SymbolOperand); | 5436 _mov(RegTemp, SymbolOperand); |
5451 // If we have a base variable here, we should add the lea instruction | 5437 // If we have a base variable here, we should add the lea instruction |
5452 // to add the value of the base variable to RegTemp. If there is no | 5438 // to add the value of the base variable to RegTemp. If there is no |
5453 // base variable, we won't need this lea instruction. | 5439 // base variable, we won't need this lea instruction. |
5454 if (MemOperand->getBase()) { | 5440 if (MemOperand->getBase()) { |
5455 typename Traits::X86OperandMem *CalculateOperand = | 5441 typename Traits::X86OperandMem *CalculateOperand = |
5456 Traits::X86OperandMem::create( | 5442 Traits::X86OperandMem::create( |
5457 Func, MemOperand->getType(), MemOperand->getBase(), nullptr, | 5443 Func, MemOperand->getType(), MemOperand->getBase(), nullptr, |
5458 RegTemp, 0, MemOperand->getSegmentRegister()); | 5444 RegTemp, 0, MemOperand->getSegmentRegister()); |
5459 _lea(RegTemp, CalculateOperand); | 5445 _lea(RegTemp, CalculateOperand); |
5460 _set_dest_nonkillable(); | |
5461 } | 5446 } |
5462 typename Traits::X86OperandMem *NewMemOperand = | 5447 typename Traits::X86OperandMem *NewMemOperand = |
5463 Traits::X86OperandMem::create(Func, MemOperand->getType(), RegTemp, | 5448 Traits::X86OperandMem::create(Func, MemOperand->getType(), RegTemp, |
5464 nullptr, MemOperand->getIndex(), | 5449 nullptr, MemOperand->getIndex(), |
5465 MemOperand->getShift(), | 5450 MemOperand->getShift(), |
5466 MemOperand->getSegmentRegister()); | 5451 MemOperand->getSegmentRegister()); |
5467 return NewMemOperand; | 5452 return NewMemOperand; |
5468 } | 5453 } |
5469 assert("Unsupported -randomize-pool-immediates option" && false); | 5454 assert("Unsupported -randomize-pool-immediates option" && false); |
5470 } | 5455 } |
5471 } | 5456 } |
5472 // the offset is not eligible for blinding or pooling, return the original | 5457 // the offset is not eligible for blinding or pooling, return the original |
5473 // mem operand | 5458 // mem operand |
5474 return MemOperand; | 5459 return MemOperand; |
5475 } | 5460 } |
5476 | 5461 |
5477 } // end of namespace X86Internal | 5462 } // end of namespace X86Internal |
5478 } // end of namespace Ice | 5463 } // end of namespace Ice |
5479 | 5464 |
5480 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H | 5465 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H |
OLD | NEW |