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::FixupKindPcRel; | |
331 RelFixup = | |
332 Flags.getUseNonsfi() ? Traits::FixupKindGotoff : Traits::FixupKindAbs; | |
329 } | 333 } |
330 | 334 |
331 template <class Machine> void TargetX86Base<Machine>::translateO2() { | 335 template <class Machine> void TargetX86Base<Machine>::translateO2() { |
332 TimerMarker T(TimerStack::TT_O2, Func); | 336 TimerMarker T(TimerStack::TT_O2, Func); |
333 | 337 |
338 if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) { | |
339 GotVar = Func->makeVariable(IceType_i32); | |
340 } | |
334 genTargetHelperCalls(); | 341 genTargetHelperCalls(); |
335 Func->dump("After target helper call insertion"); | 342 Func->dump("After target helper call insertion"); |
336 | 343 |
337 // Merge Alloca instructions, and lay out the stack. | 344 // Merge Alloca instructions, and lay out the stack. |
338 static constexpr bool SortAndCombineAllocas = true; | 345 static constexpr bool SortAndCombineAllocas = true; |
339 Func->processAllocas(SortAndCombineAllocas); | 346 Func->processAllocas(SortAndCombineAllocas); |
340 Func->dump("After Alloca processing"); | 347 Func->dump("After Alloca processing"); |
341 | 348 |
342 if (!Ctx->getFlags().getPhiEdgeSplit()) { | 349 if (!Ctx->getFlags().getPhiEdgeSplit()) { |
343 // Lower Phi instructions. | 350 // Lower Phi instructions. |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
392 Func->dump("After x86 address mode opt"); | 399 Func->dump("After x86 address mode opt"); |
393 | 400 |
394 // Disable constant blinding or pooling for load optimization. | 401 // Disable constant blinding or pooling for load optimization. |
395 { | 402 { |
396 BoolFlagSaver B(RandomizationPoolingPaused, true); | 403 BoolFlagSaver B(RandomizationPoolingPaused, true); |
397 doLoadOpt(); | 404 doLoadOpt(); |
398 } | 405 } |
399 Func->genCode(); | 406 Func->genCode(); |
400 if (Func->hasError()) | 407 if (Func->hasError()) |
401 return; | 408 return; |
409 initGotVar(); | |
402 Func->dump("After x86 codegen"); | 410 Func->dump("After x86 codegen"); |
403 | 411 |
404 // Register allocation. This requires instruction renumbering and full | 412 // Register allocation. This requires instruction renumbering and full |
405 // liveness analysis. Loops must be identified before liveness so variable | 413 // liveness analysis. Loops must be identified before liveness so variable |
406 // use weights are correct. | 414 // use weights are correct. |
407 Func->renumberInstructions(); | 415 Func->renumberInstructions(); |
408 if (Func->hasError()) | 416 if (Func->hasError()) |
409 return; | 417 return; |
410 Func->liveness(Liveness_Intervals); | 418 Func->liveness(Liveness_Intervals); |
411 if (Func->hasError()) | 419 if (Func->hasError()) |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
450 Func->doNopInsertion(); | 458 Func->doNopInsertion(); |
451 | 459 |
452 // Mark nodes that require sandbox alignment | 460 // Mark nodes that require sandbox alignment |
453 if (Ctx->getFlags().getUseSandboxing()) | 461 if (Ctx->getFlags().getUseSandboxing()) |
454 Func->markNodesForSandboxing(); | 462 Func->markNodesForSandboxing(); |
455 } | 463 } |
456 | 464 |
457 template <class Machine> void TargetX86Base<Machine>::translateOm1() { | 465 template <class Machine> void TargetX86Base<Machine>::translateOm1() { |
458 TimerMarker T(TimerStack::TT_Om1, Func); | 466 TimerMarker T(TimerStack::TT_Om1, Func); |
459 | 467 |
468 if (!Traits::Is64Bit && Func->getContext()->getFlags().getUseNonsfi()) { | |
469 GotVar = Func->makeVariable(IceType_i32); | |
470 } | |
460 genTargetHelperCalls(); | 471 genTargetHelperCalls(); |
461 | 472 |
462 // Do not merge Alloca instructions, and lay out the stack. | 473 // Do not merge Alloca instructions, and lay out the stack. |
463 static constexpr bool SortAndCombineAllocas = false; | 474 static constexpr bool SortAndCombineAllocas = false; |
464 Func->processAllocas(SortAndCombineAllocas); | 475 Func->processAllocas(SortAndCombineAllocas); |
465 Func->dump("After Alloca processing"); | 476 Func->dump("After Alloca processing"); |
466 | 477 |
467 Func->placePhiLoads(); | 478 Func->placePhiLoads(); |
468 if (Func->hasError()) | 479 if (Func->hasError()) |
469 return; | 480 return; |
470 Func->placePhiStores(); | 481 Func->placePhiStores(); |
471 if (Func->hasError()) | 482 if (Func->hasError()) |
472 return; | 483 return; |
473 Func->deletePhis(); | 484 Func->deletePhis(); |
474 if (Func->hasError()) | 485 if (Func->hasError()) |
475 return; | 486 return; |
476 Func->dump("After Phi lowering"); | 487 Func->dump("After Phi lowering"); |
477 | 488 |
478 Func->doArgLowering(); | 489 Func->doArgLowering(); |
479 Func->genCode(); | 490 Func->genCode(); |
480 if (Func->hasError()) | 491 if (Func->hasError()) |
481 return; | 492 return; |
493 initGotVar(); | |
John
2015/12/22 15:44:38
My first thought here was "a if (SFI) is missing."
Jim Stichnoth
2015/12/28 07:54:07
Done - renamed to initGotVarIfNeeded().
| |
482 Func->dump("After initial x8632 codegen"); | 494 Func->dump("After initial x8632 codegen"); |
483 | 495 |
484 regAlloc(RAK_InfOnly); | 496 regAlloc(RAK_InfOnly); |
485 if (Func->hasError()) | 497 if (Func->hasError()) |
486 return; | 498 return; |
487 Func->dump("After regalloc of infinite-weight variables"); | 499 Func->dump("After regalloc of infinite-weight variables"); |
488 | 500 |
489 Func->genFrame(); | 501 Func->genFrame(); |
490 if (Func->hasError()) | 502 if (Func->hasError()) |
491 return; | 503 return; |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
797 template <class Machine> | 809 template <class Machine> |
798 void TargetX86Base<Machine>::emitVariable(const Variable *Var) const { | 810 void TargetX86Base<Machine>::emitVariable(const Variable *Var) const { |
799 if (!BuildDefs::dump()) | 811 if (!BuildDefs::dump()) |
800 return; | 812 return; |
801 Ostream &Str = Ctx->getStrEmit(); | 813 Ostream &Str = Ctx->getStrEmit(); |
802 if (Var->hasReg()) { | 814 if (Var->hasReg()) { |
803 Str << "%" << getRegName(Var->getRegNum(), Var->getType()); | 815 Str << "%" << getRegName(Var->getRegNum(), Var->getType()); |
804 return; | 816 return; |
805 } | 817 } |
806 if (Var->mustHaveReg()) { | 818 if (Var->mustHaveReg()) { |
807 llvm_unreachable("Infinite-weight Variable has no register assigned"); | 819 llvm::report_fatal_error( |
820 "Infinite-weight Variable has no register assigned"); | |
808 } | 821 } |
809 const int32_t Offset = Var->getStackOffset(); | 822 const int32_t Offset = Var->getStackOffset(); |
810 int32_t BaseRegNum = Var->getBaseRegNum(); | 823 int32_t BaseRegNum = Var->getBaseRegNum(); |
811 if (BaseRegNum == Variable::NoRegister) | 824 if (BaseRegNum == Variable::NoRegister) |
812 BaseRegNum = getFrameOrStackReg(); | 825 BaseRegNum = getFrameOrStackReg(); |
813 // Print in the form "Offset(%reg)", taking care that: | 826 // Print in the form "Offset(%reg)", taking care that: |
814 // - Offset is never printed when it is 0 | 827 // - Offset is never printed when it is 0 |
815 | 828 |
816 const bool DecorateAsm = Func->getContext()->getFlags().getDecorateAsm(); | 829 const bool DecorateAsm = Func->getContext()->getFlags().getDecorateAsm(); |
817 // Only print Offset when it is nonzero, regardless of DecorateAsm. | 830 // Only print Offset when it is nonzero, regardless of DecorateAsm. |
818 if (Offset) { | 831 if (Offset) { |
819 if (DecorateAsm) { | 832 if (DecorateAsm) { |
820 Str << Var->getSymbolicStackOffset(Func); | 833 Str << Var->getSymbolicStackOffset(Func); |
821 } else { | 834 } else { |
822 Str << Offset; | 835 Str << Offset; |
823 } | 836 } |
824 } | 837 } |
825 const Type FrameSPTy = Traits::WordType; | 838 const Type FrameSPTy = Traits::WordType; |
826 Str << "(%" << getRegName(BaseRegNum, FrameSPTy) << ")"; | 839 Str << "(%" << getRegName(BaseRegNum, FrameSPTy) << ")"; |
827 } | 840 } |
828 | 841 |
829 template <class Machine> | 842 template <class Machine> |
830 typename TargetX86Base<Machine>::Traits::Address | 843 typename TargetX86Base<Machine>::Traits::Address |
831 TargetX86Base<Machine>::stackVarToAsmOperand(const Variable *Var) const { | 844 TargetX86Base<Machine>::stackVarToAsmOperand(const Variable *Var) const { |
832 if (Var->hasReg()) | 845 if (Var->hasReg()) |
833 llvm_unreachable("Stack Variable has a register assigned"); | 846 llvm::report_fatal_error("Stack Variable has a register assigned"); |
834 if (Var->mustHaveReg()) { | 847 if (Var->mustHaveReg()) { |
835 llvm_unreachable("Infinite-weight Variable has no register assigned"); | 848 llvm::report_fatal_error( |
849 "Infinite-weight Variable has no register assigned"); | |
836 } | 850 } |
837 int32_t Offset = Var->getStackOffset(); | 851 int32_t Offset = Var->getStackOffset(); |
838 int32_t BaseRegNum = Var->getBaseRegNum(); | 852 int32_t BaseRegNum = Var->getBaseRegNum(); |
839 if (Var->getBaseRegNum() == Variable::NoRegister) | 853 if (Var->getBaseRegNum() == Variable::NoRegister) |
840 BaseRegNum = getFrameOrStackReg(); | 854 BaseRegNum = getFrameOrStackReg(); |
841 return typename Traits::Address(Traits::getEncodedGPR(BaseRegNum), Offset, | 855 return typename Traits::Address(Traits::getEncodedGPR(BaseRegNum), Offset, |
842 AssemblerFixup::NoFixup); | 856 AssemblerFixup::NoFixup); |
843 } | 857 } |
844 | 858 |
845 /// Helper function for addProlog(). | 859 /// Helper function for addProlog(). |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
906 return Var64On32->getLo(); | 920 return Var64On32->getLo(); |
907 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | 921 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
908 auto *ConstInt = llvm::dyn_cast<ConstantInteger32>( | 922 auto *ConstInt = llvm::dyn_cast<ConstantInteger32>( |
909 Ctx->getConstantInt32(static_cast<int32_t>(Const->getValue()))); | 923 Ctx->getConstantInt32(static_cast<int32_t>(Const->getValue()))); |
910 // Check if we need to blind/pool the constant. | 924 // Check if we need to blind/pool the constant. |
911 return legalize(ConstInt); | 925 return legalize(ConstInt); |
912 } | 926 } |
913 if (auto *Mem = llvm::dyn_cast<typename Traits::X86OperandMem>(Operand)) { | 927 if (auto *Mem = llvm::dyn_cast<typename Traits::X86OperandMem>(Operand)) { |
914 auto *MemOperand = Traits::X86OperandMem::create( | 928 auto *MemOperand = Traits::X86OperandMem::create( |
915 Func, IceType_i32, Mem->getBase(), Mem->getOffset(), Mem->getIndex(), | 929 Func, IceType_i32, Mem->getBase(), Mem->getOffset(), Mem->getIndex(), |
916 Mem->getShift(), Mem->getSegmentRegister()); | 930 Mem->getShift(), Mem->getSegmentRegister(), Mem->getIsPIC()); |
917 // Test if we should randomize or pool the offset, if so randomize it or | 931 // Test if we should randomize or pool the offset, if so randomize it or |
918 // pool it then create mem operand with the blinded/pooled constant. | 932 // pool it then create mem operand with the blinded/pooled constant. |
919 // Otherwise, return the mem operand as ordinary mem operand. | 933 // Otherwise, return the mem operand as ordinary mem operand. |
920 return legalize(MemOperand); | 934 return legalize(MemOperand); |
921 } | 935 } |
922 llvm_unreachable("Unsupported operand type"); | 936 llvm_unreachable("Unsupported operand type"); |
923 return nullptr; | 937 return nullptr; |
924 } | 938 } |
925 | 939 |
926 template <class Machine> | 940 template <class Machine> |
(...skipping 19 matching lines...) Expand all Loading... | |
946 } else if (auto *IntOffset = llvm::dyn_cast<ConstantInteger32>(Offset)) { | 960 } else if (auto *IntOffset = llvm::dyn_cast<ConstantInteger32>(Offset)) { |
947 Offset = Ctx->getConstantInt32(4 + IntOffset->getValue()); | 961 Offset = Ctx->getConstantInt32(4 + IntOffset->getValue()); |
948 } else if (auto *SymOffset = llvm::dyn_cast<ConstantRelocatable>(Offset)) { | 962 } else if (auto *SymOffset = llvm::dyn_cast<ConstantRelocatable>(Offset)) { |
949 assert(!Utils::WouldOverflowAdd(SymOffset->getOffset(), 4)); | 963 assert(!Utils::WouldOverflowAdd(SymOffset->getOffset(), 4)); |
950 Offset = | 964 Offset = |
951 Ctx->getConstantSym(4 + SymOffset->getOffset(), SymOffset->getName(), | 965 Ctx->getConstantSym(4 + SymOffset->getOffset(), SymOffset->getName(), |
952 SymOffset->getSuppressMangling()); | 966 SymOffset->getSuppressMangling()); |
953 } | 967 } |
954 auto *MemOperand = Traits::X86OperandMem::create( | 968 auto *MemOperand = Traits::X86OperandMem::create( |
955 Func, IceType_i32, Mem->getBase(), Offset, Mem->getIndex(), | 969 Func, IceType_i32, Mem->getBase(), Offset, Mem->getIndex(), |
956 Mem->getShift(), Mem->getSegmentRegister()); | 970 Mem->getShift(), Mem->getSegmentRegister(), Mem->getIsPIC()); |
957 // Test if the Offset is an eligible i32 constants for randomization and | 971 // Test if the Offset is an eligible i32 constants for randomization and |
958 // pooling. Blind/pool it if it is. Otherwise return as oridinary mem | 972 // pooling. Blind/pool it if it is. Otherwise return as oridinary mem |
959 // operand. | 973 // operand. |
960 return legalize(MemOperand); | 974 return legalize(MemOperand); |
961 } | 975 } |
962 llvm_unreachable("Unsupported operand type"); | 976 llvm_unreachable("Unsupported operand type"); |
963 return nullptr; | 977 return nullptr; |
964 } | 978 } |
965 | 979 |
966 template <class Machine> | 980 template <class Machine> |
967 llvm::SmallBitVector | 981 llvm::SmallBitVector |
968 TargetX86Base<Machine>::getRegisterSet(RegSetMask Include, | 982 TargetX86Base<Machine>::getRegisterSet(RegSetMask Include, |
969 RegSetMask Exclude) const { | 983 RegSetMask Exclude) const { |
970 return Traits::getRegisterSet(Include, Exclude); | 984 return Traits::getRegisterSet(Include, Exclude); |
971 } | 985 } |
972 | 986 |
987 template <class Machine> void TargetX86Base<Machine>::initGotVar() { | |
988 if (Traits::Is64Bit) { | |
989 // Probably no implementation is needed, but error to be safe for now. | |
990 llvm::report_fatal_error("Need to implement initGotVar() for 64-bit."); | |
991 } | |
992 if (!Func->getContext()->getFlags().getUseNonsfi()) | |
993 return; | |
994 // Insert the GotVar assignment as the very first lowered instruction. Later, | |
995 // it will be moved into the right place - after the stack frame is set up but | |
996 // before in-args are copied into registers. | |
997 Context.init(Func->getEntryNode()); | |
998 Context.setInsertPoint(Context.getCur()); | |
999 Context.insert(InstX86GetIP<Machine>::create(Func, GotVar)); | |
1000 } | |
1001 | |
973 template <class Machine> | 1002 template <class Machine> |
974 void TargetX86Base<Machine>::lowerAlloca(const InstAlloca *Inst) { | 1003 void TargetX86Base<Machine>::lowerAlloca(const InstAlloca *Inst) { |
975 // Conservatively require the stack to be aligned. Some stack adjustment | 1004 // Conservatively require the stack to be aligned. Some stack adjustment |
976 // operations implemented below assume that the stack is aligned before the | 1005 // operations implemented below assume that the stack is aligned before the |
977 // alloca. All the alloca code ensures that the stack alignment is preserved | 1006 // alloca. All the alloca code ensures that the stack alignment is preserved |
978 // after the alloca. The stack alignment restriction can be relaxed in some | 1007 // after the alloca. The stack alignment restriction can be relaxed in some |
979 // cases. | 1008 // cases. |
980 NeedsStackAlignment = true; | 1009 NeedsStackAlignment = true; |
981 | 1010 |
982 // For default align=0, set it to the real value 1, to avoid any | 1011 // For default align=0, set it to the real value 1, to avoid any |
(...skipping 2985 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3968 } | 3997 } |
3969 _test(SecondVar, SecondVar); | 3998 _test(SecondVar, SecondVar); |
3970 _cmov(T_Dest2, T_Dest, Traits::Cond::Br_e); | 3999 _cmov(T_Dest2, T_Dest, Traits::Cond::Br_e); |
3971 _mov(DestLo, T_Dest2); | 4000 _mov(DestLo, T_Dest2); |
3972 _mov(DestHi, Ctx->getConstantZero(IceType_i32)); | 4001 _mov(DestHi, Ctx->getConstantZero(IceType_i32)); |
3973 } | 4002 } |
3974 | 4003 |
3975 template <class Machine> | 4004 template <class Machine> |
3976 void TargetX86Base<Machine>::typedLoad(Type Ty, Variable *Dest, Variable *Base, | 4005 void TargetX86Base<Machine>::typedLoad(Type Ty, Variable *Dest, Variable *Base, |
3977 Constant *Offset) { | 4006 Constant *Offset) { |
4007 // If Offset is a ConstantRelocatable in Non-SFI mode, we will need to | |
4008 // legalize Mem properly. | |
4009 if (Offset) | |
4010 assert(!llvm::isa<ConstantRelocatable>(Offset)); | |
4011 | |
3978 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); | 4012 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); |
3979 | 4013 |
3980 if (isVectorType(Ty)) | 4014 if (isVectorType(Ty)) |
3981 _movp(Dest, Mem); | 4015 _movp(Dest, Mem); |
3982 else if (Ty == IceType_f64) | 4016 else if (Ty == IceType_f64) |
3983 _movq(Dest, Mem); | 4017 _movq(Dest, Mem); |
3984 else | 4018 else |
3985 _mov(Dest, Mem); | 4019 _mov(Dest, Mem); |
3986 } | 4020 } |
3987 | 4021 |
3988 template <class Machine> | 4022 template <class Machine> |
3989 void TargetX86Base<Machine>::typedStore(Type Ty, Variable *Value, | 4023 void TargetX86Base<Machine>::typedStore(Type Ty, Variable *Value, |
3990 Variable *Base, Constant *Offset) { | 4024 Variable *Base, Constant *Offset) { |
4025 // If Offset is a ConstantRelocatable in Non-SFI mode, we will need to | |
4026 // legalize Mem properly. | |
4027 if (Offset) | |
4028 assert(!llvm::isa<ConstantRelocatable>(Offset)); | |
4029 | |
3991 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); | 4030 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); |
3992 | 4031 |
3993 if (isVectorType(Ty)) | 4032 if (isVectorType(Ty)) |
3994 _storep(Value, Mem); | 4033 _storep(Value, Mem); |
3995 else if (Ty == IceType_f64) | 4034 else if (Ty == IceType_f64) |
3996 _storeq(Value, Mem); | 4035 _storeq(Value, Mem); |
3997 else | 4036 else |
3998 _store(Value, Mem); | 4037 _store(Value, Mem); |
3999 } | 4038 } |
4000 | 4039 |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4284 Str << "<null>"; | 4323 Str << "<null>"; |
4285 Str << ", Index="; | 4324 Str << ", Index="; |
4286 if (Index) | 4325 if (Index) |
4287 Index->dump(Func); | 4326 Index->dump(Func); |
4288 else | 4327 else |
4289 Str << "<null>"; | 4328 Str << "<null>"; |
4290 Str << ", Shift=" << Shift << ", Offset=" << Offset | 4329 Str << ", Shift=" << Shift << ", Offset=" << Offset |
4291 << ", Relocatable=" << Relocatable << "\n"; | 4330 << ", Relocatable=" << Relocatable << "\n"; |
4292 } | 4331 } |
4293 | 4332 |
4294 inline bool matchAssign(const VariablesMetadata *VMetadata, Variable *&Var, | 4333 inline bool matchAssign(const VariablesMetadata *VMetadata, Variable *GotVar, |
4295 ConstantRelocatable *&Relocatable, int32_t &Offset, | 4334 Variable *&Var, ConstantRelocatable *&Relocatable, |
4296 const Inst *&Reason) { | 4335 int32_t &Offset, const Inst *&Reason) { |
4297 // Var originates from Var=SrcVar ==> set Var:=SrcVar | 4336 // Var originates from Var=SrcVar ==> set Var:=SrcVar |
4298 if (Var == nullptr) | 4337 if (Var == nullptr) |
4299 return false; | 4338 return false; |
4300 if (const Inst *VarAssign = VMetadata->getSingleDefinition(Var)) { | 4339 if (const Inst *VarAssign = VMetadata->getSingleDefinition(Var)) { |
4301 assert(!VMetadata->isMultiDef(Var)); | 4340 assert(!VMetadata->isMultiDef(Var)); |
4302 if (llvm::isa<InstAssign>(VarAssign)) { | 4341 if (llvm::isa<InstAssign>(VarAssign)) { |
4303 Operand *SrcOp = VarAssign->getSrc(0); | 4342 Operand *SrcOp = VarAssign->getSrc(0); |
4304 assert(SrcOp); | 4343 assert(SrcOp); |
4305 if (auto *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) { | 4344 if (auto *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) { |
4306 if (!VMetadata->isMultiDef(SrcVar) && | 4345 if (!VMetadata->isMultiDef(SrcVar) && |
4307 // TODO: ensure SrcVar stays single-BB | 4346 // TODO: ensure SrcVar stays single-BB |
4308 true) { | 4347 true) { |
4309 Var = SrcVar; | 4348 Var = SrcVar; |
4310 Reason = VarAssign; | 4349 Reason = VarAssign; |
4311 return true; | 4350 return true; |
4312 } | 4351 } |
4313 } else if (auto *Const = llvm::dyn_cast<ConstantInteger32>(SrcOp)) { | 4352 } else if (auto *Const = llvm::dyn_cast<ConstantInteger32>(SrcOp)) { |
4314 int32_t MoreOffset = Const->getValue(); | 4353 int32_t MoreOffset = Const->getValue(); |
4315 if (Utils::WouldOverflowAdd(Offset, MoreOffset)) | 4354 if (Utils::WouldOverflowAdd(Offset, MoreOffset)) |
4316 return false; | 4355 return false; |
4317 Var = nullptr; | 4356 Var = nullptr; |
4318 Offset += MoreOffset; | 4357 Offset += MoreOffset; |
4319 Reason = VarAssign; | 4358 Reason = VarAssign; |
4320 return true; | 4359 return true; |
4321 } else if (auto *AddReloc = llvm::dyn_cast<ConstantRelocatable>(SrcOp)) { | 4360 } else if (auto *AddReloc = llvm::dyn_cast<ConstantRelocatable>(SrcOp)) { |
4322 if (Relocatable == nullptr) { | 4361 if (Relocatable == nullptr) { |
4323 Var = nullptr; | 4362 Var = GotVar; |
4324 Relocatable = AddReloc; | 4363 Relocatable = AddReloc; |
4325 Reason = VarAssign; | 4364 Reason = VarAssign; |
4326 return true; | 4365 return true; |
4327 } | 4366 } |
4328 } | 4367 } |
4329 } | 4368 } |
4330 } | 4369 } |
4331 return false; | 4370 return false; |
4332 } | 4371 } |
4333 | 4372 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4432 return true; | 4471 return true; |
4433 } | 4472 } |
4434 } | 4473 } |
4435 } | 4474 } |
4436 } | 4475 } |
4437 } | 4476 } |
4438 } | 4477 } |
4439 return false; | 4478 return false; |
4440 } | 4479 } |
4441 | 4480 |
4442 inline bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base, | 4481 inline bool matchOffsetBase(const VariablesMetadata *VMetadata, |
4482 Variable *GotVar, Variable *&Base, | |
4483 Variable *&BaseOther, | |
4443 ConstantRelocatable *&Relocatable, int32_t &Offset, | 4484 ConstantRelocatable *&Relocatable, int32_t &Offset, |
4444 const Inst *&Reason) { | 4485 const Inst *&Reason) { |
4445 // Base is Base=Var+Const || Base is Base=Const+Var ==> | 4486 // Base is Base=Var+Const || Base is Base=Const+Var ==> |
4446 // set Base=Var, Offset+=Const | 4487 // set Base=Var, Offset+=Const |
4447 // Base is Base=Var-Const ==> | 4488 // Base is Base=Var-Const ==> |
4448 // set Base=Var, Offset-=Const | 4489 // set Base=Var, Offset-=Const |
4449 if (Base == nullptr) { | 4490 if (Base == nullptr) { |
4450 return false; | 4491 return false; |
4451 } | 4492 } |
4452 const Inst *BaseInst = VMetadata->getSingleDefinition(Base); | 4493 const Inst *BaseInst = VMetadata->getSingleDefinition(Base); |
(...skipping 30 matching lines...) Expand all Loading... | |
4483 if ((Relocatable && (Reloc0 || Reloc1)) || (Reloc0 && Reloc1)) | 4524 if ((Relocatable && (Reloc0 || Reloc1)) || (Reloc0 && Reloc1)) |
4484 return false; | 4525 return false; |
4485 // Don't know how to subtract a relocatable. | 4526 // Don't know how to subtract a relocatable. |
4486 if (!IsAdd && Reloc1) | 4527 if (!IsAdd && Reloc1) |
4487 return false; | 4528 return false; |
4488 // Incorporate ConstantRelocatables. | 4529 // Incorporate ConstantRelocatables. |
4489 if (Reloc0) | 4530 if (Reloc0) |
4490 NewRelocatable = Reloc0; | 4531 NewRelocatable = Reloc0; |
4491 else if (Reloc1) | 4532 else if (Reloc1) |
4492 NewRelocatable = Reloc1; | 4533 NewRelocatable = Reloc1; |
4534 if (NewRelocatable && BaseOther && GotVar) | |
4535 return false; | |
4493 // Compute the updated constant offset. | 4536 // Compute the updated constant offset. |
4494 if (Const0) { | 4537 if (Const0) { |
4495 int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue(); | 4538 int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue(); |
4496 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) | 4539 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) |
4497 return false; | 4540 return false; |
4498 NewOffset += MoreOffset; | 4541 NewOffset += MoreOffset; |
4499 } | 4542 } |
4500 if (Const1) { | 4543 if (Const1) { |
4501 int32_t MoreOffset = IsAdd ? Const1->getValue() : -Const1->getValue(); | 4544 int32_t MoreOffset = IsAdd ? Const1->getValue() : -Const1->getValue(); |
4502 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) | 4545 if (Utils::WouldOverflowAdd(NewOffset, MoreOffset)) |
4503 return false; | 4546 return false; |
4504 NewOffset += MoreOffset; | 4547 NewOffset += MoreOffset; |
4505 } | 4548 } |
4506 // Update the computed address parameters once we are sure optimization | 4549 // Update the computed address parameters once we are sure optimization |
4507 // is valid. | 4550 // is valid. |
4551 if (NewRelocatable && GotVar) { | |
4552 assert(BaseOther == nullptr); | |
4553 BaseOther = GotVar; | |
4554 } | |
4508 Base = NewBase; | 4555 Base = NewBase; |
4509 Offset = NewOffset; | 4556 Offset = NewOffset; |
4510 Relocatable = NewRelocatable; | 4557 Relocatable = NewRelocatable; |
4511 Reason = BaseInst; | 4558 Reason = BaseInst; |
4512 return true; | 4559 return true; |
4513 } | 4560 } |
4514 return false; | 4561 return false; |
4515 } | 4562 } |
4516 | 4563 |
4517 // Builds information for a canonical address expresion: | 4564 // Builds information for a canonical address expresion: |
4518 // <Relocatable + Offset>(Base, Index, Shift) | 4565 // <Relocatable + Offset>(Base, Index, Shift) |
4519 // On entry: | 4566 // On entry: |
4520 // Relocatable == null, | 4567 // Relocatable == null, |
4521 // Offset == 0, | 4568 // Offset == 0, |
4522 // Base is a Variable, | 4569 // Base is a Variable, |
4523 // Index == nullptr, | 4570 // Index == nullptr, |
4524 // Shift == 0 | 4571 // Shift == 0 |
4525 inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, | 4572 inline bool computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *GotVar, |
4526 ConstantRelocatable *&Relocatable, | 4573 ConstantRelocatable *&Relocatable, |
4527 int32_t &Offset, Variable *&Base, | 4574 int32_t &Offset, Variable *&Base, |
4528 Variable *&Index, uint16_t &Shift) { | 4575 Variable *&Index, uint16_t &Shift) { |
4529 bool AddressWasOptimized = false; | 4576 bool AddressWasOptimized = false; |
4530 Func->resetCurrentNode(); | 4577 Func->resetCurrentNode(); |
4531 if (Func->isVerbose(IceV_AddrOpt)) { | 4578 if (Func->isVerbose(IceV_AddrOpt)) { |
4532 OstreamLocker L(Func->getContext()); | 4579 OstreamLocker L(Func->getContext()); |
4533 Ostream &Str = Func->getContext()->getStrDump(); | 4580 Ostream &Str = Func->getContext()->getStrDump(); |
4534 Str << "\nStarting computeAddressOpt for instruction:\n "; | 4581 Str << "\nStarting computeAddressOpt for instruction:\n "; |
4535 Instr->dumpDecorated(Func); | 4582 Instr->dumpDecorated(Func); |
(...skipping 10 matching lines...) Expand all Loading... | |
4546 const bool MockBounds = Func->getContext()->getFlags().getMockBoundsCheck(); | 4593 const bool MockBounds = Func->getContext()->getFlags().getMockBoundsCheck(); |
4547 const VariablesMetadata *VMetadata = Func->getVMetadata(); | 4594 const VariablesMetadata *VMetadata = Func->getVMetadata(); |
4548 const Inst *Reason = nullptr; | 4595 const Inst *Reason = nullptr; |
4549 do { | 4596 do { |
4550 if (Reason) { | 4597 if (Reason) { |
4551 dumpAddressOpt(Func, Relocatable, Offset, Base, Index, Shift, Reason); | 4598 dumpAddressOpt(Func, Relocatable, Offset, Base, Index, Shift, Reason); |
4552 AddressWasOptimized = true; | 4599 AddressWasOptimized = true; |
4553 Reason = nullptr; | 4600 Reason = nullptr; |
4554 } | 4601 } |
4555 // Update Base and Index to follow through assignments to definitions. | 4602 // Update Base and Index to follow through assignments to definitions. |
4556 if (matchAssign(VMetadata, Base, Relocatable, Offset, Reason)) { | 4603 if (matchAssign(VMetadata, GotVar, Base, Relocatable, Offset, Reason)) { |
4557 // Assignments of Base from a Relocatable or ConstantInt32 can result | 4604 // Assignments of Base from a Relocatable or ConstantInt32 can result |
4558 // in Base becoming nullptr. To avoid code duplication in this loop we | 4605 // in Base becoming nullptr. To avoid code duplication in this loop we |
4559 // prefer that Base be non-nullptr if possible. | 4606 // prefer that Base be non-nullptr if possible. |
4560 if ((Base == nullptr) && (Index != nullptr) && Shift == 0) | 4607 if ((Base == nullptr) && (Index != nullptr) && Shift == 0) |
4561 std::swap(Base, Index); | 4608 std::swap(Base, Index); |
4562 continue; | 4609 continue; |
4563 } | 4610 } |
4564 if (matchAssign(VMetadata, Index, Relocatable, Offset, Reason)) | 4611 if (matchAssign(VMetadata, GotVar, Index, Relocatable, Offset, Reason)) |
4565 continue; | 4612 continue; |
4566 | 4613 |
4567 if (!MockBounds) { | 4614 if (!MockBounds) { |
4568 // Transition from: | 4615 // Transition from: |
4569 // <Relocatable + Offset>(Base) to | 4616 // <Relocatable + Offset>(Base) to |
4570 // <Relocatable + Offset>(Base, Index) | 4617 // <Relocatable + Offset>(Base, Index) |
4571 if (matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason)) | 4618 if (matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason)) |
4572 continue; | 4619 continue; |
4573 // Recognize multiply/shift and update Shift amount. | 4620 // Recognize multiply/shift and update Shift amount. |
4574 // Index becomes Index=Var<<Const && Const+Shift<=3 ==> | 4621 // Index becomes Index=Var<<Const && Const+Shift<=3 ==> |
4575 // Index=Var, Shift+=Const | 4622 // Index=Var, Shift+=Const |
4576 // Index becomes Index=Const*Var && log2(Const)+Shift<=3 ==> | 4623 // Index becomes Index=Const*Var && log2(Const)+Shift<=3 ==> |
4577 // Index=Var, Shift+=log2(Const) | 4624 // Index=Var, Shift+=log2(Const) |
4578 if (matchShiftedIndex(VMetadata, Index, Shift, Reason)) | 4625 if (matchShiftedIndex(VMetadata, Index, Shift, Reason)) |
4579 continue; | 4626 continue; |
4580 // If Shift is zero, the choice of Base and Index was purely arbitrary. | 4627 // If Shift is zero, the choice of Base and Index was purely arbitrary. |
4581 // Recognize multiply/shift and set Shift amount. | 4628 // Recognize multiply/shift and set Shift amount. |
4582 // Shift==0 && Base is Base=Var*Const && log2(Const)+Shift<=3 ==> | 4629 // Shift==0 && Base is Base=Var*Const && log2(Const)+Shift<=3 ==> |
4583 // swap(Index,Base) | 4630 // swap(Index,Base) |
4584 // Similar for Base=Const*Var and Base=Var<<Const | 4631 // Similar for Base=Const*Var and Base=Var<<Const |
4585 if (Shift == 0 && matchShiftedIndex(VMetadata, Base, Shift, Reason)) { | 4632 if (Shift == 0 && matchShiftedIndex(VMetadata, Base, Shift, Reason)) { |
4586 std::swap(Base, Index); | 4633 std::swap(Base, Index); |
4587 continue; | 4634 continue; |
4588 } | 4635 } |
4589 } | 4636 } |
4590 // Update Offset to reflect additions/subtractions with constants and | 4637 // Update Offset to reflect additions/subtractions with constants and |
4591 // relocatables. | 4638 // relocatables. |
4592 // TODO: consider overflow issues with respect to Offset. | 4639 // TODO: consider overflow issues with respect to Offset. |
4593 if (matchOffsetBase(VMetadata, Base, Relocatable, Offset, Reason)) | 4640 if (matchOffsetBase(VMetadata, GotVar, Base, Index, Relocatable, Offset, |
4641 Reason)) | |
4594 continue; | 4642 continue; |
4595 if (Shift == 0 && | 4643 if (Shift == 0 && matchOffsetBase(VMetadata, GotVar, Index, Base, |
4596 matchOffsetBase(VMetadata, Index, Relocatable, Offset, Reason)) | 4644 Relocatable, Offset, Reason)) |
4597 continue; | 4645 continue; |
4598 // TODO(sehr, stichnot): Handle updates of Index with Shift != 0. | 4646 // TODO(sehr, stichnot): Handle updates of Index with Shift != 0. |
4599 // Index is Index=Var+Const ==> | 4647 // Index is Index=Var+Const ==> |
4600 // set Index=Var, Offset+=(Const<<Shift) | 4648 // set Index=Var, Offset+=(Const<<Shift) |
4601 // Index is Index=Const+Var ==> | 4649 // Index is Index=Const+Var ==> |
4602 // set Index=Var, Offset+=(Const<<Shift) | 4650 // set Index=Var, Offset+=(Const<<Shift) |
4603 // Index is Index=Var-Const ==> | 4651 // Index is Index=Var-Const ==> |
4604 // set Index=Var, Offset-=(Const<<Shift) | 4652 // set Index=Var, Offset-=(Const<<Shift) |
4605 break; | 4653 break; |
4606 } while (Reason); | 4654 } while (Reason); |
4655 // Undo any addition of GotVar. It will be added back when the mem operand is | |
4656 // legalized. | |
4657 if (Base == GotVar) | |
4658 Base = nullptr; | |
4659 if (Index == GotVar) | |
4660 Index = nullptr; | |
4607 return AddressWasOptimized; | 4661 return AddressWasOptimized; |
4608 } | 4662 } |
4609 | 4663 |
4610 /// Add a mock bounds check on the memory address before using it as a load or | 4664 /// Add a mock bounds check on the memory address before using it as a load or |
4611 /// store operand. The basic idea is that given a memory operand [reg], we | 4665 /// store operand. The basic idea is that given a memory operand [reg], we |
4612 /// would first add bounds-check code something like: | 4666 /// would first add bounds-check code something like: |
4613 /// | 4667 /// |
4614 /// cmp reg, <lb> | 4668 /// cmp reg, <lb> |
4615 /// jl out_of_line_error | 4669 /// jl out_of_line_error |
4616 /// cmp reg, <ub> | 4670 /// cmp reg, <ub> |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4662 _br(Traits::Cond::Br_e, Label); | 4716 _br(Traits::Cond::Br_e, Label); |
4663 _cmp(Opnd, Ctx->getConstantInt32(1)); | 4717 _cmp(Opnd, Ctx->getConstantInt32(1)); |
4664 _br(Traits::Cond::Br_e, Label); | 4718 _br(Traits::Cond::Br_e, Label); |
4665 Context.insert(Label); | 4719 Context.insert(Label); |
4666 } | 4720 } |
4667 | 4721 |
4668 template <class Machine> | 4722 template <class Machine> |
4669 void TargetX86Base<Machine>::lowerLoad(const InstLoad *Load) { | 4723 void TargetX86Base<Machine>::lowerLoad(const InstLoad *Load) { |
4670 // A Load instruction can be treated the same as an Assign instruction, after | 4724 // A Load instruction can be treated the same as an Assign instruction, after |
4671 // the source operand is transformed into an Traits::X86OperandMem operand. | 4725 // the source operand is transformed into an Traits::X86OperandMem operand. |
4672 // Note that the address mode optimization already creates an | 4726 // Note that the address mode optimization already creates a |
4673 // Traits::X86OperandMem operand, so it doesn't need another level of | 4727 // Traits::X86OperandMem operand, so it doesn't need another level of |
4674 // transformation. | 4728 // transformation. |
4675 Variable *DestLoad = Load->getDest(); | 4729 Variable *DestLoad = Load->getDest(); |
4676 Type Ty = DestLoad->getType(); | 4730 Type Ty = DestLoad->getType(); |
4677 Operand *Src0 = formMemoryOperand(Load->getSourceAddress(), Ty); | 4731 Operand *Src0 = formMemoryOperand(Load->getSourceAddress(), Ty); |
4678 doMockBoundsCheck(Src0); | 4732 doMockBoundsCheck(Src0); |
4679 auto *Assign = InstAssign::create(Func, DestLoad, Src0); | 4733 auto *Assign = InstAssign::create(Func, DestLoad, Src0); |
4680 lowerAssign(Assign); | 4734 lowerAssign(Assign); |
4681 } | 4735 } |
4682 | 4736 |
4683 template <class Machine> void TargetX86Base<Machine>::doAddressOptLoad() { | 4737 template <class Machine> void TargetX86Base<Machine>::doAddressOptLoad() { |
4684 Inst *Inst = Context.getCur(); | 4738 Inst *Inst = Context.getCur(); |
4685 Variable *Dest = Inst->getDest(); | 4739 Variable *Dest = Inst->getDest(); |
4686 Operand *Addr = Inst->getSrc(0); | 4740 Operand *Addr = Inst->getSrc(0); |
4687 Variable *Index = nullptr; | 4741 Variable *Index = nullptr; |
4688 ConstantRelocatable *Relocatable = nullptr; | 4742 ConstantRelocatable *Relocatable = nullptr; |
4689 uint16_t Shift = 0; | 4743 uint16_t Shift = 0; |
4690 int32_t Offset = 0; | 4744 int32_t Offset = 0; |
4691 // Vanilla ICE load instructions should not use the segment registers, and | 4745 // Vanilla ICE load instructions should not use the segment registers, and |
4692 // computeAddressOpt only works at the level of Variables and Constants, not | 4746 // computeAddressOpt only works at the level of Variables and Constants, not |
4693 // other Traits::X86OperandMem, so there should be no mention of segment | 4747 // other Traits::X86OperandMem, so there should be no mention of segment |
4694 // registers there either. | 4748 // registers there either. |
4695 const typename Traits::X86OperandMem::SegmentRegisters SegmentReg = | 4749 constexpr auto SegmentReg = Traits::X86OperandMem::DefaultSegment; |
4696 Traits::X86OperandMem::DefaultSegment; | |
4697 auto *Base = llvm::dyn_cast<Variable>(Addr); | 4750 auto *Base = llvm::dyn_cast<Variable>(Addr); |
4698 if (computeAddressOpt(Func, Inst, Relocatable, Offset, Base, Index, Shift)) { | 4751 if (computeAddressOpt(Func, Inst, GotVar, Relocatable, Offset, Base, Index, |
4752 Shift)) { | |
4699 Inst->setDeleted(); | 4753 Inst->setDeleted(); |
4700 Constant *OffsetOp = nullptr; | 4754 Constant *OffsetOp = nullptr; |
4701 if (Relocatable == nullptr) { | 4755 if (Relocatable == nullptr) { |
4702 OffsetOp = Ctx->getConstantInt32(Offset); | 4756 OffsetOp = Ctx->getConstantInt32(Offset); |
4703 } else { | 4757 } else { |
4704 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset, | 4758 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset, |
4705 Relocatable->getName(), | 4759 Relocatable->getName(), |
4706 Relocatable->getSuppressMangling()); | 4760 Relocatable->getSuppressMangling()); |
4707 } | 4761 } |
4762 // The new mem operand is created without IsPIC being set, because | |
4763 // computeAddressOpt() doesn't include GotVar in its final result. | |
4708 Addr = Traits::X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp, | 4764 Addr = Traits::X86OperandMem::create(Func, Dest->getType(), Base, OffsetOp, |
4709 Index, Shift, SegmentReg); | 4765 Index, Shift, SegmentReg); |
4710 Context.insert<InstLoad>(Dest, Addr); | 4766 Context.insert<InstLoad>(Dest, Addr); |
4711 } | 4767 } |
4712 } | 4768 } |
4713 | 4769 |
4714 template <class Machine> | 4770 template <class Machine> |
4715 void TargetX86Base<Machine>::randomlyInsertNop(float Probability, | 4771 void TargetX86Base<Machine>::randomlyInsertNop(float Probability, |
4716 RandomNumberGenerator &RNG) { | 4772 RandomNumberGenerator &RNG) { |
4717 RandomNumberGeneratorWrapper RNGW(RNG); | 4773 RandomNumberGeneratorWrapper RNGW(RNG); |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4992 Operand *Addr = Inst->getAddr(); | 5048 Operand *Addr = Inst->getAddr(); |
4993 Variable *Index = nullptr; | 5049 Variable *Index = nullptr; |
4994 ConstantRelocatable *Relocatable = nullptr; | 5050 ConstantRelocatable *Relocatable = nullptr; |
4995 uint16_t Shift = 0; | 5051 uint16_t Shift = 0; |
4996 int32_t Offset = 0; | 5052 int32_t Offset = 0; |
4997 auto *Base = llvm::dyn_cast<Variable>(Addr); | 5053 auto *Base = llvm::dyn_cast<Variable>(Addr); |
4998 // Vanilla ICE store instructions should not use the segment registers, and | 5054 // Vanilla ICE store instructions should not use the segment registers, and |
4999 // computeAddressOpt only works at the level of Variables and Constants, not | 5055 // computeAddressOpt only works at the level of Variables and Constants, not |
5000 // other Traits::X86OperandMem, so there should be no mention of segment | 5056 // other Traits::X86OperandMem, so there should be no mention of segment |
5001 // registers there either. | 5057 // registers there either. |
5002 const typename Traits::X86OperandMem::SegmentRegisters SegmentReg = | 5058 constexpr auto SegmentReg = Traits::X86OperandMem::DefaultSegment; |
John
2015/12/22 15:44:38
I personally like this idiom, but this is an "unsa
Jim Stichnoth
2015/12/28 07:54:07
OK, I modified it such that the fully written out
| |
5003 Traits::X86OperandMem::DefaultSegment; | 5059 if (computeAddressOpt(Func, Inst, GotVar, Relocatable, Offset, Base, Index, |
5004 if (computeAddressOpt(Func, Inst, Relocatable, Offset, Base, Index, Shift)) { | 5060 Shift)) { |
5005 Inst->setDeleted(); | 5061 Inst->setDeleted(); |
5006 Constant *OffsetOp = nullptr; | 5062 Constant *OffsetOp = nullptr; |
5007 if (Relocatable == nullptr) { | 5063 if (Relocatable == nullptr) { |
5008 OffsetOp = Ctx->getConstantInt32(Offset); | 5064 OffsetOp = Ctx->getConstantInt32(Offset); |
5009 } else { | 5065 } else { |
5010 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset, | 5066 OffsetOp = Ctx->getConstantSym(Relocatable->getOffset() + Offset, |
5011 Relocatable->getName(), | 5067 Relocatable->getName(), |
5012 Relocatable->getSuppressMangling()); | 5068 Relocatable->getSuppressMangling()); |
5013 } | 5069 } |
5070 // The new mem operand is created without IsPIC being set, because | |
5071 // computeAddressOpt() doesn't include GotVar in its final result. | |
5014 Addr = Traits::X86OperandMem::create(Func, Data->getType(), Base, OffsetOp, | 5072 Addr = Traits::X86OperandMem::create(Func, Data->getType(), Base, OffsetOp, |
5015 Index, Shift, SegmentReg); | 5073 Index, Shift, SegmentReg); |
5016 auto *NewStore = Context.insert<InstStore>(Data, Addr); | 5074 auto *NewStore = Context.insert<InstStore>(Data, Addr); |
5017 if (Inst->getDest()) | 5075 if (Inst->getDest()) |
5018 NewStore->setRmwBeacon(Inst->getRmwBeacon()); | 5076 NewStore->setRmwBeacon(Inst->getRmwBeacon()); |
5019 } | 5077 } |
5020 } | 5078 } |
5021 | 5079 |
5022 template <class Machine> | 5080 template <class Machine> |
5023 Operand *TargetX86Base<Machine>::lowerCmpRange(Operand *Comparison, | 5081 Operand *TargetX86Base<Machine>::lowerCmpRange(Operand *Comparison, |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5064 Variable *Index; | 5122 Variable *Index; |
5065 if (RangeIndex->getType() != getPointerType()) { | 5123 if (RangeIndex->getType() != getPointerType()) { |
5066 Index = makeReg(getPointerType()); | 5124 Index = makeReg(getPointerType()); |
5067 _movzx(Index, RangeIndex); | 5125 _movzx(Index, RangeIndex); |
5068 } else { | 5126 } else { |
5069 Index = legalizeToReg(RangeIndex); | 5127 Index = legalizeToReg(RangeIndex); |
5070 } | 5128 } |
5071 | 5129 |
5072 constexpr RelocOffsetT RelocOffset = 0; | 5130 constexpr RelocOffsetT RelocOffset = 0; |
5073 constexpr bool SuppressMangling = true; | 5131 constexpr bool SuppressMangling = true; |
5132 const bool IsPIC = Ctx->getFlags().getUseNonsfi(); | |
5074 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); | 5133 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); |
5075 Constant *Base = Ctx->getConstantSym( | 5134 Variable *Base = IsPIC ? legalizeToReg(GotVar) : nullptr; |
5135 Constant *Offset = Ctx->getConstantSym( | |
5076 RelocOffset, InstJumpTable::makeName(MangledName, JumpTable->getId()), | 5136 RelocOffset, InstJumpTable::makeName(MangledName, JumpTable->getId()), |
5077 SuppressMangling); | 5137 SuppressMangling); |
5078 Constant *Offset = nullptr; | |
5079 uint16_t Shift = typeWidthInBytesLog2(getPointerType()); | 5138 uint16_t Shift = typeWidthInBytesLog2(getPointerType()); |
5080 // TODO(ascull): remove need for legalize by allowing null base in memop | 5139 constexpr auto Segment = Traits::X86OperandMem::DefaultSegment; |
5081 auto *TargetInMemory = Traits::X86OperandMem::create( | 5140 auto *TargetInMemory = Traits::X86OperandMem::create( |
5082 Func, getPointerType(), legalizeToReg(Base), Offset, Index, Shift); | 5141 Func, getPointerType(), Base, Offset, Index, Shift, Segment, IsPIC); |
5083 Variable *Target = nullptr; | 5142 Variable *Target = nullptr; |
5084 _mov(Target, TargetInMemory); | 5143 _mov(Target, TargetInMemory); |
5085 lowerIndirectJump(Target); | 5144 lowerIndirectJump(Target); |
5086 | 5145 |
5087 if (DefaultTarget == nullptr) | 5146 if (DefaultTarget == nullptr) |
5088 Context.insert(SkipJumpTable); | 5147 Context.insert(SkipJumpTable); |
5089 return; | 5148 return; |
5090 } | 5149 } |
5091 case CaseCluster::Range: { | 5150 case CaseCluster::Range: { |
5092 if (Case.isUnitRange()) { | 5151 if (Case.isUnitRange()) { |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5403 if (const auto *RMW = | 5462 if (const auto *RMW = |
5404 llvm::dyn_cast<typename Traits::Insts::FakeRMW>(Instr)) { | 5463 llvm::dyn_cast<typename Traits::Insts::FakeRMW>(Instr)) { |
5405 lowerRMW(RMW); | 5464 lowerRMW(RMW); |
5406 } else { | 5465 } else { |
5407 TargetLowering::lowerOther(Instr); | 5466 TargetLowering::lowerOther(Instr); |
5408 } | 5467 } |
5409 } | 5468 } |
5410 | 5469 |
5411 /// Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve | 5470 /// Turn an i64 Phi instruction into a pair of i32 Phi instructions, to preserve |
5412 /// integrity of liveness analysis. Undef values are also turned into zeroes, | 5471 /// integrity of liveness analysis. Undef values are also turned into zeroes, |
5413 /// since loOperand() and hiOperand() don't expect Undef input. | 5472 /// since loOperand() and hiOperand() don't expect Undef input. Also, in |
5473 /// Non-SFI mode, add a FakeUse(GotVar) for every pooled constant operand. | |
5414 template <class Machine> void TargetX86Base<Machine>::prelowerPhis() { | 5474 template <class Machine> void TargetX86Base<Machine>::prelowerPhis() { |
5475 if (Ctx->getFlags().getUseNonsfi()) { | |
5476 assert(GotVar); | |
5477 CfgNode *Node = Context.getNode(); | |
5478 uint32_t GotVarUseCount = 0; | |
5479 for (Inst &I : Node->getPhis()) { | |
5480 auto *Phi = llvm::dyn_cast<InstPhi>(&I); | |
5481 if (Phi->isDeleted()) | |
5482 continue; | |
5483 for (SizeT I = 0; I < Phi->getSrcSize(); ++I) { | |
5484 Operand *Src = Phi->getSrc(I); | |
5485 // TODO(stichnot): This over-counts for +0.0, and under-counts for other | |
5486 // kinds of pooling. | |
5487 if (llvm::isa<ConstantRelocatable>(Src) || | |
5488 llvm::isa<ConstantFloat>(Src) || llvm::isa<ConstantDouble>(Src)) { | |
5489 ++GotVarUseCount; | |
5490 } | |
5491 } | |
5492 } | |
5493 if (GotVarUseCount) { | |
5494 Node->getInsts().push_front(InstFakeUse::create(Func, GotVar)); | |
5495 } | |
5496 } | |
5415 if (Traits::Is64Bit) { | 5497 if (Traits::Is64Bit) { |
5416 // On x86-64 we don't need to prelower phis -- the architecture can handle | 5498 // On x86-64 we don't need to prelower phis -- the architecture can handle |
5417 // 64-bit integer natively. | 5499 // 64-bit integer natively. |
5418 return; | 5500 return; |
5419 } | 5501 } |
5420 | 5502 |
5421 // Pause constant blinding or pooling, blinding or pooling will be done later | 5503 // Pause constant blinding or pooling, blinding or pooling will be done later |
5422 // during phi lowering assignments | 5504 // during phi lowering assignments |
5423 BoolFlagSaver B(RandomizationPoolingPaused, true); | 5505 BoolFlagSaver B(RandomizationPoolingPaused, true); |
5424 PhiLowering::prelowerPhis32Bit<TargetX86Base<Machine>>( | 5506 PhiLowering::prelowerPhis32Bit<TargetX86Base<Machine>>( |
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5885 _movp(Reg, Src); | 5967 _movp(Reg, Src); |
5886 } else { | 5968 } else { |
5887 _mov(Reg, Src); | 5969 _mov(Reg, Src); |
5888 } | 5970 } |
5889 return Reg; | 5971 return Reg; |
5890 } | 5972 } |
5891 | 5973 |
5892 template <class Machine> | 5974 template <class Machine> |
5893 Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, | 5975 Operand *TargetX86Base<Machine>::legalize(Operand *From, LegalMask Allowed, |
5894 int32_t RegNum) { | 5976 int32_t RegNum) { |
5895 Type Ty = From->getType(); | 5977 const bool UseNonsfi = Func->getContext()->getFlags().getUseNonsfi(); |
5978 const Type Ty = From->getType(); | |
5896 // Assert that a physical register is allowed. To date, all calls to | 5979 // Assert that a physical register is allowed. To date, all calls to |
5897 // legalize() allow a physical register. If a physical register needs to be | 5980 // legalize() allow a physical register. If a physical register needs to be |
5898 // explicitly disallowed, then new code will need to be written to force a | 5981 // explicitly disallowed, then new code will need to be written to force a |
5899 // spill. | 5982 // spill. |
5900 assert(Allowed & Legal_Reg); | 5983 assert(Allowed & Legal_Reg); |
5901 // If we're asking for a specific physical register, make sure we're not | 5984 // If we're asking for a specific physical register, make sure we're not |
5902 // allowing any other operand kinds. (This could be future work, e.g. allow | 5985 // allowing any other operand kinds. (This could be future work, e.g. allow |
5903 // the shl shift amount to be either an immediate or in ecx.) | 5986 // the shl shift amount to be either an immediate or in ecx.) |
5904 assert(RegNum == Variable::NoRegister || Allowed == Legal_Reg); | 5987 assert(RegNum == Variable::NoRegister || Allowed == Legal_Reg); |
5905 | 5988 |
(...skipping 13 matching lines...) Expand all Loading... | |
5919 } | 6002 } |
5920 } | 6003 } |
5921 } | 6004 } |
5922 } | 6005 } |
5923 | 6006 |
5924 if (auto *Mem = llvm::dyn_cast<typename Traits::X86OperandMem>(From)) { | 6007 if (auto *Mem = llvm::dyn_cast<typename Traits::X86OperandMem>(From)) { |
5925 // Before doing anything with a Mem operand, we need to ensure that the | 6008 // Before doing anything with a Mem operand, we need to ensure that the |
5926 // Base and Index components are in physical registers. | 6009 // Base and Index components are in physical registers. |
5927 Variable *Base = Mem->getBase(); | 6010 Variable *Base = Mem->getBase(); |
5928 Variable *Index = Mem->getIndex(); | 6011 Variable *Index = Mem->getIndex(); |
6012 Constant *Offset = Mem->getOffset(); | |
5929 Variable *RegBase = nullptr; | 6013 Variable *RegBase = nullptr; |
5930 Variable *RegIndex = nullptr; | 6014 Variable *RegIndex = nullptr; |
5931 if (Base) { | 6015 if (Base) { |
5932 RegBase = llvm::cast<Variable>( | 6016 RegBase = llvm::cast<Variable>( |
5933 legalize(Base, Legal_Reg | Legal_Rematerializable)); | 6017 legalize(Base, Legal_Reg | Legal_Rematerializable)); |
5934 } | 6018 } |
5935 if (Index) { | 6019 if (Index) { |
5936 RegIndex = llvm::cast<Variable>( | 6020 RegIndex = llvm::cast<Variable>( |
5937 legalize(Index, Legal_Reg | Legal_Rematerializable)); | 6021 legalize(Index, Legal_Reg | Legal_Rematerializable)); |
5938 } | 6022 } |
6023 // For Non-SFI mode, if the Offset field is a ConstantRelocatable, we | |
6024 // replace either Base or Index with a legalized GotVar. At emission time, | |
6025 // the ConstantRelocatable will be emitted with the @GOTOFF relocation. | |
6026 bool NeedPIC = false; | |
6027 if (UseNonsfi && !Mem->getIsPIC() && Offset && | |
6028 llvm::isa<ConstantRelocatable>(Offset)) { | |
6029 assert(!(Allowed & Legal_AddrAbs)); | |
6030 NeedPIC = true; | |
6031 if (RegBase == nullptr) { | |
6032 RegBase = legalizeToReg(GotVar); | |
6033 } else if (RegIndex == nullptr) { | |
6034 RegIndex = legalizeToReg(GotVar); | |
6035 } else { | |
6036 llvm::report_fatal_error( | |
6037 "Either Base or Index must be unused in Non-SFI mode"); | |
6038 } | |
6039 } | |
5939 if (Base != RegBase || Index != RegIndex) { | 6040 if (Base != RegBase || Index != RegIndex) { |
5940 Mem = Traits::X86OperandMem::create(Func, Ty, RegBase, Mem->getOffset(), | 6041 Mem = Traits::X86OperandMem::create(Func, Ty, RegBase, Offset, RegIndex, |
5941 RegIndex, Mem->getShift(), | 6042 Mem->getShift(), |
5942 Mem->getSegmentRegister()); | 6043 Mem->getSegmentRegister(), NeedPIC); |
5943 } | 6044 } |
5944 | 6045 |
5945 // For all Memory Operands, we do randomization/pooling here | 6046 // For all Memory Operands, we do randomization/pooling here |
5946 From = randomizeOrPoolImmediate(Mem); | 6047 From = randomizeOrPoolImmediate(Mem); |
5947 | 6048 |
5948 if (!(Allowed & Legal_Mem)) { | 6049 if (!(Allowed & Legal_Mem)) { |
5949 From = copyToReg(From, RegNum); | 6050 From = copyToReg(From, RegNum); |
5950 } | 6051 } |
5951 return From; | 6052 return From; |
5952 } | 6053 } |
6054 | |
5953 if (auto *Const = llvm::dyn_cast<Constant>(From)) { | 6055 if (auto *Const = llvm::dyn_cast<Constant>(From)) { |
5954 if (llvm::isa<ConstantUndef>(Const)) { | 6056 if (llvm::isa<ConstantUndef>(Const)) { |
5955 From = legalizeUndef(Const, RegNum); | 6057 From = legalizeUndef(Const, RegNum); |
5956 if (isVectorType(Ty)) | 6058 if (isVectorType(Ty)) |
5957 return From; | 6059 return From; |
5958 Const = llvm::cast<Constant>(From); | 6060 Const = llvm::cast<Constant>(From); |
5959 } | 6061 } |
5960 // There should be no constants of vector type (other than undef). | 6062 // There should be no constants of vector type (other than undef). |
5961 assert(!isVectorType(Ty)); | 6063 assert(!isVectorType(Ty)); |
5962 | 6064 |
5963 // If the operand is a 64 bit constant integer we need to legalize it to a | 6065 // If the operand is a 64 bit constant integer we need to legalize it to a |
5964 // register in x86-64. | 6066 // register in x86-64. |
5965 if (Traits::Is64Bit) { | 6067 if (Traits::Is64Bit) { |
5966 if (llvm::isa<ConstantInteger64>(Const)) { | 6068 if (llvm::isa<ConstantInteger64>(Const)) { |
5967 Variable *V = copyToReg(Const, RegNum); | 6069 Variable *V = copyToReg(Const, RegNum); |
5968 return V; | 6070 return V; |
5969 } | 6071 } |
5970 } | 6072 } |
5971 | 6073 |
5972 // If the operand is an 32 bit constant integer, we should check whether we | 6074 // If the operand is an 32 bit constant integer, we should check whether we |
5973 // need to randomize it or pool it. | 6075 // need to randomize it or pool it. |
5974 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Const)) { | 6076 if (auto *C = llvm::dyn_cast<ConstantInteger32>(Const)) { |
5975 Operand *NewConst = randomizeOrPoolImmediate(C, RegNum); | 6077 Operand *NewConst = randomizeOrPoolImmediate(C, RegNum); |
5976 if (NewConst != Const) { | 6078 if (NewConst != Const) { |
5977 return NewConst; | 6079 return NewConst; |
5978 } | 6080 } |
5979 } | 6081 } |
5980 | 6082 |
6083 // If the operand is a ConstantRelocatable, and Legal_AddrAbs is not | |
6084 // specified, and UseNonsfi is indicated, we need to add GotVar. | |
6085 if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Const)) { | |
6086 if (UseNonsfi && !(Allowed & Legal_AddrAbs)) { | |
6087 assert(Ty == IceType_i32); | |
6088 Variable *RegBase = legalizeToReg(GotVar); | |
6089 Variable *NewVar = makeReg(Ty, RegNum); | |
6090 auto *Mem = Traits::X86OperandMem::create(Func, Ty, RegBase, CR); | |
6091 Mem->setIsPIC(); | |
6092 _lea(NewVar, Mem); | |
6093 From = NewVar; | |
6094 } | |
6095 } | |
6096 | |
5981 // Convert a scalar floating point constant into an explicit memory | 6097 // Convert a scalar floating point constant into an explicit memory |
5982 // operand. | 6098 // operand. |
5983 if (isScalarFloatingType(Ty)) { | 6099 if (isScalarFloatingType(Ty)) { |
5984 if (auto *ConstFloat = llvm::dyn_cast<ConstantFloat>(Const)) { | 6100 if (auto *ConstFloat = llvm::dyn_cast<ConstantFloat>(Const)) { |
5985 if (Utils::isPositiveZero(ConstFloat->getValue())) | 6101 if (Utils::isPositiveZero(ConstFloat->getValue())) |
5986 return makeZeroedRegister(Ty, RegNum); | 6102 return makeZeroedRegister(Ty, RegNum); |
5987 } else if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(Const)) { | 6103 } else if (auto *ConstDouble = llvm::dyn_cast<ConstantDouble>(Const)) { |
5988 if (Utils::isPositiveZero(ConstDouble->getValue())) | 6104 if (Utils::isPositiveZero(ConstDouble->getValue())) |
5989 return makeZeroedRegister(Ty, RegNum); | 6105 return makeZeroedRegister(Ty, RegNum); |
5990 } | 6106 } |
5991 Variable *Base = nullptr; | 6107 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr; |
5992 std::string Buffer; | 6108 std::string Buffer; |
5993 llvm::raw_string_ostream StrBuf(Buffer); | 6109 llvm::raw_string_ostream StrBuf(Buffer); |
5994 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx); | 6110 llvm::cast<Constant>(From)->emitPoolLabel(StrBuf, Ctx); |
5995 llvm::cast<Constant>(From)->setShouldBePooled(true); | 6111 llvm::cast<Constant>(From)->setShouldBePooled(true); |
5996 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); | 6112 Constant *Offset = Ctx->getConstantSym(0, StrBuf.str(), true); |
5997 From = Traits::X86OperandMem::create(Func, Ty, Base, Offset); | 6113 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); |
6114 if (UseNonsfi) | |
6115 Mem->setIsPIC(); | |
6116 From = Mem; | |
5998 } | 6117 } |
5999 bool NeedsReg = false; | 6118 bool NeedsReg = false; |
6000 if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty)) | 6119 if (!(Allowed & Legal_Imm) && !isScalarFloatingType(Ty)) |
6001 // Immediate specifically not allowed | 6120 // Immediate specifically not allowed |
6002 NeedsReg = true; | 6121 NeedsReg = true; |
6003 if (!(Allowed & Legal_Mem) && isScalarFloatingType(Ty)) | 6122 if (!(Allowed & Legal_Mem) && isScalarFloatingType(Ty)) |
6004 // On x86, FP constants are lowered to mem operands. | 6123 // On x86, FP constants are lowered to mem operands. |
6005 NeedsReg = true; | 6124 NeedsReg = true; |
6006 if (NeedsReg) { | 6125 if (NeedsReg) { |
6007 From = copyToReg(From, RegNum); | 6126 From = copyToReg(From, RegNum); |
6008 } | 6127 } |
6009 return From; | 6128 return From; |
6010 } | 6129 } |
6130 | |
6011 if (auto *Var = llvm::dyn_cast<Variable>(From)) { | 6131 if (auto *Var = llvm::dyn_cast<Variable>(From)) { |
6012 // Check if the variable is guaranteed a physical register. This can happen | 6132 // Check if the variable is guaranteed a physical register. This can happen |
6013 // either when the variable is pre-colored or when it is assigned infinite | 6133 // either when the variable is pre-colored or when it is assigned infinite |
6014 // weight. | 6134 // weight. |
6015 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); | 6135 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); |
6016 bool MustRematerialize = | 6136 bool MustRematerialize = |
6017 (Var->isRematerializable() && !(Allowed & Legal_Rematerializable)); | 6137 (Var->isRematerializable() && !(Allowed & Legal_Rematerializable)); |
6018 // We need a new physical register for the operand if: | 6138 // We need a new physical register for the operand if: |
6019 // - Mem is not allowed and Var isn't guaranteed a physical register, or | 6139 // - Mem is not allowed and Var isn't guaranteed a physical register, or |
6020 // - RegNum is required and Var->getRegNum() doesn't match, or | 6140 // - RegNum is required and Var->getRegNum() doesn't match, or |
6021 // - Var is a rematerializable variable and rematerializable pass-through is | 6141 // - Var is a rematerializable variable and rematerializable pass-through is |
6022 // not allowed (in which case we need an lea instruction). | 6142 // not allowed (in which case we need an lea instruction). |
6023 if (MustRematerialize) { | 6143 if (MustRematerialize) { |
6024 assert(Ty == IceType_i32); | 6144 assert(Ty == IceType_i32); |
6025 Variable *NewVar = makeReg(Ty, RegNum); | 6145 Variable *NewVar = makeReg(Ty, RegNum); |
6026 // Since Var is rematerializable, the offset will be added when the lea is | 6146 // Since Var is rematerializable, the offset will be added when the lea is |
6027 // emitted. | 6147 // emitted. |
6028 constexpr Constant *NoOffset = nullptr; | 6148 constexpr Constant *NoOffset = nullptr; |
6029 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Var, NoOffset); | 6149 auto *Mem = Traits::X86OperandMem::create(Func, Ty, Var, NoOffset); |
6030 _lea(NewVar, Mem); | 6150 _lea(NewVar, Mem); |
6031 From = NewVar; | 6151 From = NewVar; |
6032 } else if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || | 6152 } else if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || |
6033 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum()) || | 6153 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum()) || |
6034 MustRematerialize) { | 6154 MustRematerialize) { |
6035 From = copyToReg(From, RegNum); | 6155 From = copyToReg(From, RegNum); |
6036 } | 6156 } |
6037 return From; | 6157 return From; |
6038 } | 6158 } |
6039 llvm_unreachable("Unhandled operand kind in legalize()"); | 6159 |
6160 llvm::report_fatal_error("Unhandled operand kind in legalize()"); | |
6040 return From; | 6161 return From; |
6041 } | 6162 } |
6042 | 6163 |
6043 /// Provide a trivial wrapper to legalize() for this common usage. | 6164 /// Provide a trivial wrapper to legalize() for this common usage. |
6044 template <class Machine> | 6165 template <class Machine> |
6045 Variable *TargetX86Base<Machine>::legalizeToReg(Operand *From, int32_t RegNum) { | 6166 Variable *TargetX86Base<Machine>::legalizeToReg(Operand *From, int32_t RegNum) { |
6046 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); | 6167 return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum)); |
6047 } | 6168 } |
6048 | 6169 |
6049 /// Legalize undef values to concrete values. | 6170 /// Legalize undef values to concrete values. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6097 // transformation. | 6218 // transformation. |
6098 if (!Mem) { | 6219 if (!Mem) { |
6099 auto *Base = llvm::dyn_cast<Variable>(Opnd); | 6220 auto *Base = llvm::dyn_cast<Variable>(Opnd); |
6100 auto *Offset = llvm::dyn_cast<Constant>(Opnd); | 6221 auto *Offset = llvm::dyn_cast<Constant>(Opnd); |
6101 assert(Base || Offset); | 6222 assert(Base || Offset); |
6102 if (Offset) { | 6223 if (Offset) { |
6103 // During memory operand building, we do not blind or pool the constant | 6224 // During memory operand building, we do not blind or pool the constant |
6104 // offset, we will work on the whole memory operand later as one entity | 6225 // offset, we will work on the whole memory operand later as one entity |
6105 // later, this save one instruction. By turning blinding and pooling off, | 6226 // later, this save one instruction. By turning blinding and pooling off, |
6106 // we guarantee legalize(Offset) will return a Constant*. | 6227 // we guarantee legalize(Offset) will return a Constant*. |
6107 { | 6228 if (!llvm::isa<ConstantRelocatable>(Offset)) { |
6108 BoolFlagSaver B(RandomizationPoolingPaused, true); | 6229 BoolFlagSaver B(RandomizationPoolingPaused, true); |
6109 | 6230 |
6110 Offset = llvm::cast<Constant>(legalize(Offset)); | 6231 Offset = llvm::cast<Constant>(legalize(Offset)); |
6111 } | 6232 } |
6112 | 6233 |
6113 assert(llvm::isa<ConstantInteger32>(Offset) || | 6234 assert(llvm::isa<ConstantInteger32>(Offset) || |
6114 llvm::isa<ConstantRelocatable>(Offset)); | 6235 llvm::isa<ConstantRelocatable>(Offset)); |
6115 } | 6236 } |
6237 // Not completely sure whether it's OK to leave IsPIC unset when creating | |
6238 // the mem operand. If DoLegalize is true, it will definitely be applied | |
6239 // during the legalize() call, but perhaps not during the | |
6240 // randomizeOrPoolImmediate() call. In any case, the emit routines will | |
6241 // assert that PIC legalization has been applied. | |
6116 Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); | 6242 Mem = Traits::X86OperandMem::create(Func, Ty, Base, Offset); |
6117 } | 6243 } |
6118 // Do legalization, which contains randomization/pooling or do | 6244 // Do legalization, which contains randomization/pooling or do |
6119 // randomization/pooling. | 6245 // randomization/pooling. |
6120 return llvm::cast<typename Traits::X86OperandMem>( | 6246 return llvm::cast<typename Traits::X86OperandMem>( |
6121 DoLegalize ? legalize(Mem) : randomizeOrPoolImmediate(Mem)); | 6247 DoLegalize ? legalize(Mem) : randomizeOrPoolImmediate(Mem)); |
6122 } | 6248 } |
6123 | 6249 |
6124 template <class Machine> | 6250 template <class Machine> |
6125 Variable *TargetX86Base<Machine>::makeReg(Type Type, int32_t RegNum) { | 6251 Variable *TargetX86Base<Machine>::makeReg(Type Type, int32_t RegNum) { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6174 const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const { | 6300 const llvm::SmallBitVector &ExcludeRegisters, uint64_t Salt) const { |
6175 Traits::makeRandomRegisterPermutation(Ctx, Func, Permutation, | 6301 Traits::makeRandomRegisterPermutation(Ctx, Func, Permutation, |
6176 ExcludeRegisters, Salt); | 6302 ExcludeRegisters, Salt); |
6177 } | 6303 } |
6178 | 6304 |
6179 template <class Machine> | 6305 template <class Machine> |
6180 void TargetX86Base<Machine>::emit(const ConstantInteger32 *C) const { | 6306 void TargetX86Base<Machine>::emit(const ConstantInteger32 *C) const { |
6181 if (!BuildDefs::dump()) | 6307 if (!BuildDefs::dump()) |
6182 return; | 6308 return; |
6183 Ostream &Str = Ctx->getStrEmit(); | 6309 Ostream &Str = Ctx->getStrEmit(); |
6184 Str << getConstantPrefix() << C->getValue(); | 6310 Str << "$" << C->getValue(); |
6185 } | 6311 } |
6186 | 6312 |
6187 template <class Machine> | 6313 template <class Machine> |
6188 void TargetX86Base<Machine>::emit(const ConstantInteger64 *C) const { | 6314 void TargetX86Base<Machine>::emit(const ConstantInteger64 *C) const { |
6189 if (!Traits::Is64Bit) { | 6315 if (!Traits::Is64Bit) { |
6190 llvm::report_fatal_error("Not expecting to emit 64-bit integers"); | 6316 llvm::report_fatal_error("Not expecting to emit 64-bit integers"); |
6191 } else { | 6317 } else { |
6192 if (!BuildDefs::dump()) | 6318 if (!BuildDefs::dump()) |
6193 return; | 6319 return; |
6194 Ostream &Str = Ctx->getStrEmit(); | 6320 Ostream &Str = Ctx->getStrEmit(); |
6195 Str << getConstantPrefix() << C->getValue(); | 6321 Str << "$" << C->getValue(); |
6196 } | 6322 } |
6197 } | 6323 } |
6198 | 6324 |
6199 template <class Machine> | 6325 template <class Machine> |
6200 void TargetX86Base<Machine>::emit(const ConstantFloat *C) const { | 6326 void TargetX86Base<Machine>::emit(const ConstantFloat *C) const { |
6201 if (!BuildDefs::dump()) | 6327 if (!BuildDefs::dump()) |
6202 return; | 6328 return; |
6203 Ostream &Str = Ctx->getStrEmit(); | 6329 Ostream &Str = Ctx->getStrEmit(); |
6204 C->emitPoolLabel(Str, Ctx); | 6330 C->emitPoolLabel(Str, Ctx); |
6205 } | 6331 } |
6206 | 6332 |
6207 template <class Machine> | 6333 template <class Machine> |
6208 void TargetX86Base<Machine>::emit(const ConstantDouble *C) const { | 6334 void TargetX86Base<Machine>::emit(const ConstantDouble *C) const { |
6209 if (!BuildDefs::dump()) | 6335 if (!BuildDefs::dump()) |
6210 return; | 6336 return; |
6211 Ostream &Str = Ctx->getStrEmit(); | 6337 Ostream &Str = Ctx->getStrEmit(); |
6212 C->emitPoolLabel(Str, Ctx); | 6338 C->emitPoolLabel(Str, Ctx); |
6213 } | 6339 } |
6214 | 6340 |
6215 template <class Machine> | 6341 template <class Machine> |
6216 void TargetX86Base<Machine>::emit(const ConstantUndef *) const { | 6342 void TargetX86Base<Machine>::emit(const ConstantUndef *) const { |
6217 llvm::report_fatal_error("undef value encountered by emitter."); | 6343 llvm::report_fatal_error("undef value encountered by emitter."); |
6218 } | 6344 } |
6219 | 6345 |
6346 template <class Machine> | |
6347 void TargetX86Base<Machine>::emit(const ConstantRelocatable *C) const { | |
6348 if (!BuildDefs::dump()) | |
6349 return; | |
6350 assert(!Ctx->getFlags().getUseNonsfi()); | |
6351 Ostream &Str = Ctx->getStrEmit(); | |
6352 Str << "$"; | |
6353 emitWithoutPrefix(C); | |
6354 } | |
6355 | |
6220 /// Randomize or pool an Immediate. | 6356 /// Randomize or pool an Immediate. |
6221 template <class Machine> | 6357 template <class Machine> |
6222 Operand *TargetX86Base<Machine>::randomizeOrPoolImmediate(Constant *Immediate, | 6358 Operand *TargetX86Base<Machine>::randomizeOrPoolImmediate(Constant *Immediate, |
6223 int32_t RegNum) { | 6359 int32_t RegNum) { |
6224 assert(llvm::isa<ConstantInteger32>(Immediate) || | 6360 assert(llvm::isa<ConstantInteger32>(Immediate) || |
6225 llvm::isa<ConstantRelocatable>(Immediate)); | 6361 llvm::isa<ConstantRelocatable>(Immediate)); |
6226 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || | 6362 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None || |
6227 RandomizationPoolingPaused == true) { | 6363 RandomizationPoolingPaused == true) { |
6228 // Immediates randomization/pooling off or paused | 6364 // Immediates randomization/pooling off or paused |
6229 return Immediate; | 6365 return Immediate; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6273 // assigned register as this assignment is that start of its use-def | 6409 // assigned register as this assignment is that start of its use-def |
6274 // chain. So we add RegNum argument here. | 6410 // chain. So we add RegNum argument here. |
6275 Variable *Reg = makeReg(Immediate->getType(), RegNum); | 6411 Variable *Reg = makeReg(Immediate->getType(), RegNum); |
6276 IceString Label; | 6412 IceString Label; |
6277 llvm::raw_string_ostream Label_stream(Label); | 6413 llvm::raw_string_ostream Label_stream(Label); |
6278 Immediate->emitPoolLabel(Label_stream, Ctx); | 6414 Immediate->emitPoolLabel(Label_stream, Ctx); |
6279 constexpr RelocOffsetT Offset = 0; | 6415 constexpr RelocOffsetT Offset = 0; |
6280 constexpr bool SuppressMangling = true; | 6416 constexpr bool SuppressMangling = true; |
6281 Constant *Symbol = | 6417 Constant *Symbol = |
6282 Ctx->getConstantSym(Offset, Label_stream.str(), SuppressMangling); | 6418 Ctx->getConstantSym(Offset, Label_stream.str(), SuppressMangling); |
6419 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); | |
6420 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr; | |
6283 typename Traits::X86OperandMem *MemOperand = | 6421 typename Traits::X86OperandMem *MemOperand = |
6284 Traits::X86OperandMem::create(Func, Immediate->getType(), nullptr, | 6422 Traits::X86OperandMem::create(Func, Immediate->getType(), Base, |
6285 Symbol); | 6423 Symbol); |
6424 if (UseNonsfi) | |
6425 MemOperand->setIsPIC(); | |
6286 _mov(Reg, MemOperand); | 6426 _mov(Reg, MemOperand); |
6287 return Reg; | 6427 return Reg; |
6288 } | 6428 } |
6289 assert("Unsupported -randomize-pool-immediates option" && false); | 6429 assert("Unsupported -randomize-pool-immediates option" && false); |
6290 } | 6430 } |
6291 // the constant Immediate is not eligible for blinding/pooling | 6431 // the constant Immediate is not eligible for blinding/pooling |
6292 return Immediate; | 6432 return Immediate; |
6293 } | 6433 } |
6294 | 6434 |
6295 template <class Machine> | 6435 template <class Machine> |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6370 return MemOperand; | 6510 return MemOperand; |
6371 Variable *RegTemp = makeReg(IceType_i32); | 6511 Variable *RegTemp = makeReg(IceType_i32); |
6372 IceString Label; | 6512 IceString Label; |
6373 llvm::raw_string_ostream Label_stream(Label); | 6513 llvm::raw_string_ostream Label_stream(Label); |
6374 MemOperand->getOffset()->emitPoolLabel(Label_stream, Ctx); | 6514 MemOperand->getOffset()->emitPoolLabel(Label_stream, Ctx); |
6375 MemOperand->getOffset()->setShouldBePooled(true); | 6515 MemOperand->getOffset()->setShouldBePooled(true); |
6376 constexpr RelocOffsetT SymOffset = 0; | 6516 constexpr RelocOffsetT SymOffset = 0; |
6377 constexpr bool SuppressMangling = true; | 6517 constexpr bool SuppressMangling = true; |
6378 Constant *Symbol = Ctx->getConstantSym(SymOffset, Label_stream.str(), | 6518 Constant *Symbol = Ctx->getConstantSym(SymOffset, Label_stream.str(), |
6379 SuppressMangling); | 6519 SuppressMangling); |
6520 const bool UseNonsfi = Ctx->getFlags().getUseNonsfi(); | |
6521 Variable *Base = UseNonsfi ? legalizeToReg(GotVar) : nullptr; | |
6380 typename Traits::X86OperandMem *SymbolOperand = | 6522 typename Traits::X86OperandMem *SymbolOperand = |
6381 Traits::X86OperandMem::create( | 6523 Traits::X86OperandMem::create( |
6382 Func, MemOperand->getOffset()->getType(), nullptr, Symbol); | 6524 Func, MemOperand->getOffset()->getType(), Base, Symbol); |
6525 if (UseNonsfi) | |
6526 SymbolOperand->setIsPIC(); | |
6383 _mov(RegTemp, SymbolOperand); | 6527 _mov(RegTemp, SymbolOperand); |
6384 // If we have a base variable here, we should add the lea instruction | 6528 // If we have a base variable here, we should add the lea instruction |
6385 // to add the value of the base variable to RegTemp. If there is no | 6529 // to add the value of the base variable to RegTemp. If there is no |
6386 // base variable, we won't need this lea instruction. | 6530 // base variable, we won't need this lea instruction. |
6387 if (MemOperand->getBase()) { | 6531 if (MemOperand->getBase()) { |
6388 typename Traits::X86OperandMem *CalculateOperand = | 6532 typename Traits::X86OperandMem *CalculateOperand = |
6389 Traits::X86OperandMem::create( | 6533 Traits::X86OperandMem::create( |
6390 Func, MemOperand->getType(), MemOperand->getBase(), nullptr, | 6534 Func, MemOperand->getType(), MemOperand->getBase(), nullptr, |
6391 RegTemp, 0, MemOperand->getSegmentRegister()); | 6535 RegTemp, 0, MemOperand->getSegmentRegister()); |
6392 _lea(RegTemp, CalculateOperand); | 6536 _lea(RegTemp, CalculateOperand); |
(...skipping 10 matching lines...) Expand all Loading... | |
6403 } | 6547 } |
6404 // the offset is not eligible for blinding or pooling, return the original | 6548 // the offset is not eligible for blinding or pooling, return the original |
6405 // mem operand | 6549 // mem operand |
6406 return MemOperand; | 6550 return MemOperand; |
6407 } | 6551 } |
6408 | 6552 |
6409 } // end of namespace X86Internal | 6553 } // end of namespace X86Internal |
6410 } // end of namespace Ice | 6554 } // end of namespace Ice |
6411 | 6555 |
6412 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H | 6556 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H |
OLD | NEW |