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 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 380 // The post-codegen dump is done here, after liveness analysis and associated | 380 // The post-codegen dump is done here, after liveness analysis and associated |
| 381 // cleanup, to make the dump cleaner and more useful. | 381 // cleanup, to make the dump cleaner and more useful. |
| 382 Func->dump("After initial x8632 codegen"); | 382 Func->dump("After initial x8632 codegen"); |
| 383 Func->getVMetadata()->init(VMK_All); | 383 Func->getVMetadata()->init(VMK_All); |
| 384 regAlloc(RAK_Global); | 384 regAlloc(RAK_Global); |
| 385 if (Func->hasError()) | 385 if (Func->hasError()) |
| 386 return; | 386 return; |
| 387 Func->dump("After linear scan regalloc"); | 387 Func->dump("After linear scan regalloc"); |
| 388 | 388 |
| 389 if (Ctx->getFlags().getPhiEdgeSplit()) { | 389 if (Ctx->getFlags().getPhiEdgeSplit()) { |
| 390 // We need to pause constant blinding or pooling during advanced phi | 390 Func->advancedPhiLowering(); |
| 391 // lowering, unless the lowering assignment has a physical register for the | |
| 392 // dest Variable. | |
| 393 { | |
| 394 BoolFlagSaver B(RandomizationPoolingPaused, true); | |
| 395 Func->advancedPhiLowering(); | |
| 396 } | |
| 397 Func->dump("After advanced Phi lowering"); | 391 Func->dump("After advanced Phi lowering"); |
| 398 } | 392 } |
| 399 | 393 |
| 400 // Stack frame mapping. | 394 // Stack frame mapping. |
| 401 Func->genFrame(); | 395 Func->genFrame(); |
| 402 if (Func->hasError()) | 396 if (Func->hasError()) |
| 403 return; | 397 return; |
| 404 Func->dump("After stack frame mapping"); | 398 Func->dump("After stack frame mapping"); |
| 405 | 399 |
| 406 Func->contractEmptyNodes(); | 400 Func->contractEmptyNodes(); |
| (...skipping 1625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2032 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2026 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 2033 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2027 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 2034 Variable *T_Lo = nullptr, *T_Hi = nullptr; | 2028 Variable *T_Lo = nullptr, *T_Hi = nullptr; |
| 2035 _mov(T_Lo, Src0Lo); | 2029 _mov(T_Lo, Src0Lo); |
| 2036 _mov(DestLo, T_Lo); | 2030 _mov(DestLo, T_Lo); |
| 2037 _mov(T_Hi, Src0Hi); | 2031 _mov(T_Hi, Src0Hi); |
| 2038 _mov(DestHi, T_Hi); | 2032 _mov(DestHi, T_Hi); |
| 2039 } else { | 2033 } else { |
| 2040 Operand *RI; | 2034 Operand *RI; |
| 2041 if (Dest->hasReg()) { | 2035 if (Dest->hasReg()) { |
| 2042 // If Dest already has a physical register, then legalize the | 2036 // If Dest already has a physical register, then legalize the Src operand |
| 2043 // Src operand into a Variable with the same register | 2037 // into a Variable with the same register assignment. (This just reduces |
| 2044 // assignment. This is mostly a workaround for advanced phi | 2038 // a bit of work that the register allocator would have figured out by |
| 2045 // lowering's ad-hoc register allocation which assumes no | 2039 // itself.) |
| 2046 // register allocation is needed when at least one of the | 2040 RI = legalize(Src0, Legal_Reg, Dest->getRegNum()); |
| 2047 // operands is non-memory. | |
| 2048 | |
| 2049 // If we have a physical register for the dest variable, we can | |
| 2050 // enable our constant blinding or pooling again. Note this is | |
| 2051 // only for advancedPhiLowering(), the flag flip should leave | |
| 2052 // no other side effect. | |
| 2053 { | |
| 2054 BoolFlagSaver B(RandomizationPoolingPaused, false); | |
| 2055 RI = legalize(Src0, Legal_Reg, Dest->getRegNum()); | |
| 2056 } | |
| 2057 } else { | 2041 } else { |
| 2058 // If Dest could be a stack operand, then RI must be a physical | 2042 // If Dest could be a stack operand, then RI must be a physical |
| 2059 // register or a scalar integer immediate. | 2043 // register or a scalar integer immediate. |
| 2060 RI = legalize(Src0, Legal_Reg | Legal_Imm); | 2044 RI = legalize(Src0, Legal_Reg | Legal_Imm); |
| 2061 } | 2045 } |
| 2062 if (isVectorType(Dest->getType())) | 2046 if (isVectorType(Dest->getType())) |
| 2063 _movp(Dest, RI); | 2047 _movp(Dest, RI); |
| 2064 else | 2048 else |
| 2065 _mov(Dest, RI); | 2049 _mov(Dest, RI); |
| 2066 } | 2050 } |
| (...skipping 2837 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4904 /// turned into zeroes, since loOperand() and hiOperand() don't expect | 4888 /// turned into zeroes, since loOperand() and hiOperand() don't expect |
| 4905 /// Undef input. | 4889 /// Undef input. |
| 4906 template <class Machine> void TargetX86Base<Machine>::prelowerPhis() { | 4890 template <class Machine> void TargetX86Base<Machine>::prelowerPhis() { |
| 4907 // Pause constant blinding or pooling, blinding or pooling will be done later | 4891 // Pause constant blinding or pooling, blinding or pooling will be done later |
| 4908 // during phi lowering assignments | 4892 // during phi lowering assignments |
| 4909 BoolFlagSaver B(RandomizationPoolingPaused, true); | 4893 BoolFlagSaver B(RandomizationPoolingPaused, true); |
| 4910 PhiLowering::prelowerPhis32Bit<TargetX86Base<Machine>>( | 4894 PhiLowering::prelowerPhis32Bit<TargetX86Base<Machine>>( |
| 4911 this, Context.getNode(), Func); | 4895 this, Context.getNode(), Func); |
| 4912 } | 4896 } |
| 4913 | 4897 |
| 4914 inline bool isMemoryOperand(const Operand *Opnd) { | 4898 inline bool isMemoryOperand(const Operand *Opnd) { |
|
jvoung (off chromium)
2015/07/24 19:43:08
I think you can remove isMemoryOperand now too, si
Jim Stichnoth
2015/07/26 04:47:50
Done.
| |
| 4915 if (const auto Var = llvm::dyn_cast<Variable>(Opnd)) | 4899 if (const auto Var = llvm::dyn_cast<Variable>(Opnd)) |
| 4916 return !Var->hasReg(); | 4900 return !Var->hasReg(); |
| 4917 // We treat vector undef values the same as a memory operand, | 4901 // We treat vector undef values the same as a memory operand, |
| 4918 // because they do in fact need a register to materialize the vector | 4902 // because they do in fact need a register to materialize the vector |
| 4919 // of zeroes into. | 4903 // of zeroes into. |
| 4920 if (llvm::isa<ConstantUndef>(Opnd)) | 4904 if (llvm::isa<ConstantUndef>(Opnd)) |
| 4921 return isScalarFloatingType(Opnd->getType()) || | 4905 return isScalarFloatingType(Opnd->getType()) || |
| 4922 isVectorType(Opnd->getType()); | 4906 isVectorType(Opnd->getType()); |
| 4923 if (llvm::isa<Constant>(Opnd)) | 4907 if (llvm::isa<Constant>(Opnd)) |
| 4924 return isScalarFloatingType(Opnd->getType()); | 4908 return isScalarFloatingType(Opnd->getType()); |
| 4925 return true; | 4909 return true; |
| 4926 } | 4910 } |
| 4927 | 4911 |
| 4928 /// Lower the pre-ordered list of assignments into mov instructions. | |
| 4929 /// Also has to do some ad-hoc register allocation as necessary. | |
| 4930 template <class Machine> | |
| 4931 void TargetX86Base<Machine>::lowerPhiAssignments( | |
| 4932 CfgNode *Node, const AssignList &Assignments) { | |
| 4933 // Check that this is a properly initialized shell of a node. | |
| 4934 assert(Node->getOutEdges().size() == 1); | |
| 4935 assert(Node->getInsts().empty()); | |
| 4936 assert(Node->getPhis().empty()); | |
| 4937 CfgNode *Succ = Node->getOutEdges().front(); | |
| 4938 getContext().init(Node); | |
| 4939 // Register set setup similar to regAlloc(). | |
| 4940 RegSetMask RegInclude = RegSet_All; | |
| 4941 RegSetMask RegExclude = RegSet_StackPointer; | |
| 4942 if (hasFramePointer()) | |
| 4943 RegExclude |= RegSet_FramePointer; | |
| 4944 llvm::SmallBitVector Available = getRegisterSet(RegInclude, RegExclude); | |
| 4945 bool NeedsRegs = false; | |
| 4946 // Initialize the set of available registers to the set of what is | |
| 4947 // available (not live) at the beginning of the successor block, | |
| 4948 // minus all registers used as Dest operands in the Assignments. To | |
| 4949 // do this, we start off assuming all registers are available, then | |
| 4950 // iterate through the Assignments and remove Dest registers. | |
| 4951 // During this iteration, we also determine whether we will actually | |
| 4952 // need any extra registers for memory-to-memory copies. If so, we | |
| 4953 // do the actual work of removing the live-in registers from the | |
| 4954 // set. TODO(stichnot): This work is being repeated for every split | |
| 4955 // edge to the successor, so consider updating LiveIn just once | |
| 4956 // after all the edges are split. | |
| 4957 for (const Inst &I : Assignments) { | |
| 4958 Variable *Dest = I.getDest(); | |
| 4959 if (Dest->hasReg()) { | |
| 4960 Available[Dest->getRegNum()] = false; | |
| 4961 } else if (isMemoryOperand(I.getSrc(0))) { | |
| 4962 NeedsRegs = true; // Src and Dest are both in memory | |
| 4963 } | |
| 4964 } | |
| 4965 if (NeedsRegs) { | |
| 4966 LivenessBV &LiveIn = Func->getLiveness()->getLiveIn(Succ); | |
| 4967 for (int i = LiveIn.find_first(); i != -1; i = LiveIn.find_next(i)) { | |
| 4968 Variable *Var = Func->getLiveness()->getVariable(i, Succ); | |
| 4969 if (Var->hasReg()) | |
| 4970 Available[Var->getRegNum()] = false; | |
| 4971 } | |
| 4972 } | |
| 4973 // Iterate backwards through the Assignments. After lowering each | |
| 4974 // assignment, add Dest to the set of available registers, and | |
| 4975 // remove Src from the set of available registers. Iteration is | |
| 4976 // done backwards to enable incremental updates of the available | |
| 4977 // register set, and the lowered instruction numbers may be out of | |
| 4978 // order, but that can be worked around by renumbering the block | |
| 4979 // afterwards if necessary. | |
| 4980 for (const Inst &I : reverse_range(Assignments)) { | |
| 4981 Context.rewind(); | |
| 4982 auto Assign = llvm::dyn_cast<InstAssign>(&I); | |
| 4983 Variable *Dest = Assign->getDest(); | |
| 4984 | |
| 4985 // If the source operand is ConstantUndef, do not legalize it. In function | |
| 4986 // test_split_undef_int_vec, the advanced phi lowering process will find an | |
| 4987 // assignment of undefined vector. This vector, as the Src here, will crash | |
| 4988 // if it go through legalize(). legalize() will create a new variable with | |
| 4989 // makeVectorOfZeros(), but this new variable will be assigned a stack | |
| 4990 // slot. This will fail with pxor(Var, Var) because it is an illegal | |
| 4991 // instruction form. Note this failure is irrelevant to randomization or | |
| 4992 // pooling of constants. So, we do not call legalize() to add pool label | |
| 4993 // for the src operands of phi assignment instructions. Instead, we | |
| 4994 // manually add pool label for constant float and constant double values | |
| 4995 // here. Note going through legalize() does not affect the testing results | |
| 4996 // of SPEC2K and xtests. | |
| 4997 Operand *Src = Assign->getSrc(0); | |
| 4998 if (!llvm::isa<ConstantUndef>(Assign->getSrc(0))) { | |
| 4999 Src = legalize(Src); | |
| 5000 } | |
| 5001 | |
| 5002 Variable *SrcVar = llvm::dyn_cast<Variable>(Src); | |
| 5003 // Use normal assignment lowering, except lower mem=mem specially | |
| 5004 // so we can register-allocate at the same time. | |
| 5005 if (!isMemoryOperand(Dest) || !isMemoryOperand(Src)) { | |
| 5006 lowerAssign(Assign); | |
| 5007 } else { | |
| 5008 assert(Dest->getType() == Src->getType()); | |
| 5009 const llvm::SmallBitVector &RegsForType = | |
| 5010 getRegisterSetForType(Dest->getType()); | |
| 5011 llvm::SmallBitVector AvailRegsForType = RegsForType & Available; | |
| 5012 Variable *SpillLoc = nullptr; | |
| 5013 Variable *Preg = nullptr; | |
| 5014 // TODO(stichnot): Opportunity for register randomization. | |
| 5015 int32_t RegNum = AvailRegsForType.find_first(); | |
| 5016 bool IsVector = isVectorType(Dest->getType()); | |
| 5017 bool NeedSpill = (RegNum == -1); | |
| 5018 if (NeedSpill) { | |
| 5019 // Pick some register to spill and update RegNum. | |
| 5020 // TODO(stichnot): Opportunity for register randomization. | |
| 5021 RegNum = RegsForType.find_first(); | |
| 5022 Preg = getPhysicalRegister(RegNum, Dest->getType()); | |
| 5023 SpillLoc = Func->makeVariable(Dest->getType()); | |
| 5024 // Create a fake def of the physical register to avoid | |
| 5025 // liveness inconsistency problems during late-stage liveness | |
| 5026 // analysis (e.g. asm-verbose mode). | |
| 5027 Context.insert(InstFakeDef::create(Func, Preg)); | |
| 5028 if (IsVector) | |
| 5029 _movp(SpillLoc, Preg); | |
| 5030 else | |
| 5031 _mov(SpillLoc, Preg); | |
| 5032 } | |
| 5033 assert(RegNum >= 0); | |
| 5034 if (llvm::isa<ConstantUndef>(Src)) | |
| 5035 // Materialize an actual constant instead of undef. RegNum is | |
| 5036 // passed in for vector types because undef vectors are | |
| 5037 // lowered to vector register of zeroes. | |
| 5038 Src = | |
| 5039 legalize(Src, Legal_All, IsVector ? RegNum : Variable::NoRegister); | |
| 5040 Variable *Tmp = makeReg(Dest->getType(), RegNum); | |
| 5041 if (IsVector) { | |
| 5042 _movp(Tmp, Src); | |
| 5043 _movp(Dest, Tmp); | |
| 5044 } else { | |
| 5045 _mov(Tmp, Src); | |
| 5046 _mov(Dest, Tmp); | |
| 5047 } | |
| 5048 if (NeedSpill) { | |
| 5049 // Restore the spilled register. | |
| 5050 if (IsVector) | |
| 5051 _movp(Preg, SpillLoc); | |
| 5052 else | |
| 5053 _mov(Preg, SpillLoc); | |
| 5054 // Create a fake use of the physical register to keep it live | |
| 5055 // for late-stage liveness analysis (e.g. asm-verbose mode). | |
| 5056 Context.insert(InstFakeUse::create(Func, Preg)); | |
| 5057 } | |
| 5058 } | |
| 5059 // Update register availability before moving to the previous | |
| 5060 // instruction on the Assignments list. | |
| 5061 if (Dest->hasReg()) | |
| 5062 Available[Dest->getRegNum()] = true; | |
| 5063 if (SrcVar && SrcVar->hasReg()) | |
| 5064 Available[SrcVar->getRegNum()] = false; | |
| 5065 } | |
| 5066 | |
| 5067 // Add the terminator branch instruction to the end. | |
| 5068 Context.setInsertPoint(Context.getEnd()); | |
| 5069 _br(Succ); | |
| 5070 } | |
| 5071 | |
| 5072 // There is no support for loading or emitting vector constants, so the | 4912 // There is no support for loading or emitting vector constants, so the |
| 5073 // vector values returned from makeVectorOfZeros, makeVectorOfOnes, | 4913 // vector values returned from makeVectorOfZeros, makeVectorOfOnes, |
| 5074 // etc. are initialized with register operations. | 4914 // etc. are initialized with register operations. |
| 5075 // | 4915 // |
| 5076 // TODO(wala): Add limited support for vector constants so that | 4916 // TODO(wala): Add limited support for vector constants so that |
| 5077 // complex initialization in registers is unnecessary. | 4917 // complex initialization in registers is unnecessary. |
| 5078 | 4918 |
| 5079 template <class Machine> | 4919 template <class Machine> |
| 5080 Variable *TargetX86Base<Machine>::makeVectorOfZeros(Type Ty, int32_t RegNum) { | 4920 Variable *TargetX86Base<Machine>::makeVectorOfZeros(Type Ty, int32_t RegNum) { |
| 5081 Variable *Reg = makeReg(Ty, RegNum); | 4921 Variable *Reg = makeReg(Ty, RegNum); |
| (...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5616 } | 5456 } |
| 5617 // the offset is not eligible for blinding or pooling, return the original | 5457 // the offset is not eligible for blinding or pooling, return the original |
| 5618 // mem operand | 5458 // mem operand |
| 5619 return MemOperand; | 5459 return MemOperand; |
| 5620 } | 5460 } |
| 5621 | 5461 |
| 5622 } // end of namespace X86Internal | 5462 } // end of namespace X86Internal |
| 5623 } // end of namespace Ice | 5463 } // end of namespace Ice |
| 5624 | 5464 |
| 5625 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H | 5465 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H |
| OLD | NEW |