Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(479)

Side by Side Diff: src/IceTargetLoweringX86BaseImpl.h

Issue 1253833002: Subzero: Cleanly implement register allocation after phi lowering. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Cleanup Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW
« src/IceTargetLoweringARM32.cpp ('K') | « src/IceTargetLoweringX86Base.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698