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 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
317 "Traits::InstructionSet range different from TargetInstructionSet"); | 317 "Traits::InstructionSet range different from TargetInstructionSet"); |
318 if (Func->getContext()->getFlags().getTargetInstructionSet() != | 318 if (Func->getContext()->getFlags().getTargetInstructionSet() != |
319 TargetInstructionSet::BaseInstructionSet) { | 319 TargetInstructionSet::BaseInstructionSet) { |
320 InstructionSet = static_cast<typename Traits::InstructionSet>( | 320 InstructionSet = static_cast<typename Traits::InstructionSet>( |
321 (Func->getContext()->getFlags().getTargetInstructionSet() - | 321 (Func->getContext()->getFlags().getTargetInstructionSet() - |
322 TargetInstructionSet::X86InstructionSet_Begin) + | 322 TargetInstructionSet::X86InstructionSet_Begin) + |
323 Traits::InstructionSet::Begin); | 323 Traits::InstructionSet::Begin); |
324 } | 324 } |
325 } | 325 } |
326 | 326 |
327 template <class Machine> void TargetX86Base<Machine>::staticInit() { | 327 template <class Machine> |
328 void TargetX86Base<Machine>::staticInit(const ClFlags &Flags) { | |
328 Traits::initRegisterSet(&TypeToRegisterSet, &RegisterAliases, &ScratchRegs); | 329 Traits::initRegisterSet(&TypeToRegisterSet, &RegisterAliases, &ScratchRegs); |
330 PcRelFixup = Traits::FK_PcRel; | |
331 AbsFixup = Flags.getUseNonsfi() ? Traits::FK_Gotoff : Traits::FK_Abs; | |
329 } | 332 } |
330 | 333 |
331 template <class Machine> void TargetX86Base<Machine>::translateO2() { | 334 template <class Machine> void TargetX86Base<Machine>::translateO2() { |
332 TimerMarker T(TimerStack::TT_O2, Func); | 335 TimerMarker T(TimerStack::TT_O2, Func); |
333 | 336 |
337 if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) { | |
338 GotVar = Func->makeVariable(IceType_i32); | |
339 } | |
334 genTargetHelperCalls(); | 340 genTargetHelperCalls(); |
335 Func->dump("After target helper call insertion"); | 341 Func->dump("After target helper call insertion"); |
336 | 342 |
337 // Merge Alloca instructions, and lay out the stack. | 343 // Merge Alloca instructions, and lay out the stack. |
338 static constexpr bool SortAndCombineAllocas = true; | 344 static constexpr bool SortAndCombineAllocas = true; |
339 Func->processAllocas(SortAndCombineAllocas); | 345 Func->processAllocas(SortAndCombineAllocas); |
340 Func->dump("After Alloca processing"); | 346 Func->dump("After Alloca processing"); |
341 | 347 |
342 if (!Ctx->getFlags().getPhiEdgeSplit()) { | 348 if (!Ctx->getFlags().getPhiEdgeSplit()) { |
343 // Lower Phi instructions. | 349 // Lower Phi instructions. |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
392 Func->dump("After x86 address mode opt"); | 398 Func->dump("After x86 address mode opt"); |
393 | 399 |
394 // Disable constant blinding or pooling for load optimization. | 400 // Disable constant blinding or pooling for load optimization. |
395 { | 401 { |
396 BoolFlagSaver B(RandomizationPoolingPaused, true); | 402 BoolFlagSaver B(RandomizationPoolingPaused, true); |
397 doLoadOpt(); | 403 doLoadOpt(); |
398 } | 404 } |
399 Func->genCode(); | 405 Func->genCode(); |
400 if (Func->hasError()) | 406 if (Func->hasError()) |
401 return; | 407 return; |
408 initGotVarIfNeeded(); | |
402 Func->dump("After x86 codegen"); | 409 Func->dump("After x86 codegen"); |
403 | 410 |
404 // Register allocation. This requires instruction renumbering and full | 411 // Register allocation. This requires instruction renumbering and full |
405 // liveness analysis. Loops must be identified before liveness so variable | 412 // liveness analysis. Loops must be identified before liveness so variable |
406 // use weights are correct. | 413 // use weights are correct. |
407 Func->renumberInstructions(); | 414 Func->renumberInstructions(); |
408 if (Func->hasError()) | 415 if (Func->hasError()) |
409 return; | 416 return; |
410 Func->liveness(Liveness_Intervals); | 417 Func->liveness(Liveness_Intervals); |
411 if (Func->hasError()) | 418 if (Func->hasError()) |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
450 Func->doNopInsertion(); | 457 Func->doNopInsertion(); |
451 | 458 |
452 // Mark nodes that require sandbox alignment | 459 // Mark nodes that require sandbox alignment |
453 if (Ctx->getFlags().getUseSandboxing()) | 460 if (Ctx->getFlags().getUseSandboxing()) |
454 Func->markNodesForSandboxing(); | 461 Func->markNodesForSandboxing(); |
455 } | 462 } |
456 | 463 |
457 template <class Machine> void TargetX86Base<Machine>::translateOm1() { | 464 template <class Machine> void TargetX86Base<Machine>::translateOm1() { |
458 TimerMarker T(TimerStack::TT_Om1, Func); | 465 TimerMarker T(TimerStack::TT_Om1, Func); |
459 | 466 |
467 if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) { | |
468 GotVar = Func->makeVariable(IceType_i32); | |
469 } | |
460 genTargetHelperCalls(); | 470 genTargetHelperCalls(); |
461 | 471 |
462 // Do not merge Alloca instructions, and lay out the stack. | 472 // Do not merge Alloca instructions, and lay out the stack. |
463 static constexpr bool SortAndCombineAllocas = false; | 473 static constexpr bool SortAndCombineAllocas = false; |
464 Func->processAllocas(SortAndCombineAllocas); | 474 Func->processAllocas(SortAndCombineAllocas); |
465 Func->dump("After Alloca processing"); | 475 Func->dump("After Alloca processing"); |
466 | 476 |
467 Func->placePhiLoads(); | 477 Func->placePhiLoads(); |
468 if (Func->hasError()) | 478 if (Func->hasError()) |
469 return; | 479 return; |
470 Func->placePhiStores(); | 480 Func->placePhiStores(); |
471 if (Func->hasError()) | 481 if (Func->hasError()) |
472 return; | 482 return; |
473 Func->deletePhis(); | 483 Func->deletePhis(); |
474 if (Func->hasError()) | 484 if (Func->hasError()) |
475 return; | 485 return; |
476 Func->dump("After Phi lowering"); | 486 Func->dump("After Phi lowering"); |
477 | 487 |
478 Func->doArgLowering(); | 488 Func->doArgLowering(); |
479 Func->genCode(); | 489 Func->genCode(); |
480 if (Func->hasError()) | 490 if (Func->hasError()) |
481 return; | 491 return; |
492 initGotVarIfNeeded(); | |
482 Func->dump("After initial x8632 codegen"); | 493 Func->dump("After initial x8632 codegen"); |
483 | 494 |
484 regAlloc(RAK_InfOnly); | 495 regAlloc(RAK_InfOnly); |
485 if (Func->hasError()) | 496 if (Func->hasError()) |
486 return; | 497 return; |
487 Func->dump("After regalloc of infinite-weight variables"); | 498 Func->dump("After regalloc of infinite-weight variables"); |
488 | 499 |
489 Func->genFrame(); | 500 Func->genFrame(); |
490 if (Func->hasError()) | 501 if (Func->hasError()) |
491 return; | 502 return; |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
794 template <class Machine> | 805 template <class Machine> |
795 void TargetX86Base<Machine>::emitVariable(const Variable *Var) const { | 806 void TargetX86Base<Machine>::emitVariable(const Variable *Var) const { |
796 if (!BuildDefs::dump()) | 807 if (!BuildDefs::dump()) |
797 return; | 808 return; |
798 Ostream &Str = Ctx->getStrEmit(); | 809 Ostream &Str = Ctx->getStrEmit(); |
799 if (Var->hasReg()) { | 810 if (Var->hasReg()) { |
800 Str << "%" << getRegName(Var->getRegNum(), Var->getType()); | 811 Str << "%" << getRegName(Var->getRegNum(), Var->getType()); |
801 return; | 812 return; |
802 } | 813 } |
803 if (Var->mustHaveReg()) { | 814 if (Var->mustHaveReg()) { |
804 llvm_unreachable("Infinite-weight Variable has no register assigned"); | 815 llvm::report_fatal_error( |
816 "Infinite-weight Variable has no register assigned"); | |
805 } | 817 } |
806 const int32_t Offset = Var->getStackOffset(); | 818 const int32_t Offset = Var->getStackOffset(); |
807 int32_t BaseRegNum = Var->getBaseRegNum(); | 819 int32_t BaseRegNum = Var->getBaseRegNum(); |
808 if (BaseRegNum == Variable::NoRegister) | 820 if (BaseRegNum == Variable::NoRegister) |
809 BaseRegNum = getFrameOrStackReg(); | 821 BaseRegNum = getFrameOrStackReg(); |
810 // Print in the form "Offset(%reg)", taking care that: | 822 // Print in the form "Offset(%reg)", taking care that: |
811 // - Offset is never printed when it is 0 | 823 // - Offset is never printed when it is 0 |
812 | 824 |
813 const bool DecorateAsm = Func->getContext()->getFlags().getDecorateAsm(); | 825 const bool DecorateAsm = Func->getContext()->getFlags().getDecorateAsm(); |
814 // Only print Offset when it is nonzero, regardless of DecorateAsm. | 826 // Only print Offset when it is nonzero, regardless of DecorateAsm. |
815 if (Offset) { | 827 if (Offset) { |
816 if (DecorateAsm) { | 828 if (DecorateAsm) { |
817 Str << Var->getSymbolicStackOffset(Func); | 829 Str << Var->getSymbolicStackOffset(Func); |
818 } else { | 830 } else { |
819 Str << Offset; | 831 Str << Offset; |
820 } | 832 } |
821 } | 833 } |
822 const Type FrameSPTy = Traits::WordType; | 834 const Type FrameSPTy = Traits::WordType; |
823 Str << "(%" << getRegName(BaseRegNum, FrameSPTy) << ")"; | 835 Str << "(%" << getRegName(BaseRegNum, FrameSPTy) << ")"; |
824 } | 836 } |
825 | 837 |
826 template <class Machine> | 838 template <class Machine> |
827 typename TargetX86Base<Machine>::Traits::Address | 839 typename TargetX86Base<Machine>::Traits::Address |
828 TargetX86Base<Machine>::stackVarToAsmOperand(const Variable *Var) const { | 840 TargetX86Base<Machine>::stackVarToAsmOperand(const Variable *Var) const { |
829 if (Var->hasReg()) | 841 if (Var->hasReg()) |
830 llvm_unreachable("Stack Variable has a register assigned"); | 842 llvm::report_fatal_error("Stack Variable has a register assigned"); |
831 if (Var->mustHaveReg()) { | 843 if (Var->mustHaveReg()) { |
832 llvm_unreachable("Infinite-weight Variable has no register assigned"); | 844 llvm::report_fatal_error( |
845 "Infinite-weight Variable has no register assigned"); | |
833 } | 846 } |
834 int32_t Offset = Var->getStackOffset(); | 847 int32_t Offset = Var->getStackOffset(); |
835 int32_t BaseRegNum = Var->getBaseRegNum(); | 848 int32_t BaseRegNum = Var->getBaseRegNum(); |
836 if (Var->getBaseRegNum() == Variable::NoRegister) | 849 if (Var->getBaseRegNum() == Variable::NoRegister) |
837 BaseRegNum = getFrameOrStackReg(); | 850 BaseRegNum = getFrameOrStackReg(); |
838 return typename Traits::Address(Traits::getEncodedGPR(BaseRegNum), Offset, | 851 return typename Traits::Address(Traits::getEncodedGPR(BaseRegNum), Offset, |
839 AssemblerFixup::NoFixup); | 852 AssemblerFixup::NoFixup); |
840 } | 853 } |
841 | 854 |
842 /// Helper function for addProlog(). | 855 /// Helper function for addProlog(). |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
903 return Var64On32->getLo(); | 916 return Var64On32->getLo(); |
904 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | 917 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
905 auto *ConstInt = llvm::dyn_cast<ConstantInteger32>( | 918 auto *ConstInt = llvm::dyn_cast<ConstantInteger32>( |
906 Ctx->getConstantInt32(static_cast<int32_t>(Const->getValue()))); | 919 Ctx->getConstantInt32(static_cast<int32_t>(Const->getValue()))); |
907 // Check if we need to blind/pool the constant. | 920 // Check if we need to blind/pool the constant. |
908 return legalize(ConstInt); | 921 return legalize(ConstInt); |
909 } | 922 } |
910 if (auto *Mem = llvm::dyn_cast<typename Traits::X86OperandMem>(Operand)) { | 923 if (auto *Mem = llvm::dyn_cast<typename Traits::X86OperandMem>(Operand)) { |
911 auto *MemOperand = Traits::X86OperandMem::create( | 924 auto *MemOperand = Traits::X86OperandMem::create( |
912 Func, IceType_i32, Mem->getBase(), Mem->getOffset(), Mem->getIndex(), | 925 Func, IceType_i32, Mem->getBase(), Mem->getOffset(), Mem->getIndex(), |
913 Mem->getShift(), Mem->getSegmentRegister()); | 926 Mem->getShift(), Mem->getSegmentRegister(), Mem->getIsPIC()); |
914 // Test if we should randomize or pool the offset, if so randomize it or | 927 // Test if we should randomize or pool the offset, if so randomize it or |
915 // pool it then create mem operand with the blinded/pooled constant. | 928 // pool it then create mem operand with the blinded/pooled constant. |
916 // Otherwise, return the mem operand as ordinary mem operand. | 929 // Otherwise, return the mem operand as ordinary mem operand. |
917 return legalize(MemOperand); | 930 return legalize(MemOperand); |
918 } | 931 } |
919 llvm_unreachable("Unsupported operand type"); | 932 llvm_unreachable("Unsupported operand type"); |
920 return nullptr; | 933 return nullptr; |
921 } | 934 } |
922 | 935 |
923 template <class Machine> | 936 template <class Machine> |
(...skipping 19 matching lines...) Expand all Loading... | |
943 } else if (auto *IntOffset = llvm::dyn_cast<ConstantInteger32>(Offset)) { | 956 } else if (auto *IntOffset = llvm::dyn_cast<ConstantInteger32>(Offset)) { |
944 Offset = Ctx->getConstantInt32(4 + IntOffset->getValue()); | 957 Offset = Ctx->getConstantInt32(4 + IntOffset->getValue()); |
945 } else if (auto *SymOffset = llvm::dyn_cast<ConstantRelocatable>(Offset)) { | 958 } else if (auto *SymOffset = llvm::dyn_cast<ConstantRelocatable>(Offset)) { |
946 assert(!Utils::WouldOverflowAdd(SymOffset->getOffset(), 4)); | 959 assert(!Utils::WouldOverflowAdd(SymOffset->getOffset(), 4)); |
947 Offset = | 960 Offset = |
948 Ctx->getConstantSym(4 + SymOffset->getOffset(), SymOffset->getName(), | 961 Ctx->getConstantSym(4 + SymOffset->getOffset(), SymOffset->getName(), |
949 SymOffset->getSuppressMangling()); | 962 SymOffset->getSuppressMangling()); |
950 } | 963 } |
951 auto *MemOperand = Traits::X86OperandMem::create( | 964 auto *MemOperand = Traits::X86OperandMem::create( |
952 Func, IceType_i32, Mem->getBase(), Offset, Mem->getIndex(), | 965 Func, IceType_i32, Mem->getBase(), Offset, Mem->getIndex(), |
953 Mem->getShift(), Mem->getSegmentRegister()); | 966 Mem->getShift(), Mem->getSegmentRegister(), Mem->getIsPIC()); |
954 // Test if the Offset is an eligible i32 constants for randomization and | 967 // Test if the Offset is an eligible i32 constants for randomization and |
955 // pooling. Blind/pool it if it is. Otherwise return as oridinary mem | 968 // pooling. Blind/pool it if it is. Otherwise return as oridinary mem |
956 // operand. | 969 // operand. |
957 return legalize(MemOperand); | 970 return legalize(MemOperand); |
958 } | 971 } |
959 llvm_unreachable("Unsupported operand type"); | 972 llvm_unreachable("Unsupported operand type"); |
960 return nullptr; | 973 return nullptr; |
961 } | 974 } |
962 | 975 |
963 template <class Machine> | 976 template <class Machine> |
964 llvm::SmallBitVector | 977 llvm::SmallBitVector |
965 TargetX86Base<Machine>::getRegisterSet(RegSetMask Include, | 978 TargetX86Base<Machine>::getRegisterSet(RegSetMask Include, |
966 RegSetMask Exclude) const { | 979 RegSetMask Exclude) const { |
967 return Traits::getRegisterSet(Include, Exclude); | 980 return Traits::getRegisterSet(Include, Exclude); |
968 } | 981 } |
969 | 982 |
983 template <class Machine> void TargetX86Base<Machine>::initGotVarIfNeeded() { | |
984 if (!Func->getContext()->getFlags().getUseNonsfi()) | |
985 return; | |
986 if (Traits::Is64Bit) { | |
987 // Probably no implementation is needed, but error to be safe for now. | |
988 llvm::report_fatal_error( | |
989 "Need to implement initGotVarIfNeeded() for 64-bit."); | |
990 } | |
991 // Insert the GotVar assignment as the very first lowered instruction. Later, | |
992 // it will be moved into the right place - after the stack frame is set up but | |
993 // before in-args are copied into registers. | |
994 Context.init(Func->getEntryNode()); | |
995 Context.setInsertPoint(Context.getCur()); | |
996 Context.insert(InstX86GetIP<Machine>::create(Func, GotVar)); | |
997 } | |
998 | |
970 template <class Machine> | 999 template <class Machine> |
971 void TargetX86Base<Machine>::lowerAlloca(const InstAlloca *Inst) { | 1000 void TargetX86Base<Machine>::lowerAlloca(const InstAlloca *Inst) { |
972 // Conservatively require the stack to be aligned. Some stack adjustment | 1001 // Conservatively require the stack to be aligned. Some stack adjustment |
973 // operations implemented below assume that the stack is aligned before the | 1002 // operations implemented below assume that the stack is aligned before the |
974 // alloca. All the alloca code ensures that the stack alignment is preserved | 1003 // alloca. All the alloca code ensures that the stack alignment is preserved |
975 // after the alloca. The stack alignment restriction can be relaxed in some | 1004 // after the alloca. The stack alignment restriction can be relaxed in some |
976 // cases. | 1005 // cases. |
977 NeedsStackAlignment = true; | 1006 NeedsStackAlignment = true; |
978 | 1007 |
979 // For default align=0, set it to the real value 1, to avoid any | 1008 // For default align=0, set it to the real value 1, to avoid any |
(...skipping 3011 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3991 } | 4020 } |
3992 _test(SecondVar, SecondVar); | 4021 _test(SecondVar, SecondVar); |
3993 _cmov(T_Dest2, T_Dest, Traits::Cond::Br_e); | 4022 _cmov(T_Dest2, T_Dest, Traits::Cond::Br_e); |
3994 _mov(DestLo, T_Dest2); | 4023 _mov(DestLo, T_Dest2); |
3995 _mov(DestHi, Ctx->getConstantZero(IceType_i32)); | 4024 _mov(DestHi, Ctx->getConstantZero(IceType_i32)); |
3996 } | 4025 } |
3997 | 4026 |
3998 template <class Machine> | 4027 template <class Machine> |
3999 void TargetX86Base<Machine>::typedLoad(Type Ty, Variable *Dest, Variable *Base, | 4028 void TargetX86Base<Machine>::typedLoad(Type Ty, Variable *Dest, Variable *Base, |
4000 Constant *Offset) { | 4029 Constant *Offset) { |
4030 // If Offset is a ConstantRelocatable in Non-SFI mode, we will need to | |
4031 // legalize Mem properly. | |
4032 if (Offset) | |
4033 assert(!llvm::isa<ConstantRelocatable>(Offset)); | |
4034 | |
4001 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); | 4035 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); |
4002 | 4036 |
4003 if (isVectorType(Ty)) | 4037 if (isVectorType(Ty)) |
4004 _movp(Dest, Mem); | 4038 _movp(Dest, Mem); |
4005 else if (Ty == IceType_f64) | 4039 else if (Ty == IceType_f64) |
4006 _movq(Dest, Mem); | 4040 _movq(Dest, Mem); |
4007 else | 4041 else |
4008 _mov(Dest, Mem); | 4042 _mov(Dest, Mem); |
4009 } | 4043 } |
4010 | 4044 |
4011 template <class Machine> | 4045 template <class Machine> |
4012 void TargetX86Base<Machine>::typedStore(Type Ty, Variable *Value, | 4046 void TargetX86Base<Machine>::typedStore(Type Ty, Variable *Value, |
4013 Variable *Base, Constant *Offset) { | 4047 Variable *Base, Constant *Offset) { |
4048 // If Offset is a ConstantRelocatable in Non-SFI mode, we will need to | |
4049 // legalize Mem properly. | |
4050 if (Offset) | |
4051 assert(!llvm::isa<ConstantRelocatable>(Offset)); | |
4052 | |
4014 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); | 4053 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); |
4015 | 4054 |
4016 if (isVectorType(Ty)) | 4055 if (isVectorType(Ty)) |
4017 _storep(Value, Mem); | 4056 _storep(Value, Mem); |
4018 else if (Ty == IceType_f64) | 4057 else if (Ty == IceType_f64) |
4019 _storeq(Value, Mem); | 4058 _storeq(Value, Mem); |
4020 else | 4059 else |
4021 _store(Value, Mem); | 4060 _store(Value, Mem); |
4022 } | 4061 } |
4023 | 4062 |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4313 Str << "<null>"; | 4352 Str << "<null>"; |
4314 Str << ", Index="; | 4353 Str << ", Index="; |
4315 if (Index) | 4354 if (Index) |
4316 Index->dump(Func); | 4355 Index->dump(Func); |
4317 else | 4356 else |
4318 Str << "<null>"; | 4357 Str << "<null>"; |
4319 Str << ", Shift=" << Shift << ", Offset=" << Offset | 4358 Str << ", Shift=" << Shift << ", Offset=" << Offset |
4320 << ", Relocatable=" << Relocatable << "\n"; | 4359 << ", Relocatable=" << Relocatable << "\n"; |
4321 } | 4360 } |
4322 | 4361 |
4323 inline bool matchAssign(const VariablesMetadata *VMetadata, Variable *&Var, | 4362 inline bool matchAssign(const VariablesMetadata *VMetadata, Variable *GotVar, |
4324 ConstantRelocatable *&Relocatable, int32_t &Offset, | 4363 Variable *&Var, ConstantRelocatable *&Relocatable, |
4325 const Inst *&Reason) { | 4364 int32_t &Offset, const Inst *&Reason) { |
4326 // Var originates from Var=SrcVar ==> set Var:=SrcVar | 4365 // Var originates from Var=SrcVar ==> set Var:=SrcVar |
4327 if (Var == nullptr) | 4366 if (Var == nullptr) |
4328 return false; | 4367 return false; |
4329 if (const Inst *VarAssign = VMetadata->getSingleDefinition(Var)) { | 4368 if (const Inst *VarAssign = VMetadata->getSingleDefinition(Var)) { |
4330 assert(!VMetadata->isMultiDef(Var)); | 4369 assert(!VMetadata->isMultiDef(Var)); |
4331 if (llvm::isa<InstAssign>(VarAssign)) { | 4370 if (llvm::isa<InstAssign>(VarAssign)) { |
4332 Operand *SrcOp = VarAssign->getSrc(0); | 4371 Operand *SrcOp = VarAssign->getSrc(0); |
4333 assert(SrcOp); | 4372 assert(SrcOp); |
4334 if (auto *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) { | 4373 if (auto *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) { |
4335 if (!VMetadata->isMultiDef(SrcVar) && | 4374 if (!VMetadata->isMultiDef(SrcVar) && |
4336 // TODO: ensure SrcVar stays single-BB | 4375 // TODO: ensure SrcVar stays single-BB |
4337 true) { | 4376 true) { |
4338 Var = SrcVar; | 4377 Var = SrcVar; |
4339 Reason = VarAssign; | 4378 Reason = VarAssign; |
4340 return true; | 4379 return true; |
4341 } | 4380 } |
4342 } else if (auto *Const = llvm::dyn_cast<ConstantInteger32>(SrcOp)) { | 4381 } else if (auto *Const = llvm::dyn_cast<ConstantInteger32>(SrcOp)) { |
4343 int32_t MoreOffset = Const->getValue(); | 4382 int32_t MoreOffset = Const->getValue(); |
4344 if (Utils::WouldOverflowAdd(Offset, MoreOffset)) | 4383 if (Utils::WouldOverflowAdd(Offset, MoreOffset)) |
4345 return false; | 4384 return false; |
4346 Var = nullptr; | 4385 Var = nullptr; |
4347 Offset += MoreOffset; | 4386 Offset += MoreOffset; |
4348 Reason = VarAssign; | 4387 Reason = VarAssign; |
4349 return true; | 4388 return true; |
4350 } else if (auto *AddReloc = llvm::dyn_cast<ConstantRelocatable>(SrcOp)) { | 4389 } else if (auto *AddReloc = llvm::dyn_cast<ConstantRelocatable>(SrcOp)) { |
4351 if (Relocatable == nullptr) { | 4390 if (Relocatable == nullptr) { |
4352 Var = nullptr; | 4391 Var = GotVar; |
4353 Relocatable = AddReloc; | 4392 Relocatable = AddReloc; |
4354 Reason = VarAssign; | 4393 Reason = VarAssign; |
4355 return true; | 4394 return true; |
4356 } | 4395 } |
4357 } | 4396 } |
4358 } | 4397 } |
4359 } | 4398 } |
4360 return false; | 4399 return false; |
4361 } | 4400 } |
4362 | 4401 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4461 return true; | 4500 return true; |
4462 } | 4501 } |
4463 } | 4502 } |
4464 } | 4503 } |
4465 } | 4504 } |
4466 } | 4505 } |
4467 } | 4506 } |
4468 return false; | 4507 return false; |
4469 } | 4508 } |
4470 | 4509 |
4471 inline bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base, | 4510 inline bool matchOffsetBase(const VariablesMetadata *VMetadata, |
4511 Variable *GotVar, Variable *&Base, | |
4512 Variable *&BaseOther, | |
4472 ConstantRelocatable *&Relocatable, int32_t &Offset, | 4513 ConstantRelocatable *&Relocatable, int32_t &Offset, |
4473 const Inst *&Reason) { | 4514 const Inst *&Reason) { |
4474 // Base is Base=Var+Const || Base is Base=Const+Var ==> | 4515 // Base is Base=Var+Const || Base is Base=Const+Var ==> |
4475 // set Base=Var, Offset+=Const | 4516 // set Base=Var, Offset+=Const |
4476 // Base is Base=Var-Const ==> | 4517 // Base is Base=Var-Const ==> |
4477 // set Base=Var, Offset-=Const | 4518 // set Base=Var, Offset-=Const |
4478 if (Base == nullptr) { | 4519 if (Base == nullptr) { |
4479 return false; | 4520 return false; |
4480 } | 4521 } |
4481 const Inst *BaseInst = VMetadata->getSingleDefinition(Base); | 4522 const Inst *BaseInst = VMetadata->getSingleDefinition(Base); |
(...skipping 30 matching lines...) Expand all Loading... | |
4512 if ((Relocatable && (Reloc0 || Reloc1)) || (Reloc0 && Reloc1)) | 4553 if ((Relocatable && (Reloc0 || Reloc1)) || (Reloc0 && Reloc1)) |
4513 return false; | 4554 return false; |
4514 // Don't know how to subtract a relocatable. | 4555 // Don't know how to subtract a relocatable. |
4515 if (!IsAdd && Reloc1) | 4556 if (!IsAdd && Reloc1) |
4516 return false; | 4557 return false; |
4517 // Incorporate ConstantRelocatables. | 4558 // Incorporate ConstantRelocatables. |
4518 if (Reloc0) | 4559 if (Reloc0) |
4519 NewRelocatable = Reloc0; | 4560 NewRelocatable = Reloc0; |
4520 else if (Reloc1) | 4561 else if (Reloc1) |
4521 NewRelocatable = Reloc1; | 4562 NewRelocatable = Reloc1; |
4563 if ((Reloc0 || Reloc1) && BaseOther && GotVar) | |
John
2016/01/04 21:33:51
add '!= nullptr'? or not. :)
Jim Stichnoth
2016/01/04 23:32:12
hmm, maybe not, since this follows the style of th
| |
4564 return false; | |
4522 // Compute the updated constant offset. | 4565 // Compute the updated constant offset. |
4523 if (Const0) { | 4566 if (Const0) { |
4524 int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue(); | 4567 int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue(); |
4525 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) | 4568 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) |
4526 return false; | 4569 return false; |
4527 NewOffset += MoreOffset; | 4570 NewOffset += MoreOffset; |
4528 } | 4571 } |
4529 if (Const1) { | 4572 if (Const1) { |
4530 int32_t MoreOffset = IsAdd ? Const1->getValue() : -Const1->getValue(); | 4573 int32_t MoreOffset = IsAdd ? Const1->getValue() : -Const1->getValue(); |
4531 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) | 4574 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) |
4532 return false; | 4575 return false; |
4533 NewOffset += MoreOffset; | 4576 NewOffset += MoreOffset; |
4534 } | 4577 } |
4535 // Update the computed address parameters once we are sure optimization | 4578 // Update the computed address parameters once we are sure optimization |
4536 // is valid. | 4579 // is valid. |
4580 if ((Reloc0 || Reloc1) && GotVar) { | |
4581 assert(BaseOther == nullptr); | |
4582 BaseOther = GotVar; | |
4583 } | |
4537 Base = NewBase; | 4584 Base = NewBase; |
4538 Offset = NewOffset; | 4585 Offset = NewOffset; |
4539 Relocatable = NewRelocatable; | 4586 Relocatable = NewRelocatable; |
4540 Reason = BaseInst; | 4587 Reason = BaseInst; |
4541 return true; | 4588 return true; |
4542 } | 4589 } |
4543 return false; | 4590 return false; |
4544 } | 4591 } |
4545 | 4592 |
4546 // Builds information for a canonical address expresion: | 4593 // Builds information for a canonical address expresion: |
4547 // <Relocatable + Offset>(Base, Index, Shift) | 4594 // <Relocatable + Offset>(Base, Index, Shift) |
4548 // On entry: | 4595 // On entry: |
4549 // Relocatable == null, | 4596 // Relocatable == null, |
4550 // Offset == 0, | 4597 // Offset == 0, |
4551 // Base is a Variable, | 4598 // Base is a Variable, |
4552 // Index == nullptr, | 4599 // Index == nullptr, |
4553 // Shift == 0 | 4600 // Shift == 0 |
4554 inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, | 4601 inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *GotVar, |
4555 ConstantRelocatable *&Relocatable, | 4602 ConstantRelocatable *&Relocatable, |
4556 int32_t &Offset, Variable *&Base, | 4603 int32_t &Offset, Variable *&Base, |
4557 Variable *&Index, uint16_t &Shift) { | 4604 Variable *&Index, uint16_t &Shift) { |
4558 bool AddressWasOptimized = false; | 4605 bool AddressWasOptimized = false; |
4559 Func->resetCurrentNode(); | 4606 Func->resetCurrentNode(); |
4560 if (Func->isVerbose(IceV_AddrOpt)) { | 4607 if (Func->isVerbose(IceV_AddrOpt)) { |
4561 OstreamLocker L(Func->getContext()); | 4608 OstreamLocker L(Func->getContext()); |
4562 Ostream &Str = Func->getContext()->getStrDump(); | 4609 Ostream &Str = Func->getContext()->getStrDump(); |
4563 Str << "\nStarting computeAddressOpt for instruction:\n "; | 4610 Str << "\nStarting computeAddressOpt for instruction:\n "; |
4564 Instr->dumpDecorated(Func); | 4611 Instr->dumpDecorated(Func); |
(...skipping 10 matching lines...) Expand all Loading... | |
4575 const bool MockBounds = Func->getContext()->getFlags().getMockBoundsCheck(); | 4622 const bool MockBounds = Func->getContext()->getFlags().getMockBoundsCheck(); |
4576 const VariablesMetadata *VMetadata = Func->getVMetadata(); | 4623 const VariablesMetadata *VMetadata = Func->getVMetadata(); |
4577 const Inst *Reason = nullptr; | 4624 const Inst *Reason = nullptr; |
4578 do { | 4625 do { |
4579 if (Reason) { | 4626 if (Reason) { |
4580 dumpAddressOpt(Func, Relocatable, Offset, Base, Index, Shift, Reason); | 4627 dumpAddressOpt(Func, Relocatable, Offset, Base, Index, Shift, Reason); |
4581 AddressWasOptimized = true; | 4628 AddressWasOptimized = true; |
4582 Reason = nullptr; | 4629 Reason = nullptr; |
4583 } | 4630 } |
4584 // Update Base and Index to follow through assignments to definitions. | 4631 // Update Base and Index to follow through assignments to definitions. |
4585 if (matchAssign(VMetadata, Base, Relocatable, Offset, Reason)) { | 4632 if (matchAssign(VMetadata, GotVar, Base, Relocatable, Offset, Reason)) { |
4586 // Assignments of Base from a Relocatable or ConstantInt32 can result | 4633 // Assignments of Base from a Relocatable or ConstantInt32 can result |
4587 // in Base becoming nullptr. To avoid code duplication in this loop we | 4634 // in Base becoming nullptr. To avoid code duplication in this loop we |
4588 // prefer that Base be non-nullptr if possible. | 4635 // prefer that Base be non-nullptr if possible. |
4589 if ((Base == nullptr) && (Index != nullptr) && Shift == 0) | 4636 if ((Base == nullptr) && (Index != nullptr) && Shift == 0) |
4590 std::swap(Base, Index); | 4637 std::swap(Base, Index); |
4591 continue; | 4638 continue; |
4592 } | 4639 } |
4593 if (matchAssign(VMetadata, Index, Relocatable, Offset, Reason)) | 4640 if (matchAssign(VMetadata, GotVar, Index, Relocatable, Offset, Reason)) |
4594 continue; | 4641 continue; |
4595 | 4642 |
4596 if (!MockBounds) { | 4643 if (!MockBounds) { |
4597 // Transition from: | 4644 // Transition from: |
4598 // <Relocatable + Offset>(Base) to | 4645 // <Relocatable + Offset>(Base) to |
4599 // <Relocatable + Offset>(Base, Index) | 4646 // <Relocatable + Offset>(Base, Index) |
4600 if (matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason)) | 4647 if (matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason)) |
4601 continue; | 4648 continue; |
4602 // Recognize multiply/shift and update Shift amount. | 4649 // Recognize multiply/shift and update Shift amount. |
4603 // Index becomes Index=Var<<Const && Const+Shift<=3 ==> | 4650 // Index becomes Index=Var<<Const && Const+Shift<=3 ==> |
4604 // Index=Var, Shift+=Const | 4651 // Index=Var, Shift+=Const |
4605 // Index becomes Index=Const*Var && log2(Const)+Shift<=3 ==> | 4652 // Index becomes Index=Const*Var && log2(Const)+Shift<=3 ==> |
4606 // Index=Var, Shift+=log2(Const) | 4653 // Index=Var, Shift+=log2(Const) |
4607 if (matchShiftedIndex(VMetadata, Index, Shift, Reason)) | 4654 if (matchShiftedIndex(VMetadata, Index, Shift, Reason)) |
4608 continue; | 4655 continue; |
4609 // If Shift is zero, the choice of Base and Index was purely arbitrary. | 4656 // If Shift is zero, the choice of Base and Index was purely arbitrary. |
4610 // Recognize multiply/shift and set Shift amount. | 4657 // Recognize multiply/shift and set Shift amount. |
4611 // Shift==0 && Base is Base=Var*Const && log2(Const)+Shift<=3 ==> | 4658 // Shift==0 && Base is Base=Var*Const && log2(Const)+Shift<=3 ==> |
4612 // swap(Index,Base) | 4659 // swap(Index,Base) |
4613 // Similar for Base=Const*Var and Base=Var<<Const | 4660 // Similar for Base=Const*Var and Base=Var<<Const |
4614 if (Shift == 0 && matchShiftedIndex(VMetadata, Base, Shift, Reason)) { | 4661 if (Shift == 0 && matchShiftedIndex(VMetadata, Base, Shift, Reason)) { |
4615 std::swap(Base, Index); | 4662 std::swap(Base, Index); |
4616 continue; | 4663 continue; |
4617 } | 4664 } |
4618 } | 4665 } |
4619 // Update Offset to reflect additions/subtractions with constants and | 4666 // Update Offset to reflect additions/subtractions with constants and |
4620 // relocatables. | 4667 // relocatables. |
4621 // TODO: consider overflow issues with respect to Offset. | 4668 // TODO: consider overflow issues with respect to Offset. |
4622 if (matchOffsetBase(VMetadata, Base, Relocatable, Offset, Reason)) | 4669 if (matchOffsetBase(VMetadata, GotVar, Base, Index, Relocatable, Offset, |
4670 Reason)) | |
4623 continue; | 4671 continue; |
4624 if (Shift == 0 && | 4672 if (Shift == 0 && matchOffsetBase(VMetadata, GotVar, Index, Base, |
4625 matchOffsetBase(VMetadata, Index, Relocatable, Offset, Reason)) | 4673 Relocatable, Offset, Reason)) |
4626 continue; | 4674 continue; |
4627 // TODO(sehr, stichnot): Handle updates of Index with Shift != 0. | 4675 // TODO(sehr, stichnot): Handle updates of Index with Shift != 0. |
4628 // Index is Index=Var+Const ==> | 4676 // Index is Index=Var+Const ==> |
4629 // set Index=Var, Offset+=(Const<<Shift) | 4677 // set Index=Var, Offset+=(Const<<Shift) |
4630 // Index is Index=Const+Var ==> | 4678 // Index is Index=Const+Var ==> |
4631 // set Index=Var, Offset+=(Const<<Shift) | 4679 // set Index=Var, Offset+=(Const<<Shift) |
4632 // Index is Index=Var-Const ==> | 4680 // Index is Index=Var-Const ==> |
4633 // set Index=Var, Offset-=(Const<<Shift) | 4681 // set Index=Var, Offset-=(Const<<Shift) |
4634 break; | 4682 break; |
4635 } while (Reason); | 4683 } while (Reason); |
4684 // Undo any addition of GotVar. It will be added back when the mem operand is | |
4685 // legalized. | |
4686 if (Base == GotVar) | |
4687 Base = nullptr; | |
4688 if (Index == GotVar) | |
4689 Index = nullptr; | |
4636 return AddressWasOptimized; | 4690 return AddressWasOptimized; |
4637 } | 4691 } |
4638 | 4692 |
4639 /// Add a mock bounds check on the memory address before using it as a load or | 4693 /// Add a mock bounds check on the memory address before using it as a load or |
4640 /// store operand. The basic idea is that given a memory operand [reg], we | 4694 /// store operand. The basic idea is that given a memory operand [reg], we |
4641 /// would first add bounds-check code something like: | 4695 /// would first add bounds-check code something like: |
4642 /// | 4696 /// |
4643 /// cmp reg, <lb> | 4697 /// cmp reg, <lb> |
4644 /// jl out_of_line_error | 4698 /// jl out_of_line_error |
4645 /// cmp reg, <ub> | 4699 /// cmp reg, <ub> |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4691 _br(Traits::Cond::Br_e, Label); | 4745 _br(Traits::Cond::Br_e, Label); |
4692 _cmp(Opnd, Ctx->getConstantInt32(1)); | 4746 _cmp(Opnd, Ctx->getConstantInt32(1)); |
4693 _br(Traits::Cond::Br_e, Label); | 4747 _br(Traits::Cond::Br_e, Label); |
4694 Context.insert(Label); | 4748 Context.insert(Label); |
4695 } | 4749 } |
4696 | 4750 |
4697 template <class Machine> | 4751 template <class Machine> |
4698 void TargetX86Base<Machine>::lowerLoad(const InstLoad *Load) { | 4752 void TargetX86Base<Machine>::lowerLoad(const InstLoad *Load) { |
4699 // A Load instruction can be treated the same as an Assign instruction, after | 4753 // A Load instruction can be treated the same as an Assign instruction, after |
4700 // the source operand is transformed into an Traits::X86OperandMem operand. | 4754 // the source operand is transformed into an Traits::X86OperandMem operand. |
4701 // Note that the address mode optimization already creates an | 4755 // Note that the address mode optimization already creates a |
4702 // Traits::X86OperandMem operand, so it doesn't need another level of | 4756 // Traits::X86OperandMem operand, so it doesn't need another level of |
4703 // transformation. | 4757 // transformation. |
4704 Variable *DestLoad = Load->getDest(); | 4758 Variable *DestLoad = Load->getDest(); |
4705 Type Ty = DestLoad->getType(); | 4759 Type Ty = DestLoad->getType(); |
4706 Operand *Src0 = formMemoryOperand(Load->getSourceAddress(), Ty); | 4760 Operand *Src0 = formMemoryOperand(Load->getSourceAddress(), Ty); |
4707 doMockBoundsCheck(Src0); | 4761 doMockBoundsCheck(Src0); |
4708 auto *Assign = InstAssign::create(Func, DestLoad, Src0); | 4762 auto *Assign = InstAssign::create(Func, DestLoad, Src0); |
4709 lowerAssign(Assign); | 4763 lowerAssign(Assign); |
4710 } | 4764 } |
4711 | 4765 |
4712 template <class Machine> void TargetX86Base<Machine>::doAddressOptLoad() { | 4766 template <class Machine> void TargetX86Base<Machine>::doAddressOptLoad() { |
4713 Inst *Inst = Context.getCur(); | 4767 Inst *Inst = Context.getCur(); |
4714 Variable *Dest = Inst->getDest(); | 4768 Variable *Dest = Inst->getDest(); |
4715 Operand *Addr = Inst->getSrc(0); | 4769 Operand *Addr = Inst->getSrc(0); |
4716 Variable *Index = nullptr; | 4770 Variable *Index = nullptr; |
4717 ConstantRelocatable *Relocatable = nullptr; | 4771 ConstantRelocatable *Relocatable = nullptr; |
4718 uint16_t Shift = 0; | 4772 uint16_t Shift = 0; |
4719 int32_t Offset = 0; | 4773 int32_t Offset = 0; |
4720 // Vanilla ICE load instructions should not use the segment registers, and | 4774 // Vanilla ICE load instructions should not use the segment registers, and |
4721 // computeAddressOpt only works at the level of Variables and Constants, not | 4775 // computeAddressOpt only works at the level of Variables and Constants, not |
4722 // other Traits::X86OperandMem, so there should be no mention of segment | 4776 // other Traits::X86OperandMem, so there should be no mention of segment |
4723 // registers there either. | 4777 // registers there either. |
4724 const typename Traits::X86OperandMem::SegmentRegisters SegmentReg = | 4778 constexpr auto SegmentReg = |
4725 Traits::X86OperandMem::DefaultSegment; | 4779 Traits::X86OperandMem::SegmentRegisters::DefaultSegment; |
4726 auto *Base = llvm::dyn_cast<Variable>(Addr); | 4780 auto *Base = llvm::dyn_cast<Variable>(Addr); |
4727 if (computeAddressOpt(Func, Inst, Relocatable, Offset, Base, Index, Shift)) { | 4781 if (computeAddressOpt(Func, Inst, GotVar, Relocatable, Offset, Base, Index, |
4782 Shift)) { | |
4728 Inst->setDeleted(); | 4783 Inst->setDeleted(); |
4729 Constant *OffsetOp = nullptr; | 4784 Constant *OffsetOp = nullptr; |
4730 if (Relocatable == nullptr) { | 4785 if (Relocatable == nullptr) { |
4731 OffsetOp = Ctx->getConstantInt32(Offset); | 4786 OffsetOp = Ctx->getConstantInt32(Offset); |
4732 } else { | 4787 } else { |
4733 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset, | 4788 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset, |
4734 Relocatable->getName(), | 4789 Relocatable->getName(), |
4735 Relocatable->getSuppressMangling()); | 4790 Relocatable->getSuppressMangling()); |
4736 } | 4791 } |
4792 // The new mem operand is created without IsPIC being set, because | |
4793 // computeAddressOpt() doesn't include GotVar in its final result. | |
4737 Addr = Traits::X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp, | 4794 Addr = Traits::X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp, |
4738 Index, Shift, SegmentReg); | 4795 Index, Shift, SegmentReg); |
4739 Context.insert<InstLoad>(Dest, Addr); | 4796 Context.insert<InstLoad>(Dest, Addr); |
4740 } | 4797 } |
4741 } | 4798 } |
4742 | 4799 |
4743 template <class Machine> | 4800 template <class Machine> |
4744 void TargetX86Base<Machine>::randomlyInsertNop(float Probability, | 4801 void TargetX86Base<Machine>::randomlyInsertNop(float Probability, |
4745 RandomNumberGenerator &RNG) { | 4802 RandomNumberGenerator &RNG) { |
4746 RandomNumberGeneratorWrapper RNGW(RNG); | 4803 RandomNumberGeneratorWrapper RNGW(RNG); |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5021 Operand *Addr = Inst->getAddr(); | 5078 Operand *Addr = Inst->getAddr(); |
5022 Variable *Index = nullptr; | 5079 Variable *Index = nullptr; |
5023 ConstantRelocatable *Relocatable = nullptr; | 5080 ConstantRelocatable *Relocatable = nullptr; |
5024 uint16_t Shift = 0; | 5081 uint16_t Shift = 0; |
5025 int32_t Offset = 0; | 5082 int32_t Offset = 0; |
5026 auto *Base = llvm::dyn_cast<Variable>(Addr); | 5083 auto *Base = llvm::dyn_cast<Variable>(Addr); |
5027 // Vanilla ICE store instructions should not use the segment registers, and | 5084 // Vanilla ICE store instructions should not use the segment registers, and |
5028 // computeAddressOpt only works at the level of Variables and Constants, not | 5085 // computeAddressOpt only works at the level of Variables and Constants, not |
5029 // other Traits::X86OperandMem, so there should be no mention of segment | 5086 // other Traits::X86OperandMem, so there should be no mention of segment |
5030 // registers there either. | 5087 // registers there either. |
5031 const typename Traits::X86OperandMem::SegmentRegisters SegmentReg = | 5088 constexpr auto SegmentReg = Traits::X86OperandMem::DefaultSegment; |
5032 Traits::X86OperandMem::DefaultSegment; | 5089 if (computeAddressOpt(Func, Inst, GotVar, Relocatable, Offset, Base, Index, |
John
2016/01/04 21:33:51
These address mode formation helpers are now bette
Jim Stichnoth
2016/01/04 23:32:12
That seems good, but maybe as a follow-on CL? Giv
| |
5033 if (computeAddressOpt(Func, Inst, Relocatable, Offset, Base, Index, Shift)) { | 5090 Shift)) { |
5034 Inst->setDeleted(); | 5091 Inst->setDeleted(); |
5035 Constant *OffsetOp = nullptr; | 5092 Constant *OffsetOp = nullptr; |
5036 if (Relocatable == nullptr) { | 5093 if (Relocatable == nullptr) { |
5037 OffsetOp = Ctx->getConstantInt32(Offset); | 5094 OffsetOp = Ctx->getConstantInt32(Offset); |
5038 } else { | 5095 } else { |
5039 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset, | 5096 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset, |
5040 Relocatable->getName(), | 5097 Relocatable->getName(), |
5041 Relocatable->getSuppressMangling()); | 5098 Relocatable->getSuppressMangling()); |
5042 } | 5099 } |
5100 // The new mem operand is created without IsPIC being set, because | |
5101 // computeAddressOpt() doesn't include GotVar in its final result. | |
5043 Addr = Traits::X86OperandMem::create(Func, Data->getType(), Base, OffsetOp, | 5102 Addr = Traits::X86OperandMem::create(Func, Data->getType(), Base, OffsetOp, |
5044 Index, Shift, SegmentReg); | 5103 Index, Shift, SegmentReg); |
5045 auto *NewStore = Context.insert<InstStore>(Data, Addr); | 5104 auto *NewStore = Context.insert<InstStore>(Data, Addr); |
5046 if (Inst->getDest()) | 5105 if (Inst->getDest()) |
5047 NewStore->setRmwBeacon(Inst->getRmwBeacon()); | 5106 NewStore->setRmwBeacon(Inst->getRmwBeacon()); |
5048 } | 5107 } |
5049 } | 5108 } |
5050 | 5109 |
5051 template <class Machine> | 5110 template <class Machine> |
5052 Operand *TargetX86Base<Machine>::lowerCmpRange(Operand *Comparison, | 5111 Operand *TargetX86Base<Machine>::lowerCmpRange(Operand *Comparison, |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5093 Variable *Index; | 5152 Variable *Index; |
5094 if (RangeIndex->getType() != getPointerType()) { | 5153 if (RangeIndex->getType() != getPointerType()) { |
5095 Index = makeReg(getPointerType()); | 5154 Index = makeReg(getPointerType()); |
5096 _movzx(Index, RangeIndex); | 5155 _movzx(Index, RangeIndex); |
5097 } else { | 5156 } else { |
5098 Index = legalizeToReg(RangeIndex); | 5157 Index = legalizeToReg(RangeIndex); |
5099 } | 5158 } |
5100 | 5159 |
5101 constexpr RelocOffsetT RelocOffset = 0; | 5160 constexpr RelocOffsetT RelocOffset = 0; |
5102 constexpr bool SuppressMangling = true; | 5161 constexpr bool SuppressMangling = true; |
5162 const bool IsPIC = Ctx->getFlags().getUseNonsfi(); | |
5103 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); | 5163 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); |
5104 Constant *Base = Ctx->getConstantSym( | 5164 Variable *Base = IsPIC ? legalizeToReg(GotVar) : nullptr; |
5165 Constant *Offset = Ctx->getConstantSym( | |
5105 RelocOffset, InstJumpTable::makeName(MangledName, JumpTable->getId()), | 5166 RelocOffset, InstJumpTable::makeName(MangledName, JumpTable->getId()), |
5106 SuppressMangling); | 5167 SuppressMangling); |
5107 Constant *Offset = nullptr; | |
5108 uint16_t Shift = typeWidthInBytesLog2(getPointerType()); | 5168 uint16_t Shift = typeWidthInBytesLog2(getPointerType()); |
5109 // TODO(ascull): remove need for legalize by allowing null base in memop | 5169 constexpr auto Segment = Traits::X86OperandMem::DefaultSegment; |
5110 auto *TargetInMemory = Traits::X86OperandMem::create( | 5170 auto *TargetInMemory = Traits::X86OperandMem::create( |
5111 Func, getPointerType(), legalizeToReg(Base), Offset, Index, Shift); | 5171 Func, getPointerType(), Base, Offset, Index, Shift, Segment, IsPIC); |
5112 Variable *Target = nullptr; | 5172 Variable *Target = nullptr; |
5113 _mov(Target, TargetInMemory); | 5173 _mov(Target, TargetInMemory); |
5114 lowerIndirectJump(Target); | 5174 lowerIndirectJump(Target); |
5115 | 5175 |
5116 if (DefaultTarget == nullptr) | 5176 if (DefaultTarget == nullptr) |
5117 Context.insert(SkipJumpTable); | 5177 Context.insert(SkipJumpTable); |
5118 return; | 5178 return; |
5119 } | 5179 } |
5120 case CaseCluster::Range: { | 5180 case CaseCluster::Range: { |
5121 if (Case.isUnitRange()) { | 5181 if (Case.isUnitRange()) { |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5432 if (const auto *RMW = | 5492 if (const auto *RMW = |
5433 llvm::dyn_cast<typename Traits::Insts::FakeRMW>(Instr)) { | 5493 llvm::dyn_cast<typename Traits::Insts::FakeRMW>(Instr)) { |
5434 lowerRMW(RMW); | 5494 lowerRMW(RMW); |
5435 } else { | 5495 } else { |
5436 TargetLowering::lowerOther(Instr); | 5496 TargetLowering::lowerOther(Instr); |
5437 } | 5497 } |
5438 } | 5498 } |
5439 | 5499 |
5440 /// Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve | 5500 /// Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve |
5441 /// integrity of liveness analysis. Undef values are also turned into zeroes, | 5501 /// integrity of liveness analysis. Undef values are also turned into zeroes, |
5442 /// since loOperand() and hiOperand() don't expect Undef input. | 5502 /// since loOperand() and hiOperand() don't expect Undef input. Also, in |
5503 /// Non-SFI mode, add a FakeUse(GotVar) for every pooled constant operand. | |
5443 template <class Machine> void TargetX86Base<Machine>::prelowerPhis() { | 5504 template <class Machine> void TargetX86Base<Machine>::prelowerPhis() { |
5505 if (Ctx->getFlags().getUseNonsfi()) { | |
5506 assert(GotVar); | |
5507 CfgNode *Node = Context.getNode(); | |
5508 uint32_t GotVarUseCount = 0; | |
5509 for (Inst &I : Node->getPhis()) { | |
5510 auto *Phi = llvm::dyn_cast<InstPhi>(&I); | |
5511 if (Phi->isDeleted()) | |
5512 continue; | |
5513 for (SizeT I = 0; I < Phi->getSrcSize(); ++I) { | |
5514 Operand *Src = Phi->getSrc(I); | |
5515 // TODO(stichnot): This over-counts for +0.0, and under-counts for other | |
5516 // kinds of pooling. | |
5517 if (llvm::isa<ConstantRelocatable>(Src) || | |
5518 llvm::isa<ConstantFloat>(Src) || llvm::isa<ConstantDouble>(Src)) { | |
5519 ++GotVarUseCount; | |
5520 } | |
5521 } | |
5522 } | |
5523 if (GotVarUseCount) { | |
5524 Node->getInsts().push_front(InstFakeUse::create(Func, GotVar)); | |
5525 } | |
5526 } | |
5444 if (Traits::Is64Bit) { | 5527 if (Traits::Is64Bit) { |
5445 // On x86-64 we don't need to prelower phis -- the architecture can handle | 5528 // On x86-64 we don't need to prelower phis -- the architecture can handle |
5446 // 64-bit integer natively. | 5529 // 64-bit integer natively. |
5447 return; | 5530 return; |
5448 } | 5531 } |
5449 | 5532 |
5450 // Pause constant blinding or pooling, blinding or pooling will be done later | 5533 // Pause constant blinding or pooling, blinding or pooling will be done later |
5451 // during phi lowering assignments | 5534 // during phi lowering assignments |
5452 BoolFlagSaver B(RandomizationPoolingPaused, true); | 5535 BoolFlagSaver B(RandomizationPoolingPaused, true); |
5453 PhiLowering::prelowerPhis32Bit<TargetX86Base<Machine>>( | 5536 PhiLowering::prelowerPhis32Bit<TargetX86Base<Machine>>( |
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5914 _movp(Reg, Src); | 5997 _movp(Reg, Src); |
5915 } else { | 5998 } else { |
5916 _mov(Reg, Src); | 5999 _mov(Reg, Src); |
5917 } | 6000 } |
5918 return Reg; | 6001 return Reg; |
5919 } | 6002 } |
5920 | 6003 |
5921 template <class Machine> | 6004 template <class Machine> |
5922 Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, | 6005 Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, |
5923 int32_t RegNum) { | 6006 int32_t RegNum) { |
5924 Type Ty = From->getType(); | 6007 const bool UseNonsfi = Func->getContext()->getFlags().getUseNonsfi(); |
6008 const Type Ty = From->getType(); | |
5925 // Assert that a physical register is allowed. To date, all calls to | 6009 // Assert that a physical register is allowed. To date, all calls to |
5926 // legalize() allow a physical register. If a physical register needs to be | 6010 // legalize() allow a physical register. If a physical register needs to be |
5927 // explicitly disallowed, then new code will need to be written to force a | 6011 // explicitly disallowed, then new code will need to be written to force a |
5928 // spill. | 6012 // spill. |
5929 assert(Allowed & Legal_Reg); | 6013 assert(Allowed & Legal_Reg); |
5930 // If we're asking for a specific physical register, make sure we're not | 6014 // If we're asking for a specific physical register, make sure we're not |
5931 // allowing any other operand kinds. (This could be future work, e.g. allow | 6015 // allowing any other operand kinds. (This could be future work, e.g. allow |
5932 // the shl shift amount to be either an immediate or in ecx.) | 6016 // the shl shift amount to be either an immediate or in ecx.) |
5933 assert(RegNum == Variable::NoRegister || Allowed == Legal_Reg); | 6017 assert(RegNum == Variable::NoRegister || Allowed == Legal_Reg); |
5934 | 6018 |
(...skipping 13 matching lines...) Expand all Loading... | |
5948 } | 6032 } |
5949 } | 6033 } |
5950 } | 6034 } |
5951 } | 6035 } |
5952 | 6036 |
5953 if (auto *Mem = llvm::dyn_cast<typename Traits::X86OperandMem>(From)) { | 6037 if (auto *Mem = llvm::dyn_cast<typename Traits::X86OperandMem>(From)) { |
5954 // Before doing anything with a Mem operand, we need to ensure that the | 6038 // Before doing anything with a Mem operand, we need to ensure that the |
5955 // Base and Index components are in physical registers. | 6039 // Base and Index components are in physical registers. |
5956 Variable *Base = Mem->getBase(); | 6040 Variable *Base = Mem->getBase(); |
5957 Variable *Index = Mem->getIndex(); | 6041 Variable *Index = Mem->getIndex(); |
6042 Constant *Offset = Mem->getOffset(); | |
5958 Variable *RegBase = nullptr; | 6043 Variable *RegBase = nullptr; |
5959 Variable *RegIndex = nullptr; | 6044 Variable *RegIndex = nullptr; |
5960 if (Base) { | 6045 if (Base) { |
5961 RegBase = llvm::cast<Variable>( | 6046 RegBase = llvm::cast<Variable>( |
5962 legalize(Base, Legal_Reg | Legal_Rematerializable)); | 6047 legalize(Base, Legal_Reg | Legal_Rematerializable)); |
5963 } | 6048 } |
5964 if (Index) { | 6049 if (Index) { |
5965 RegIndex = llvm::cast<Variable>( | 6050 RegIndex = llvm::cast<Variable>( |
5966 legalize(Index, Legal_Reg | Legal_Rematerializable)); | 6051 legalize(Index, Legal_Reg | Legal_Rematerializable)); |
5967 } | 6052 } |
6053 // For Non-SFI mode, if the Offset field is a ConstantRelocatable, we | |
6054 // replace either Base or Index with a legalized GotVar. At emission time, | |
6055 // the ConstantRelocatable will be emitted with the @GOTOFF relocation. | |
6056 bool NeedPIC = false; | |
6057 if (UseNonsfi && !Mem->getIsPIC() && Offset && | |
6058 llvm::isa<ConstantRelocatable>(Offset)) { | |
6059 assert(!(Allowed & Legal_AddrAbs)); | |
6060 NeedPIC = true; | |
6061 if (RegBase == nullptr) { | |
6062 RegBase = legalizeToReg(GotVar); | |
6063 } else if (RegIndex == nullptr) { | |
6064 RegIndex = legalizeToReg(GotVar); | |
6065 } else { | |
6066 llvm::report_fatal_error( | |
6067 "Either Base or Index must be unused in Non-SFI mode"); | |
6068 } | |
6069 } | |
5968 if (Base != RegBase || Index != RegIndex) { | 6070 if (Base != RegBase || Index != RegIndex) { |
5969 Mem = Traits::X86OperandMem::create(Func, Ty, RegBase, Mem->getOffset(), | 6071 Mem = Traits::X86OperandMem::create(Func, Ty, RegBase, Offset, RegIndex, |
5970 RegIndex, Mem->getShift(), | 6072 Mem->getShift(), |
5971 Mem->getSegmentRegister()); | 6073 Mem->getSegmentRegister(), NeedPIC); |
5972 } | 6074 } |
5973 | 6075 |
5974 // For all Memory Operands, we do randomization/pooling here | 6076 // For all Memory Operands, we do randomization/pooling here |
5975 From = randomizeOrPoolImmediate(Mem); | 6077 From = randomizeOrPoolImmediate(Mem); |
5976 | 6078 |
5977 if (!(Allowed & Legal_Mem)) { | 6079 if (!(Allowed & Legal_Mem)) { |
5978 From = copyToReg(From, RegNum); | 6080 From = copyToReg(From, RegNum); |
5979 } | 6081 } |
5980 return From; | 6082 return From; |
5981 } | 6083 } |
6084 | |
5982 if (auto *Const = llvm::dyn_cast<Constant>(From)) { | 6085 if (auto *Const = llvm::dyn_cast<Constant>(From)) { |
5983 if (llvm::isa<ConstantUndef>(Const)) { | 6086 if (llvm::isa<ConstantUndef>(Const)) { |
5984 From = legalizeUndef(Const, RegNum); | 6087 From = legalizeUndef(Const, RegNum); |
5985 if (isVectorType(Ty)) | 6088 if (isVectorType(Ty)) |
5986 return From; | 6089 return From; |
5987 Const = llvm::cast<Constant>(From); | 6090 Const = llvm::cast<Constant>(From); |
5988 } | 6091 } |
5989 // There should be no constants of vector type (other than undef). | 6092 // There should be no constants of vector type (other than undef). |
5990 assert(!isVectorType(Ty)); | 6093 assert(!isVectorType(Ty)); |
5991 | 6094 |
(...skipping 10 matching lines...) Expand all Loading... | |
6002 | 6105 |
6003 // If the operand is an 32 bit constant integer, we should check whether we | 6106 // If the operand is an 32 bit constant integer, we should check whether we |
6004 // need to randomize it or pool it. | 6107 // need to randomize it or pool it. |
6005 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Const)) { | 6108 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Const)) { |
6006 Operand *NewConst = randomizeOrPoolImmediate(C, RegNum); | 6109 Operand *NewConst = randomizeOrPoolImmediate(C, RegNum); |
6007 if (NewConst != Const) { | 6110 if (NewConst != Const) { |
6008 return NewConst; | 6111 return NewConst; |
6009 } | 6112 } |
6010 } | 6113 } |
6011 | 6114 |
6115 // If the operand is a ConstantRelocatable, and Legal_AddrAbs is not | |
6116 // specified, and UseNonsfi is indicated, we need to add GotVar. | |
6117 if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Const)) { | |
6118 if (UseNonsfi && !(Allowed & Legal_AddrAbs)) { | |
6119 assert(Ty == IceType_i32); | |
6120 Variable *RegBase = legalizeToReg(GotVar); | |
6121 Variable *NewVar = makeReg(Ty, RegNum); | |
6122 auto *Mem = Traits::X86OperandMem::create(Func, Ty, RegBase, CR); | |
6123 Mem->setIsPIC(); | |
6124 _lea(NewVar, Mem); | |
6125 From = NewVar; | |
6126 } | |
6127 } | |
6128 | |
6012 // Convert a scalar floating point constant into an explicit memory | 6129 // Convert a scalar floating point constant into an explicit memory |
6013 // operand. | 6130 // operand. |
6014 if (isScalarFloatingType(Ty)) { | 6131 if (isScalarFloatingType(Ty)) { |
6015 if (auto *ConstFloat = llvm::dyn_cast<ConstantFloat>(Const)) { | 6132 if (auto *ConstFloat = llvm::dyn_cast<ConstantFloat>(Const)) { |
6016 if (Utils::isPositiveZero(ConstFloat->getValue())) | 6133 if (Utils::isPositiveZero(ConstFloat->getValue())) |
6017 return makeZeroedRegister(Ty, RegNum); | 6134 return makeZeroedRegister(Ty, RegNum); |
6018 } else if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(Const)) { | 6135 } else if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(Const)) { |
6019 if (Utils::isPositiveZero(ConstDouble->getValue())) | 6136 if (Utils::isPositiveZero(ConstDouble->getValue())) |
6020 return makeZeroedRegister(Ty, RegNum); | 6137 return makeZeroedRegister(Ty, RegNum); |
6021 } | 6138 } |
6022 Variable *Base = nullptr; | 6139 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr; |
6023 std::string Buffer; | 6140 std::string Buffer; |
6024 llvm::raw_string_ostream StrBuf(Buffer); | 6141 llvm::raw_string_ostream StrBuf(Buffer); |
6025 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx); | 6142 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx); |
6026 llvm::cast<Constant>(From)->setShouldBePooled(true); | 6143 llvm::cast<Constant>(From)->setShouldBePooled(true); |
6027 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); | 6144 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); |
6028 From = Traits::X86OperandMem::create(Func, Ty, Base, Offset); | 6145 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); |
6146 if (UseNonsfi) | |
6147 Mem->setIsPIC(); | |
6148 From = Mem; | |
6029 } | 6149 } |
6030 bool NeedsReg = false; | 6150 bool NeedsReg = false; |
6031 if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty)) | 6151 if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty)) |
6032 // Immediate specifically not allowed | 6152 // Immediate specifically not allowed |
6033 NeedsReg = true; | 6153 NeedsReg = true; |
6034 if (!(Allowed & Legal_Mem) && isScalarFloatingType(Ty)) | 6154 if (!(Allowed & Legal_Mem) && isScalarFloatingType(Ty)) |
6035 // On x86, FP constants are lowered to mem operands. | 6155 // On x86, FP constants are lowered to mem operands. |
6036 NeedsReg = true; | 6156 NeedsReg = true; |
6037 if (NeedsReg) { | 6157 if (NeedsReg) { |
6038 From = copyToReg(From, RegNum); | 6158 From = copyToReg(From, RegNum); |
6039 } | 6159 } |
6040 return From; | 6160 return From; |
6041 } | 6161 } |
6162 | |
6042 if (auto *Var = llvm::dyn_cast<Variable>(From)) { | 6163 if (auto *Var = llvm::dyn_cast<Variable>(From)) { |
6043 // Check if the variable is guaranteed a physical register. This can happen | 6164 // Check if the variable is guaranteed a physical register. This can happen |
6044 // either when the variable is pre-colored or when it is assigned infinite | 6165 // either when the variable is pre-colored or when it is assigned infinite |
6045 // weight. | 6166 // weight. |
6046 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); | 6167 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); |
6047 bool MustRematerialize = | 6168 bool MustRematerialize = |
6048 (Var->isRematerializable() && !(Allowed & Legal_Rematerializable)); | 6169 (Var->isRematerializable() && !(Allowed & Legal_Rematerializable)); |
6049 // We need a new physical register for the operand if: | 6170 // We need a new physical register for the operand if: |
6050 // - Mem is not allowed and Var isn't guaranteed a physical register, or | 6171 // - Mem is not allowed and Var isn't guaranteed a physical register, or |
6051 // - RegNum is required and Var->getRegNum() doesn't match, or | 6172 // - RegNum is required and Var->getRegNum() doesn't match, or |
6052 // - Var is a rematerializable variable and rematerializable pass-through is | 6173 // - Var is a rematerializable variable and rematerializable pass-through is |
6053 // not allowed (in which case we need an lea instruction). | 6174 // not allowed (in which case we need an lea instruction). |
6054 if (MustRematerialize) { | 6175 if (MustRematerialize) { |
6055 assert(Ty == IceType_i32); | 6176 assert(Ty == IceType_i32); |
6056 Variable *NewVar = makeReg(Ty, RegNum); | 6177 Variable *NewVar = makeReg(Ty, RegNum); |
6057 // Since Var is rematerializable, the offset will be added when the lea is | 6178 // Since Var is rematerializable, the offset will be added when the lea is |
6058 // emitted. | 6179 // emitted. |
6059 constexpr Constant *NoOffset = nullptr; | 6180 constexpr Constant *NoOffset = nullptr; |
6060 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Var, NoOffset); | 6181 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Var, NoOffset); |
6061 _lea(NewVar, Mem); | 6182 _lea(NewVar, Mem); |
6062 From = NewVar; | 6183 From = NewVar; |
6063 } else if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || | 6184 } else if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || |
6064 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum()) || | 6185 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum()) || |
6065 MustRematerialize) { | 6186 MustRematerialize) { |
6066 From = copyToReg(From, RegNum); | 6187 From = copyToReg(From, RegNum); |
6067 } | 6188 } |
6068 return From; | 6189 return From; |
6069 } | 6190 } |
6070 llvm_unreachable("Unhandled operand kind in legalize()"); | 6191 |
6192 llvm::report_fatal_error("Unhandled operand kind in legalize()"); | |
6071 return From; | 6193 return From; |
6072 } | 6194 } |
6073 | 6195 |
6074 /// Provide a trivial wrapper to legalize() for this common usage. | 6196 /// Provide a trivial wrapper to legalize() for this common usage. |
6075 template <class Machine> | 6197 template <class Machine> |
6076 Variable *TargetX86Base<Machine>::legalizeToReg(Operand *From, int32_t RegNum) { | 6198 Variable *TargetX86Base<Machine>::legalizeToReg(Operand *From, int32_t RegNum) { |
6077 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); | 6199 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); |
6078 } | 6200 } |
6079 | 6201 |
6080 /// Legalize undef values to concrete values. | 6202 /// Legalize undef values to concrete values. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6128 // transformation. | 6250 // transformation. |
6129 if (!Mem) { | 6251 if (!Mem) { |
6130 auto *Base = llvm::dyn_cast<Variable>(Opnd); | 6252 auto *Base = llvm::dyn_cast<Variable>(Opnd); |
6131 auto *Offset = llvm::dyn_cast<Constant>(Opnd); | 6253 auto *Offset = llvm::dyn_cast<Constant>(Opnd); |
6132 assert(Base || Offset); | 6254 assert(Base || Offset); |
6133 if (Offset) { | 6255 if (Offset) { |
6134 // During memory operand building, we do not blind or pool the constant | 6256 // During memory operand building, we do not blind or pool the constant |
6135 // offset, we will work on the whole memory operand later as one entity | 6257 // offset, we will work on the whole memory operand later as one entity |
6136 // later, this save one instruction. By turning blinding and pooling off, | 6258 // later, this save one instruction. By turning blinding and pooling off, |
6137 // we guarantee legalize(Offset) will return a Constant*. | 6259 // we guarantee legalize(Offset) will return a Constant*. |
6138 { | 6260 if (!llvm::isa<ConstantRelocatable>(Offset)) { |
6139 BoolFlagSaver B(RandomizationPoolingPaused, true); | 6261 BoolFlagSaver B(RandomizationPoolingPaused, true); |
6140 | 6262 |
6141 Offset = llvm::cast<Constant>(legalize(Offset)); | 6263 Offset = llvm::cast<Constant>(legalize(Offset)); |
6142 } | 6264 } |
6143 | 6265 |
6144 assert(llvm::isa<ConstantInteger32>(Offset) || | 6266 assert(llvm::isa<ConstantInteger32>(Offset) || |
6145 llvm::isa<ConstantRelocatable>(Offset)); | 6267 llvm::isa<ConstantRelocatable>(Offset)); |
6146 } | 6268 } |
6269 // Not completely sure whether it's OK to leave IsPIC unset when creating | |
6270 // the mem operand. If DoLegalize is true, it will definitely be applied | |
6271 // during the legalize() call, but perhaps not during the | |
6272 // randomizeOrPoolImmediate() call. In any case, the emit routines will | |
6273 // assert that PIC legalization has been applied. | |
6147 Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); | 6274 Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); |
6148 } | 6275 } |
6149 // Do legalization, which contains randomization/pooling or do | 6276 // Do legalization, which contains randomization/pooling or do |
6150 // randomization/pooling. | 6277 // randomization/pooling. |
6151 return llvm::cast<typename Traits::X86OperandMem>( | 6278 return llvm::cast<typename Traits::X86OperandMem>( |
6152 DoLegalize ? legalize(Mem) : randomizeOrPoolImmediate(Mem)); | 6279 DoLegalize ? legalize(Mem) : randomizeOrPoolImmediate(Mem)); |
6153 } | 6280 } |
6154 | 6281 |
6155 template <class Machine> | 6282 template <class Machine> |
6156 Variable *TargetX86Base<Machine>::makeReg(Type Type, int32_t RegNum) { | 6283 Variable *TargetX86Base<Machine>::makeReg(Type Type, int32_t RegNum) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6204 const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const { | 6331 const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const { |
6205 Traits::makeRandomRegisterPermutation(Ctx, Func, Permutation, | 6332 Traits::makeRandomRegisterPermutation(Ctx, Func, Permutation, |
6206 ExcludeRegisters, Salt); | 6333 ExcludeRegisters, Salt); |
6207 } | 6334 } |
6208 | 6335 |
6209 template <class Machine> | 6336 template <class Machine> |
6210 void TargetX86Base<Machine>::emit(const ConstantInteger32 *C) const { | 6337 void TargetX86Base<Machine>::emit(const ConstantInteger32 *C) const { |
6211 if (!BuildDefs::dump()) | 6338 if (!BuildDefs::dump()) |
6212 return; | 6339 return; |
6213 Ostream &Str = Ctx->getStrEmit(); | 6340 Ostream &Str = Ctx->getStrEmit(); |
6214 Str << getConstantPrefix() << C->getValue(); | 6341 Str << "$" << C->getValue(); |
6215 } | 6342 } |
6216 | 6343 |
6217 template <class Machine> | 6344 template <class Machine> |
6218 void TargetX86Base<Machine>::emit(const ConstantInteger64 *C) const { | 6345 void TargetX86Base<Machine>::emit(const ConstantInteger64 *C) const { |
6219 if (!Traits::Is64Bit) { | 6346 if (!Traits::Is64Bit) { |
6220 llvm::report_fatal_error("Not expecting to emit 64-bit integers"); | 6347 llvm::report_fatal_error("Not expecting to emit 64-bit integers"); |
6221 } else { | 6348 } else { |
6222 if (!BuildDefs::dump()) | 6349 if (!BuildDefs::dump()) |
6223 return; | 6350 return; |
6224 Ostream &Str = Ctx->getStrEmit(); | 6351 Ostream &Str = Ctx->getStrEmit(); |
6225 Str << getConstantPrefix() << C->getValue(); | 6352 Str << "$" << C->getValue(); |
6226 } | 6353 } |
6227 } | 6354 } |
6228 | 6355 |
6229 template <class Machine> | 6356 template <class Machine> |
6230 void TargetX86Base<Machine>::emit(const ConstantFloat *C) const { | 6357 void TargetX86Base<Machine>::emit(const ConstantFloat *C) const { |
6231 if (!BuildDefs::dump()) | 6358 if (!BuildDefs::dump()) |
6232 return; | 6359 return; |
6233 Ostream &Str = Ctx->getStrEmit(); | 6360 Ostream &Str = Ctx->getStrEmit(); |
6234 C->emitPoolLabel(Str, Ctx); | 6361 C->emitPoolLabel(Str, Ctx); |
6235 } | 6362 } |
6236 | 6363 |
6237 template <class Machine> | 6364 template <class Machine> |
6238 void TargetX86Base<Machine>::emit(const ConstantDouble *C) const { | 6365 void TargetX86Base<Machine>::emit(const ConstantDouble *C) const { |
6239 if (!BuildDefs::dump()) | 6366 if (!BuildDefs::dump()) |
6240 return; | 6367 return; |
6241 Ostream &Str = Ctx->getStrEmit(); | 6368 Ostream &Str = Ctx->getStrEmit(); |
6242 C->emitPoolLabel(Str, Ctx); | 6369 C->emitPoolLabel(Str, Ctx); |
6243 } | 6370 } |
6244 | 6371 |
6245 template <class Machine> | 6372 template <class Machine> |
6246 void TargetX86Base<Machine>::emit(const ConstantUndef *) const { | 6373 void TargetX86Base<Machine>::emit(const ConstantUndef *) const { |
6247 llvm::report_fatal_error("undef value encountered by emitter."); | 6374 llvm::report_fatal_error("undef value encountered by emitter."); |
6248 } | 6375 } |
6249 | 6376 |
6377 template <class Machine> | |
6378 void TargetX86Base<Machine>::emit(const ConstantRelocatable *C) const { | |
6379 if (!BuildDefs::dump()) | |
6380 return; | |
6381 assert(!Ctx->getFlags().getUseNonsfi()); | |
6382 Ostream &Str = Ctx->getStrEmit(); | |
6383 Str << "$"; | |
6384 emitWithoutPrefix(C); | |
6385 } | |
6386 | |
6250 /// Randomize or pool an Immediate. | 6387 /// Randomize or pool an Immediate. |
6251 template <class Machine> | 6388 template <class Machine> |
6252 Operand *TargetX86Base<Machine>::randomizeOrPoolImmediate(Constant *Immediate, | 6389 Operand *TargetX86Base<Machine>::randomizeOrPoolImmediate(Constant *Immediate, |
6253 int32_t RegNum) { | 6390 int32_t RegNum) { |
6254 assert(llvm::isa<ConstantInteger32>(Immediate) || | 6391 assert(llvm::isa<ConstantInteger32>(Immediate) || |
6255 llvm::isa<ConstantRelocatable>(Immediate)); | 6392 llvm::isa<ConstantRelocatable>(Immediate)); |
6256 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || | 6393 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || |
6257 RandomizationPoolingPaused == true) { | 6394 RandomizationPoolingPaused == true) { |
6258 // Immediates randomization/pooling off or paused | 6395 // Immediates randomization/pooling off or paused |
6259 return Immediate; | 6396 return Immediate; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6303 // assigned register as this assignment is that start of its use-def | 6440 // assigned register as this assignment is that start of its use-def |
6304 // chain. So we add RegNum argument here. | 6441 // chain. So we add RegNum argument here. |
6305 Variable *Reg = makeReg(Immediate->getType(), RegNum); | 6442 Variable *Reg = makeReg(Immediate->getType(), RegNum); |
6306 IceString Label; | 6443 IceString Label; |
6307 llvm::raw_string_ostream Label_stream(Label); | 6444 llvm::raw_string_ostream Label_stream(Label); |
6308 Immediate->emitPoolLabel(Label_stream, Ctx); | 6445 Immediate->emitPoolLabel(Label_stream, Ctx); |
6309 constexpr RelocOffsetT Offset = 0; | 6446 constexpr RelocOffsetT Offset = 0; |
6310 constexpr bool SuppressMangling = true; | 6447 constexpr bool SuppressMangling = true; |
6311 Constant *Symbol = | 6448 Constant *Symbol = |
6312 Ctx->getConstantSym(Offset, Label_stream.str(), SuppressMangling); | 6449 Ctx->getConstantSym(Offset, Label_stream.str(), SuppressMangling); |
6450 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); | |
6451 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr; | |
6313 typename Traits::X86OperandMem *MemOperand = | 6452 typename Traits::X86OperandMem *MemOperand = |
6314 Traits::X86OperandMem::create(Func, Immediate->getType(), nullptr, | 6453 Traits::X86OperandMem::create(Func, Immediate->getType(), Base, |
6315 Symbol); | 6454 Symbol); |
6455 if (UseNonsfi) | |
6456 MemOperand->setIsPIC(); | |
6316 _mov(Reg, MemOperand); | 6457 _mov(Reg, MemOperand); |
6317 return Reg; | 6458 return Reg; |
6318 } | 6459 } |
6319 assert("Unsupported -randomize-pool-immediates option" && false); | 6460 assert("Unsupported -randomize-pool-immediates option" && false); |
6320 } | 6461 } |
6321 // the constant Immediate is not eligible for blinding/pooling | 6462 // the constant Immediate is not eligible for blinding/pooling |
6322 return Immediate; | 6463 return Immediate; |
6323 } | 6464 } |
6324 | 6465 |
6325 template <class Machine> | 6466 template <class Machine> |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6400 return MemOperand; | 6541 return MemOperand; |
6401 Variable *RegTemp = makeReg(IceType_i32); | 6542 Variable *RegTemp = makeReg(IceType_i32); |
6402 IceString Label; | 6543 IceString Label; |
6403 llvm::raw_string_ostream Label_stream(Label); | 6544 llvm::raw_string_ostream Label_stream(Label); |
6404 MemOperand->getOffset()->emitPoolLabel(Label_stream, Ctx); | 6545 MemOperand->getOffset()->emitPoolLabel(Label_stream, Ctx); |
6405 MemOperand->getOffset()->setShouldBePooled(true); | 6546 MemOperand->getOffset()->setShouldBePooled(true); |
6406 constexpr RelocOffsetT SymOffset = 0; | 6547 constexpr RelocOffsetT SymOffset = 0; |
6407 constexpr bool SuppressMangling = true; | 6548 constexpr bool SuppressMangling = true; |
6408 Constant *Symbol = Ctx->getConstantSym(SymOffset, Label_stream.str(), | 6549 Constant *Symbol = Ctx->getConstantSym(SymOffset, Label_stream.str(), |
6409 SuppressMangling); | 6550 SuppressMangling); |
6551 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); | |
6552 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr; | |
6410 typename Traits::X86OperandMem *SymbolOperand = | 6553 typename Traits::X86OperandMem *SymbolOperand = |
6411 Traits::X86OperandMem::create( | 6554 Traits::X86OperandMem::create( |
6412 Func, MemOperand->getOffset()->getType(), nullptr, Symbol); | 6555 Func, MemOperand->getOffset()->getType(), Base, Symbol); |
6556 if (UseNonsfi) | |
6557 SymbolOperand->setIsPIC(); | |
6413 _mov(RegTemp, SymbolOperand); | 6558 _mov(RegTemp, SymbolOperand); |
6414 // If we have a base variable here, we should add the lea instruction | 6559 // If we have a base variable here, we should add the lea instruction |
6415 // to add the value of the base variable to RegTemp. If there is no | 6560 // to add the value of the base variable to RegTemp. If there is no |
6416 // base variable, we won't need this lea instruction. | 6561 // base variable, we won't need this lea instruction. |
6417 if (MemOperand->getBase()) { | 6562 if (MemOperand->getBase()) { |
6418 typename Traits::X86OperandMem *CalculateOperand = | 6563 typename Traits::X86OperandMem *CalculateOperand = |
6419 Traits::X86OperandMem::create( | 6564 Traits::X86OperandMem::create( |
6420 Func, MemOperand->getType(), MemOperand->getBase(), nullptr, | 6565 Func, MemOperand->getType(), MemOperand->getBase(), nullptr, |
6421 RegTemp, 0, MemOperand->getSegmentRegister()); | 6566 RegTemp, 0, MemOperand->getSegmentRegister()); |
6422 _lea(RegTemp, CalculateOperand); | 6567 _lea(RegTemp, CalculateOperand); |
(...skipping 10 matching lines...) Expand all Loading... | |
6433 } | 6578 } |
6434 // the offset is not eligible for blinding or pooling, return the original | 6579 // the offset is not eligible for blinding or pooling, return the original |
6435 // mem operand | 6580 // mem operand |
6436 return MemOperand; | 6581 return MemOperand; |
6437 } | 6582 } |
6438 | 6583 |
6439 } // end of namespace X86Internal | 6584 } // end of namespace X86Internal |
6440 } // end of namespace Ice | 6585 } // end of namespace Ice |
6441 | 6586 |
6442 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H | 6587 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H |
OLD | NEW |