Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===// | 1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===// |
| 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 // This file implements the TargetLoweringX8632 class, which | 10 // This file implements the TargetLoweringX8632 class, which |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 270 "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE"); | 270 "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE"); |
| 271 ICETYPE_TABLE; | 271 ICETYPE_TABLE; |
| 272 #undef X | 272 #undef X |
| 273 } // end of namespace dummy3 | 273 } // end of namespace dummy3 |
| 274 | 274 |
| 275 } // end of anonymous namespace | 275 } // end of anonymous namespace |
| 276 | 276 |
| 277 TargetX8632::TargetX8632(Cfg *Func) | 277 TargetX8632::TargetX8632(Cfg *Func) |
| 278 : TargetLowering(Func), InstructionSet(CLInstructionSet), | 278 : TargetLowering(Func), InstructionSet(CLInstructionSet), |
| 279 IsEbpBasedFrame(false), NeedsStackAlignment(false), FrameSizeLocals(0), | 279 IsEbpBasedFrame(false), NeedsStackAlignment(false), FrameSizeLocals(0), |
| 280 SpillAreaSizeBytes(0), NextLabelNumber(0), ComputedLiveRanges(false) { | 280 SpillAreaSizeBytes(0), NextLabelNumber(0) { |
| 281 // TODO: Don't initialize IntegerRegisters and friends every time. | 281 // TODO: Don't initialize IntegerRegisters and friends every time. |
| 282 // Instead, initialize in some sort of static initializer for the | 282 // Instead, initialize in some sort of static initializer for the |
| 283 // class. | 283 // class. |
| 284 llvm::SmallBitVector IntegerRegisters(RegX8632::Reg_NUM); | 284 llvm::SmallBitVector IntegerRegisters(RegX8632::Reg_NUM); |
| 285 llvm::SmallBitVector IntegerRegistersI8(RegX8632::Reg_NUM); | 285 llvm::SmallBitVector IntegerRegistersI8(RegX8632::Reg_NUM); |
| 286 llvm::SmallBitVector FloatRegisters(RegX8632::Reg_NUM); | 286 llvm::SmallBitVector FloatRegisters(RegX8632::Reg_NUM); |
| 287 llvm::SmallBitVector VectorRegisters(RegX8632::Reg_NUM); | 287 llvm::SmallBitVector VectorRegisters(RegX8632::Reg_NUM); |
| 288 llvm::SmallBitVector InvalidRegisters(RegX8632::Reg_NUM); | 288 llvm::SmallBitVector InvalidRegisters(RegX8632::Reg_NUM); |
| 289 ScratchRegs.resize(RegX8632::Reg_NUM); | 289 ScratchRegs.resize(RegX8632::Reg_NUM); |
| 290 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ | 290 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 366 // full liveness analysis. | 366 // full liveness analysis. |
| 367 Func->renumberInstructions(); | 367 Func->renumberInstructions(); |
| 368 if (Func->hasError()) | 368 if (Func->hasError()) |
| 369 return; | 369 return; |
| 370 Func->liveness(Liveness_Intervals); | 370 Func->liveness(Liveness_Intervals); |
| 371 if (Func->hasError()) | 371 if (Func->hasError()) |
| 372 return; | 372 return; |
| 373 // Validate the live range computations. The expensive validation | 373 // Validate the live range computations. The expensive validation |
| 374 // call is deliberately only made when assertions are enabled. | 374 // call is deliberately only made when assertions are enabled. |
| 375 assert(Func->validateLiveness()); | 375 assert(Func->validateLiveness()); |
| 376 ComputedLiveRanges = true; | |
| 377 // The post-codegen dump is done here, after liveness analysis and | 376 // The post-codegen dump is done here, after liveness analysis and |
| 378 // associated cleanup, to make the dump cleaner and more useful. | 377 // associated cleanup, to make the dump cleaner and more useful. |
| 379 Func->dump("After initial x8632 codegen"); | 378 Func->dump("After initial x8632 codegen"); |
| 380 Func->getVMetadata()->init(VMK_All); | 379 Func->getVMetadata()->init(VMK_All); |
| 381 regAlloc(); | 380 regAlloc(); |
| 382 if (Func->hasError()) | 381 if (Func->hasError()) |
| 383 return; | 382 return; |
| 384 Func->dump("After linear scan regalloc"); | 383 Func->dump("After linear scan regalloc"); |
| 385 | 384 |
| 386 if (Ctx->getFlags().PhiEdgeSplit) { | 385 if (Ctx->getFlags().PhiEdgeSplit) { |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 660 // | 659 // |
| 661 // The following variables record the size in bytes of the given areas: | 660 // The following variables record the size in bytes of the given areas: |
| 662 // * X86_RET_IP_SIZE_BYTES: area 1 | 661 // * X86_RET_IP_SIZE_BYTES: area 1 |
| 663 // * PreservedRegsSizeBytes: area 2 | 662 // * PreservedRegsSizeBytes: area 2 |
| 664 // * SpillAreaPaddingBytes: area 3 | 663 // * SpillAreaPaddingBytes: area 3 |
| 665 // * GlobalsSize: area 4 | 664 // * GlobalsSize: area 4 |
| 666 // * GlobalsAndSubsequentPaddingSize: areas 4 - 5 | 665 // * GlobalsAndSubsequentPaddingSize: areas 4 - 5 |
| 667 // * LocalsSpillAreaSize: area 6 | 666 // * LocalsSpillAreaSize: area 6 |
| 668 // * SpillAreaSizeBytes: areas 3 - 7 | 667 // * SpillAreaSizeBytes: areas 3 - 7 |
| 669 | 668 |
| 669 // Make a final pass over the Cfg to determine which variables need | |
| 670 // stack slots. | |
| 671 llvm::BitVector NeedsStackSlot(Func->getNumVariables()); | |
| 672 for (CfgNode *Node : Func->getNodes()) { | |
| 673 for (auto Inst = Node->getInsts().begin(), E = Node->getInsts().end(); | |
| 674 Inst != E; ++Inst) { | |
| 675 if (Inst->isDeleted()) | |
| 676 continue; | |
|
jvoung (off chromium)
2014/11/11 17:18:09
If the instruction isRedundantAssign() should this
Jim Stichnoth
2014/11/11 17:43:38
No, isRedundantAssign() depends on the frame offse
| |
| 677 if (const Variable *Var = Inst->getDest()) | |
| 678 NeedsStackSlot[Var->getIndex()] = true; | |
|
jvoung (off chromium)
2014/11/11 17:18:10
should this check if (!Var->hasReg()) first?
Jim Stichnoth
2014/11/11 17:43:39
Good point. It turns out that neither hasReg() ch
| |
| 679 for (SizeT I = 0; I < Inst->getSrcSize(); ++I) { | |
| 680 Operand *Src = Inst->getSrc(I); | |
| 681 SizeT NumVars = Src->getNumVars(); | |
| 682 for (SizeT J = 0; J < NumVars; ++J) { | |
| 683 const Variable *Var = Src->getVar(J); | |
| 684 if (!Var->hasReg()) | |
| 685 NeedsStackSlot[Var->getIndex()] = true; | |
| 686 } | |
| 687 } | |
| 688 } | |
| 689 } | |
| 690 | |
| 670 // If SimpleCoalescing is false, each variable without a register | 691 // If SimpleCoalescing is false, each variable without a register |
| 671 // gets its own unique stack slot, which leads to large stack | 692 // gets its own unique stack slot, which leads to large stack |
| 672 // frames. If SimpleCoalescing is true, then each "global" variable | 693 // frames. If SimpleCoalescing is true, then each "global" variable |
| 673 // without a register gets its own slot, but "local" variable slots | 694 // without a register gets its own slot, but "local" variable slots |
| 674 // are reused across basic blocks. E.g., if A and B are local to | 695 // are reused across basic blocks. E.g., if A and B are local to |
| 675 // block 1 and C is local to block 2, then C may share a slot with A or B. | 696 // block 1 and C is local to block 2, then C may share a slot with A or B. |
| 676 // | 697 // |
| 677 // We cannot coalesce stack slots if this function calls a "returns twice" | 698 // We cannot coalesce stack slots if this function calls a "returns twice" |
| 678 // function. In that case, basic blocks may be revisited, and variables | 699 // function. In that case, basic blocks may be revisited, and variables |
| 679 // local to those basic blocks are actually live until after the | 700 // local to those basic blocks are actually live until after the |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 719 for (Variable *Var : Variables) { | 740 for (Variable *Var : Variables) { |
| 720 if (Var->hasReg()) { | 741 if (Var->hasReg()) { |
| 721 RegsUsed[Var->getRegNum()] = true; | 742 RegsUsed[Var->getRegNum()] = true; |
| 722 continue; | 743 continue; |
| 723 } | 744 } |
| 724 // An argument either does not need a stack slot (if passed in a | 745 // An argument either does not need a stack slot (if passed in a |
| 725 // register) or already has one (if passed on the stack). | 746 // register) or already has one (if passed on the stack). |
| 726 if (Var->getIsArg()) | 747 if (Var->getIsArg()) |
| 727 continue; | 748 continue; |
| 728 // An unreferenced variable doesn't need a stack slot. | 749 // An unreferenced variable doesn't need a stack slot. |
| 729 if (ComputedLiveRanges && !Var->needsStackSlot()) | 750 if (!NeedsStackSlot[Var->getIndex()]) |
| 730 continue; | 751 continue; |
| 731 // A spill slot linked to a variable with a stack slot should reuse | 752 // A spill slot linked to a variable with a stack slot should reuse |
| 732 // that stack slot. | 753 // that stack slot. |
| 733 if (SpillVariable *SpillVar = llvm::dyn_cast<SpillVariable>(Var)) { | 754 if (SpillVariable *SpillVar = llvm::dyn_cast<SpillVariable>(Var)) { |
| 734 assert(Var->getWeight() == RegWeight::Zero); | 755 assert(Var->getWeight() == RegWeight::Zero); |
| 735 if (!SpillVar->getLinkedTo()->hasReg()) { | 756 if (!SpillVar->getLinkedTo()->hasReg()) { |
| 736 VariablesLinkedToSpillSlots.push_back(Var); | 757 VariablesLinkedToSpillSlots.push_back(Var); |
| 737 continue; | 758 continue; |
| 738 } | 759 } |
| 739 } | 760 } |
| (...skipping 3507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4247 // TODO(stichnot): Opportunity for register randomization. | 4268 // TODO(stichnot): Opportunity for register randomization. |
| 4248 int32_t RegNum = AvailRegsForType.find_first(); | 4269 int32_t RegNum = AvailRegsForType.find_first(); |
| 4249 bool IsVector = isVectorType(Dest->getType()); | 4270 bool IsVector = isVectorType(Dest->getType()); |
| 4250 bool NeedSpill = (RegNum == -1); | 4271 bool NeedSpill = (RegNum == -1); |
| 4251 if (NeedSpill) { | 4272 if (NeedSpill) { |
| 4252 // Pick some register to spill and update RegNum. | 4273 // Pick some register to spill and update RegNum. |
| 4253 // TODO(stichnot): Opportunity for register randomization. | 4274 // TODO(stichnot): Opportunity for register randomization. |
| 4254 RegNum = RegsForType.find_first(); | 4275 RegNum = RegsForType.find_first(); |
| 4255 Preg = getPhysicalRegister(RegNum, Dest->getType()); | 4276 Preg = getPhysicalRegister(RegNum, Dest->getType()); |
| 4256 SpillLoc = Func->makeVariable(Dest->getType()); | 4277 SpillLoc = Func->makeVariable(Dest->getType()); |
| 4257 SpillLoc->setNeedsStackSlot(); | |
| 4258 if (IsVector) | 4278 if (IsVector) |
| 4259 _movp(SpillLoc, Preg); | 4279 _movp(SpillLoc, Preg); |
| 4260 else | 4280 else |
| 4261 _mov(SpillLoc, Preg); | 4281 _mov(SpillLoc, Preg); |
| 4262 } | 4282 } |
| 4263 assert(RegNum >= 0); | 4283 assert(RegNum >= 0); |
| 4264 if (llvm::isa<ConstantUndef>(Src)) | 4284 if (llvm::isa<ConstantUndef>(Src)) |
| 4265 // Materialize an actual constant instead of undef. RegNum is | 4285 // Materialize an actual constant instead of undef. RegNum is |
| 4266 // passed in for vector types because undef vectors are | 4286 // passed in for vector types because undef vectors are |
| 4267 // lowered to vector register of zeroes. | 4287 // lowered to vector register of zeroes. |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4724 } else if (IsConstant || IsExternal) | 4744 } else if (IsConstant || IsExternal) |
| 4725 Str << "\t.zero\t" << Size << "\n"; | 4745 Str << "\t.zero\t" << Size << "\n"; |
| 4726 // Size is part of .comm. | 4746 // Size is part of .comm. |
| 4727 | 4747 |
| 4728 if (IsConstant || HasNonzeroInitializer || IsExternal) | 4748 if (IsConstant || HasNonzeroInitializer || IsExternal) |
| 4729 Str << "\t.size\t" << MangledName << ", " << Size << "\n"; | 4749 Str << "\t.size\t" << MangledName << ", " << Size << "\n"; |
| 4730 // Size is part of .comm. | 4750 // Size is part of .comm. |
| 4731 } | 4751 } |
| 4732 | 4752 |
| 4733 } // end of namespace Ice | 4753 } // end of namespace Ice |
| OLD | NEW |