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 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 } | 257 } |
258 | 258 |
259 template <class Machine> | 259 template <class Machine> |
260 void TargetX86Base<Machine>::initNodeForLowering(CfgNode *Node) { | 260 void TargetX86Base<Machine>::initNodeForLowering(CfgNode *Node) { |
261 FoldingInfo.init(Node); | 261 FoldingInfo.init(Node); |
262 FoldingInfo.dump(Func); | 262 FoldingInfo.dump(Func); |
263 } | 263 } |
264 | 264 |
265 template <class Machine> | 265 template <class Machine> |
266 TargetX86Base<Machine>::TargetX86Base(Cfg *Func) | 266 TargetX86Base<Machine>::TargetX86Base(Cfg *Func) |
267 : Machine(Func) { | 267 : TargetLowering(Func) { |
268 static_assert( | 268 static_assert( |
269 (Traits::InstructionSet::End - Traits::InstructionSet::Begin) == | 269 (Traits::InstructionSet::End - Traits::InstructionSet::Begin) == |
270 (TargetInstructionSet::X86InstructionSet_End - | 270 (TargetInstructionSet::X86InstructionSet_End - |
271 TargetInstructionSet::X86InstructionSet_Begin), | 271 TargetInstructionSet::X86InstructionSet_Begin), |
272 "Traits::InstructionSet range different from TargetInstructionSet"); | 272 "Traits::InstructionSet range different from TargetInstructionSet"); |
273 if (Func->getContext()->getFlags().getTargetInstructionSet() != | 273 if (Func->getContext()->getFlags().getTargetInstructionSet() != |
274 TargetInstructionSet::BaseInstructionSet) { | 274 TargetInstructionSet::BaseInstructionSet) { |
275 InstructionSet = static_cast<typename Traits::InstructionSet>( | 275 InstructionSet = static_cast<typename Traits::InstructionSet>( |
276 (Func->getContext()->getFlags().getTargetInstructionSet() - | 276 (Func->getContext()->getFlags().getTargetInstructionSet() - |
277 TargetInstructionSet::X86InstructionSet_Begin) + | 277 TargetInstructionSet::X86InstructionSet_Begin) + |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 if (Func->hasError()) | 445 if (Func->hasError()) |
446 return; | 446 return; |
447 Func->dump("After stack frame mapping"); | 447 Func->dump("After stack frame mapping"); |
448 | 448 |
449 // Nop insertion | 449 // Nop insertion |
450 if (Ctx->getFlags().shouldDoNopInsertion()) { | 450 if (Ctx->getFlags().shouldDoNopInsertion()) { |
451 Func->doNopInsertion(); | 451 Func->doNopInsertion(); |
452 } | 452 } |
453 } | 453 } |
454 | 454 |
455 bool canRMW(const InstArithmetic *Arith) { | 455 inline bool canRMW(const InstArithmetic *Arith) { |
456 Type Ty = Arith->getDest()->getType(); | 456 Type Ty = Arith->getDest()->getType(); |
457 // X86 vector instructions write to a register and have no RMW option. | 457 // X86 vector instructions write to a register and have no RMW option. |
458 if (isVectorType(Ty)) | 458 if (isVectorType(Ty)) |
459 return false; | 459 return false; |
460 bool isI64 = Ty == IceType_i64; | 460 bool isI64 = Ty == IceType_i64; |
461 | 461 |
462 switch (Arith->getOp()) { | 462 switch (Arith->getOp()) { |
463 // Not handled for lack of simple lowering: | 463 // Not handled for lack of simple lowering: |
464 // shift on i64 | 464 // shift on i64 |
465 // mul, udiv, urem, sdiv, srem, frem | 465 // mul, udiv, urem, sdiv, srem, frem |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 continue; | 569 continue; |
570 if (Func->isVerbose(IceV_RMW)) { | 570 if (Func->isVerbose(IceV_RMW)) { |
571 Str << "Found RMW in " << Func->getFunctionName() << ":\n "; | 571 Str << "Found RMW in " << Func->getFunctionName() << ":\n "; |
572 Load->dump(Func); | 572 Load->dump(Func); |
573 Str << "\n "; | 573 Str << "\n "; |
574 Arith->dump(Func); | 574 Arith->dump(Func); |
575 Str << "\n "; | 575 Str << "\n "; |
576 Store->dump(Func); | 576 Store->dump(Func); |
577 Str << "\n"; | 577 Str << "\n"; |
578 } | 578 } |
579 Variable *Beacon = Func->template makeVariable(IceType_i32); | 579 Variable *Beacon = Func->makeVariable(IceType_i32); |
580 Beacon->setWeight(0); | 580 Beacon->setWeight(0); |
581 Store->setRmwBeacon(Beacon); | 581 Store->setRmwBeacon(Beacon); |
582 InstFakeDef *BeaconDef = InstFakeDef::create(Func, Beacon); | 582 InstFakeDef *BeaconDef = InstFakeDef::create(Func, Beacon); |
583 Node->getInsts().insert(I3, BeaconDef); | 583 Node->getInsts().insert(I3, BeaconDef); |
584 auto *RMW = Traits::Insts::FakeRMW::create( | 584 auto *RMW = Traits::Insts::FakeRMW::create( |
585 Func, ArithSrcOther, Store->getAddr(), Beacon, Arith->getOp()); | 585 Func, ArithSrcOther, Store->getAddr(), Beacon, Arith->getOp()); |
586 Node->getInsts().insert(I3, RMW); | 586 Node->getInsts().insert(I3, RMW); |
587 } | 587 } |
588 } | 588 } |
589 } | 589 } |
590 } | 590 } |
591 } | 591 } |
592 } | 592 } |
593 | 593 |
594 // Converts a ConstantInteger32 operand into its constant value, or | 594 // Converts a ConstantInteger32 operand into its constant value, or |
595 // MemoryOrderInvalid if the operand is not a ConstantInteger32. | 595 // MemoryOrderInvalid if the operand is not a ConstantInteger32. |
596 uint64_t getConstantMemoryOrder(Operand *Opnd) { | 596 inline uint64_t getConstantMemoryOrder(Operand *Opnd) { |
597 if (auto Integer = llvm::dyn_cast<ConstantInteger32>(Opnd)) | 597 if (auto Integer = llvm::dyn_cast<ConstantInteger32>(Opnd)) |
598 return Integer->getValue(); | 598 return Integer->getValue(); |
599 return Intrinsics::MemoryOrderInvalid; | 599 return Intrinsics::MemoryOrderInvalid; |
600 } | 600 } |
601 | 601 |
602 /// Determines whether the dest of a Load instruction can be folded | 602 /// Determines whether the dest of a Load instruction can be folded |
603 /// into one of the src operands of a 2-operand instruction. This is | 603 /// into one of the src operands of a 2-operand instruction. This is |
604 /// true as long as the load dest matches exactly one of the binary | 604 /// true as long as the load dest matches exactly one of the binary |
605 /// instruction's src operands. Replaces Src0 or Src1 with LoadSrc if | 605 /// instruction's src operands. Replaces Src0 or Src1 with LoadSrc if |
606 /// the answer is true. | 606 /// the answer is true. |
607 bool canFoldLoadIntoBinaryInst(Operand *LoadSrc, Variable *LoadDest, | 607 inline bool canFoldLoadIntoBinaryInst(Operand *LoadSrc, Variable *LoadDest, |
608 Operand *&Src0, Operand *&Src1) { | 608 Operand *&Src0, Operand *&Src1) { |
609 if (Src0 == LoadDest && Src1 != LoadDest) { | 609 if (Src0 == LoadDest && Src1 != LoadDest) { |
610 Src0 = LoadSrc; | 610 Src0 = LoadSrc; |
611 return true; | 611 return true; |
612 } | 612 } |
613 if (Src0 != LoadDest && Src1 == LoadDest) { | 613 if (Src0 != LoadDest && Src1 == LoadDest) { |
614 Src1 = LoadSrc; | 614 Src1 = LoadSrc; |
615 return true; | 615 return true; |
616 } | 616 } |
617 return false; | 617 return false; |
618 } | 618 } |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
717 | 717 |
718 template <class Machine> | 718 template <class Machine> |
719 Variable *TargetX86Base<Machine>::getPhysicalRegister(SizeT RegNum, Type Ty) { | 719 Variable *TargetX86Base<Machine>::getPhysicalRegister(SizeT RegNum, Type Ty) { |
720 if (Ty == IceType_void) | 720 if (Ty == IceType_void) |
721 Ty = IceType_i32; | 721 Ty = IceType_i32; |
722 if (PhysicalRegisters[Ty].empty()) | 722 if (PhysicalRegisters[Ty].empty()) |
723 PhysicalRegisters[Ty].resize(Traits::RegisterSet::Reg_NUM); | 723 PhysicalRegisters[Ty].resize(Traits::RegisterSet::Reg_NUM); |
724 assert(RegNum < PhysicalRegisters[Ty].size()); | 724 assert(RegNum < PhysicalRegisters[Ty].size()); |
725 Variable *Reg = PhysicalRegisters[Ty][RegNum]; | 725 Variable *Reg = PhysicalRegisters[Ty][RegNum]; |
726 if (Reg == nullptr) { | 726 if (Reg == nullptr) { |
727 Reg = Func->template makeVariable(Ty); | 727 Reg = Func->makeVariable(Ty); |
728 Reg->setRegNum(RegNum); | 728 Reg->setRegNum(RegNum); |
729 PhysicalRegisters[Ty][RegNum] = Reg; | 729 PhysicalRegisters[Ty][RegNum] = Reg; |
730 // Specially mark esp as an "argument" so that it is considered | 730 // Specially mark esp as an "argument" so that it is considered |
731 // live upon function entry. | 731 // live upon function entry. |
732 if (RegNum == Traits::RegisterSet::Reg_esp) { | 732 if (RegNum == Traits::RegisterSet::Reg_esp) { |
733 Func->addImplicitArg(Reg); | 733 Func->addImplicitArg(Reg); |
734 Reg->setIgnoreLiveness(); | 734 Reg->setIgnoreLiveness(); |
735 } | 735 } |
736 } | 736 } |
737 return Reg; | 737 return Reg; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
790 I < E && NumXmmArgs < Traits::X86_MAX_XMM_ARGS; ++I) { | 790 I < E && NumXmmArgs < Traits::X86_MAX_XMM_ARGS; ++I) { |
791 Variable *Arg = Args[I]; | 791 Variable *Arg = Args[I]; |
792 Type Ty = Arg->getType(); | 792 Type Ty = Arg->getType(); |
793 if (!isVectorType(Ty)) | 793 if (!isVectorType(Ty)) |
794 continue; | 794 continue; |
795 // Replace Arg in the argument list with the home register. Then | 795 // Replace Arg in the argument list with the home register. Then |
796 // generate an instruction in the prolog to copy the home register | 796 // generate an instruction in the prolog to copy the home register |
797 // to the assigned location of Arg. | 797 // to the assigned location of Arg. |
798 int32_t RegNum = Traits::RegisterSet::Reg_xmm0 + NumXmmArgs; | 798 int32_t RegNum = Traits::RegisterSet::Reg_xmm0 + NumXmmArgs; |
799 ++NumXmmArgs; | 799 ++NumXmmArgs; |
800 Variable *RegisterArg = Func->template makeVariable(Ty); | 800 Variable *RegisterArg = Func->makeVariable(Ty); |
801 if (BuildDefs::dump()) | 801 if (BuildDefs::dump()) |
802 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | 802 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
803 RegisterArg->setRegNum(RegNum); | 803 RegisterArg->setRegNum(RegNum); |
804 RegisterArg->setIsArg(); | 804 RegisterArg->setIsArg(); |
805 Arg->setIsArg(false); | 805 Arg->setIsArg(false); |
806 | 806 |
807 Args[I] = RegisterArg; | 807 Args[I] = RegisterArg; |
808 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | 808 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); |
809 } | 809 } |
810 } | 810 } |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1105 | 1105 |
1106 if (!Ctx->getFlags().getUseSandboxing()) | 1106 if (!Ctx->getFlags().getUseSandboxing()) |
1107 return; | 1107 return; |
1108 // Change the original ret instruction into a sandboxed return sequence. | 1108 // Change the original ret instruction into a sandboxed return sequence. |
1109 // t:ecx = pop | 1109 // t:ecx = pop |
1110 // bundle_lock | 1110 // bundle_lock |
1111 // and t, ~31 | 1111 // and t, ~31 |
1112 // jmp *t | 1112 // jmp *t |
1113 // bundle_unlock | 1113 // bundle_unlock |
1114 // FakeUse <original_ret_operand> | 1114 // FakeUse <original_ret_operand> |
1115 const SizeT BundleSize = | 1115 const SizeT BundleSize = 1 |
1116 1 << Func->template getAssembler<>()->getBundleAlignLog2Bytes(); | 1116 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); |
1117 Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx); | 1117 Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx); |
1118 _pop(T_ecx); | 1118 _pop(T_ecx); |
1119 _bundle_lock(); | 1119 _bundle_lock(); |
1120 _and(T_ecx, Ctx->getConstantInt32(~(BundleSize - 1))); | 1120 _and(T_ecx, Ctx->getConstantInt32(~(BundleSize - 1))); |
1121 _jmp(T_ecx); | 1121 _jmp(T_ecx); |
1122 _bundle_unlock(); | 1122 _bundle_unlock(); |
1123 if (RI->getSrcSize()) { | 1123 if (RI->getSrcSize()) { |
1124 Variable *RetValue = llvm::cast<Variable>(RI->getSrc(0)); | 1124 Variable *RetValue = llvm::cast<Variable>(RI->getSrc(0)); |
1125 Context.insert(InstFakeUse::create(Func, RetValue)); | 1125 Context.insert(InstFakeUse::create(Func, RetValue)); |
1126 } | 1126 } |
(...skipping 11 matching lines...) Expand all Loading... |
1138 case IceType_f64: | 1138 case IceType_f64: |
1139 break; | 1139 break; |
1140 } | 1140 } |
1141 Variable *Lo = Var->getLo(); | 1141 Variable *Lo = Var->getLo(); |
1142 Variable *Hi = Var->getHi(); | 1142 Variable *Hi = Var->getHi(); |
1143 if (Lo) { | 1143 if (Lo) { |
1144 assert(Hi); | 1144 assert(Hi); |
1145 return; | 1145 return; |
1146 } | 1146 } |
1147 assert(Hi == nullptr); | 1147 assert(Hi == nullptr); |
1148 Lo = Func->template makeVariable(IceType_i32); | 1148 Lo = Func->makeVariable(IceType_i32); |
1149 Hi = Func->template makeVariable(IceType_i32); | 1149 Hi = Func->makeVariable(IceType_i32); |
1150 if (BuildDefs::dump()) { | 1150 if (BuildDefs::dump()) { |
1151 Lo->setName(Func, Var->getName(Func) + "__lo"); | 1151 Lo->setName(Func, Var->getName(Func) + "__lo"); |
1152 Hi->setName(Func, Var->getName(Func) + "__hi"); | 1152 Hi->setName(Func, Var->getName(Func) + "__hi"); |
1153 } | 1153 } |
1154 Var->setLoHi(Lo, Hi); | 1154 Var->setLoHi(Lo, Hi); |
1155 if (Var->getIsArg()) { | 1155 if (Var->getIsArg()) { |
1156 Lo->setIsArg(); | 1156 Lo->setIsArg(); |
1157 Hi->setIsArg(); | 1157 Hi->setIsArg(); |
1158 } | 1158 } |
1159 } | 1159 } |
(...skipping 1072 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2232 Operand *CallTarget = legalize(Instr->getCallTarget()); | 2232 Operand *CallTarget = legalize(Instr->getCallTarget()); |
2233 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); | 2233 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); |
2234 if (NeedSandboxing) { | 2234 if (NeedSandboxing) { |
2235 if (llvm::isa<Constant>(CallTarget)) { | 2235 if (llvm::isa<Constant>(CallTarget)) { |
2236 _bundle_lock(InstBundleLock::Opt_AlignToEnd); | 2236 _bundle_lock(InstBundleLock::Opt_AlignToEnd); |
2237 } else { | 2237 } else { |
2238 Variable *CallTargetVar = nullptr; | 2238 Variable *CallTargetVar = nullptr; |
2239 _mov(CallTargetVar, CallTarget); | 2239 _mov(CallTargetVar, CallTarget); |
2240 _bundle_lock(InstBundleLock::Opt_AlignToEnd); | 2240 _bundle_lock(InstBundleLock::Opt_AlignToEnd); |
2241 const SizeT BundleSize = | 2241 const SizeT BundleSize = |
2242 1 << Func->template getAssembler<>()->getBundleAlignLog2Bytes(); | 2242 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); |
2243 _and(CallTargetVar, Ctx->getConstantInt32(~(BundleSize - 1))); | 2243 _and(CallTargetVar, Ctx->getConstantInt32(~(BundleSize - 1))); |
2244 CallTarget = CallTargetVar; | 2244 CallTarget = CallTargetVar; |
2245 } | 2245 } |
2246 } | 2246 } |
2247 Inst *NewCall = Traits::Insts::Call::create(Func, ReturnReg, CallTarget); | 2247 Inst *NewCall = Traits::Insts::Call::create(Func, ReturnReg, CallTarget); |
2248 Context.insert(NewCall); | 2248 Context.insert(NewCall); |
2249 if (NeedSandboxing) | 2249 if (NeedSandboxing) |
2250 _bundle_unlock(); | 2250 _bundle_unlock(); |
2251 if (ReturnRegHi) | 2251 if (ReturnRegHi) |
2252 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | 2252 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2661 assert((DestType == IceType_i32 && SrcType == IceType_f32) || | 2661 assert((DestType == IceType_i32 && SrcType == IceType_f32) || |
2662 (DestType == IceType_f32 && SrcType == IceType_i32)); | 2662 (DestType == IceType_f32 && SrcType == IceType_i32)); |
2663 // a.i32 = bitcast b.f32 ==> | 2663 // a.i32 = bitcast b.f32 ==> |
2664 // t.f32 = b.f32 | 2664 // t.f32 = b.f32 |
2665 // s.f32 = spill t.f32 | 2665 // s.f32 = spill t.f32 |
2666 // a.i32 = s.f32 | 2666 // a.i32 = s.f32 |
2667 Variable *T = nullptr; | 2667 Variable *T = nullptr; |
2668 // TODO: Should be able to force a spill setup by calling legalize() with | 2668 // TODO: Should be able to force a spill setup by calling legalize() with |
2669 // Legal_Mem and not Legal_Reg or Legal_Imm. | 2669 // Legal_Mem and not Legal_Reg or Legal_Imm. |
2670 typename Traits::SpillVariable *SpillVar = | 2670 typename Traits::SpillVariable *SpillVar = |
2671 Func->template makeVariable<typename Traits::SpillVariable>(SrcType); | 2671 Func->makeVariable<typename Traits::SpillVariable>(SrcType); |
2672 SpillVar->setLinkedTo(Dest); | 2672 SpillVar->setLinkedTo(Dest); |
2673 Variable *Spill = SpillVar; | 2673 Variable *Spill = SpillVar; |
2674 Spill->setWeight(RegWeight::Zero); | 2674 Spill->setWeight(RegWeight::Zero); |
2675 _mov(T, Src0RM); | 2675 _mov(T, Src0RM); |
2676 _mov(Spill, T); | 2676 _mov(Spill, T); |
2677 _mov(Dest, Spill); | 2677 _mov(Dest, Spill); |
2678 } break; | 2678 } break; |
2679 case IceType_i64: { | 2679 case IceType_i64: { |
2680 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); | 2680 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); |
2681 assert(Src0RM->getType() == IceType_f64); | 2681 assert(Src0RM->getType() == IceType_f64); |
2682 // a.i64 = bitcast b.f64 ==> | 2682 // a.i64 = bitcast b.f64 ==> |
2683 // s.f64 = spill b.f64 | 2683 // s.f64 = spill b.f64 |
2684 // t_lo.i32 = lo(s.f64) | 2684 // t_lo.i32 = lo(s.f64) |
2685 // a_lo.i32 = t_lo.i32 | 2685 // a_lo.i32 = t_lo.i32 |
2686 // t_hi.i32 = hi(s.f64) | 2686 // t_hi.i32 = hi(s.f64) |
2687 // a_hi.i32 = t_hi.i32 | 2687 // a_hi.i32 = t_hi.i32 |
2688 Operand *SpillLo, *SpillHi; | 2688 Operand *SpillLo, *SpillHi; |
2689 if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0RM)) { | 2689 if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0RM)) { |
2690 typename Traits::SpillVariable *SpillVar = | 2690 typename Traits::SpillVariable *SpillVar = |
2691 Func->template makeVariable<typename Traits::SpillVariable>( | 2691 Func->makeVariable<typename Traits::SpillVariable>(IceType_f64); |
2692 IceType_f64); | |
2693 SpillVar->setLinkedTo(Src0Var); | 2692 SpillVar->setLinkedTo(Src0Var); |
2694 Variable *Spill = SpillVar; | 2693 Variable *Spill = SpillVar; |
2695 Spill->setWeight(RegWeight::Zero); | 2694 Spill->setWeight(RegWeight::Zero); |
2696 _movq(Spill, Src0RM); | 2695 _movq(Spill, Src0RM); |
2697 SpillLo = Traits::VariableSplit::create(Func, Spill, | 2696 SpillLo = Traits::VariableSplit::create(Func, Spill, |
2698 Traits::VariableSplit::Low); | 2697 Traits::VariableSplit::Low); |
2699 SpillHi = Traits::VariableSplit::create(Func, Spill, | 2698 SpillHi = Traits::VariableSplit::create(Func, Spill, |
2700 Traits::VariableSplit::High); | 2699 Traits::VariableSplit::High); |
2701 } else { | 2700 } else { |
2702 SpillLo = loOperand(Src0RM); | 2701 SpillLo = loOperand(Src0RM); |
2703 SpillHi = hiOperand(Src0RM); | 2702 SpillHi = hiOperand(Src0RM); |
2704 } | 2703 } |
2705 | 2704 |
2706 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2705 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
2707 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2706 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
2708 Variable *T_Lo = makeReg(IceType_i32); | 2707 Variable *T_Lo = makeReg(IceType_i32); |
2709 Variable *T_Hi = makeReg(IceType_i32); | 2708 Variable *T_Hi = makeReg(IceType_i32); |
2710 | 2709 |
2711 _mov(T_Lo, SpillLo); | 2710 _mov(T_Lo, SpillLo); |
2712 _mov(DestLo, T_Lo); | 2711 _mov(DestLo, T_Lo); |
2713 _mov(T_Hi, SpillHi); | 2712 _mov(T_Hi, SpillHi); |
2714 _mov(DestHi, T_Hi); | 2713 _mov(DestHi, T_Hi); |
2715 } break; | 2714 } break; |
2716 case IceType_f64: { | 2715 case IceType_f64: { |
2717 Src0 = legalize(Src0); | 2716 Src0 = legalize(Src0); |
2718 assert(Src0->getType() == IceType_i64); | 2717 assert(Src0->getType() == IceType_i64); |
2719 if (llvm::isa<typename Traits::X86OperandMem>(Src0)) { | 2718 if (llvm::isa<typename Traits::X86OperandMem>(Src0)) { |
2720 Variable *T = Func->template makeVariable(Dest->getType()); | 2719 Variable *T = Func->makeVariable(Dest->getType()); |
2721 _movq(T, Src0); | 2720 _movq(T, Src0); |
2722 _movq(Dest, T); | 2721 _movq(Dest, T); |
2723 break; | 2722 break; |
2724 } | 2723 } |
2725 // a.f64 = bitcast b.i64 ==> | 2724 // a.f64 = bitcast b.i64 ==> |
2726 // t_lo.i32 = b_lo.i32 | 2725 // t_lo.i32 = b_lo.i32 |
2727 // FakeDef(s.f64) | 2726 // FakeDef(s.f64) |
2728 // lo(s.f64) = t_lo.i32 | 2727 // lo(s.f64) = t_lo.i32 |
2729 // t_hi.i32 = b_hi.i32 | 2728 // t_hi.i32 = b_hi.i32 |
2730 // hi(s.f64) = t_hi.i32 | 2729 // hi(s.f64) = t_hi.i32 |
2731 // a.f64 = s.f64 | 2730 // a.f64 = s.f64 |
2732 typename Traits::SpillVariable *SpillVar = | 2731 typename Traits::SpillVariable *SpillVar = |
2733 Func->template makeVariable<typename Traits::SpillVariable>( | 2732 Func->makeVariable<typename Traits::SpillVariable>(IceType_f64); |
2734 IceType_f64); | |
2735 SpillVar->setLinkedTo(Dest); | 2733 SpillVar->setLinkedTo(Dest); |
2736 Variable *Spill = SpillVar; | 2734 Variable *Spill = SpillVar; |
2737 Spill->setWeight(RegWeight::Zero); | 2735 Spill->setWeight(RegWeight::Zero); |
2738 | 2736 |
2739 Variable *T_Lo = nullptr, *T_Hi = nullptr; | 2737 Variable *T_Lo = nullptr, *T_Hi = nullptr; |
2740 typename Traits::VariableSplit *SpillLo = Traits::VariableSplit::create( | 2738 typename Traits::VariableSplit *SpillLo = Traits::VariableSplit::create( |
2741 Func, Spill, Traits::VariableSplit::Low); | 2739 Func, Spill, Traits::VariableSplit::Low); |
2742 typename Traits::VariableSplit *SpillHi = Traits::VariableSplit::create( | 2740 typename Traits::VariableSplit *SpillHi = Traits::VariableSplit::create( |
2743 Func, Spill, Traits::VariableSplit::High); | 2741 Func, Spill, Traits::VariableSplit::High); |
2744 _mov(T_Lo, loOperand(Src0)); | 2742 _mov(T_Lo, loOperand(Src0)); |
2745 // Technically, the Spill is defined after the _store happens, but | 2743 // Technically, the Spill is defined after the _store happens, but |
2746 // SpillLo is considered a "use" of Spill so define Spill before it | 2744 // SpillLo is considered a "use" of Spill so define Spill before it |
2747 // is used. | 2745 // is used. |
2748 Context.insert(InstFakeDef::create(Func, Spill)); | 2746 Context.insert(InstFakeDef::create(Func, Spill)); |
2749 _store(T_Lo, SpillLo); | 2747 _store(T_Lo, SpillLo); |
2750 _mov(T_Hi, hiOperand(Src0)); | 2748 _mov(T_Hi, hiOperand(Src0)); |
2751 _store(T_Hi, SpillHi); | 2749 _store(T_Hi, SpillHi); |
2752 _movq(Dest, Spill); | 2750 _movq(Dest, Spill); |
2753 } break; | 2751 } break; |
2754 case IceType_v8i1: { | 2752 case IceType_v8i1: { |
2755 assert(Src0->getType() == IceType_i8); | 2753 assert(Src0->getType() == IceType_i8); |
2756 InstCall *Call = makeHelperCall(H_bitcast_i8_8xi1, Dest, 1); | 2754 InstCall *Call = makeHelperCall(H_bitcast_i8_8xi1, Dest, 1); |
2757 Variable *Src0AsI32 = Func->template makeVariable(stackSlotType()); | 2755 Variable *Src0AsI32 = Func->makeVariable(stackSlotType()); |
2758 // Arguments to functions are required to be at least 32 bits wide. | 2756 // Arguments to functions are required to be at least 32 bits wide. |
2759 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); | 2757 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); |
2760 Call->addArg(Src0AsI32); | 2758 Call->addArg(Src0AsI32); |
2761 lowerCall(Call); | 2759 lowerCall(Call); |
2762 } break; | 2760 } break; |
2763 case IceType_v16i1: { | 2761 case IceType_v16i1: { |
2764 assert(Src0->getType() == IceType_i16); | 2762 assert(Src0->getType() == IceType_i16); |
2765 InstCall *Call = makeHelperCall(H_bitcast_i16_16xi1, Dest, 1); | 2763 InstCall *Call = makeHelperCall(H_bitcast_i16_16xi1, Dest, 1); |
2766 Variable *Src0AsI32 = Func->template makeVariable(stackSlotType()); | 2764 Variable *Src0AsI32 = Func->makeVariable(stackSlotType()); |
2767 // Arguments to functions are required to be at least 32 bits wide. | 2765 // Arguments to functions are required to be at least 32 bits wide. |
2768 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); | 2766 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); |
2769 Call->addArg(Src0AsI32); | 2767 Call->addArg(Src0AsI32); |
2770 lowerCall(Call); | 2768 lowerCall(Call); |
2771 } break; | 2769 } break; |
2772 case IceType_v8i16: | 2770 case IceType_v8i16: |
2773 case IceType_v16i8: | 2771 case IceType_v16i8: |
2774 case IceType_v4i32: | 2772 case IceType_v4i32: |
2775 case IceType_v4f32: { | 2773 case IceType_v4f32: { |
2776 _movp(Dest, legalizeToVar(Src0)); | 2774 _movp(Dest, legalizeToVar(Src0)); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2827 // keep the live range analysis consistent. | 2825 // keep the live range analysis consistent. |
2828 Context.insert(InstFakeDef::create(Func, ExtractedElementR)); | 2826 Context.insert(InstFakeDef::create(Func, ExtractedElementR)); |
2829 _movss(ExtractedElementR, T); | 2827 _movss(ExtractedElementR, T); |
2830 } | 2828 } |
2831 } else { | 2829 } else { |
2832 assert(Ty == IceType_v16i8 || Ty == IceType_v16i1); | 2830 assert(Ty == IceType_v16i8 || Ty == IceType_v16i1); |
2833 // Spill the value to a stack slot and do the extraction in memory. | 2831 // Spill the value to a stack slot and do the extraction in memory. |
2834 // | 2832 // |
2835 // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when | 2833 // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when |
2836 // support for legalizing to mem is implemented. | 2834 // support for legalizing to mem is implemented. |
2837 Variable *Slot = Func->template makeVariable(Ty); | 2835 Variable *Slot = Func->makeVariable(Ty); |
2838 Slot->setWeight(RegWeight::Zero); | 2836 Slot->setWeight(RegWeight::Zero); |
2839 _movp(Slot, legalizeToVar(SourceVectNotLegalized)); | 2837 _movp(Slot, legalizeToVar(SourceVectNotLegalized)); |
2840 | 2838 |
2841 // Compute the location of the element in memory. | 2839 // Compute the location of the element in memory. |
2842 unsigned Offset = Index * typeWidthInBytes(InVectorElementTy); | 2840 unsigned Offset = Index * typeWidthInBytes(InVectorElementTy); |
2843 typename Traits::X86OperandMem *Loc = | 2841 typename Traits::X86OperandMem *Loc = |
2844 getMemoryOperandForStackSlot(InVectorElementTy, Slot, Offset); | 2842 getMemoryOperandForStackSlot(InVectorElementTy, Slot, Offset); |
2845 _mov(ExtractedElementR, Loc); | 2843 _mov(ExtractedElementR, Loc); |
2846 } | 2844 } |
2847 | 2845 |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2992 case IceType_v4i1: | 2990 case IceType_v4i1: |
2993 NewTy = IceType_v4i32; | 2991 NewTy = IceType_v4i32; |
2994 break; | 2992 break; |
2995 case IceType_v8i1: | 2993 case IceType_v8i1: |
2996 NewTy = IceType_v8i16; | 2994 NewTy = IceType_v8i16; |
2997 break; | 2995 break; |
2998 case IceType_v16i1: | 2996 case IceType_v16i1: |
2999 NewTy = IceType_v16i8; | 2997 NewTy = IceType_v16i8; |
3000 break; | 2998 break; |
3001 } | 2999 } |
3002 Variable *NewSrc0 = Func->template makeVariable(NewTy); | 3000 Variable *NewSrc0 = Func->makeVariable(NewTy); |
3003 Variable *NewSrc1 = Func->template makeVariable(NewTy); | 3001 Variable *NewSrc1 = Func->makeVariable(NewTy); |
3004 lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc0, Src0)); | 3002 lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc0, Src0)); |
3005 lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc1, Src1)); | 3003 lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc1, Src1)); |
3006 Src0 = NewSrc0; | 3004 Src0 = NewSrc0; |
3007 Src1 = NewSrc1; | 3005 Src1 = NewSrc1; |
3008 Ty = NewTy; | 3006 Ty = NewTy; |
3009 } | 3007 } |
3010 | 3008 |
3011 InstIcmp::ICond Condition = Inst->getCondition(); | 3009 InstIcmp::ICond Condition = Inst->getCondition(); |
3012 | 3010 |
3013 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); | 3011 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3135 unsigned Index = ElementIndex->getValue(); | 3133 unsigned Index = ElementIndex->getValue(); |
3136 assert(Index < typeNumElements(SourceVectNotLegalized->getType())); | 3134 assert(Index < typeNumElements(SourceVectNotLegalized->getType())); |
3137 | 3135 |
3138 Type Ty = SourceVectNotLegalized->getType(); | 3136 Type Ty = SourceVectNotLegalized->getType(); |
3139 Type ElementTy = typeElementType(Ty); | 3137 Type ElementTy = typeElementType(Ty); |
3140 Type InVectorElementTy = Traits::getInVectorElementType(Ty); | 3138 Type InVectorElementTy = Traits::getInVectorElementType(Ty); |
3141 | 3139 |
3142 if (ElementTy == IceType_i1) { | 3140 if (ElementTy == IceType_i1) { |
3143 // Expand the element to the appropriate size for it to be inserted | 3141 // Expand the element to the appropriate size for it to be inserted |
3144 // in the vector. | 3142 // in the vector. |
3145 Variable *Expanded = Func->template makeVariable(InVectorElementTy); | 3143 Variable *Expanded = Func->makeVariable(InVectorElementTy); |
3146 InstCast *Cast = InstCast::create(Func, InstCast::Zext, Expanded, | 3144 InstCast *Cast = InstCast::create(Func, InstCast::Zext, Expanded, |
3147 ElementToInsertNotLegalized); | 3145 ElementToInsertNotLegalized); |
3148 lowerCast(Cast); | 3146 lowerCast(Cast); |
3149 ElementToInsertNotLegalized = Expanded; | 3147 ElementToInsertNotLegalized = Expanded; |
3150 } | 3148 } |
3151 | 3149 |
3152 if (Ty == IceType_v8i16 || Ty == IceType_v8i1 || | 3150 if (Ty == IceType_v8i16 || Ty == IceType_v8i1 || |
3153 InstructionSet >= Traits::SSE4_1) { | 3151 InstructionSet >= Traits::SSE4_1) { |
3154 // Use insertps, pinsrb, pinsrw, or pinsrd. | 3152 // Use insertps, pinsrb, pinsrw, or pinsrd. |
3155 Operand *ElementRM = | 3153 Operand *ElementRM = |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3226 _shufps(T, ElementR, Mask2Constant); | 3224 _shufps(T, ElementR, Mask2Constant); |
3227 _movp(Inst->getDest(), T); | 3225 _movp(Inst->getDest(), T); |
3228 } | 3226 } |
3229 } else { | 3227 } else { |
3230 assert(Ty == IceType_v16i8 || Ty == IceType_v16i1); | 3228 assert(Ty == IceType_v16i8 || Ty == IceType_v16i1); |
3231 // Spill the value to a stack slot and perform the insertion in | 3229 // Spill the value to a stack slot and perform the insertion in |
3232 // memory. | 3230 // memory. |
3233 // | 3231 // |
3234 // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when | 3232 // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when |
3235 // support for legalizing to mem is implemented. | 3233 // support for legalizing to mem is implemented. |
3236 Variable *Slot = Func->template makeVariable(Ty); | 3234 Variable *Slot = Func->makeVariable(Ty); |
3237 Slot->setWeight(RegWeight::Zero); | 3235 Slot->setWeight(RegWeight::Zero); |
3238 _movp(Slot, legalizeToVar(SourceVectNotLegalized)); | 3236 _movp(Slot, legalizeToVar(SourceVectNotLegalized)); |
3239 | 3237 |
3240 // Compute the location of the position to insert in memory. | 3238 // Compute the location of the position to insert in memory. |
3241 unsigned Offset = Index * typeWidthInBytes(InVectorElementTy); | 3239 unsigned Offset = Index * typeWidthInBytes(InVectorElementTy); |
3242 typename Traits::X86OperandMem *Loc = | 3240 typename Traits::X86OperandMem *Loc = |
3243 getMemoryOperandForStackSlot(InVectorElementTy, Slot, Offset); | 3241 getMemoryOperandForStackSlot(InVectorElementTy, Slot, Offset); |
3244 _store(legalizeToVar(ElementToInsertNotLegalized), Loc); | 3242 _store(legalizeToVar(ElementToInsertNotLegalized), Loc); |
3245 | 3243 |
3246 Variable *T = makeReg(Ty); | 3244 Variable *T = makeReg(Ty); |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3519 Call->addArg(Instr->getArg(2)); | 3517 Call->addArg(Instr->getArg(2)); |
3520 lowerCall(Call); | 3518 lowerCall(Call); |
3521 return; | 3519 return; |
3522 } | 3520 } |
3523 case Intrinsics::Memset: { | 3521 case Intrinsics::Memset: { |
3524 // The value operand needs to be extended to a stack slot size | 3522 // The value operand needs to be extended to a stack slot size |
3525 // because the PNaCl ABI requires arguments to be at least 32 bits | 3523 // because the PNaCl ABI requires arguments to be at least 32 bits |
3526 // wide. | 3524 // wide. |
3527 Operand *ValOp = Instr->getArg(1); | 3525 Operand *ValOp = Instr->getArg(1); |
3528 assert(ValOp->getType() == IceType_i8); | 3526 assert(ValOp->getType() == IceType_i8); |
3529 Variable *ValExt = Func->template makeVariable(stackSlotType()); | 3527 Variable *ValExt = Func->makeVariable(stackSlotType()); |
3530 lowerCast(InstCast::create(Func, InstCast::Zext, ValExt, ValOp)); | 3528 lowerCast(InstCast::create(Func, InstCast::Zext, ValExt, ValOp)); |
3531 InstCall *Call = makeHelperCall(H_call_memset, nullptr, 3); | 3529 InstCall *Call = makeHelperCall(H_call_memset, nullptr, 3); |
3532 Call->addArg(Instr->getArg(0)); | 3530 Call->addArg(Instr->getArg(0)); |
3533 Call->addArg(ValExt); | 3531 Call->addArg(ValExt); |
3534 Call->addArg(Instr->getArg(2)); | 3532 Call->addArg(Instr->getArg(2)); |
3535 lowerCall(Call); | 3533 lowerCall(Call); |
3536 return; | 3534 return; |
3537 } | 3535 } |
3538 case Intrinsics::NaClReadTP: { | 3536 case Intrinsics::NaClReadTP: { |
3539 if (Ctx->getFlags().getUseSandboxing()) { | 3537 if (Ctx->getFlags().getUseSandboxing()) { |
3540 Constant *Zero = Ctx->getConstantZero(IceType_i32); | 3538 Operand *Src = dispatchToConcrete(&Machine::createNaClReadTPSrcOperand); |
3541 Operand *Src = Traits::X86OperandMem::create( | |
3542 Func, IceType_i32, nullptr, Zero, nullptr, 0, | |
3543 Traits::X86OperandMem::SegReg_GS); | |
3544 Variable *Dest = Instr->getDest(); | 3539 Variable *Dest = Instr->getDest(); |
3545 Variable *T = nullptr; | 3540 Variable *T = nullptr; |
3546 _mov(T, Src); | 3541 _mov(T, Src); |
3547 _mov(Dest, T); | 3542 _mov(Dest, T); |
3548 } else { | 3543 } else { |
3549 InstCall *Call = makeHelperCall(H_call_read_tp, Instr->getDest(), 0); | 3544 InstCall *Call = makeHelperCall(H_call_read_tp, Instr->getDest(), 0); |
3550 lowerCall(Call); | 3545 lowerCall(Call); |
3551 } | 3546 } |
3552 return; | 3547 return; |
3553 } | 3548 } |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3966 } else { | 3961 } else { |
3967 _bsr(T_Dest2, SecondVar); | 3962 _bsr(T_Dest2, SecondVar); |
3968 _xor(T_Dest2, ThirtyOne); | 3963 _xor(T_Dest2, ThirtyOne); |
3969 } | 3964 } |
3970 _test(SecondVar, SecondVar); | 3965 _test(SecondVar, SecondVar); |
3971 _cmov(T_Dest2, T_Dest, Traits::Cond::Br_e); | 3966 _cmov(T_Dest2, T_Dest, Traits::Cond::Br_e); |
3972 _mov(DestLo, T_Dest2); | 3967 _mov(DestLo, T_Dest2); |
3973 _mov(DestHi, Ctx->getConstantZero(IceType_i32)); | 3968 _mov(DestHi, Ctx->getConstantZero(IceType_i32)); |
3974 } | 3969 } |
3975 | 3970 |
3976 bool isAdd(const Inst *Inst) { | 3971 inline bool isAdd(const Inst *Inst) { |
3977 if (const InstArithmetic *Arith = | 3972 if (const InstArithmetic *Arith = |
3978 llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) { | 3973 llvm::dyn_cast_or_null<const InstArithmetic>(Inst)) { |
3979 return (Arith->getOp() == InstArithmetic::Add); | 3974 return (Arith->getOp() == InstArithmetic::Add); |
3980 } | 3975 } |
3981 return false; | 3976 return false; |
3982 } | 3977 } |
3983 | 3978 |
3984 void dumpAddressOpt(const Cfg *Func, const Variable *Base, | 3979 inline void dumpAddressOpt(const Cfg *Func, const Variable *Base, |
3985 const Variable *Index, uint16_t Shift, int32_t Offset, | 3980 const Variable *Index, uint16_t Shift, |
3986 const Inst *Reason) { | 3981 int32_t Offset, const Inst *Reason) { |
3987 if (!BuildDefs::dump()) | 3982 if (!BuildDefs::dump()) |
3988 return; | 3983 return; |
3989 if (!Func->isVerbose(IceV_AddrOpt)) | 3984 if (!Func->isVerbose(IceV_AddrOpt)) |
3990 return; | 3985 return; |
3991 OstreamLocker L(Func->getContext()); | 3986 OstreamLocker L(Func->getContext()); |
3992 Ostream &Str = Func->getContext()->getStrDump(); | 3987 Ostream &Str = Func->getContext()->getStrDump(); |
3993 Str << "Instruction: "; | 3988 Str << "Instruction: "; |
3994 Reason->dumpDecorated(Func); | 3989 Reason->dumpDecorated(Func); |
3995 Str << " results in Base="; | 3990 Str << " results in Base="; |
3996 if (Base) | 3991 if (Base) |
3997 Base->dump(Func); | 3992 Base->dump(Func); |
3998 else | 3993 else |
3999 Str << "<null>"; | 3994 Str << "<null>"; |
4000 Str << ", Index="; | 3995 Str << ", Index="; |
4001 if (Index) | 3996 if (Index) |
4002 Index->dump(Func); | 3997 Index->dump(Func); |
4003 else | 3998 else |
4004 Str << "<null>"; | 3999 Str << "<null>"; |
4005 Str << ", Shift=" << Shift << ", Offset=" << Offset << "\n"; | 4000 Str << ", Shift=" << Shift << ", Offset=" << Offset << "\n"; |
4006 } | 4001 } |
4007 | 4002 |
4008 bool matchTransitiveAssign(const VariablesMetadata *VMetadata, Variable *&Var, | 4003 inline bool matchTransitiveAssign(const VariablesMetadata *VMetadata, |
4009 const Inst *&Reason) { | 4004 Variable *&Var, const Inst *&Reason) { |
4010 // Var originates from Var=SrcVar ==> | 4005 // Var originates from Var=SrcVar ==> |
4011 // set Var:=SrcVar | 4006 // set Var:=SrcVar |
4012 if (Var == nullptr) | 4007 if (Var == nullptr) |
4013 return false; | 4008 return false; |
4014 if (const Inst *VarAssign = VMetadata->getSingleDefinition(Var)) { | 4009 if (const Inst *VarAssign = VMetadata->getSingleDefinition(Var)) { |
4015 assert(!VMetadata->isMultiDef(Var)); | 4010 assert(!VMetadata->isMultiDef(Var)); |
4016 if (llvm::isa<InstAssign>(VarAssign)) { | 4011 if (llvm::isa<InstAssign>(VarAssign)) { |
4017 Operand *SrcOp = VarAssign->getSrc(0); | 4012 Operand *SrcOp = VarAssign->getSrc(0); |
4018 assert(SrcOp); | 4013 assert(SrcOp); |
4019 if (Variable *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) { | 4014 if (Variable *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) { |
4020 if (!VMetadata->isMultiDef(SrcVar) && | 4015 if (!VMetadata->isMultiDef(SrcVar) && |
4021 // TODO: ensure SrcVar stays single-BB | 4016 // TODO: ensure SrcVar stays single-BB |
4022 true) { | 4017 true) { |
4023 Var = SrcVar; | 4018 Var = SrcVar; |
4024 Reason = VarAssign; | 4019 Reason = VarAssign; |
4025 return true; | 4020 return true; |
4026 } | 4021 } |
4027 } | 4022 } |
4028 } | 4023 } |
4029 } | 4024 } |
4030 return false; | 4025 return false; |
4031 } | 4026 } |
4032 | 4027 |
4033 bool matchCombinedBaseIndex(const VariablesMetadata *VMetadata, Variable *&Base, | 4028 inline bool matchCombinedBaseIndex(const VariablesMetadata *VMetadata, |
4034 Variable *&Index, uint16_t &Shift, | 4029 Variable *&Base, Variable *&Index, |
4035 const Inst *&Reason) { | 4030 uint16_t &Shift, const Inst *&Reason) { |
4036 // Index==nullptr && Base is Base=Var1+Var2 ==> | 4031 // Index==nullptr && Base is Base=Var1+Var2 ==> |
4037 // set Base=Var1, Index=Var2, Shift=0 | 4032 // set Base=Var1, Index=Var2, Shift=0 |
4038 if (Base == nullptr) | 4033 if (Base == nullptr) |
4039 return false; | 4034 return false; |
4040 if (Index != nullptr) | 4035 if (Index != nullptr) |
4041 return false; | 4036 return false; |
4042 const Inst *BaseInst = VMetadata->getSingleDefinition(Base); | 4037 const Inst *BaseInst = VMetadata->getSingleDefinition(Base); |
4043 if (BaseInst == nullptr) | 4038 if (BaseInst == nullptr) |
4044 return false; | 4039 return false; |
4045 assert(!VMetadata->isMultiDef(Base)); | 4040 assert(!VMetadata->isMultiDef(Base)); |
(...skipping 12 matching lines...) Expand all Loading... |
4058 Index = Var2; | 4053 Index = Var2; |
4059 Shift = 0; // should already have been 0 | 4054 Shift = 0; // should already have been 0 |
4060 Reason = BaseInst; | 4055 Reason = BaseInst; |
4061 return true; | 4056 return true; |
4062 } | 4057 } |
4063 } | 4058 } |
4064 } | 4059 } |
4065 return false; | 4060 return false; |
4066 } | 4061 } |
4067 | 4062 |
4068 bool matchShiftedIndex(const VariablesMetadata *VMetadata, Variable *&Index, | 4063 inline bool matchShiftedIndex(const VariablesMetadata *VMetadata, |
4069 uint16_t &Shift, const Inst *&Reason) { | 4064 Variable *&Index, uint16_t &Shift, |
| 4065 const Inst *&Reason) { |
4070 // Index is Index=Var*Const && log2(Const)+Shift<=3 ==> | 4066 // Index is Index=Var*Const && log2(Const)+Shift<=3 ==> |
4071 // Index=Var, Shift+=log2(Const) | 4067 // Index=Var, Shift+=log2(Const) |
4072 if (Index == nullptr) | 4068 if (Index == nullptr) |
4073 return false; | 4069 return false; |
4074 const Inst *IndexInst = VMetadata->getSingleDefinition(Index); | 4070 const Inst *IndexInst = VMetadata->getSingleDefinition(Index); |
4075 if (IndexInst == nullptr) | 4071 if (IndexInst == nullptr) |
4076 return false; | 4072 return false; |
4077 assert(!VMetadata->isMultiDef(Index)); | 4073 assert(!VMetadata->isMultiDef(Index)); |
4078 if (IndexInst->getSrcSize() < 2) | 4074 if (IndexInst->getSrcSize() < 2) |
4079 return false; | 4075 return false; |
(...skipping 28 matching lines...) Expand all Loading... |
4108 Reason = IndexInst; | 4104 Reason = IndexInst; |
4109 return true; | 4105 return true; |
4110 } | 4106 } |
4111 } | 4107 } |
4112 } | 4108 } |
4113 } | 4109 } |
4114 } | 4110 } |
4115 return false; | 4111 return false; |
4116 } | 4112 } |
4117 | 4113 |
4118 bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base, | 4114 inline bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base, |
4119 int32_t &Offset, const Inst *&Reason) { | 4115 int32_t &Offset, const Inst *&Reason) { |
4120 // Base is Base=Var+Const || Base is Base=Const+Var ==> | 4116 // Base is Base=Var+Const || Base is Base=Const+Var ==> |
4121 // set Base=Var, Offset+=Const | 4117 // set Base=Var, Offset+=Const |
4122 // Base is Base=Var-Const ==> | 4118 // Base is Base=Var-Const ==> |
4123 // set Base=Var, Offset-=Const | 4119 // set Base=Var, Offset-=Const |
4124 if (Base == nullptr) | 4120 if (Base == nullptr) |
4125 return false; | 4121 return false; |
4126 const Inst *BaseInst = VMetadata->getSingleDefinition(Base); | 4122 const Inst *BaseInst = VMetadata->getSingleDefinition(Base); |
4127 if (BaseInst == nullptr) | 4123 if (BaseInst == nullptr) |
4128 return false; | 4124 return false; |
4129 assert(!VMetadata->isMultiDef(Base)); | 4125 assert(!VMetadata->isMultiDef(Base)); |
(...skipping 19 matching lines...) Expand all Loading... |
4149 if (Utils::WouldOverflowAdd(Offset, MoreOffset)) | 4145 if (Utils::WouldOverflowAdd(Offset, MoreOffset)) |
4150 return false; | 4146 return false; |
4151 Base = Var; | 4147 Base = Var; |
4152 Offset += MoreOffset; | 4148 Offset += MoreOffset; |
4153 Reason = BaseInst; | 4149 Reason = BaseInst; |
4154 return true; | 4150 return true; |
4155 } | 4151 } |
4156 return false; | 4152 return false; |
4157 } | 4153 } |
4158 | 4154 |
4159 void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, | 4155 inline void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, |
4160 Variable *&Index, uint16_t &Shift, int32_t &Offset) { | 4156 Variable *&Index, uint16_t &Shift, |
| 4157 int32_t &Offset) { |
4161 Func->resetCurrentNode(); | 4158 Func->resetCurrentNode(); |
4162 if (Func->isVerbose(IceV_AddrOpt)) { | 4159 if (Func->isVerbose(IceV_AddrOpt)) { |
4163 OstreamLocker L(Func->getContext()); | 4160 OstreamLocker L(Func->getContext()); |
4164 Ostream &Str = Func->getContext()->getStrDump(); | 4161 Ostream &Str = Func->getContext()->getStrDump(); |
4165 Str << "\nStarting computeAddressOpt for instruction:\n "; | 4162 Str << "\nStarting computeAddressOpt for instruction:\n "; |
4166 Instr->dumpDecorated(Func); | 4163 Instr->dumpDecorated(Func); |
4167 } | 4164 } |
4168 (void)Offset; // TODO: pattern-match for non-zero offsets. | 4165 (void)Offset; // TODO: pattern-match for non-zero offsets. |
4169 if (Base == nullptr) | 4166 if (Base == nullptr) |
4170 return; | 4167 return; |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4339 } | 4336 } |
4340 // Lower select without Traits::SSE4.1: | 4337 // Lower select without Traits::SSE4.1: |
4341 // a=d?b:c ==> | 4338 // a=d?b:c ==> |
4342 // if elementtype(d) != i1: | 4339 // if elementtype(d) != i1: |
4343 // d=sext(d); | 4340 // d=sext(d); |
4344 // a=(b&d)|(c&~d); | 4341 // a=(b&d)|(c&~d); |
4345 Variable *T2 = makeReg(SrcTy); | 4342 Variable *T2 = makeReg(SrcTy); |
4346 // Sign extend the condition operand if applicable. | 4343 // Sign extend the condition operand if applicable. |
4347 if (SrcTy == IceType_v4f32) { | 4344 if (SrcTy == IceType_v4f32) { |
4348 // The sext operation takes only integer arguments. | 4345 // The sext operation takes only integer arguments. |
4349 Variable *T3 = Func->template makeVariable(IceType_v4i32); | 4346 Variable *T3 = Func->makeVariable(IceType_v4i32); |
4350 lowerCast(InstCast::create(Func, InstCast::Sext, T3, Condition)); | 4347 lowerCast(InstCast::create(Func, InstCast::Sext, T3, Condition)); |
4351 _movp(T, T3); | 4348 _movp(T, T3); |
4352 } else if (typeElementType(SrcTy) != IceType_i1) { | 4349 } else if (typeElementType(SrcTy) != IceType_i1) { |
4353 lowerCast(InstCast::create(Func, InstCast::Sext, T, Condition)); | 4350 lowerCast(InstCast::create(Func, InstCast::Sext, T, Condition)); |
4354 } else { | 4351 } else { |
4355 Operand *ConditionRM = legalize(Condition, Legal_Reg | Legal_Mem); | 4352 Operand *ConditionRM = legalize(Condition, Legal_Reg | Legal_Mem); |
4356 _movp(T, ConditionRM); | 4353 _movp(T, ConditionRM); |
4357 } | 4354 } |
4358 _movp(T2, T); | 4355 _movp(T2, T); |
4359 _pand(T, SrcTRM); | 4356 _pand(T, SrcTRM); |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4544 assert(isVectorType(Dest->getType())); | 4541 assert(isVectorType(Dest->getType())); |
4545 Type Ty = Dest->getType(); | 4542 Type Ty = Dest->getType(); |
4546 Type ElementTy = typeElementType(Ty); | 4543 Type ElementTy = typeElementType(Ty); |
4547 SizeT NumElements = typeNumElements(Ty); | 4544 SizeT NumElements = typeNumElements(Ty); |
4548 | 4545 |
4549 Operand *T = Ctx->getConstantUndef(Ty); | 4546 Operand *T = Ctx->getConstantUndef(Ty); |
4550 for (SizeT I = 0; I < NumElements; ++I) { | 4547 for (SizeT I = 0; I < NumElements; ++I) { |
4551 Constant *Index = Ctx->getConstantInt32(I); | 4548 Constant *Index = Ctx->getConstantInt32(I); |
4552 | 4549 |
4553 // Extract the next two inputs. | 4550 // Extract the next two inputs. |
4554 Variable *Op0 = Func->template makeVariable(ElementTy); | 4551 Variable *Op0 = Func->makeVariable(ElementTy); |
4555 lowerExtractElement(InstExtractElement::create(Func, Op0, Src0, Index)); | 4552 lowerExtractElement(InstExtractElement::create(Func, Op0, Src0, Index)); |
4556 Variable *Op1 = Func->template makeVariable(ElementTy); | 4553 Variable *Op1 = Func->makeVariable(ElementTy); |
4557 lowerExtractElement(InstExtractElement::create(Func, Op1, Src1, Index)); | 4554 lowerExtractElement(InstExtractElement::create(Func, Op1, Src1, Index)); |
4558 | 4555 |
4559 // Perform the arithmetic as a scalar operation. | 4556 // Perform the arithmetic as a scalar operation. |
4560 Variable *Res = Func->template makeVariable(ElementTy); | 4557 Variable *Res = Func->makeVariable(ElementTy); |
4561 lowerArithmetic(InstArithmetic::create(Func, Kind, Res, Op0, Op1)); | 4558 lowerArithmetic(InstArithmetic::create(Func, Kind, Res, Op0, Op1)); |
4562 | 4559 |
4563 // Insert the result into position. | 4560 // Insert the result into position. |
4564 Variable *DestT = Func->template makeVariable(Ty); | 4561 Variable *DestT = Func->makeVariable(Ty); |
4565 lowerInsertElement(InstInsertElement::create(Func, DestT, T, Res, Index)); | 4562 lowerInsertElement(InstInsertElement::create(Func, DestT, T, Res, Index)); |
4566 T = DestT; | 4563 T = DestT; |
4567 } | 4564 } |
4568 | 4565 |
4569 lowerAssign(InstAssign::create(Func, Dest, T)); | 4566 lowerAssign(InstAssign::create(Func, Dest, T)); |
4570 } | 4567 } |
4571 | 4568 |
4572 /// The following pattern occurs often in lowered C and C++ code: | 4569 /// The following pattern occurs often in lowered C and C++ code: |
4573 /// | 4570 /// |
4574 /// %cmp = fcmp/icmp pred <n x ty> %src0, %src1 | 4571 /// %cmp = fcmp/icmp pred <n x ty> %src0, %src1 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4714 PhiLo->addArgument(loOperand(Src), Label); | 4711 PhiLo->addArgument(loOperand(Src), Label); |
4715 PhiHi->addArgument(hiOperand(Src), Label); | 4712 PhiHi->addArgument(hiOperand(Src), Label); |
4716 } | 4713 } |
4717 Node->getPhis().push_back(PhiLo); | 4714 Node->getPhis().push_back(PhiLo); |
4718 Node->getPhis().push_back(PhiHi); | 4715 Node->getPhis().push_back(PhiHi); |
4719 Phi->setDeleted(); | 4716 Phi->setDeleted(); |
4720 } | 4717 } |
4721 } | 4718 } |
4722 } | 4719 } |
4723 | 4720 |
4724 bool isMemoryOperand(const Operand *Opnd) { | 4721 inline bool isMemoryOperand(const Operand *Opnd) { |
4725 if (const auto Var = llvm::dyn_cast<Variable>(Opnd)) | 4722 if (const auto Var = llvm::dyn_cast<Variable>(Opnd)) |
4726 return !Var->hasReg(); | 4723 return !Var->hasReg(); |
4727 // We treat vector undef values the same as a memory operand, | 4724 // We treat vector undef values the same as a memory operand, |
4728 // because they do in fact need a register to materialize the vector | 4725 // because they do in fact need a register to materialize the vector |
4729 // of zeroes into. | 4726 // of zeroes into. |
4730 if (llvm::isa<ConstantUndef>(Opnd)) | 4727 if (llvm::isa<ConstantUndef>(Opnd)) |
4731 return isScalarFloatingType(Opnd->getType()) || | 4728 return isScalarFloatingType(Opnd->getType()) || |
4732 isVectorType(Opnd->getType()); | 4729 isVectorType(Opnd->getType()); |
4733 if (llvm::isa<Constant>(Opnd)) | 4730 if (llvm::isa<Constant>(Opnd)) |
4734 return isScalarFloatingType(Opnd->getType()); | 4731 return isScalarFloatingType(Opnd->getType()); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4827 Variable *Preg = nullptr; | 4824 Variable *Preg = nullptr; |
4828 // TODO(stichnot): Opportunity for register randomization. | 4825 // TODO(stichnot): Opportunity for register randomization. |
4829 int32_t RegNum = AvailRegsForType.find_first(); | 4826 int32_t RegNum = AvailRegsForType.find_first(); |
4830 bool IsVector = isVectorType(Dest->getType()); | 4827 bool IsVector = isVectorType(Dest->getType()); |
4831 bool NeedSpill = (RegNum == -1); | 4828 bool NeedSpill = (RegNum == -1); |
4832 if (NeedSpill) { | 4829 if (NeedSpill) { |
4833 // Pick some register to spill and update RegNum. | 4830 // Pick some register to spill and update RegNum. |
4834 // TODO(stichnot): Opportunity for register randomization. | 4831 // TODO(stichnot): Opportunity for register randomization. |
4835 RegNum = RegsForType.find_first(); | 4832 RegNum = RegsForType.find_first(); |
4836 Preg = getPhysicalRegister(RegNum, Dest->getType()); | 4833 Preg = getPhysicalRegister(RegNum, Dest->getType()); |
4837 SpillLoc = Func->template makeVariable(Dest->getType()); | 4834 SpillLoc = Func->makeVariable(Dest->getType()); |
4838 // Create a fake def of the physical register to avoid | 4835 // Create a fake def of the physical register to avoid |
4839 // liveness inconsistency problems during late-stage liveness | 4836 // liveness inconsistency problems during late-stage liveness |
4840 // analysis (e.g. asm-verbose mode). | 4837 // analysis (e.g. asm-verbose mode). |
4841 Context.insert(InstFakeDef::create(Func, Preg)); | 4838 Context.insert(InstFakeDef::create(Func, Preg)); |
4842 if (IsVector) | 4839 if (IsVector) |
4843 _movp(SpillLoc, Preg); | 4840 _movp(SpillLoc, Preg); |
4844 else | 4841 else |
4845 _mov(SpillLoc, Preg); | 4842 _mov(SpillLoc, Preg); |
4846 } | 4843 } |
4847 assert(RegNum >= 0); | 4844 assert(RegNum >= 0); |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5157 // Do legalization, which contains randomization/pooling | 5154 // Do legalization, which contains randomization/pooling |
5158 // or do randomization/pooling. | 5155 // or do randomization/pooling. |
5159 return llvm::cast<typename Traits::X86OperandMem>( | 5156 return llvm::cast<typename Traits::X86OperandMem>( |
5160 DoLegalize ? legalize(Mem) : randomizeOrPoolImmediate(Mem)); | 5157 DoLegalize ? legalize(Mem) : randomizeOrPoolImmediate(Mem)); |
5161 } | 5158 } |
5162 | 5159 |
5163 template <class Machine> | 5160 template <class Machine> |
5164 Variable *TargetX86Base<Machine>::makeReg(Type Type, int32_t RegNum) { | 5161 Variable *TargetX86Base<Machine>::makeReg(Type Type, int32_t RegNum) { |
5165 // There aren't any 64-bit integer registers for x86-32. | 5162 // There aren't any 64-bit integer registers for x86-32. |
5166 assert(Type != IceType_i64); | 5163 assert(Type != IceType_i64); |
5167 Variable *Reg = Func->template makeVariable(Type); | 5164 Variable *Reg = Func->makeVariable(Type); |
5168 if (RegNum == Variable::NoRegister) | 5165 if (RegNum == Variable::NoRegister) |
5169 Reg->setWeightInfinite(); | 5166 Reg->setWeightInfinite(); |
5170 else | 5167 else |
5171 Reg->setRegNum(RegNum); | 5168 Reg->setRegNum(RegNum); |
5172 return Reg; | 5169 return Reg; |
5173 } | 5170 } |
5174 | 5171 |
5175 template <class Machine> void TargetX86Base<Machine>::postLower() { | 5172 template <class Machine> void TargetX86Base<Machine>::postLower() { |
5176 if (Ctx->getFlags().getOptLevel() == Opt_m1) | 5173 if (Ctx->getFlags().getOptLevel() == Opt_m1) |
5177 return; | 5174 return; |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5419 } | 5416 } |
5420 // the offset is not eligible for blinding or pooling, return the original | 5417 // the offset is not eligible for blinding or pooling, return the original |
5421 // mem operand | 5418 // mem operand |
5422 return MemOperand; | 5419 return MemOperand; |
5423 } | 5420 } |
5424 | 5421 |
5425 } // end of namespace X86Internal | 5422 } // end of namespace X86Internal |
5426 } // end of namespace Ice | 5423 } // end of namespace Ice |
5427 | 5424 |
5428 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H | 5425 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H |
OLD | NEW |