Chromium Code Reviews| 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 |