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 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 } | 260 } |
261 | 261 |
262 template <class Machine> | 262 template <class Machine> |
263 void TargetX86Base<Machine>::initNodeForLowering(CfgNode *Node) { | 263 void TargetX86Base<Machine>::initNodeForLowering(CfgNode *Node) { |
264 FoldingInfo.init(Node); | 264 FoldingInfo.init(Node); |
265 FoldingInfo.dump(Func); | 265 FoldingInfo.dump(Func); |
266 } | 266 } |
267 | 267 |
268 template <class Machine> | 268 template <class Machine> |
269 TargetX86Base<Machine>::TargetX86Base(Cfg *Func) | 269 TargetX86Base<Machine>::TargetX86Base(Cfg *Func) |
270 : Machine(Func) { | 270 : TargetLowering(Func) { |
271 static_assert( | 271 static_assert( |
272 (Traits::InstructionSet::End - Traits::InstructionSet::Begin) == | 272 (Traits::InstructionSet::End - Traits::InstructionSet::Begin) == |
273 (TargetInstructionSet::X86InstructionSet_End - | 273 (TargetInstructionSet::X86InstructionSet_End - |
274 TargetInstructionSet::X86InstructionSet_Begin), | 274 TargetInstructionSet::X86InstructionSet_Begin), |
275 "Traits::InstructionSet range different from TargetInstructionSet"); | 275 "Traits::InstructionSet range different from TargetInstructionSet"); |
276 if (Func->getContext()->getFlags().getTargetInstructionSet() != | 276 if (Func->getContext()->getFlags().getTargetInstructionSet() != |
277 TargetInstructionSet::BaseInstructionSet) { | 277 TargetInstructionSet::BaseInstructionSet) { |
278 InstructionSet = static_cast<typename Traits::InstructionSet>( | 278 InstructionSet = static_cast<typename Traits::InstructionSet>( |
279 (Func->getContext()->getFlags().getTargetInstructionSet() - | 279 (Func->getContext()->getFlags().getTargetInstructionSet() - |
280 TargetInstructionSet::X86InstructionSet_Begin) + | 280 TargetInstructionSet::X86InstructionSet_Begin) + |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 if (Func->hasError()) | 448 if (Func->hasError()) |
449 return; | 449 return; |
450 Func->dump("After stack frame mapping"); | 450 Func->dump("After stack frame mapping"); |
451 | 451 |
452 // Nop insertion | 452 // Nop insertion |
453 if (Ctx->getFlags().shouldDoNopInsertion()) { | 453 if (Ctx->getFlags().shouldDoNopInsertion()) { |
454 Func->doNopInsertion(); | 454 Func->doNopInsertion(); |
455 } | 455 } |
456 } | 456 } |
457 | 457 |
458 bool canRMW(const InstArithmetic *Arith) { | 458 inline bool canRMW(const InstArithmetic *Arith) { |
459 Type Ty = Arith->getDest()->getType(); | 459 Type Ty = Arith->getDest()->getType(); |
460 // X86 vector instructions write to a register and have no RMW option. | 460 // X86 vector instructions write to a register and have no RMW option. |
461 if (isVectorType(Ty)) | 461 if (isVectorType(Ty)) |
462 return false; | 462 return false; |
463 bool isI64 = Ty == IceType_i64; | 463 bool isI64 = Ty == IceType_i64; |
464 | 464 |
465 switch (Arith->getOp()) { | 465 switch (Arith->getOp()) { |
466 // Not handled for lack of simple lowering: | 466 // Not handled for lack of simple lowering: |
467 // shift on i64 | 467 // shift on i64 |
468 // mul, udiv, urem, sdiv, srem, frem | 468 // mul, udiv, urem, sdiv, srem, frem |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 continue; | 572 continue; |
573 if (Func->isVerbose(IceV_RMW)) { | 573 if (Func->isVerbose(IceV_RMW)) { |
574 Str << "Found RMW in " << Func->getFunctionName() << ":\n "; | 574 Str << "Found RMW in " << Func->getFunctionName() << ":\n "; |
575 Load->dump(Func); | 575 Load->dump(Func); |
576 Str << "\n "; | 576 Str << "\n "; |
577 Arith->dump(Func); | 577 Arith->dump(Func); |
578 Str << "\n "; | 578 Str << "\n "; |
579 Store->dump(Func); | 579 Store->dump(Func); |
580 Str << "\n"; | 580 Str << "\n"; |
581 } | 581 } |
582 Variable *Beacon = Func->template makeVariable(IceType_i32); | 582 Variable *Beacon = Func->makeVariable(IceType_i32); |
583 Beacon->setWeight(0); | 583 Beacon->setWeight(0); |
584 Store->setRmwBeacon(Beacon); | 584 Store->setRmwBeacon(Beacon); |
585 InstFakeDef *BeaconDef = InstFakeDef::create(Func, Beacon); | 585 InstFakeDef *BeaconDef = InstFakeDef::create(Func, Beacon); |
586 Node->getInsts().insert(I3, BeaconDef); | 586 Node->getInsts().insert(I3, BeaconDef); |
587 auto *RMW = Traits::Insts::FakeRMW::create( | 587 auto *RMW = Traits::Insts::FakeRMW::create( |
588 Func, ArithSrcOther, Store->getAddr(), Beacon, Arith->getOp()); | 588 Func, ArithSrcOther, Store->getAddr(), Beacon, Arith->getOp()); |
589 Node->getInsts().insert(I3, RMW); | 589 Node->getInsts().insert(I3, RMW); |
590 } | 590 } |
591 } | 591 } |
592 } | 592 } |
593 } | 593 } |
594 } | 594 } |
595 } | 595 } |
596 | 596 |
597 // Converts a ConstantInteger32 operand into its constant value, or | 597 // Converts a ConstantInteger32 operand into its constant value, or |
598 // MemoryOrderInvalid if the operand is not a ConstantInteger32. | 598 // MemoryOrderInvalid if the operand is not a ConstantInteger32. |
599 uint64_t getConstantMemoryOrder(Operand *Opnd) { | 599 inline uint64_t getConstantMemoryOrder(Operand *Opnd) { |
600 if (auto Integer = llvm::dyn_cast<ConstantInteger32>(Opnd)) | 600 if (auto Integer = llvm::dyn_cast<ConstantInteger32>(Opnd)) |
601 return Integer->getValue(); | 601 return Integer->getValue(); |
602 return Intrinsics::MemoryOrderInvalid; | 602 return Intrinsics::MemoryOrderInvalid; |
603 } | 603 } |
604 | 604 |
605 /// Determines whether the dest of a Load instruction can be folded | 605 /// Determines whether the dest of a Load instruction can be folded |
606 /// into one of the src operands of a 2-operand instruction. This is | 606 /// into one of the src operands of a 2-operand instruction. This is |
607 /// true as long as the load dest matches exactly one of the binary | 607 /// true as long as the load dest matches exactly one of the binary |
608 /// instruction's src operands. Replaces Src0 or Src1 with LoadSrc if | 608 /// instruction's src operands. Replaces Src0 or Src1 with LoadSrc if |
609 /// the answer is true. | 609 /// the answer is true. |
610 bool canFoldLoadIntoBinaryInst(Operand *LoadSrc, Variable *LoadDest, | 610 inline bool canFoldLoadIntoBinaryInst(Operand *LoadSrc, Variable *LoadDest, |
611 Operand *&Src0, Operand *&Src1) { | 611 Operand *&Src0, Operand *&Src1) { |
612 if (Src0 == LoadDest && Src1 != LoadDest) { | 612 if (Src0 == LoadDest && Src1 != LoadDest) { |
613 Src0 = LoadSrc; | 613 Src0 = LoadSrc; |
614 return true; | 614 return true; |
615 } | 615 } |
616 if (Src0 != LoadDest && Src1 == LoadDest) { | 616 if (Src0 != LoadDest && Src1 == LoadDest) { |
617 Src1 = LoadSrc; | 617 Src1 = LoadSrc; |
618 return true; | 618 return true; |
619 } | 619 } |
620 return false; | 620 return false; |
621 } | 621 } |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
720 | 720 |
721 template <class Machine> | 721 template <class Machine> |
722 Variable *TargetX86Base<Machine>::getPhysicalRegister(SizeT RegNum, Type Ty) { | 722 Variable *TargetX86Base<Machine>::getPhysicalRegister(SizeT RegNum, Type Ty) { |
723 if (Ty == IceType_void) | 723 if (Ty == IceType_void) |
724 Ty = IceType_i32; | 724 Ty = IceType_i32; |
725 if (PhysicalRegisters[Ty].empty()) | 725 if (PhysicalRegisters[Ty].empty()) |
726 PhysicalRegisters[Ty].resize(Traits::RegisterSet::Reg_NUM); | 726 PhysicalRegisters[Ty].resize(Traits::RegisterSet::Reg_NUM); |
727 assert(RegNum < PhysicalRegisters[Ty].size()); | 727 assert(RegNum < PhysicalRegisters[Ty].size()); |
728 Variable *Reg = PhysicalRegisters[Ty][RegNum]; | 728 Variable *Reg = PhysicalRegisters[Ty][RegNum]; |
729 if (Reg == nullptr) { | 729 if (Reg == nullptr) { |
730 Reg = Func->template makeVariable(Ty); | 730 Reg = Func->makeVariable(Ty); |
731 Reg->setRegNum(RegNum); | 731 Reg->setRegNum(RegNum); |
732 PhysicalRegisters[Ty][RegNum] = Reg; | 732 PhysicalRegisters[Ty][RegNum] = Reg; |
733 // Specially mark esp as an "argument" so that it is considered | 733 // Specially mark esp as an "argument" so that it is considered |
734 // live upon function entry. | 734 // live upon function entry. |
735 if (RegNum == Traits::RegisterSet::Reg_esp) { | 735 if (RegNum == Traits::RegisterSet::Reg_esp) { |
736 Func->addImplicitArg(Reg); | 736 Func->addImplicitArg(Reg); |
737 Reg->setIgnoreLiveness(); | 737 Reg->setIgnoreLiveness(); |
738 } | 738 } |
739 } | 739 } |
740 return Reg; | 740 return Reg; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
793 I < E && NumXmmArgs < Traits::X86_MAX_XMM_ARGS; ++I) { | 793 I < E && NumXmmArgs < Traits::X86_MAX_XMM_ARGS; ++I) { |
794 Variable *Arg = Args[I]; | 794 Variable *Arg = Args[I]; |
795 Type Ty = Arg->getType(); | 795 Type Ty = Arg->getType(); |
796 if (!isVectorType(Ty)) | 796 if (!isVectorType(Ty)) |
797 continue; | 797 continue; |
798 // Replace Arg in the argument list with the home register. Then | 798 // Replace Arg in the argument list with the home register. Then |
799 // generate an instruction in the prolog to copy the home register | 799 // generate an instruction in the prolog to copy the home register |
800 // to the assigned location of Arg. | 800 // to the assigned location of Arg. |
801 int32_t RegNum = Traits::RegisterSet::Reg_xmm0 + NumXmmArgs; | 801 int32_t RegNum = Traits::RegisterSet::Reg_xmm0 + NumXmmArgs; |
802 ++NumXmmArgs; | 802 ++NumXmmArgs; |
803 Variable *RegisterArg = Func->template makeVariable(Ty); | 803 Variable *RegisterArg = Func->makeVariable(Ty); |
804 if (BuildDefs::dump()) | 804 if (BuildDefs::dump()) |
805 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | 805 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
806 RegisterArg->setRegNum(RegNum); | 806 RegisterArg->setRegNum(RegNum); |
807 RegisterArg->setIsArg(); | 807 RegisterArg->setIsArg(); |
808 Arg->setIsArg(false); | 808 Arg->setIsArg(false); |
809 | 809 |
810 Args[I] = RegisterArg; | 810 Args[I] = RegisterArg; |
811 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | 811 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); |
812 } | 812 } |
813 } | 813 } |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1108 | 1108 |
1109 if (!Ctx->getFlags().getUseSandboxing()) | 1109 if (!Ctx->getFlags().getUseSandboxing()) |
1110 return; | 1110 return; |
1111 // Change the original ret instruction into a sandboxed return sequence. | 1111 // Change the original ret instruction into a sandboxed return sequence. |
1112 // t:ecx = pop | 1112 // t:ecx = pop |
1113 // bundle_lock | 1113 // bundle_lock |
1114 // and t, ~31 | 1114 // and t, ~31 |
1115 // jmp *t | 1115 // jmp *t |
1116 // bundle_unlock | 1116 // bundle_unlock |
1117 // FakeUse <original_ret_operand> | 1117 // FakeUse <original_ret_operand> |
1118 const SizeT BundleSize = | 1118 const SizeT BundleSize = 1 |
1119 1 << Func->template getAssembler<>()->getBundleAlignLog2Bytes(); | 1119 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); |
1120 Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx); | 1120 Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx); |
1121 _pop(T_ecx); | 1121 _pop(T_ecx); |
1122 _bundle_lock(); | 1122 _bundle_lock(); |
1123 _and(T_ecx, Ctx->getConstantInt32(~(BundleSize - 1))); | 1123 _and(T_ecx, Ctx->getConstantInt32(~(BundleSize - 1))); |
1124 _jmp(T_ecx); | 1124 _jmp(T_ecx); |
1125 _bundle_unlock(); | 1125 _bundle_unlock(); |
1126 if (RI->getSrcSize()) { | 1126 if (RI->getSrcSize()) { |
1127 Variable *RetValue = llvm::cast<Variable>(RI->getSrc(0)); | 1127 Variable *RetValue = llvm::cast<Variable>(RI->getSrc(0)); |
1128 Context.insert(InstFakeUse::create(Func, RetValue)); | 1128 Context.insert(InstFakeUse::create(Func, RetValue)); |
1129 } | 1129 } |
(...skipping 11 matching lines...) Expand all Loading... |
1141 case IceType_f64: | 1141 case IceType_f64: |
1142 break; | 1142 break; |
1143 } | 1143 } |
1144 Variable *Lo = Var->getLo(); | 1144 Variable *Lo = Var->getLo(); |
1145 Variable *Hi = Var->getHi(); | 1145 Variable *Hi = Var->getHi(); |
1146 if (Lo) { | 1146 if (Lo) { |
1147 assert(Hi); | 1147 assert(Hi); |
1148 return; | 1148 return; |
1149 } | 1149 } |
1150 assert(Hi == nullptr); | 1150 assert(Hi == nullptr); |
1151 Lo = Func->template makeVariable(IceType_i32); | 1151 Lo = Func->makeVariable(IceType_i32); |
1152 Hi = Func->template makeVariable(IceType_i32); | 1152 Hi = Func->makeVariable(IceType_i32); |
1153 if (BuildDefs::dump()) { | 1153 if (BuildDefs::dump()) { |
1154 Lo->setName(Func, Var->getName(Func) + "__lo"); | 1154 Lo->setName(Func, Var->getName(Func) + "__lo"); |
1155 Hi->setName(Func, Var->getName(Func) + "__hi"); | 1155 Hi->setName(Func, Var->getName(Func) + "__hi"); |
1156 } | 1156 } |
1157 Var->setLoHi(Lo, Hi); | 1157 Var->setLoHi(Lo, Hi); |
1158 if (Var->getIsArg()) { | 1158 if (Var->getIsArg()) { |
1159 Lo->setIsArg(); | 1159 Lo->setIsArg(); |
1160 Hi->setIsArg(); | 1160 Hi->setIsArg(); |
1161 } | 1161 } |
1162 } | 1162 } |
(...skipping 1071 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2234 Operand *CallTarget = legalize(Instr->getCallTarget()); | 2234 Operand *CallTarget = legalize(Instr->getCallTarget()); |
2235 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); | 2235 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); |
2236 if (NeedSandboxing) { | 2236 if (NeedSandboxing) { |
2237 if (llvm::isa<Constant>(CallTarget)) { | 2237 if (llvm::isa<Constant>(CallTarget)) { |
2238 _bundle_lock(InstBundleLock::Opt_AlignToEnd); | 2238 _bundle_lock(InstBundleLock::Opt_AlignToEnd); |
2239 } else { | 2239 } else { |
2240 Variable *CallTargetVar = nullptr; | 2240 Variable *CallTargetVar = nullptr; |
2241 _mov(CallTargetVar, CallTarget); | 2241 _mov(CallTargetVar, CallTarget); |
2242 _bundle_lock(InstBundleLock::Opt_AlignToEnd); | 2242 _bundle_lock(InstBundleLock::Opt_AlignToEnd); |
2243 const SizeT BundleSize = | 2243 const SizeT BundleSize = |
2244 1 << Func->template getAssembler<>()->getBundleAlignLog2Bytes(); | 2244 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); |
2245 _and(CallTargetVar, Ctx->getConstantInt32(~(BundleSize - 1))); | 2245 _and(CallTargetVar, Ctx->getConstantInt32(~(BundleSize - 1))); |
2246 CallTarget = CallTargetVar; | 2246 CallTarget = CallTargetVar; |
2247 } | 2247 } |
2248 } | 2248 } |
2249 Inst *NewCall = Traits::Insts::Call::create(Func, ReturnReg, CallTarget); | 2249 Inst *NewCall = Traits::Insts::Call::create(Func, ReturnReg, CallTarget); |
2250 Context.insert(NewCall); | 2250 Context.insert(NewCall); |
2251 if (NeedSandboxing) | 2251 if (NeedSandboxing) |
2252 _bundle_unlock(); | 2252 _bundle_unlock(); |
2253 if (ReturnRegHi) | 2253 if (ReturnRegHi) |
2254 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | 2254 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2663 assert((DestType == IceType_i32 && SrcType == IceType_f32) || | 2663 assert((DestType == IceType_i32 && SrcType == IceType_f32) || |
2664 (DestType == IceType_f32 && SrcType == IceType_i32)); | 2664 (DestType == IceType_f32 && SrcType == IceType_i32)); |
2665 // a.i32 = bitcast b.f32 ==> | 2665 // a.i32 = bitcast b.f32 ==> |
2666 // t.f32 = b.f32 | 2666 // t.f32 = b.f32 |
2667 // s.f32 = spill t.f32 | 2667 // s.f32 = spill t.f32 |
2668 // a.i32 = s.f32 | 2668 // a.i32 = s.f32 |
2669 Variable *T = nullptr; | 2669 Variable *T = nullptr; |
2670 // TODO: Should be able to force a spill setup by calling legalize() with | 2670 // TODO: Should be able to force a spill setup by calling legalize() with |
2671 // Legal_Mem and not Legal_Reg or Legal_Imm. | 2671 // Legal_Mem and not Legal_Reg or Legal_Imm. |
2672 typename Traits::SpillVariable *SpillVar = | 2672 typename Traits::SpillVariable *SpillVar = |
2673 Func->template makeVariable<typename Traits::SpillVariable>(SrcType); | 2673 Func->makeVariable<typename Traits::SpillVariable>(SrcType); |
2674 SpillVar->setLinkedTo(Dest); | 2674 SpillVar->setLinkedTo(Dest); |
2675 Variable *Spill = SpillVar; | 2675 Variable *Spill = SpillVar; |
2676 Spill->setWeight(RegWeight::Zero); | 2676 Spill->setWeight(RegWeight::Zero); |
2677 _mov(T, Src0RM); | 2677 _mov(T, Src0RM); |
2678 _mov(Spill, T); | 2678 _mov(Spill, T); |
2679 _mov(Dest, Spill); | 2679 _mov(Dest, Spill); |
2680 } break; | 2680 } break; |
2681 case IceType_i64: { | 2681 case IceType_i64: { |
2682 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); | 2682 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); |
2683 assert(Src0RM->getType() == IceType_f64); | 2683 assert(Src0RM->getType() == IceType_f64); |
2684 // a.i64 = bitcast b.f64 ==> | 2684 // a.i64 = bitcast b.f64 ==> |
2685 // s.f64 = spill b.f64 | 2685 // s.f64 = spill b.f64 |
2686 // t_lo.i32 = lo(s.f64) | 2686 // t_lo.i32 = lo(s.f64) |
2687 // a_lo.i32 = t_lo.i32 | 2687 // a_lo.i32 = t_lo.i32 |
2688 // t_hi.i32 = hi(s.f64) | 2688 // t_hi.i32 = hi(s.f64) |
2689 // a_hi.i32 = t_hi.i32 | 2689 // a_hi.i32 = t_hi.i32 |
2690 Operand *SpillLo, *SpillHi; | 2690 Operand *SpillLo, *SpillHi; |
2691 if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0RM)) { | 2691 if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0RM)) { |
2692 typename Traits::SpillVariable *SpillVar = | 2692 typename Traits::SpillVariable *SpillVar = |
2693 Func->template makeVariable<typename Traits::SpillVariable>( | 2693 Func->makeVariable<typename Traits::SpillVariable>(IceType_f64); |
2694 IceType_f64); | |
2695 SpillVar->setLinkedTo(Src0Var); | 2694 SpillVar->setLinkedTo(Src0Var); |
2696 Variable *Spill = SpillVar; | 2695 Variable *Spill = SpillVar; |
2697 Spill->setWeight(RegWeight::Zero); | 2696 Spill->setWeight(RegWeight::Zero); |
2698 _movq(Spill, Src0RM); | 2697 _movq(Spill, Src0RM); |
2699 SpillLo = Traits::VariableSplit::create(Func, Spill, | 2698 SpillLo = Traits::VariableSplit::create(Func, Spill, |
2700 Traits::VariableSplit::Low); | 2699 Traits::VariableSplit::Low); |
2701 SpillHi = Traits::VariableSplit::create(Func, Spill, | 2700 SpillHi = Traits::VariableSplit::create(Func, Spill, |
2702 Traits::VariableSplit::High); | 2701 Traits::VariableSplit::High); |
2703 } else { | 2702 } else { |
2704 SpillLo = loOperand(Src0RM); | 2703 SpillLo = loOperand(Src0RM); |
2705 SpillHi = hiOperand(Src0RM); | 2704 SpillHi = hiOperand(Src0RM); |
2706 } | 2705 } |
2707 | 2706 |
2708 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2707 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
2709 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2708 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
2710 Variable *T_Lo = makeReg(IceType_i32); | 2709 Variable *T_Lo = makeReg(IceType_i32); |
2711 Variable *T_Hi = makeReg(IceType_i32); | 2710 Variable *T_Hi = makeReg(IceType_i32); |
2712 | 2711 |
2713 _mov(T_Lo, SpillLo); | 2712 _mov(T_Lo, SpillLo); |
2714 _mov(DestLo, T_Lo); | 2713 _mov(DestLo, T_Lo); |
2715 _mov(T_Hi, SpillHi); | 2714 _mov(T_Hi, SpillHi); |
2716 _mov(DestHi, T_Hi); | 2715 _mov(DestHi, T_Hi); |
2717 } break; | 2716 } break; |
2718 case IceType_f64: { | 2717 case IceType_f64: { |
2719 Src0 = legalize(Src0); | 2718 Src0 = legalize(Src0); |
2720 assert(Src0->getType() == IceType_i64); | 2719 assert(Src0->getType() == IceType_i64); |
2721 if (llvm::isa<typename Traits::X86OperandMem>(Src0)) { | 2720 if (llvm::isa<typename Traits::X86OperandMem>(Src0)) { |
2722 Variable *T = Func->template makeVariable(Dest->getType()); | 2721 Variable *T = Func->makeVariable(Dest->getType()); |
2723 _movq(T, Src0); | 2722 _movq(T, Src0); |
2724 _movq(Dest, T); | 2723 _movq(Dest, T); |
2725 break; | 2724 break; |
2726 } | 2725 } |
2727 // a.f64 = bitcast b.i64 ==> | 2726 // a.f64 = bitcast b.i64 ==> |
2728 // t_lo.i32 = b_lo.i32 | 2727 // t_lo.i32 = b_lo.i32 |
2729 // FakeDef(s.f64) | 2728 // FakeDef(s.f64) |
2730 // lo(s.f64) = t_lo.i32 | 2729 // lo(s.f64) = t_lo.i32 |
2731 // t_hi.i32 = b_hi.i32 | 2730 // t_hi.i32 = b_hi.i32 |
2732 // hi(s.f64) = t_hi.i32 | 2731 // hi(s.f64) = t_hi.i32 |
2733 // a.f64 = s.f64 | 2732 // a.f64 = s.f64 |
2734 typename Traits::SpillVariable *SpillVar = | 2733 typename Traits::SpillVariable *SpillVar = |
2735 Func->template makeVariable<typename Traits::SpillVariable>( | 2734 Func->makeVariable<typename Traits::SpillVariable>(IceType_f64); |
2736 IceType_f64); | |
2737 SpillVar->setLinkedTo(Dest); | 2735 SpillVar->setLinkedTo(Dest); |
2738 Variable *Spill = SpillVar; | 2736 Variable *Spill = SpillVar; |
2739 Spill->setWeight(RegWeight::Zero); | 2737 Spill->setWeight(RegWeight::Zero); |
2740 | 2738 |
2741 Variable *T_Lo = nullptr, *T_Hi = nullptr; | 2739 Variable *T_Lo = nullptr, *T_Hi = nullptr; |
2742 typename Traits::VariableSplit *SpillLo = Traits::VariableSplit::create( | 2740 typename Traits::VariableSplit *SpillLo = Traits::VariableSplit::create( |
2743 Func, Spill, Traits::VariableSplit::Low); | 2741 Func, Spill, Traits::VariableSplit::Low); |
2744 typename Traits::VariableSplit *SpillHi = Traits::VariableSplit::create( | 2742 typename Traits::VariableSplit *SpillHi = Traits::VariableSplit::create( |
2745 Func, Spill, Traits::VariableSplit::High); | 2743 Func, Spill, Traits::VariableSplit::High); |
2746 _mov(T_Lo, loOperand(Src0)); | 2744 _mov(T_Lo, loOperand(Src0)); |
2747 // Technically, the Spill is defined after the _store happens, but | 2745 // Technically, the Spill is defined after the _store happens, but |
2748 // SpillLo is considered a "use" of Spill so define Spill before it | 2746 // SpillLo is considered a "use" of Spill so define Spill before it |
2749 // is used. | 2747 // is used. |
2750 Context.insert(InstFakeDef::create(Func, Spill)); | 2748 Context.insert(InstFakeDef::create(Func, Spill)); |
2751 _store(T_Lo, SpillLo); | 2749 _store(T_Lo, SpillLo); |
2752 _mov(T_Hi, hiOperand(Src0)); | 2750 _mov(T_Hi, hiOperand(Src0)); |
2753 _store(T_Hi, SpillHi); | 2751 _store(T_Hi, SpillHi); |
2754 _movq(Dest, Spill); | 2752 _movq(Dest, Spill); |
2755 } break; | 2753 } break; |
2756 case IceType_v8i1: { | 2754 case IceType_v8i1: { |
2757 assert(Src0->getType() == IceType_i8); | 2755 assert(Src0->getType() == IceType_i8); |
2758 InstCall *Call = makeHelperCall(H_bitcast_i8_8xi1, Dest, 1); | 2756 InstCall *Call = makeHelperCall(H_bitcast_i8_8xi1, Dest, 1); |
2759 Variable *Src0AsI32 = Func->template makeVariable(stackSlotType()); | 2757 Variable *Src0AsI32 = Func->makeVariable(stackSlotType()); |
2760 // Arguments to functions are required to be at least 32 bits wide. | 2758 // Arguments to functions are required to be at least 32 bits wide. |
2761 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); | 2759 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); |
2762 Call->addArg(Src0AsI32); | 2760 Call->addArg(Src0AsI32); |
2763 lowerCall(Call); | 2761 lowerCall(Call); |
2764 } break; | 2762 } break; |
2765 case IceType_v16i1: { | 2763 case IceType_v16i1: { |
2766 assert(Src0->getType() == IceType_i16); | 2764 assert(Src0->getType() == IceType_i16); |
2767 InstCall *Call = makeHelperCall(H_bitcast_i16_16xi1, Dest, 1); | 2765 InstCall *Call = makeHelperCall(H_bitcast_i16_16xi1, Dest, 1); |
2768 Variable *Src0AsI32 = Func->template makeVariable(stackSlotType()); | 2766 Variable *Src0AsI32 = Func->makeVariable(stackSlotType()); |
2769 // Arguments to functions are required to be at least 32 bits wide. | 2767 // Arguments to functions are required to be at least 32 bits wide. |
2770 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); | 2768 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); |
2771 Call->addArg(Src0AsI32); | 2769 Call->addArg(Src0AsI32); |
2772 lowerCall(Call); | 2770 lowerCall(Call); |
2773 } break; | 2771 } break; |
2774 case IceType_v8i16: | 2772 case IceType_v8i16: |
2775 case IceType_v16i8: | 2773 case IceType_v16i8: |
2776 case IceType_v4i32: | 2774 case IceType_v4i32: |
2777 case IceType_v4f32: { | 2775 case IceType_v4f32: { |
2778 _movp(Dest, legalizeToReg(Src0)); | 2776 _movp(Dest, legalizeToReg(Src0)); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2829 // keep the live range analysis consistent. | 2827 // keep the live range analysis consistent. |
2830 Context.insert(InstFakeDef::create(Func, ExtractedElementR)); | 2828 Context.insert(InstFakeDef::create(Func, ExtractedElementR)); |
2831 _movss(ExtractedElementR, T); | 2829 _movss(ExtractedElementR, T); |
2832 } | 2830 } |
2833 } else { | 2831 } else { |
2834 assert(Ty == IceType_v16i8 || Ty == IceType_v16i1); | 2832 assert(Ty == IceType_v16i8 || Ty == IceType_v16i1); |
2835 // Spill the value to a stack slot and do the extraction in memory. | 2833 // Spill the value to a stack slot and do the extraction in memory. |
2836 // | 2834 // |
2837 // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when | 2835 // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when |
2838 // support for legalizing to mem is implemented. | 2836 // support for legalizing to mem is implemented. |
2839 Variable *Slot = Func->template makeVariable(Ty); | 2837 Variable *Slot = Func->makeVariable(Ty); |
2840 Slot->setWeight(RegWeight::Zero); | 2838 Slot->setWeight(RegWeight::Zero); |
2841 _movp(Slot, legalizeToReg(SourceVectNotLegalized)); | 2839 _movp(Slot, legalizeToReg(SourceVectNotLegalized)); |
2842 | 2840 |
2843 // Compute the location of the element in memory. | 2841 // Compute the location of the element in memory. |
2844 unsigned Offset = Index * typeWidthInBytes(InVectorElementTy); | 2842 unsigned Offset = Index * typeWidthInBytes(InVectorElementTy); |
2845 typename Traits::X86OperandMem *Loc = | 2843 typename Traits::X86OperandMem *Loc = |
2846 getMemoryOperandForStackSlot(InVectorElementTy, Slot, Offset); | 2844 getMemoryOperandForStackSlot(InVectorElementTy, Slot, Offset); |
2847 _mov(ExtractedElementR, Loc); | 2845 _mov(ExtractedElementR, Loc); |
2848 } | 2846 } |
2849 | 2847 |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2994 case IceType_v4i1: | 2992 case IceType_v4i1: |
2995 NewTy = IceType_v4i32; | 2993 NewTy = IceType_v4i32; |
2996 break; | 2994 break; |
2997 case IceType_v8i1: | 2995 case IceType_v8i1: |
2998 NewTy = IceType_v8i16; | 2996 NewTy = IceType_v8i16; |
2999 break; | 2997 break; |
3000 case IceType_v16i1: | 2998 case IceType_v16i1: |
3001 NewTy = IceType_v16i8; | 2999 NewTy = IceType_v16i8; |
3002 break; | 3000 break; |
3003 } | 3001 } |
3004 Variable *NewSrc0 = Func->template makeVariable(NewTy); | 3002 Variable *NewSrc0 = Func->makeVariable(NewTy); |
3005 Variable *NewSrc1 = Func->template makeVariable(NewTy); | 3003 Variable *NewSrc1 = Func->makeVariable(NewTy); |
3006 lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc0, Src0)); | 3004 lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc0, Src0)); |
3007 lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc1, Src1)); | 3005 lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc1, Src1)); |
3008 Src0 = NewSrc0; | 3006 Src0 = NewSrc0; |
3009 Src1 = NewSrc1; | 3007 Src1 = NewSrc1; |
3010 Ty = NewTy; | 3008 Ty = NewTy; |
3011 } | 3009 } |
3012 | 3010 |
3013 InstIcmp::ICond Condition = Inst->getCondition(); | 3011 InstIcmp::ICond Condition = Inst->getCondition(); |
3014 | 3012 |
3015 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); | 3013 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3137 unsigned Index = ElementIndex->getValue(); | 3135 unsigned Index = ElementIndex->getValue(); |
3138 assert(Index < typeNumElements(SourceVectNotLegalized->getType())); | 3136 assert(Index < typeNumElements(SourceVectNotLegalized->getType())); |
3139 | 3137 |
3140 Type Ty = SourceVectNotLegalized->getType(); | 3138 Type Ty = SourceVectNotLegalized->getType(); |
3141 Type ElementTy = typeElementType(Ty); | 3139 Type ElementTy = typeElementType(Ty); |
3142 Type InVectorElementTy = Traits::getInVectorElementType(Ty); | 3140 Type InVectorElementTy = Traits::getInVectorElementType(Ty); |
3143 | 3141 |
3144 if (ElementTy == IceType_i1) { | 3142 if (ElementTy == IceType_i1) { |
3145 // Expand the element to the appropriate size for it to be inserted | 3143 // Expand the element to the appropriate size for it to be inserted |
3146 // in the vector. | 3144 // in the vector. |
3147 Variable *Expanded = Func->template makeVariable(InVectorElementTy); | 3145 Variable *Expanded = Func->makeVariable(InVectorElementTy); |
3148 InstCast *Cast = InstCast::create(Func, InstCast::Zext, Expanded, | 3146 InstCast *Cast = InstCast::create(Func, InstCast::Zext, Expanded, |
3149 ElementToInsertNotLegalized); | 3147 ElementToInsertNotLegalized); |
3150 lowerCast(Cast); | 3148 lowerCast(Cast); |
3151 ElementToInsertNotLegalized = Expanded; | 3149 ElementToInsertNotLegalized = Expanded; |
3152 } | 3150 } |
3153 | 3151 |
3154 if (Ty == IceType_v8i16 || Ty == IceType_v8i1 || | 3152 if (Ty == IceType_v8i16 || Ty == IceType_v8i1 || |
3155 InstructionSet >= Traits::SSE4_1) { | 3153 InstructionSet >= Traits::SSE4_1) { |
3156 // Use insertps, pinsrb, pinsrw, or pinsrd. | 3154 // Use insertps, pinsrb, pinsrw, or pinsrd. |
3157 Operand *ElementRM = | 3155 Operand *ElementRM = |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3228 _shufps(T, ElementR, Mask2Constant); | 3226 _shufps(T, ElementR, Mask2Constant); |
3229 _movp(Inst->getDest(), T); | 3227 _movp(Inst->getDest(), T); |
3230 } | 3228 } |
3231 } else { | 3229 } else { |
3232 assert(Ty == IceType_v16i8 || Ty == IceType_v16i1); | 3230 assert(Ty == IceType_v16i8 || Ty == IceType_v16i1); |
3233 // Spill the value to a stack slot and perform the insertion in | 3231 // Spill the value to a stack slot and perform the insertion in |
3234 // memory. | 3232 // memory. |
3235 // | 3233 // |
3236 // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when | 3234 // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when |
3237 // support for legalizing to mem is implemented. | 3235 // support for legalizing to mem is implemented. |
3238 Variable *Slot = Func->template makeVariable(Ty); | 3236 Variable *Slot = Func->makeVariable(Ty); |
3239 Slot->setWeight(RegWeight::Zero); | 3237 Slot->setWeight(RegWeight::Zero); |
3240 _movp(Slot, legalizeToReg(SourceVectNotLegalized)); | 3238 _movp(Slot, legalizeToReg(SourceVectNotLegalized)); |
3241 | 3239 |
3242 // Compute the location of the position to insert in memory. | 3240 // Compute the location of the position to insert in memory. |
3243 unsigned Offset = Index * typeWidthInBytes(InVectorElementTy); | 3241 unsigned Offset = Index * typeWidthInBytes(InVectorElementTy); |
3244 typename Traits::X86OperandMem *Loc = | 3242 typename Traits::X86OperandMem *Loc = |
3245 getMemoryOperandForStackSlot(InVectorElementTy, Slot, Offset); | 3243 getMemoryOperandForStackSlot(InVectorElementTy, Slot, Offset); |
3246 _store(legalizeToReg(ElementToInsertNotLegalized), Loc); | 3244 _store(legalizeToReg(ElementToInsertNotLegalized), Loc); |
3247 | 3245 |
3248 Variable *T = makeReg(Ty); | 3246 Variable *T = makeReg(Ty); |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3521 Call->addArg(Instr->getArg(1)); | 3519 Call->addArg(Instr->getArg(1)); |
3522 Call->addArg(Instr->getArg(2)); | 3520 Call->addArg(Instr->getArg(2)); |
3523 lowerCall(Call); | 3521 lowerCall(Call); |
3524 return; | 3522 return; |
3525 } | 3523 } |
3526 case Intrinsics::Memset: { | 3524 case Intrinsics::Memset: { |
3527 // The value operand needs to be extended to a stack slot size because the | 3525 // The value operand needs to be extended to a stack slot size because the |
3528 // PNaCl ABI requires arguments to be at least 32 bits wide. | 3526 // PNaCl ABI requires arguments to be at least 32 bits wide. |
3529 Operand *ValOp = Instr->getArg(1); | 3527 Operand *ValOp = Instr->getArg(1); |
3530 assert(ValOp->getType() == IceType_i8); | 3528 assert(ValOp->getType() == IceType_i8); |
3531 Variable *ValExt = Func->template makeVariable(stackSlotType()); | 3529 Variable *ValExt = Func->makeVariable(stackSlotType()); |
3532 lowerCast(InstCast::create(Func, InstCast::Zext, ValExt, ValOp)); | 3530 lowerCast(InstCast::create(Func, InstCast::Zext, ValExt, ValOp)); |
3533 InstCall *Call = makeHelperCall(H_call_memset, nullptr, 3); | 3531 InstCall *Call = makeHelperCall(H_call_memset, nullptr, 3); |
3534 Call->addArg(Instr->getArg(0)); | 3532 Call->addArg(Instr->getArg(0)); |
3535 Call->addArg(ValExt); | 3533 Call->addArg(ValExt); |
3536 Call->addArg(Instr->getArg(2)); | 3534 Call->addArg(Instr->getArg(2)); |
3537 lowerCall(Call); | 3535 lowerCall(Call); |
3538 return; | 3536 return; |
3539 } | 3537 } |
3540 case Intrinsics::NaClReadTP: { | 3538 case Intrinsics::NaClReadTP: { |
3541 if (Ctx->getFlags().getUseSandboxing()) { | 3539 if (Ctx->getFlags().getUseSandboxing()) { |
3542 Constant *Zero = Ctx->getConstantZero(IceType_i32); | 3540 Operand *Src = dispatchToConcrete(&Machine::createNaClReadTPSrcOperand); |
3543 Operand *Src = Traits::X86OperandMem::create( | |
3544 Func, IceType_i32, nullptr, Zero, nullptr, 0, | |
3545 Traits::X86OperandMem::SegReg_GS); | |
3546 Variable *Dest = Instr->getDest(); | 3541 Variable *Dest = Instr->getDest(); |
3547 Variable *T = nullptr; | 3542 Variable *T = nullptr; |
3548 _mov(T, Src); | 3543 _mov(T, Src); |
3549 _mov(Dest, T); | 3544 _mov(Dest, T); |
3550 } else { | 3545 } else { |
3551 InstCall *Call = makeHelperCall(H_call_read_tp, Instr->getDest(), 0); | 3546 InstCall *Call = makeHelperCall(H_call_read_tp, Instr->getDest(), 0); |
3552 lowerCall(Call); | 3547 lowerCall(Call); |
3553 } | 3548 } |
3554 return; | 3549 return; |
3555 } | 3550 } |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3968 } else { | 3963 } else { |
3969 _bsr(T_Dest2, SecondVar); | 3964 _bsr(T_Dest2, SecondVar); |
3970 _xor(T_Dest2, ThirtyOne); | 3965 _xor(T_Dest2, ThirtyOne); |
3971 } | 3966 } |
3972 _test(SecondVar, SecondVar); | 3967 _test(SecondVar, SecondVar); |
3973 _cmov(T_Dest2, T_Dest, Traits::Cond::Br_e); | 3968 _cmov(T_Dest2, T_Dest, Traits::Cond::Br_e); |
3974 _mov(DestLo, T_Dest2); | 3969 _mov(DestLo, T_Dest2); |
3975 _mov(DestHi, Ctx->getConstantZero(IceType_i32)); | 3970 _mov(DestHi, Ctx->getConstantZero(IceType_i32)); |
3976 } | 3971 } |
3977 | 3972 |
3978 bool isAdd(const Inst *Inst) { | 3973 inline bool isAdd(const Inst *Inst) { |
3979 if (const InstArithmetic *Arith = | 3974 if (const InstArithmetic *Arith = |
3980 llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) { | 3975 llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) { |
3981 return (Arith->getOp() == InstArithmetic::Add); | 3976 return (Arith->getOp() == InstArithmetic::Add); |
3982 } | 3977 } |
3983 return false; | 3978 return false; |
3984 } | 3979 } |
3985 | 3980 |
3986 void dumpAddressOpt(const Cfg *Func, const Variable *Base, | 3981 inline void dumpAddressOpt(const Cfg *Func, const Variable *Base, |
3987 const Variable *Index, uint16_t Shift, int32_t Offset, | 3982 const Variable *Index, uint16_t Shift, |
3988 const Inst *Reason) { | 3983 int32_t Offset, const Inst *Reason) { |
3989 if (!BuildDefs::dump()) | 3984 if (!BuildDefs::dump()) |
3990 return; | 3985 return; |
3991 if (!Func->isVerbose(IceV_AddrOpt)) | 3986 if (!Func->isVerbose(IceV_AddrOpt)) |
3992 return; | 3987 return; |
3993 OstreamLocker L(Func->getContext()); | 3988 OstreamLocker L(Func->getContext()); |
3994 Ostream &Str = Func->getContext()->getStrDump(); | 3989 Ostream &Str = Func->getContext()->getStrDump(); |
3995 Str << "Instruction: "; | 3990 Str << "Instruction: "; |
3996 Reason->dumpDecorated(Func); | 3991 Reason->dumpDecorated(Func); |
3997 Str << " results in Base="; | 3992 Str << " results in Base="; |
3998 if (Base) | 3993 if (Base) |
3999 Base->dump(Func); | 3994 Base->dump(Func); |
4000 else | 3995 else |
4001 Str << "<null>"; | 3996 Str << "<null>"; |
4002 Str << ", Index="; | 3997 Str << ", Index="; |
4003 if (Index) | 3998 if (Index) |
4004 Index->dump(Func); | 3999 Index->dump(Func); |
4005 else | 4000 else |
4006 Str << "<null>"; | 4001 Str << "<null>"; |
4007 Str << ", Shift=" << Shift << ", Offset=" << Offset << "\n"; | 4002 Str << ", Shift=" << Shift << ", Offset=" << Offset << "\n"; |
4008 } | 4003 } |
4009 | 4004 |
4010 bool matchTransitiveAssign(const VariablesMetadata *VMetadata, Variable *&Var, | 4005 inline bool matchTransitiveAssign(const VariablesMetadata *VMetadata, |
4011 const Inst *&Reason) { | 4006 Variable *&Var, const Inst *&Reason) { |
4012 // Var originates from Var=SrcVar ==> | 4007 // Var originates from Var=SrcVar ==> |
4013 // set Var:=SrcVar | 4008 // set Var:=SrcVar |
4014 if (Var == nullptr) | 4009 if (Var == nullptr) |
4015 return false; | 4010 return false; |
4016 if (const Inst *VarAssign = VMetadata->getSingleDefinition(Var)) { | 4011 if (const Inst *VarAssign = VMetadata->getSingleDefinition(Var)) { |
4017 assert(!VMetadata->isMultiDef(Var)); | 4012 assert(!VMetadata->isMultiDef(Var)); |
4018 if (llvm::isa<InstAssign>(VarAssign)) { | 4013 if (llvm::isa<InstAssign>(VarAssign)) { |
4019 Operand *SrcOp = VarAssign->getSrc(0); | 4014 Operand *SrcOp = VarAssign->getSrc(0); |
4020 assert(SrcOp); | 4015 assert(SrcOp); |
4021 if (Variable *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) { | 4016 if (Variable *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) { |
4022 if (!VMetadata->isMultiDef(SrcVar) && | 4017 if (!VMetadata->isMultiDef(SrcVar) && |
4023 // TODO: ensure SrcVar stays single-BB | 4018 // TODO: ensure SrcVar stays single-BB |
4024 true) { | 4019 true) { |
4025 Var = SrcVar; | 4020 Var = SrcVar; |
4026 Reason = VarAssign; | 4021 Reason = VarAssign; |
4027 return true; | 4022 return true; |
4028 } | 4023 } |
4029 } | 4024 } |
4030 } | 4025 } |
4031 } | 4026 } |
4032 return false; | 4027 return false; |
4033 } | 4028 } |
4034 | 4029 |
4035 bool matchCombinedBaseIndex(const VariablesMetadata *VMetadata, Variable *&Base, | 4030 inline bool matchCombinedBaseIndex(const VariablesMetadata *VMetadata, |
4036 Variable *&Index, uint16_t &Shift, | 4031 Variable *&Base, Variable *&Index, |
4037 const Inst *&Reason) { | 4032 uint16_t &Shift, const Inst *&Reason) { |
4038 // Index==nullptr && Base is Base=Var1+Var2 ==> | 4033 // Index==nullptr && Base is Base=Var1+Var2 ==> |
4039 // set Base=Var1, Index=Var2, Shift=0 | 4034 // set Base=Var1, Index=Var2, Shift=0 |
4040 if (Base == nullptr) | 4035 if (Base == nullptr) |
4041 return false; | 4036 return false; |
4042 if (Index != nullptr) | 4037 if (Index != nullptr) |
4043 return false; | 4038 return false; |
4044 const Inst *BaseInst = VMetadata->getSingleDefinition(Base); | 4039 const Inst *BaseInst = VMetadata->getSingleDefinition(Base); |
4045 if (BaseInst == nullptr) | 4040 if (BaseInst == nullptr) |
4046 return false; | 4041 return false; |
4047 assert(!VMetadata->isMultiDef(Base)); | 4042 assert(!VMetadata->isMultiDef(Base)); |
(...skipping 12 matching lines...) Expand all Loading... |
4060 Index = Var2; | 4055 Index = Var2; |
4061 Shift = 0; // should already have been 0 | 4056 Shift = 0; // should already have been 0 |
4062 Reason = BaseInst; | 4057 Reason = BaseInst; |
4063 return true; | 4058 return true; |
4064 } | 4059 } |
4065 } | 4060 } |
4066 } | 4061 } |
4067 return false; | 4062 return false; |
4068 } | 4063 } |
4069 | 4064 |
4070 bool matchShiftedIndex(const VariablesMetadata *VMetadata, Variable *&Index, | 4065 inline bool matchShiftedIndex(const VariablesMetadata *VMetadata, |
4071 uint16_t &Shift, const Inst *&Reason) { | 4066 Variable *&Index, uint16_t &Shift, |
| 4067 const Inst *&Reason) { |
4072 // Index is Index=Var*Const && log2(Const)+Shift<=3 ==> | 4068 // Index is Index=Var*Const && log2(Const)+Shift<=3 ==> |
4073 // Index=Var, Shift+=log2(Const) | 4069 // Index=Var, Shift+=log2(Const) |
4074 if (Index == nullptr) | 4070 if (Index == nullptr) |
4075 return false; | 4071 return false; |
4076 const Inst *IndexInst = VMetadata->getSingleDefinition(Index); | 4072 const Inst *IndexInst = VMetadata->getSingleDefinition(Index); |
4077 if (IndexInst == nullptr) | 4073 if (IndexInst == nullptr) |
4078 return false; | 4074 return false; |
4079 assert(!VMetadata->isMultiDef(Index)); | 4075 assert(!VMetadata->isMultiDef(Index)); |
4080 if (IndexInst->getSrcSize() < 2) | 4076 if (IndexInst->getSrcSize() < 2) |
4081 return false; | 4077 return false; |
(...skipping 28 matching lines...) Expand all Loading... |
4110 Reason = IndexInst; | 4106 Reason = IndexInst; |
4111 return true; | 4107 return true; |
4112 } | 4108 } |
4113 } | 4109 } |
4114 } | 4110 } |
4115 } | 4111 } |
4116 } | 4112 } |
4117 return false; | 4113 return false; |
4118 } | 4114 } |
4119 | 4115 |
4120 bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base, | 4116 inline bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base, |
4121 int32_t &Offset, const Inst *&Reason) { | 4117 int32_t &Offset, const Inst *&Reason) { |
4122 // Base is Base=Var+Const || Base is Base=Const+Var ==> | 4118 // Base is Base=Var+Const || Base is Base=Const+Var ==> |
4123 // set Base=Var, Offset+=Const | 4119 // set Base=Var, Offset+=Const |
4124 // Base is Base=Var-Const ==> | 4120 // Base is Base=Var-Const ==> |
4125 // set Base=Var, Offset-=Const | 4121 // set Base=Var, Offset-=Const |
4126 if (Base == nullptr) | 4122 if (Base == nullptr) |
4127 return false; | 4123 return false; |
4128 const Inst *BaseInst = VMetadata->getSingleDefinition(Base); | 4124 const Inst *BaseInst = VMetadata->getSingleDefinition(Base); |
4129 if (BaseInst == nullptr) | 4125 if (BaseInst == nullptr) |
4130 return false; | 4126 return false; |
4131 assert(!VMetadata->isMultiDef(Base)); | 4127 assert(!VMetadata->isMultiDef(Base)); |
(...skipping 19 matching lines...) Expand all Loading... |
4151 if (Utils::WouldOverflowAdd(Offset, MoreOffset)) | 4147 if (Utils::WouldOverflowAdd(Offset, MoreOffset)) |
4152 return false; | 4148 return false; |
4153 Base = Var; | 4149 Base = Var; |
4154 Offset += MoreOffset; | 4150 Offset += MoreOffset; |
4155 Reason = BaseInst; | 4151 Reason = BaseInst; |
4156 return true; | 4152 return true; |
4157 } | 4153 } |
4158 return false; | 4154 return false; |
4159 } | 4155 } |
4160 | 4156 |
4161 void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, | 4157 inline void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, |
4162 Variable *&Index, uint16_t &Shift, int32_t &Offset) { | 4158 Variable *&Index, uint16_t &Shift, |
| 4159 int32_t &Offset) { |
4163 Func->resetCurrentNode(); | 4160 Func->resetCurrentNode(); |
4164 if (Func->isVerbose(IceV_AddrOpt)) { | 4161 if (Func->isVerbose(IceV_AddrOpt)) { |
4165 OstreamLocker L(Func->getContext()); | 4162 OstreamLocker L(Func->getContext()); |
4166 Ostream &Str = Func->getContext()->getStrDump(); | 4163 Ostream &Str = Func->getContext()->getStrDump(); |
4167 Str << "\nStarting computeAddressOpt for instruction:\n "; | 4164 Str << "\nStarting computeAddressOpt for instruction:\n "; |
4168 Instr->dumpDecorated(Func); | 4165 Instr->dumpDecorated(Func); |
4169 } | 4166 } |
4170 (void)Offset; // TODO: pattern-match for non-zero offsets. | 4167 (void)Offset; // TODO: pattern-match for non-zero offsets. |
4171 if (Base == nullptr) | 4168 if (Base == nullptr) |
4172 return; | 4169 return; |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4341 } | 4338 } |
4342 // Lower select without Traits::SSE4.1: | 4339 // Lower select without Traits::SSE4.1: |
4343 // a=d?b:c ==> | 4340 // a=d?b:c ==> |
4344 // if elementtype(d) != i1: | 4341 // if elementtype(d) != i1: |
4345 // d=sext(d); | 4342 // d=sext(d); |
4346 // a=(b&d)|(c&~d); | 4343 // a=(b&d)|(c&~d); |
4347 Variable *T2 = makeReg(SrcTy); | 4344 Variable *T2 = makeReg(SrcTy); |
4348 // Sign extend the condition operand if applicable. | 4345 // Sign extend the condition operand if applicable. |
4349 if (SrcTy == IceType_v4f32) { | 4346 if (SrcTy == IceType_v4f32) { |
4350 // The sext operation takes only integer arguments. | 4347 // The sext operation takes only integer arguments. |
4351 Variable *T3 = Func->template makeVariable(IceType_v4i32); | 4348 Variable *T3 = Func->makeVariable(IceType_v4i32); |
4352 lowerCast(InstCast::create(Func, InstCast::Sext, T3, Condition)); | 4349 lowerCast(InstCast::create(Func, InstCast::Sext, T3, Condition)); |
4353 _movp(T, T3); | 4350 _movp(T, T3); |
4354 } else if (typeElementType(SrcTy) != IceType_i1) { | 4351 } else if (typeElementType(SrcTy) != IceType_i1) { |
4355 lowerCast(InstCast::create(Func, InstCast::Sext, T, Condition)); | 4352 lowerCast(InstCast::create(Func, InstCast::Sext, T, Condition)); |
4356 } else { | 4353 } else { |
4357 Operand *ConditionRM = legalize(Condition, Legal_Reg | Legal_Mem); | 4354 Operand *ConditionRM = legalize(Condition, Legal_Reg | Legal_Mem); |
4358 _movp(T, ConditionRM); | 4355 _movp(T, ConditionRM); |
4359 } | 4356 } |
4360 _movp(T2, T); | 4357 _movp(T2, T); |
4361 _pand(T, SrcTRM); | 4358 _pand(T, SrcTRM); |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4759 assert(isVectorType(Dest->getType())); | 4756 assert(isVectorType(Dest->getType())); |
4760 Type Ty = Dest->getType(); | 4757 Type Ty = Dest->getType(); |
4761 Type ElementTy = typeElementType(Ty); | 4758 Type ElementTy = typeElementType(Ty); |
4762 SizeT NumElements = typeNumElements(Ty); | 4759 SizeT NumElements = typeNumElements(Ty); |
4763 | 4760 |
4764 Operand *T = Ctx->getConstantUndef(Ty); | 4761 Operand *T = Ctx->getConstantUndef(Ty); |
4765 for (SizeT I = 0; I < NumElements; ++I) { | 4762 for (SizeT I = 0; I < NumElements; ++I) { |
4766 Constant *Index = Ctx->getConstantInt32(I); | 4763 Constant *Index = Ctx->getConstantInt32(I); |
4767 | 4764 |
4768 // Extract the next two inputs. | 4765 // Extract the next two inputs. |
4769 Variable *Op0 = Func->template makeVariable(ElementTy); | 4766 Variable *Op0 = Func->makeVariable(ElementTy); |
4770 lowerExtractElement(InstExtractElement::create(Func, Op0, Src0, Index)); | 4767 lowerExtractElement(InstExtractElement::create(Func, Op0, Src0, Index)); |
4771 Variable *Op1 = Func->template makeVariable(ElementTy); | 4768 Variable *Op1 = Func->makeVariable(ElementTy); |
4772 lowerExtractElement(InstExtractElement::create(Func, Op1, Src1, Index)); | 4769 lowerExtractElement(InstExtractElement::create(Func, Op1, Src1, Index)); |
4773 | 4770 |
4774 // Perform the arithmetic as a scalar operation. | 4771 // Perform the arithmetic as a scalar operation. |
4775 Variable *Res = Func->template makeVariable(ElementTy); | 4772 Variable *Res = Func->makeVariable(ElementTy); |
4776 lowerArithmetic(InstArithmetic::create(Func, Kind, Res, Op0, Op1)); | 4773 lowerArithmetic(InstArithmetic::create(Func, Kind, Res, Op0, Op1)); |
4777 | 4774 |
4778 // Insert the result into position. | 4775 // Insert the result into position. |
4779 Variable *DestT = Func->template makeVariable(Ty); | 4776 Variable *DestT = Func->makeVariable(Ty); |
4780 lowerInsertElement(InstInsertElement::create(Func, DestT, T, Res, Index)); | 4777 lowerInsertElement(InstInsertElement::create(Func, DestT, T, Res, Index)); |
4781 T = DestT; | 4778 T = DestT; |
4782 } | 4779 } |
4783 | 4780 |
4784 lowerAssign(InstAssign::create(Func, Dest, T)); | 4781 lowerAssign(InstAssign::create(Func, Dest, T)); |
4785 } | 4782 } |
4786 | 4783 |
4787 /// The following pattern occurs often in lowered C and C++ code: | 4784 /// The following pattern occurs often in lowered C and C++ code: |
4788 /// | 4785 /// |
4789 /// %cmp = fcmp/icmp pred <n x ty> %src0, %src1 | 4786 /// %cmp = fcmp/icmp pred <n x ty> %src0, %src1 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4907 /// turned into zeroes, since loOperand() and hiOperand() don't expect | 4904 /// turned into zeroes, since loOperand() and hiOperand() don't expect |
4908 /// Undef input. | 4905 /// Undef input. |
4909 template <class Machine> void TargetX86Base<Machine>::prelowerPhis() { | 4906 template <class Machine> void TargetX86Base<Machine>::prelowerPhis() { |
4910 // Pause constant blinding or pooling, blinding or pooling will be done later | 4907 // Pause constant blinding or pooling, blinding or pooling will be done later |
4911 // during phi lowering assignments | 4908 // during phi lowering assignments |
4912 BoolFlagSaver B(RandomizationPoolingPaused, true); | 4909 BoolFlagSaver B(RandomizationPoolingPaused, true); |
4913 PhiLowering::prelowerPhis32Bit<TargetX86Base<Machine>>( | 4910 PhiLowering::prelowerPhis32Bit<TargetX86Base<Machine>>( |
4914 this, Context.getNode(), Func); | 4911 this, Context.getNode(), Func); |
4915 } | 4912 } |
4916 | 4913 |
4917 bool isMemoryOperand(const Operand *Opnd) { | 4914 inline bool isMemoryOperand(const Operand *Opnd) { |
4918 if (const auto Var = llvm::dyn_cast<Variable>(Opnd)) | 4915 if (const auto Var = llvm::dyn_cast<Variable>(Opnd)) |
4919 return !Var->hasReg(); | 4916 return !Var->hasReg(); |
4920 // We treat vector undef values the same as a memory operand, | 4917 // We treat vector undef values the same as a memory operand, |
4921 // because they do in fact need a register to materialize the vector | 4918 // because they do in fact need a register to materialize the vector |
4922 // of zeroes into. | 4919 // of zeroes into. |
4923 if (llvm::isa<ConstantUndef>(Opnd)) | 4920 if (llvm::isa<ConstantUndef>(Opnd)) |
4924 return isScalarFloatingType(Opnd->getType()) || | 4921 return isScalarFloatingType(Opnd->getType()) || |
4925 isVectorType(Opnd->getType()); | 4922 isVectorType(Opnd->getType()); |
4926 if (llvm::isa<Constant>(Opnd)) | 4923 if (llvm::isa<Constant>(Opnd)) |
4927 return isScalarFloatingType(Opnd->getType()); | 4924 return isScalarFloatingType(Opnd->getType()); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5016 Variable *Preg = nullptr; | 5013 Variable *Preg = nullptr; |
5017 // TODO(stichnot): Opportunity for register randomization. | 5014 // TODO(stichnot): Opportunity for register randomization. |
5018 int32_t RegNum = AvailRegsForType.find_first(); | 5015 int32_t RegNum = AvailRegsForType.find_first(); |
5019 bool IsVector = isVectorType(Dest->getType()); | 5016 bool IsVector = isVectorType(Dest->getType()); |
5020 bool NeedSpill = (RegNum == -1); | 5017 bool NeedSpill = (RegNum == -1); |
5021 if (NeedSpill) { | 5018 if (NeedSpill) { |
5022 // Pick some register to spill and update RegNum. | 5019 // Pick some register to spill and update RegNum. |
5023 // TODO(stichnot): Opportunity for register randomization. | 5020 // TODO(stichnot): Opportunity for register randomization. |
5024 RegNum = RegsForType.find_first(); | 5021 RegNum = RegsForType.find_first(); |
5025 Preg = getPhysicalRegister(RegNum, Dest->getType()); | 5022 Preg = getPhysicalRegister(RegNum, Dest->getType()); |
5026 SpillLoc = Func->template makeVariable(Dest->getType()); | 5023 SpillLoc = Func->makeVariable(Dest->getType()); |
5027 // Create a fake def of the physical register to avoid | 5024 // Create a fake def of the physical register to avoid |
5028 // liveness inconsistency problems during late-stage liveness | 5025 // liveness inconsistency problems during late-stage liveness |
5029 // analysis (e.g. asm-verbose mode). | 5026 // analysis (e.g. asm-verbose mode). |
5030 Context.insert(InstFakeDef::create(Func, Preg)); | 5027 Context.insert(InstFakeDef::create(Func, Preg)); |
5031 if (IsVector) | 5028 if (IsVector) |
5032 _movp(SpillLoc, Preg); | 5029 _movp(SpillLoc, Preg); |
5033 else | 5030 else |
5034 _mov(SpillLoc, Preg); | 5031 _mov(SpillLoc, Preg); |
5035 } | 5032 } |
5036 assert(RegNum >= 0); | 5033 assert(RegNum >= 0); |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5358 // Do legalization, which contains randomization/pooling | 5355 // Do legalization, which contains randomization/pooling |
5359 // or do randomization/pooling. | 5356 // or do randomization/pooling. |
5360 return llvm::cast<typename Traits::X86OperandMem>( | 5357 return llvm::cast<typename Traits::X86OperandMem>( |
5361 DoLegalize ? legalize(Mem) : randomizeOrPoolImmediate(Mem)); | 5358 DoLegalize ? legalize(Mem) : randomizeOrPoolImmediate(Mem)); |
5362 } | 5359 } |
5363 | 5360 |
5364 template <class Machine> | 5361 template <class Machine> |
5365 Variable *TargetX86Base<Machine>::makeReg(Type Type, int32_t RegNum) { | 5362 Variable *TargetX86Base<Machine>::makeReg(Type Type, int32_t RegNum) { |
5366 // There aren't any 64-bit integer registers for x86-32. | 5363 // There aren't any 64-bit integer registers for x86-32. |
5367 assert(Type != IceType_i64); | 5364 assert(Type != IceType_i64); |
5368 Variable *Reg = Func->template makeVariable(Type); | 5365 Variable *Reg = Func->makeVariable(Type); |
5369 if (RegNum == Variable::NoRegister) | 5366 if (RegNum == Variable::NoRegister) |
5370 Reg->setWeightInfinite(); | 5367 Reg->setWeightInfinite(); |
5371 else | 5368 else |
5372 Reg->setRegNum(RegNum); | 5369 Reg->setRegNum(RegNum); |
5373 return Reg; | 5370 return Reg; |
5374 } | 5371 } |
5375 | 5372 |
5376 template <class Machine> void TargetX86Base<Machine>::postLower() { | 5373 template <class Machine> void TargetX86Base<Machine>::postLower() { |
5377 if (Ctx->getFlags().getOptLevel() == Opt_m1) | 5374 if (Ctx->getFlags().getOptLevel() == Opt_m1) |
5378 return; | 5375 return; |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5619 } | 5616 } |
5620 // the offset is not eligible for blinding or pooling, return the original | 5617 // the offset is not eligible for blinding or pooling, return the original |
5621 // mem operand | 5618 // mem operand |
5622 return MemOperand; | 5619 return MemOperand; |
5623 } | 5620 } |
5624 | 5621 |
5625 } // end of namespace X86Internal | 5622 } // end of namespace X86Internal |
5626 } // end of namespace Ice | 5623 } // end of namespace Ice |
5627 | 5624 |
5628 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H | 5625 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H |
OLD | NEW |