| 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 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 T_placePhiStores.printElapsedUs(Context, "placePhiStores()"); | 315 T_placePhiStores.printElapsedUs(Context, "placePhiStores()"); |
| 316 Timer T_deletePhis; | 316 Timer T_deletePhis; |
| 317 Func->deletePhis(); | 317 Func->deletePhis(); |
| 318 if (Func->hasError()) | 318 if (Func->hasError()) |
| 319 return; | 319 return; |
| 320 T_deletePhis.printElapsedUs(Context, "deletePhis()"); | 320 T_deletePhis.printElapsedUs(Context, "deletePhis()"); |
| 321 Func->dump("After Phi lowering"); | 321 Func->dump("After Phi lowering"); |
| 322 | 322 |
| 323 // Address mode optimization. | 323 // Address mode optimization. |
| 324 Timer T_doAddressOpt; | 324 Timer T_doAddressOpt; |
| 325 Func->getVMetadata()->init(); |
| 325 Func->doAddressOpt(); | 326 Func->doAddressOpt(); |
| 326 T_doAddressOpt.printElapsedUs(Context, "doAddressOpt()"); | 327 T_doAddressOpt.printElapsedUs(Context, "doAddressOpt()"); |
| 327 | 328 |
| 328 // Argument lowering | 329 // Argument lowering |
| 329 Timer T_argLowering; | 330 Timer T_argLowering; |
| 330 Func->doArgLowering(); | 331 Func->doArgLowering(); |
| 331 T_argLowering.printElapsedUs(Context, "lowerArguments()"); | 332 T_argLowering.printElapsedUs(Context, "lowerArguments()"); |
| 332 | 333 |
| 333 // Target lowering. This requires liveness analysis for some parts | 334 // Target lowering. This requires liveness analysis for some parts |
| 334 // of the lowering decisions, such as compare/branch fusing. If | 335 // of the lowering decisions, such as compare/branch fusing. If |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 463 frameptr, isI8, isInt, isFP) \ | 464 frameptr, isI8, isInt, isFP) \ |
| 464 name, | 465 name, |
| 465 REGX8632_TABLE | 466 REGX8632_TABLE |
| 466 #undef X | 467 #undef X |
| 467 }; | 468 }; |
| 468 | 469 |
| 469 Variable *TargetX8632::getPhysicalRegister(SizeT RegNum) { | 470 Variable *TargetX8632::getPhysicalRegister(SizeT RegNum) { |
| 470 assert(RegNum < PhysicalRegisters.size()); | 471 assert(RegNum < PhysicalRegisters.size()); |
| 471 Variable *Reg = PhysicalRegisters[RegNum]; | 472 Variable *Reg = PhysicalRegisters[RegNum]; |
| 472 if (Reg == NULL) { | 473 if (Reg == NULL) { |
| 473 CfgNode *Node = NULL; // NULL means multi-block lifetime | 474 Reg = Func->makeVariable(IceType_i32); |
| 474 Reg = Func->makeVariable(IceType_i32, Node); | |
| 475 Reg->setRegNum(RegNum); | 475 Reg->setRegNum(RegNum); |
| 476 PhysicalRegisters[RegNum] = Reg; | 476 PhysicalRegisters[RegNum] = Reg; |
| 477 // Specially mark esp as an "argument" so that it is considered |
| 478 // live upon function entry. |
| 479 if (RegNum == RegX8632::Reg_esp) |
| 480 Func->addImplicitArg(Reg); |
| 477 } | 481 } |
| 478 return Reg; | 482 return Reg; |
| 479 } | 483 } |
| 480 | 484 |
| 481 IceString TargetX8632::getRegName(SizeT RegNum, Type Ty) const { | 485 IceString TargetX8632::getRegName(SizeT RegNum, Type Ty) const { |
| 482 assert(RegNum < RegX8632::Reg_NUM); | 486 assert(RegNum < RegX8632::Reg_NUM); |
| 483 static IceString RegNames8[] = { | 487 static IceString RegNames8[] = { |
| 484 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ | 488 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ |
| 485 frameptr, isI8, isInt, isFP) \ | 489 frameptr, isI8, isInt, isFP) \ |
| 486 name8, | 490 name8, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 498 case IceType_i1: | 502 case IceType_i1: |
| 499 case IceType_i8: | 503 case IceType_i8: |
| 500 return RegNames8[RegNum]; | 504 return RegNames8[RegNum]; |
| 501 case IceType_i16: | 505 case IceType_i16: |
| 502 return RegNames16[RegNum]; | 506 return RegNames16[RegNum]; |
| 503 default: | 507 default: |
| 504 return RegNames[RegNum]; | 508 return RegNames[RegNum]; |
| 505 } | 509 } |
| 506 } | 510 } |
| 507 | 511 |
| 508 void TargetX8632::emitVariable(const Variable *Var, const Cfg *Func) const { | 512 void TargetX8632::emitVariable(const Variable *Var) const { |
| 509 Ostream &Str = Ctx->getStrEmit(); | 513 Ostream &Str = Ctx->getStrEmit(); |
| 510 assert(Var->getLocalUseNode() == NULL || | |
| 511 Var->getLocalUseNode() == Func->getCurrentNode()); | |
| 512 if (Var->hasReg()) { | 514 if (Var->hasReg()) { |
| 513 Str << getRegName(Var->getRegNum(), Var->getType()); | 515 Str << getRegName(Var->getRegNum(), Var->getType()); |
| 514 return; | 516 return; |
| 515 } | 517 } |
| 516 Str << InstX8632::getWidthString(Var->getType()); | 518 Str << InstX8632::getWidthString(Var->getType()); |
| 517 Str << " [" << getRegName(getFrameOrStackReg(), IceType_i32); | 519 Str << " [" << getRegName(getFrameOrStackReg(), IceType_i32); |
| 518 int32_t Offset = Var->getStackOffset(); | 520 int32_t Offset = Var->getStackOffset(); |
| 519 if (!hasFramePointer()) | 521 if (!hasFramePointer()) |
| 520 Offset += getStackAdjustment(); | 522 Offset += getStackAdjustment(); |
| 521 if (Offset) { | 523 if (Offset) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 541 Variable *Arg = Args[I]; | 543 Variable *Arg = Args[I]; |
| 542 Type Ty = Arg->getType(); | 544 Type Ty = Arg->getType(); |
| 543 if (!isVectorType(Ty)) | 545 if (!isVectorType(Ty)) |
| 544 continue; | 546 continue; |
| 545 // Replace Arg in the argument list with the home register. Then | 547 // Replace Arg in the argument list with the home register. Then |
| 546 // generate an instruction in the prolog to copy the home register | 548 // generate an instruction in the prolog to copy the home register |
| 547 // to the assigned location of Arg. | 549 // to the assigned location of Arg. |
| 548 int32_t RegNum = RegX8632::Reg_xmm0 + NumXmmArgs; | 550 int32_t RegNum = RegX8632::Reg_xmm0 + NumXmmArgs; |
| 549 ++NumXmmArgs; | 551 ++NumXmmArgs; |
| 550 IceString Name = "home_reg:" + Arg->getName(); | 552 IceString Name = "home_reg:" + Arg->getName(); |
| 551 const CfgNode *DefNode = NULL; | 553 Variable *RegisterArg = Func->makeVariable(Ty, Name); |
| 552 Variable *RegisterArg = Func->makeVariable(Ty, DefNode, Name); | |
| 553 RegisterArg->setRegNum(RegNum); | 554 RegisterArg->setRegNum(RegNum); |
| 554 RegisterArg->setIsArg(Func); | 555 RegisterArg->setIsArg(); |
| 555 Arg->setIsArg(Func, false); | 556 Arg->setIsArg(false); |
| 556 | 557 |
| 557 Args[I] = RegisterArg; | 558 Args[I] = RegisterArg; |
| 558 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | 559 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); |
| 559 } | 560 } |
| 560 } | 561 } |
| 561 | 562 |
| 562 void TargetX8632::sortByAlignment(VarList &Dest, const VarList &Source) const { | 563 void TargetX8632::sortByAlignment(VarList &Dest, const VarList &Source) const { |
| 563 // Sort the variables into buckets according to the log of their width | 564 // Sort the variables into buckets according to the log of their width |
| 564 // in bytes. | 565 // in bytes. |
| 565 const SizeT NumBuckets = | 566 const SizeT NumBuckets = |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 // block 1 and C is local to block 2, then C may share a slot with A or B. | 669 // block 1 and C is local to block 2, then C may share a slot with A or B. |
| 669 // | 670 // |
| 670 // We cannot coalesce stack slots if this function calls a "returns twice" | 671 // We cannot coalesce stack slots if this function calls a "returns twice" |
| 671 // function. In that case, basic blocks may be revisited, and variables | 672 // function. In that case, basic blocks may be revisited, and variables |
| 672 // local to those basic blocks are actually live until after the | 673 // local to those basic blocks are actually live until after the |
| 673 // called function returns a second time. | 674 // called function returns a second time. |
| 674 const bool SimpleCoalescing = !callsReturnsTwice(); | 675 const bool SimpleCoalescing = !callsReturnsTwice(); |
| 675 size_t InArgsSizeBytes = 0; | 676 size_t InArgsSizeBytes = 0; |
| 676 size_t PreservedRegsSizeBytes = 0; | 677 size_t PreservedRegsSizeBytes = 0; |
| 677 SpillAreaSizeBytes = 0; | 678 SpillAreaSizeBytes = 0; |
| 679 const VariablesMetadata *VMetadata = Func->getVMetadata(); |
| 678 Context.init(Node); | 680 Context.init(Node); |
| 679 Context.setInsertPoint(Context.getCur()); | 681 Context.setInsertPoint(Context.getCur()); |
| 680 | 682 |
| 681 // Determine stack frame offsets for each Variable without a | 683 // Determine stack frame offsets for each Variable without a |
| 682 // register assignment. This can be done as one variable per stack | 684 // register assignment. This can be done as one variable per stack |
| 683 // slot. Or, do coalescing by running the register allocator again | 685 // slot. Or, do coalescing by running the register allocator again |
| 684 // with an infinite set of registers (as a side effect, this gives | 686 // with an infinite set of registers (as a side effect, this gives |
| 685 // variables a second chance at physical register assignment). | 687 // variables a second chance at physical register assignment). |
| 686 // | 688 // |
| 687 // A middle ground approach is to leverage sparsity and allocate one | 689 // A middle ground approach is to leverage sparsity and allocate one |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 736 | 738 |
| 737 SortedSpilledVariables.reserve(SpilledVariables.size()); | 739 SortedSpilledVariables.reserve(SpilledVariables.size()); |
| 738 sortByAlignment(SortedSpilledVariables, SpilledVariables); | 740 sortByAlignment(SortedSpilledVariables, SpilledVariables); |
| 739 for (VarList::const_iterator I = SortedSpilledVariables.begin(), | 741 for (VarList::const_iterator I = SortedSpilledVariables.begin(), |
| 740 E = SortedSpilledVariables.end(); | 742 E = SortedSpilledVariables.end(); |
| 741 I != E; ++I) { | 743 I != E; ++I) { |
| 742 Variable *Var = *I; | 744 Variable *Var = *I; |
| 743 size_t Increment = typeWidthInBytesOnStack(Var->getType()); | 745 size_t Increment = typeWidthInBytesOnStack(Var->getType()); |
| 744 if (!SpillAreaAlignmentBytes) | 746 if (!SpillAreaAlignmentBytes) |
| 745 SpillAreaAlignmentBytes = Increment; | 747 SpillAreaAlignmentBytes = Increment; |
| 746 if (SimpleCoalescing) { | 748 if (SimpleCoalescing && VMetadata->isTracked(Var)) { |
| 747 if (Var->isMultiblockLife()) { | 749 if (VMetadata->isMultiBlock(Var)) { |
| 748 GlobalsSize += Increment; | 750 GlobalsSize += Increment; |
| 749 } else { | 751 } else { |
| 750 SizeT NodeIndex = Var->getLocalUseNode()->getIndex(); | 752 SizeT NodeIndex = VMetadata->getLocalUseNode(Var)->getIndex(); |
| 751 LocalsSize[NodeIndex] += Increment; | 753 LocalsSize[NodeIndex] += Increment; |
| 752 if (LocalsSize[NodeIndex] > SpillAreaSizeBytes) | 754 if (LocalsSize[NodeIndex] > SpillAreaSizeBytes) |
| 753 SpillAreaSizeBytes = LocalsSize[NodeIndex]; | 755 SpillAreaSizeBytes = LocalsSize[NodeIndex]; |
| 754 if (!LocalsSlotsAlignmentBytes) | 756 if (!LocalsSlotsAlignmentBytes) |
| 755 LocalsSlotsAlignmentBytes = Increment; | 757 LocalsSlotsAlignmentBytes = Increment; |
| 756 } | 758 } |
| 757 } else { | 759 } else { |
| 758 SpillAreaSizeBytes += Increment; | 760 SpillAreaSizeBytes += Increment; |
| 759 } | 761 } |
| 760 } | 762 } |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 845 | 847 |
| 846 // Fill in stack offsets for locals. | 848 // Fill in stack offsets for locals. |
| 847 size_t GlobalsSpaceUsed = SpillAreaPaddingBytes; | 849 size_t GlobalsSpaceUsed = SpillAreaPaddingBytes; |
| 848 LocalsSize.assign(LocalsSize.size(), 0); | 850 LocalsSize.assign(LocalsSize.size(), 0); |
| 849 size_t NextStackOffset = GlobalsSpaceUsed; | 851 size_t NextStackOffset = GlobalsSpaceUsed; |
| 850 for (VarList::const_iterator I = SortedSpilledVariables.begin(), | 852 for (VarList::const_iterator I = SortedSpilledVariables.begin(), |
| 851 E = SortedSpilledVariables.end(); | 853 E = SortedSpilledVariables.end(); |
| 852 I != E; ++I) { | 854 I != E; ++I) { |
| 853 Variable *Var = *I; | 855 Variable *Var = *I; |
| 854 size_t Increment = typeWidthInBytesOnStack(Var->getType()); | 856 size_t Increment = typeWidthInBytesOnStack(Var->getType()); |
| 855 if (SimpleCoalescing) { | 857 if (SimpleCoalescing && VMetadata->isTracked(Var)) { |
| 856 if (Var->isMultiblockLife()) { | 858 if (VMetadata->isMultiBlock(Var)) { |
| 857 GlobalsSpaceUsed += Increment; | 859 GlobalsSpaceUsed += Increment; |
| 858 NextStackOffset = GlobalsSpaceUsed; | 860 NextStackOffset = GlobalsSpaceUsed; |
| 859 } else { | 861 } else { |
| 860 SizeT NodeIndex = Var->getLocalUseNode()->getIndex(); | 862 SizeT NodeIndex = VMetadata->getLocalUseNode(Var)->getIndex(); |
| 861 LocalsSize[NodeIndex] += Increment; | 863 LocalsSize[NodeIndex] += Increment; |
| 862 NextStackOffset = SpillAreaPaddingBytes + | 864 NextStackOffset = SpillAreaPaddingBytes + |
| 863 GlobalsAndSubsequentPaddingSize + | 865 GlobalsAndSubsequentPaddingSize + |
| 864 LocalsSize[NodeIndex]; | 866 LocalsSize[NodeIndex]; |
| 865 } | 867 } |
| 866 } else { | 868 } else { |
| 867 NextStackOffset += Increment; | 869 NextStackOffset += Increment; |
| 868 } | 870 } |
| 869 if (IsEbpBasedFrame) | 871 if (IsEbpBasedFrame) |
| 870 Var->setStackOffset(-NextStackOffset); | 872 Var->setStackOffset(-NextStackOffset); |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1028 case IceType_f64: | 1030 case IceType_f64: |
| 1029 break; | 1031 break; |
| 1030 } | 1032 } |
| 1031 Variable *Lo = Var->getLo(); | 1033 Variable *Lo = Var->getLo(); |
| 1032 Variable *Hi = Var->getHi(); | 1034 Variable *Hi = Var->getHi(); |
| 1033 if (Lo) { | 1035 if (Lo) { |
| 1034 assert(Hi); | 1036 assert(Hi); |
| 1035 return; | 1037 return; |
| 1036 } | 1038 } |
| 1037 assert(Hi == NULL); | 1039 assert(Hi == NULL); |
| 1038 Lo = Func->makeVariable(IceType_i32, Context.getNode(), | 1040 Lo = Func->makeVariable(IceType_i32, Var->getName() + "__lo"); |
| 1039 Var->getName() + "__lo"); | 1041 Hi = Func->makeVariable(IceType_i32, Var->getName() + "__hi"); |
| 1040 Hi = Func->makeVariable(IceType_i32, Context.getNode(), | |
| 1041 Var->getName() + "__hi"); | |
| 1042 Var->setLoHi(Lo, Hi); | 1042 Var->setLoHi(Lo, Hi); |
| 1043 if (Var->getIsArg()) { | 1043 if (Var->getIsArg()) { |
| 1044 Lo->setIsArg(Func); | 1044 Lo->setIsArg(); |
| 1045 Hi->setIsArg(Func); | 1045 Hi->setIsArg(); |
| 1046 } | 1046 } |
| 1047 } | 1047 } |
| 1048 | 1048 |
| 1049 Operand *TargetX8632::loOperand(Operand *Operand) { | 1049 Operand *TargetX8632::loOperand(Operand *Operand) { |
| 1050 assert(Operand->getType() == IceType_i64); | 1050 assert(Operand->getType() == IceType_i64); |
| 1051 if (Operand->getType() != IceType_i64) | 1051 if (Operand->getType() != IceType_i64) |
| 1052 return Operand; | 1052 return Operand; |
| 1053 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { | 1053 if (Variable *Var = llvm::dyn_cast<Variable>(Operand)) { |
| 1054 split64(Var); | 1054 split64(Var); |
| 1055 return Var->getLo(); | 1055 return Var->getLo(); |
| (...skipping 1213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2269 (void)DestType; | 2269 (void)DestType; |
| 2270 assert((DestType == IceType_i32 && SrcType == IceType_f32) || | 2270 assert((DestType == IceType_i32 && SrcType == IceType_f32) || |
| 2271 (DestType == IceType_f32 && SrcType == IceType_i32)); | 2271 (DestType == IceType_f32 && SrcType == IceType_i32)); |
| 2272 // a.i32 = bitcast b.f32 ==> | 2272 // a.i32 = bitcast b.f32 ==> |
| 2273 // t.f32 = b.f32 | 2273 // t.f32 = b.f32 |
| 2274 // s.f32 = spill t.f32 | 2274 // s.f32 = spill t.f32 |
| 2275 // a.i32 = s.f32 | 2275 // a.i32 = s.f32 |
| 2276 Variable *T = NULL; | 2276 Variable *T = NULL; |
| 2277 // TODO: Should be able to force a spill setup by calling legalize() with | 2277 // TODO: Should be able to force a spill setup by calling legalize() with |
| 2278 // Legal_Mem and not Legal_Reg or Legal_Imm. | 2278 // Legal_Mem and not Legal_Reg or Legal_Imm. |
| 2279 SpillVariable *SpillVar = | 2279 SpillVariable *SpillVar = Func->makeVariable<SpillVariable>(SrcType); |
| 2280 Func->makeVariable<SpillVariable>(SrcType, Context.getNode()); | |
| 2281 SpillVar->setLinkedTo(Dest); | 2280 SpillVar->setLinkedTo(Dest); |
| 2282 Variable *Spill = SpillVar; | 2281 Variable *Spill = SpillVar; |
| 2283 Spill->setWeight(RegWeight::Zero); | 2282 Spill->setWeight(RegWeight::Zero); |
| 2284 _mov(T, Src0RM); | 2283 _mov(T, Src0RM); |
| 2285 _mov(Spill, T); | 2284 _mov(Spill, T); |
| 2286 _mov(Dest, Spill); | 2285 _mov(Dest, Spill); |
| 2287 } break; | 2286 } break; |
| 2288 case IceType_i64: { | 2287 case IceType_i64: { |
| 2289 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); | 2288 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); |
| 2290 assert(Src0RM->getType() == IceType_f64); | 2289 assert(Src0RM->getType() == IceType_f64); |
| 2291 // a.i64 = bitcast b.f64 ==> | 2290 // a.i64 = bitcast b.f64 ==> |
| 2292 // s.f64 = spill b.f64 | 2291 // s.f64 = spill b.f64 |
| 2293 // t_lo.i32 = lo(s.f64) | 2292 // t_lo.i32 = lo(s.f64) |
| 2294 // a_lo.i32 = t_lo.i32 | 2293 // a_lo.i32 = t_lo.i32 |
| 2295 // t_hi.i32 = hi(s.f64) | 2294 // t_hi.i32 = hi(s.f64) |
| 2296 // a_hi.i32 = t_hi.i32 | 2295 // a_hi.i32 = t_hi.i32 |
| 2297 SpillVariable *SpillVar = | 2296 SpillVariable *SpillVar = Func->makeVariable<SpillVariable>(IceType_f64); |
| 2298 Func->makeVariable<SpillVariable>(IceType_f64, Context.getNode()); | |
| 2299 SpillVar->setLinkedTo(llvm::dyn_cast<Variable>(Src0RM)); | 2297 SpillVar->setLinkedTo(llvm::dyn_cast<Variable>(Src0RM)); |
| 2300 Variable *Spill = SpillVar; | 2298 Variable *Spill = SpillVar; |
| 2301 Spill->setWeight(RegWeight::Zero); | 2299 Spill->setWeight(RegWeight::Zero); |
| 2302 _movq(Spill, Src0RM); | 2300 _movq(Spill, Src0RM); |
| 2303 | 2301 |
| 2304 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2302 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 2305 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2303 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 2306 Variable *T_Lo = makeReg(IceType_i32); | 2304 Variable *T_Lo = makeReg(IceType_i32); |
| 2307 Variable *T_Hi = makeReg(IceType_i32); | 2305 Variable *T_Hi = makeReg(IceType_i32); |
| 2308 VariableSplit *SpillLo = | 2306 VariableSplit *SpillLo = |
| 2309 VariableSplit::create(Func, Spill, VariableSplit::Low); | 2307 VariableSplit::create(Func, Spill, VariableSplit::Low); |
| 2310 VariableSplit *SpillHi = | 2308 VariableSplit *SpillHi = |
| 2311 VariableSplit::create(Func, Spill, VariableSplit::High); | 2309 VariableSplit::create(Func, Spill, VariableSplit::High); |
| 2312 | 2310 |
| 2313 _mov(T_Lo, SpillLo); | 2311 _mov(T_Lo, SpillLo); |
| 2314 _mov(DestLo, T_Lo); | 2312 _mov(DestLo, T_Lo); |
| 2315 _mov(T_Hi, SpillHi); | 2313 _mov(T_Hi, SpillHi); |
| 2316 _mov(DestHi, T_Hi); | 2314 _mov(DestHi, T_Hi); |
| 2317 } break; | 2315 } break; |
| 2318 case IceType_f64: { | 2316 case IceType_f64: { |
| 2319 Src0 = legalize(Src0); | 2317 Src0 = legalize(Src0); |
| 2320 assert(Src0->getType() == IceType_i64); | 2318 assert(Src0->getType() == IceType_i64); |
| 2321 // a.f64 = bitcast b.i64 ==> | 2319 // a.f64 = bitcast b.i64 ==> |
| 2322 // t_lo.i32 = b_lo.i32 | 2320 // t_lo.i32 = b_lo.i32 |
| 2323 // FakeDef(s.f64) | 2321 // FakeDef(s.f64) |
| 2324 // lo(s.f64) = t_lo.i32 | 2322 // lo(s.f64) = t_lo.i32 |
| 2325 // t_hi.i32 = b_hi.i32 | 2323 // t_hi.i32 = b_hi.i32 |
| 2326 // hi(s.f64) = t_hi.i32 | 2324 // hi(s.f64) = t_hi.i32 |
| 2327 // a.f64 = s.f64 | 2325 // a.f64 = s.f64 |
| 2328 SpillVariable *SpillVar = | 2326 SpillVariable *SpillVar = Func->makeVariable<SpillVariable>(IceType_f64); |
| 2329 Func->makeVariable<SpillVariable>(IceType_f64, Context.getNode()); | |
| 2330 SpillVar->setLinkedTo(Dest); | 2327 SpillVar->setLinkedTo(Dest); |
| 2331 Variable *Spill = SpillVar; | 2328 Variable *Spill = SpillVar; |
| 2332 Spill->setWeight(RegWeight::Zero); | 2329 Spill->setWeight(RegWeight::Zero); |
| 2333 | 2330 |
| 2334 Variable *T_Lo = NULL, *T_Hi = NULL; | 2331 Variable *T_Lo = NULL, *T_Hi = NULL; |
| 2335 VariableSplit *SpillLo = | 2332 VariableSplit *SpillLo = |
| 2336 VariableSplit::create(Func, Spill, VariableSplit::Low); | 2333 VariableSplit::create(Func, Spill, VariableSplit::Low); |
| 2337 VariableSplit *SpillHi = | 2334 VariableSplit *SpillHi = |
| 2338 VariableSplit::create(Func, Spill, VariableSplit::High); | 2335 VariableSplit::create(Func, Spill, VariableSplit::High); |
| 2339 _mov(T_Lo, loOperand(Src0)); | 2336 _mov(T_Lo, loOperand(Src0)); |
| 2340 // Technically, the Spill is defined after the _store happens, but | 2337 // Technically, the Spill is defined after the _store happens, but |
| 2341 // SpillLo is considered a "use" of Spill so define Spill before it | 2338 // SpillLo is considered a "use" of Spill so define Spill before it |
| 2342 // is used. | 2339 // is used. |
| 2343 Context.insert(InstFakeDef::create(Func, Spill)); | 2340 Context.insert(InstFakeDef::create(Func, Spill)); |
| 2344 _store(T_Lo, SpillLo); | 2341 _store(T_Lo, SpillLo); |
| 2345 _mov(T_Hi, hiOperand(Src0)); | 2342 _mov(T_Hi, hiOperand(Src0)); |
| 2346 _store(T_Hi, SpillHi); | 2343 _store(T_Hi, SpillHi); |
| 2347 _movq(Dest, Spill); | 2344 _movq(Dest, Spill); |
| 2348 } break; | 2345 } break; |
| 2349 case IceType_v8i1: { | 2346 case IceType_v8i1: { |
| 2350 assert(Src0->getType() == IceType_i8); | 2347 assert(Src0->getType() == IceType_i8); |
| 2351 InstCall *Call = makeHelperCall("Sz_bitcast_i8_to_v8i1", Dest, 1); | 2348 InstCall *Call = makeHelperCall("Sz_bitcast_i8_to_v8i1", Dest, 1); |
| 2352 Variable *Src0AsI32 = Func->makeVariable(stackSlotType(), | 2349 Variable *Src0AsI32 = Func->makeVariable(stackSlotType()); |
| 2353 Context.getNode()); | |
| 2354 // Arguments to functions are required to be at least 32 bits wide. | 2350 // Arguments to functions are required to be at least 32 bits wide. |
| 2355 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); | 2351 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); |
| 2356 Call->addArg(Src0AsI32); | 2352 Call->addArg(Src0AsI32); |
| 2357 lowerCall(Call); | 2353 lowerCall(Call); |
| 2358 } break; | 2354 } break; |
| 2359 case IceType_v16i1: { | 2355 case IceType_v16i1: { |
| 2360 assert(Src0->getType() == IceType_i16); | 2356 assert(Src0->getType() == IceType_i16); |
| 2361 InstCall *Call = makeHelperCall("Sz_bitcast_i16_to_v16i1", Dest, 1); | 2357 InstCall *Call = makeHelperCall("Sz_bitcast_i16_to_v16i1", Dest, 1); |
| 2362 Variable *Src0AsI32 = Func->makeVariable(stackSlotType(), | 2358 Variable *Src0AsI32 = Func->makeVariable(stackSlotType()); |
| 2363 Context.getNode()); | |
| 2364 // Arguments to functions are required to be at least 32 bits wide. | 2359 // Arguments to functions are required to be at least 32 bits wide. |
| 2365 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); | 2360 lowerCast(InstCast::create(Func, InstCast::Zext, Src0AsI32, Src0)); |
| 2366 Call->addArg(Src0AsI32); | 2361 Call->addArg(Src0AsI32); |
| 2367 lowerCall(Call); | 2362 lowerCall(Call); |
| 2368 } break; | 2363 } break; |
| 2369 case IceType_v8i16: | 2364 case IceType_v8i16: |
| 2370 case IceType_v16i8: | 2365 case IceType_v16i8: |
| 2371 case IceType_v4i32: | 2366 case IceType_v4i32: |
| 2372 case IceType_v4f32: { | 2367 case IceType_v4f32: { |
| 2373 _movp(Dest, legalizeToVar(Src0)); | 2368 _movp(Dest, legalizeToVar(Src0)); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2422 // keep the live range analysis consistent. | 2417 // keep the live range analysis consistent. |
| 2423 Context.insert(InstFakeDef::create(Func, ExtractedElementR)); | 2418 Context.insert(InstFakeDef::create(Func, ExtractedElementR)); |
| 2424 _movss(ExtractedElementR, T); | 2419 _movss(ExtractedElementR, T); |
| 2425 } | 2420 } |
| 2426 } else { | 2421 } else { |
| 2427 assert(Ty == IceType_v16i8 || Ty == IceType_v16i1); | 2422 assert(Ty == IceType_v16i8 || Ty == IceType_v16i1); |
| 2428 // Spill the value to a stack slot and do the extraction in memory. | 2423 // Spill the value to a stack slot and do the extraction in memory. |
| 2429 // | 2424 // |
| 2430 // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when | 2425 // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when |
| 2431 // support for legalizing to mem is implemented. | 2426 // support for legalizing to mem is implemented. |
| 2432 Variable *Slot = Func->makeVariable(Ty, Context.getNode()); | 2427 Variable *Slot = Func->makeVariable(Ty); |
| 2433 Slot->setWeight(RegWeight::Zero); | 2428 Slot->setWeight(RegWeight::Zero); |
| 2434 _movp(Slot, legalizeToVar(SourceVectNotLegalized)); | 2429 _movp(Slot, legalizeToVar(SourceVectNotLegalized)); |
| 2435 | 2430 |
| 2436 // Compute the location of the element in memory. | 2431 // Compute the location of the element in memory. |
| 2437 unsigned Offset = Index * typeWidthInBytes(InVectorElementTy); | 2432 unsigned Offset = Index * typeWidthInBytes(InVectorElementTy); |
| 2438 OperandX8632Mem *Loc = | 2433 OperandX8632Mem *Loc = |
| 2439 getMemoryOperandForStackSlot(InVectorElementTy, Slot, Offset); | 2434 getMemoryOperandForStackSlot(InVectorElementTy, Slot, Offset); |
| 2440 _mov(ExtractedElementR, Loc); | 2435 _mov(ExtractedElementR, Loc); |
| 2441 } | 2436 } |
| 2442 | 2437 |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2577 case IceType_v4i1: | 2572 case IceType_v4i1: |
| 2578 NewTy = IceType_v4i32; | 2573 NewTy = IceType_v4i32; |
| 2579 break; | 2574 break; |
| 2580 case IceType_v8i1: | 2575 case IceType_v8i1: |
| 2581 NewTy = IceType_v8i16; | 2576 NewTy = IceType_v8i16; |
| 2582 break; | 2577 break; |
| 2583 case IceType_v16i1: | 2578 case IceType_v16i1: |
| 2584 NewTy = IceType_v16i8; | 2579 NewTy = IceType_v16i8; |
| 2585 break; | 2580 break; |
| 2586 } | 2581 } |
| 2587 Variable *NewSrc0 = Func->makeVariable(NewTy, Context.getNode()); | 2582 Variable *NewSrc0 = Func->makeVariable(NewTy); |
| 2588 Variable *NewSrc1 = Func->makeVariable(NewTy, Context.getNode()); | 2583 Variable *NewSrc1 = Func->makeVariable(NewTy); |
| 2589 lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc0, Src0)); | 2584 lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc0, Src0)); |
| 2590 lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc1, Src1)); | 2585 lowerCast(InstCast::create(Func, InstCast::Sext, NewSrc1, Src1)); |
| 2591 Src0 = NewSrc0; | 2586 Src0 = NewSrc0; |
| 2592 Src1 = NewSrc1; | 2587 Src1 = NewSrc1; |
| 2593 Ty = NewTy; | 2588 Ty = NewTy; |
| 2594 } | 2589 } |
| 2595 | 2590 |
| 2596 InstIcmp::ICond Condition = Inst->getCondition(); | 2591 InstIcmp::ICond Condition = Inst->getCondition(); |
| 2597 | 2592 |
| 2598 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); | 2593 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2753 unsigned Index = ElementIndex->getValue(); | 2748 unsigned Index = ElementIndex->getValue(); |
| 2754 assert(Index < typeNumElements(SourceVectNotLegalized->getType())); | 2749 assert(Index < typeNumElements(SourceVectNotLegalized->getType())); |
| 2755 | 2750 |
| 2756 Type Ty = SourceVectNotLegalized->getType(); | 2751 Type Ty = SourceVectNotLegalized->getType(); |
| 2757 Type ElementTy = typeElementType(Ty); | 2752 Type ElementTy = typeElementType(Ty); |
| 2758 Type InVectorElementTy = getInVectorElementType(Ty); | 2753 Type InVectorElementTy = getInVectorElementType(Ty); |
| 2759 | 2754 |
| 2760 if (ElementTy == IceType_i1) { | 2755 if (ElementTy == IceType_i1) { |
| 2761 // Expand the element to the appropriate size for it to be inserted | 2756 // Expand the element to the appropriate size for it to be inserted |
| 2762 // in the vector. | 2757 // in the vector. |
| 2763 Variable *Expanded = | 2758 Variable *Expanded = Func->makeVariable(InVectorElementTy); |
| 2764 Func->makeVariable(InVectorElementTy, Context.getNode()); | |
| 2765 InstCast *Cast = InstCast::create(Func, InstCast::Zext, Expanded, | 2759 InstCast *Cast = InstCast::create(Func, InstCast::Zext, Expanded, |
| 2766 ElementToInsertNotLegalized); | 2760 ElementToInsertNotLegalized); |
| 2767 lowerCast(Cast); | 2761 lowerCast(Cast); |
| 2768 ElementToInsertNotLegalized = Expanded; | 2762 ElementToInsertNotLegalized = Expanded; |
| 2769 } | 2763 } |
| 2770 | 2764 |
| 2771 if (Ty == IceType_v8i16 || Ty == IceType_v8i1 || InstructionSet >= SSE4_1) { | 2765 if (Ty == IceType_v8i16 || Ty == IceType_v8i1 || InstructionSet >= SSE4_1) { |
| 2772 // Use insertps, pinsrb, pinsrw, or pinsrd. | 2766 // Use insertps, pinsrb, pinsrw, or pinsrd. |
| 2773 Operand *ElementRM = | 2767 Operand *ElementRM = |
| 2774 legalize(ElementToInsertNotLegalized, Legal_Reg | Legal_Mem); | 2768 legalize(ElementToInsertNotLegalized, Legal_Reg | Legal_Mem); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2846 _shufps(T, ElementR, Mask2Constant); | 2840 _shufps(T, ElementR, Mask2Constant); |
| 2847 _movp(Inst->getDest(), T); | 2841 _movp(Inst->getDest(), T); |
| 2848 } | 2842 } |
| 2849 } else { | 2843 } else { |
| 2850 assert(Ty == IceType_v16i8 || Ty == IceType_v16i1); | 2844 assert(Ty == IceType_v16i8 || Ty == IceType_v16i1); |
| 2851 // Spill the value to a stack slot and perform the insertion in | 2845 // Spill the value to a stack slot and perform the insertion in |
| 2852 // memory. | 2846 // memory. |
| 2853 // | 2847 // |
| 2854 // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when | 2848 // TODO(wala): use legalize(SourceVectNotLegalized, Legal_Mem) when |
| 2855 // support for legalizing to mem is implemented. | 2849 // support for legalizing to mem is implemented. |
| 2856 Variable *Slot = Func->makeVariable(Ty, Context.getNode()); | 2850 Variable *Slot = Func->makeVariable(Ty); |
| 2857 Slot->setWeight(RegWeight::Zero); | 2851 Slot->setWeight(RegWeight::Zero); |
| 2858 _movp(Slot, legalizeToVar(SourceVectNotLegalized)); | 2852 _movp(Slot, legalizeToVar(SourceVectNotLegalized)); |
| 2859 | 2853 |
| 2860 // Compute the location of the position to insert in memory. | 2854 // Compute the location of the position to insert in memory. |
| 2861 unsigned Offset = Index * typeWidthInBytes(InVectorElementTy); | 2855 unsigned Offset = Index * typeWidthInBytes(InVectorElementTy); |
| 2862 OperandX8632Mem *Loc = | 2856 OperandX8632Mem *Loc = |
| 2863 getMemoryOperandForStackSlot(InVectorElementTy, Slot, Offset); | 2857 getMemoryOperandForStackSlot(InVectorElementTy, Slot, Offset); |
| 2864 _store(legalizeToVar(ElementToInsertNotLegalized), Loc); | 2858 _store(legalizeToVar(ElementToInsertNotLegalized), Loc); |
| 2865 | 2859 |
| 2866 Variable *T = makeReg(Ty); | 2860 Variable *T = makeReg(Ty); |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3116 Call->addArg(Instr->getArg(2)); | 3110 Call->addArg(Instr->getArg(2)); |
| 3117 lowerCall(Call); | 3111 lowerCall(Call); |
| 3118 return; | 3112 return; |
| 3119 } | 3113 } |
| 3120 case Intrinsics::Memset: { | 3114 case Intrinsics::Memset: { |
| 3121 // The value operand needs to be extended to a stack slot size | 3115 // The value operand needs to be extended to a stack slot size |
| 3122 // because the PNaCl ABI requires arguments to be at least 32 bits | 3116 // because the PNaCl ABI requires arguments to be at least 32 bits |
| 3123 // wide. | 3117 // wide. |
| 3124 Operand *ValOp = Instr->getArg(1); | 3118 Operand *ValOp = Instr->getArg(1); |
| 3125 assert(ValOp->getType() == IceType_i8); | 3119 assert(ValOp->getType() == IceType_i8); |
| 3126 Variable *ValExt = Func->makeVariable(stackSlotType(), Context.getNode()); | 3120 Variable *ValExt = Func->makeVariable(stackSlotType()); |
| 3127 lowerCast(InstCast::create(Func, InstCast::Zext, ValExt, ValOp)); | 3121 lowerCast(InstCast::create(Func, InstCast::Zext, ValExt, ValOp)); |
| 3128 InstCall *Call = makeHelperCall("memset", NULL, 3); | 3122 InstCall *Call = makeHelperCall("memset", NULL, 3); |
| 3129 Call->addArg(Instr->getArg(0)); | 3123 Call->addArg(Instr->getArg(0)); |
| 3130 Call->addArg(ValExt); | 3124 Call->addArg(ValExt); |
| 3131 Call->addArg(Instr->getArg(2)); | 3125 Call->addArg(Instr->getArg(2)); |
| 3132 lowerCall(Call); | 3126 lowerCall(Call); |
| 3133 return; | 3127 return; |
| 3134 } | 3128 } |
| 3135 case Intrinsics::NaClReadTP: { | 3129 case Intrinsics::NaClReadTP: { |
| 3136 if (Ctx->getFlags().UseSandboxing) { | 3130 if (Ctx->getFlags().UseSandboxing) { |
| (...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3572 else | 3566 else |
| 3573 Str << "<null>"; | 3567 Str << "<null>"; |
| 3574 Str << ", Index="; | 3568 Str << ", Index="; |
| 3575 if (Index) | 3569 if (Index) |
| 3576 Index->dump(Func); | 3570 Index->dump(Func); |
| 3577 else | 3571 else |
| 3578 Str << "<null>"; | 3572 Str << "<null>"; |
| 3579 Str << ", Shift=" << Shift << ", Offset=" << Offset << "\n"; | 3573 Str << ", Shift=" << Shift << ", Offset=" << Offset << "\n"; |
| 3580 } | 3574 } |
| 3581 | 3575 |
| 3582 bool matchTransitiveAssign(Variable *&Var, const Inst *&Reason) { | 3576 bool matchTransitiveAssign(const VariablesMetadata *VMetadata, Variable *&Var, |
| 3577 const Inst *&Reason) { |
| 3583 // Var originates from Var=SrcVar ==> | 3578 // Var originates from Var=SrcVar ==> |
| 3584 // set Var:=SrcVar | 3579 // set Var:=SrcVar |
| 3585 if (Var == NULL) | 3580 if (Var == NULL) |
| 3586 return false; | 3581 return false; |
| 3587 if (const Inst *VarAssign = Var->getDefinition()) { | 3582 if (const Inst *VarAssign = VMetadata->getDefinition(Var)) { |
| 3588 if (llvm::isa<InstAssign>(VarAssign)) { | 3583 if (llvm::isa<InstAssign>(VarAssign)) { |
| 3589 Operand *SrcOp = VarAssign->getSrc(0); | 3584 Operand *SrcOp = VarAssign->getSrc(0); |
| 3590 assert(SrcOp); | 3585 assert(SrcOp); |
| 3591 if (Variable *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) { | 3586 if (Variable *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) { |
| 3592 if (!SrcVar->getIsMultidef() && | 3587 if (!VMetadata->isMultiDef(SrcVar) && |
| 3593 // TODO: ensure SrcVar stays single-BB | 3588 // TODO: ensure SrcVar stays single-BB |
| 3594 true) { | 3589 true) { |
| 3595 Var = SrcVar; | 3590 Var = SrcVar; |
| 3596 Reason = VarAssign; | 3591 Reason = VarAssign; |
| 3597 return true; | 3592 return true; |
| 3598 } | 3593 } |
| 3599 } | 3594 } |
| 3600 } | 3595 } |
| 3601 } | 3596 } |
| 3602 return false; | 3597 return false; |
| 3603 } | 3598 } |
| 3604 | 3599 |
| 3605 bool matchCombinedBaseIndex(Variable *&Base, Variable *&Index, uint16_t &Shift, | 3600 bool matchCombinedBaseIndex(const VariablesMetadata *VMetadata, Variable *&Base, |
| 3601 Variable *&Index, uint16_t &Shift, |
| 3606 const Inst *&Reason) { | 3602 const Inst *&Reason) { |
| 3607 // Index==NULL && Base is Base=Var1+Var2 ==> | 3603 // Index==NULL && Base is Base=Var1+Var2 ==> |
| 3608 // set Base=Var1, Index=Var2, Shift=0 | 3604 // set Base=Var1, Index=Var2, Shift=0 |
| 3609 if (Base == NULL) | 3605 if (Base == NULL) |
| 3610 return false; | 3606 return false; |
| 3611 if (Index != NULL) | 3607 if (Index != NULL) |
| 3612 return false; | 3608 return false; |
| 3613 const Inst *BaseInst = Base->getDefinition(); | 3609 const Inst *BaseInst = VMetadata->getDefinition(Base); |
| 3614 if (BaseInst == NULL) | 3610 if (BaseInst == NULL) |
| 3615 return false; | 3611 return false; |
| 3616 if (BaseInst->getSrcSize() < 2) | 3612 if (BaseInst->getSrcSize() < 2) |
| 3617 return false; | 3613 return false; |
| 3618 if (Variable *Var1 = llvm::dyn_cast<Variable>(BaseInst->getSrc(0))) { | 3614 if (Variable *Var1 = llvm::dyn_cast<Variable>(BaseInst->getSrc(0))) { |
| 3619 if (Var1->getIsMultidef()) | 3615 if (VMetadata->isMultiDef(Var1)) |
| 3620 return false; | 3616 return false; |
| 3621 if (Variable *Var2 = llvm::dyn_cast<Variable>(BaseInst->getSrc(1))) { | 3617 if (Variable *Var2 = llvm::dyn_cast<Variable>(BaseInst->getSrc(1))) { |
| 3622 if (Var2->getIsMultidef()) | 3618 if (VMetadata->isMultiDef(Var2)) |
| 3623 return false; | 3619 return false; |
| 3624 if (isAdd(BaseInst) && | 3620 if (isAdd(BaseInst) && |
| 3625 // TODO: ensure Var1 and Var2 stay single-BB | 3621 // TODO: ensure Var1 and Var2 stay single-BB |
| 3626 true) { | 3622 true) { |
| 3627 Base = Var1; | 3623 Base = Var1; |
| 3628 Index = Var2; | 3624 Index = Var2; |
| 3629 Shift = 0; // should already have been 0 | 3625 Shift = 0; // should already have been 0 |
| 3630 Reason = BaseInst; | 3626 Reason = BaseInst; |
| 3631 return true; | 3627 return true; |
| 3632 } | 3628 } |
| 3633 } | 3629 } |
| 3634 } | 3630 } |
| 3635 return false; | 3631 return false; |
| 3636 } | 3632 } |
| 3637 | 3633 |
| 3638 bool matchShiftedIndex(Variable *&Index, uint16_t &Shift, const Inst *&Reason) { | 3634 bool matchShiftedIndex(const VariablesMetadata *VMetadata, Variable *&Index, |
| 3635 uint16_t &Shift, const Inst *&Reason) { |
| 3639 // Index is Index=Var*Const && log2(Const)+Shift<=3 ==> | 3636 // Index is Index=Var*Const && log2(Const)+Shift<=3 ==> |
| 3640 // Index=Var, Shift+=log2(Const) | 3637 // Index=Var, Shift+=log2(Const) |
| 3641 if (Index == NULL) | 3638 if (Index == NULL) |
| 3642 return false; | 3639 return false; |
| 3643 const Inst *IndexInst = Index->getDefinition(); | 3640 const Inst *IndexInst = VMetadata->getDefinition(Index); |
| 3644 if (IndexInst == NULL) | 3641 if (IndexInst == NULL) |
| 3645 return false; | 3642 return false; |
| 3646 if (IndexInst->getSrcSize() < 2) | 3643 if (IndexInst->getSrcSize() < 2) |
| 3647 return false; | 3644 return false; |
| 3648 if (const InstArithmetic *ArithInst = | 3645 if (const InstArithmetic *ArithInst = |
| 3649 llvm::dyn_cast<InstArithmetic>(IndexInst)) { | 3646 llvm::dyn_cast<InstArithmetic>(IndexInst)) { |
| 3650 if (Variable *Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) { | 3647 if (Variable *Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) { |
| 3651 if (ConstantInteger32 *Const = | 3648 if (ConstantInteger32 *Const = |
| 3652 llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1))) { | 3649 llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1))) { |
| 3653 if (ArithInst->getOp() == InstArithmetic::Mul && | 3650 if (ArithInst->getOp() == InstArithmetic::Mul && |
| 3654 !Var->getIsMultidef() && Const->getType() == IceType_i32) { | 3651 !VMetadata->isMultiDef(Var) && Const->getType() == IceType_i32) { |
| 3655 uint64_t Mult = Const->getValue(); | 3652 uint64_t Mult = Const->getValue(); |
| 3656 uint32_t LogMult; | 3653 uint32_t LogMult; |
| 3657 switch (Mult) { | 3654 switch (Mult) { |
| 3658 case 1: | 3655 case 1: |
| 3659 LogMult = 0; | 3656 LogMult = 0; |
| 3660 break; | 3657 break; |
| 3661 case 2: | 3658 case 2: |
| 3662 LogMult = 1; | 3659 LogMult = 1; |
| 3663 break; | 3660 break; |
| 3664 case 4: | 3661 case 4: |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3676 Reason = IndexInst; | 3673 Reason = IndexInst; |
| 3677 return true; | 3674 return true; |
| 3678 } | 3675 } |
| 3679 } | 3676 } |
| 3680 } | 3677 } |
| 3681 } | 3678 } |
| 3682 } | 3679 } |
| 3683 return false; | 3680 return false; |
| 3684 } | 3681 } |
| 3685 | 3682 |
| 3686 bool matchOffsetBase(Variable *&Base, int32_t &Offset, const Inst *&Reason) { | 3683 bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable *&Base, |
| 3684 int32_t &Offset, const Inst *&Reason) { |
| 3687 // Base is Base=Var+Const || Base is Base=Const+Var ==> | 3685 // Base is Base=Var+Const || Base is Base=Const+Var ==> |
| 3688 // set Base=Var, Offset+=Const | 3686 // set Base=Var, Offset+=Const |
| 3689 // Base is Base=Var-Const ==> | 3687 // Base is Base=Var-Const ==> |
| 3690 // set Base=Var, Offset-=Const | 3688 // set Base=Var, Offset-=Const |
| 3691 if (Base == NULL) | 3689 if (Base == NULL) |
| 3692 return false; | 3690 return false; |
| 3693 const Inst *BaseInst = Base->getDefinition(); | 3691 const Inst *BaseInst = VMetadata->getDefinition(Base); |
| 3694 if (BaseInst == NULL) | 3692 if (BaseInst == NULL) |
| 3695 return false; | 3693 return false; |
| 3696 if (const InstArithmetic *ArithInst = | 3694 if (const InstArithmetic *ArithInst = |
| 3697 llvm::dyn_cast<const InstArithmetic>(BaseInst)) { | 3695 llvm::dyn_cast<const InstArithmetic>(BaseInst)) { |
| 3698 if (ArithInst->getOp() != InstArithmetic::Add && | 3696 if (ArithInst->getOp() != InstArithmetic::Add && |
| 3699 ArithInst->getOp() != InstArithmetic::Sub) | 3697 ArithInst->getOp() != InstArithmetic::Sub) |
| 3700 return false; | 3698 return false; |
| 3701 bool IsAdd = ArithInst->getOp() == InstArithmetic::Add; | 3699 bool IsAdd = ArithInst->getOp() == InstArithmetic::Add; |
| 3702 Variable *Var = NULL; | 3700 Variable *Var = NULL; |
| 3703 ConstantInteger32 *Const = NULL; | 3701 ConstantInteger32 *Const = NULL; |
| 3704 if (Variable *VariableOperand = | 3702 if (Variable *VariableOperand = |
| 3705 llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) { | 3703 llvm::dyn_cast<Variable>(ArithInst->getSrc(0))) { |
| 3706 Var = VariableOperand; | 3704 Var = VariableOperand; |
| 3707 Const = llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1)); | 3705 Const = llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1)); |
| 3708 } else if (IsAdd) { | 3706 } else if (IsAdd) { |
| 3709 Const = llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(0)); | 3707 Const = llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(0)); |
| 3710 Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(1)); | 3708 Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(1)); |
| 3711 } | 3709 } |
| 3712 if (Var == NULL || Const == NULL || Var->getIsMultidef()) | 3710 if (Var == NULL || Const == NULL || VMetadata->isMultiDef(Var)) |
| 3713 return false; | 3711 return false; |
| 3714 int32_t MoreOffset = IsAdd ? Const->getValue() : -Const->getValue(); | 3712 int32_t MoreOffset = IsAdd ? Const->getValue() : -Const->getValue(); |
| 3715 if (WouldOverflowAdd(Offset, MoreOffset)) | 3713 if (WouldOverflowAdd(Offset, MoreOffset)) |
| 3716 return false; | 3714 return false; |
| 3717 Base = Var; | 3715 Base = Var; |
| 3718 Offset += MoreOffset; | 3716 Offset += MoreOffset; |
| 3719 Reason = BaseInst; | 3717 Reason = BaseInst; |
| 3720 return true; | 3718 return true; |
| 3721 } | 3719 } |
| 3722 return false; | 3720 return false; |
| 3723 } | 3721 } |
| 3724 | 3722 |
| 3725 void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, | 3723 void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, |
| 3726 Variable *&Index, uint16_t &Shift, int32_t &Offset) { | 3724 Variable *&Index, uint16_t &Shift, int32_t &Offset) { |
| 3727 Func->resetCurrentNode(); | 3725 Func->resetCurrentNode(); |
| 3728 if (Func->getContext()->isVerbose(IceV_AddrOpt)) { | 3726 if (Func->getContext()->isVerbose(IceV_AddrOpt)) { |
| 3729 Ostream &Str = Func->getContext()->getStrDump(); | 3727 Ostream &Str = Func->getContext()->getStrDump(); |
| 3730 Str << "\nStarting computeAddressOpt for instruction:\n "; | 3728 Str << "\nStarting computeAddressOpt for instruction:\n "; |
| 3731 Instr->dumpDecorated(Func); | 3729 Instr->dumpDecorated(Func); |
| 3732 } | 3730 } |
| 3733 (void)Offset; // TODO: pattern-match for non-zero offsets. | 3731 (void)Offset; // TODO: pattern-match for non-zero offsets. |
| 3734 if (Base == NULL) | 3732 if (Base == NULL) |
| 3735 return; | 3733 return; |
| 3736 // If the Base has more than one use or is live across multiple | 3734 // If the Base has more than one use or is live across multiple |
| 3737 // blocks, then don't go further. Alternatively (?), never consider | 3735 // blocks, then don't go further. Alternatively (?), never consider |
| 3738 // a transformation that would change a variable that is currently | 3736 // a transformation that would change a variable that is currently |
| 3739 // *not* live across basic block boundaries into one that *is*. | 3737 // *not* live across basic block boundaries into one that *is*. |
| 3740 if (Base->isMultiblockLife() /* || Base->getUseCount() > 1*/) | 3738 if (Func->getVMetadata()->isMultiBlock(Base) /* || Base->getUseCount() > 1*/) |
| 3741 return; | 3739 return; |
| 3742 | 3740 |
| 3741 const VariablesMetadata *VMetadata = Func->getVMetadata(); |
| 3743 bool Continue = true; | 3742 bool Continue = true; |
| 3744 while (Continue) { | 3743 while (Continue) { |
| 3745 const Inst *Reason = NULL; | 3744 const Inst *Reason = NULL; |
| 3746 if (matchTransitiveAssign(Base, Reason) || | 3745 if (matchTransitiveAssign(VMetadata, Base, Reason) || |
| 3747 matchTransitiveAssign(Index, Reason) || | 3746 matchTransitiveAssign(VMetadata, Index, Reason) || |
| 3748 matchCombinedBaseIndex(Base, Index, Shift, Reason) || | 3747 matchCombinedBaseIndex(VMetadata, Base, Index, Shift, Reason) || |
| 3749 matchShiftedIndex(Index, Shift, Reason) || | 3748 matchShiftedIndex(VMetadata, Index, Shift, Reason) || |
| 3750 matchOffsetBase(Base, Offset, Reason)) { | 3749 matchOffsetBase(VMetadata, Base, Offset, Reason)) { |
| 3751 dumpAddressOpt(Func, Base, Index, Shift, Offset, Reason); | 3750 dumpAddressOpt(Func, Base, Index, Shift, Offset, Reason); |
| 3752 } else { | 3751 } else { |
| 3753 Continue = false; | 3752 Continue = false; |
| 3754 } | 3753 } |
| 3755 | 3754 |
| 3756 // Index is Index=Var<<Const && Const+Shift<=3 ==> | 3755 // Index is Index=Var<<Const && Const+Shift<=3 ==> |
| 3757 // Index=Var, Shift+=Const | 3756 // Index=Var, Shift+=Const |
| 3758 | 3757 |
| 3759 // Index is Index=Const*Var && log2(Const)+Shift<=3 ==> | 3758 // Index is Index=Const*Var && log2(Const)+Shift<=3 ==> |
| 3760 // Index=Var, Shift+=log2(Const) | 3759 // Index=Var, Shift+=log2(Const) |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3932 } | 3931 } |
| 3933 // Lower select without SSE4.1: | 3932 // Lower select without SSE4.1: |
| 3934 // a=d?b:c ==> | 3933 // a=d?b:c ==> |
| 3935 // if elementtype(d) != i1: | 3934 // if elementtype(d) != i1: |
| 3936 // d=sext(d); | 3935 // d=sext(d); |
| 3937 // a=(b&d)|(c&~d); | 3936 // a=(b&d)|(c&~d); |
| 3938 Variable *T2 = makeReg(SrcTy); | 3937 Variable *T2 = makeReg(SrcTy); |
| 3939 // Sign extend the condition operand if applicable. | 3938 // Sign extend the condition operand if applicable. |
| 3940 if (SrcTy == IceType_v4f32) { | 3939 if (SrcTy == IceType_v4f32) { |
| 3941 // The sext operation takes only integer arguments. | 3940 // The sext operation takes only integer arguments. |
| 3942 Variable *T3 = Func->makeVariable(IceType_v4i32, Context.getNode()); | 3941 Variable *T3 = Func->makeVariable(IceType_v4i32); |
| 3943 lowerCast(InstCast::create(Func, InstCast::Sext, T3, Condition)); | 3942 lowerCast(InstCast::create(Func, InstCast::Sext, T3, Condition)); |
| 3944 _movp(T, T3); | 3943 _movp(T, T3); |
| 3945 } else if (typeElementType(SrcTy) != IceType_i1) { | 3944 } else if (typeElementType(SrcTy) != IceType_i1) { |
| 3946 lowerCast(InstCast::create(Func, InstCast::Sext, T, Condition)); | 3945 lowerCast(InstCast::create(Func, InstCast::Sext, T, Condition)); |
| 3947 } else { | 3946 } else { |
| 3948 Operand *ConditionRM = legalize(Condition, Legal_Reg | Legal_Mem); | 3947 Operand *ConditionRM = legalize(Condition, Legal_Reg | Legal_Mem); |
| 3949 _movp(T, ConditionRM); | 3948 _movp(T, ConditionRM); |
| 3950 } | 3949 } |
| 3951 _movp(T2, T); | 3950 _movp(T2, T); |
| 3952 _pand(T, SrcTRM); | 3951 _pand(T, SrcTRM); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4063 assert(isVectorType(Dest->getType())); | 4062 assert(isVectorType(Dest->getType())); |
| 4064 Type Ty = Dest->getType(); | 4063 Type Ty = Dest->getType(); |
| 4065 Type ElementTy = typeElementType(Ty); | 4064 Type ElementTy = typeElementType(Ty); |
| 4066 SizeT NumElements = typeNumElements(Ty); | 4065 SizeT NumElements = typeNumElements(Ty); |
| 4067 | 4066 |
| 4068 Operand *T = Ctx->getConstantUndef(Ty); | 4067 Operand *T = Ctx->getConstantUndef(Ty); |
| 4069 for (SizeT I = 0; I < NumElements; ++I) { | 4068 for (SizeT I = 0; I < NumElements; ++I) { |
| 4070 Constant *Index = Ctx->getConstantInt32(IceType_i32, I); | 4069 Constant *Index = Ctx->getConstantInt32(IceType_i32, I); |
| 4071 | 4070 |
| 4072 // Extract the next two inputs. | 4071 // Extract the next two inputs. |
| 4073 Variable *Op0 = Func->makeVariable(ElementTy, Context.getNode()); | 4072 Variable *Op0 = Func->makeVariable(ElementTy); |
| 4074 lowerExtractElement(InstExtractElement::create(Func, Op0, Src0, Index)); | 4073 lowerExtractElement(InstExtractElement::create(Func, Op0, Src0, Index)); |
| 4075 Variable *Op1 = Func->makeVariable(ElementTy, Context.getNode()); | 4074 Variable *Op1 = Func->makeVariable(ElementTy); |
| 4076 lowerExtractElement(InstExtractElement::create(Func, Op1, Src1, Index)); | 4075 lowerExtractElement(InstExtractElement::create(Func, Op1, Src1, Index)); |
| 4077 | 4076 |
| 4078 // Perform the arithmetic as a scalar operation. | 4077 // Perform the arithmetic as a scalar operation. |
| 4079 Variable *Res = Func->makeVariable(ElementTy, Context.getNode()); | 4078 Variable *Res = Func->makeVariable(ElementTy); |
| 4080 lowerArithmetic(InstArithmetic::create(Func, Kind, Res, Op0, Op1)); | 4079 lowerArithmetic(InstArithmetic::create(Func, Kind, Res, Op0, Op1)); |
| 4081 | 4080 |
| 4082 // Insert the result into position. | 4081 // Insert the result into position. |
| 4083 Variable *DestT = Func->makeVariable(Ty, Context.getNode()); | 4082 Variable *DestT = Func->makeVariable(Ty); |
| 4084 lowerInsertElement(InstInsertElement::create(Func, DestT, T, Res, Index)); | 4083 lowerInsertElement(InstInsertElement::create(Func, DestT, T, Res, Index)); |
| 4085 T = DestT; | 4084 T = DestT; |
| 4086 // TODO(stichnot): Use postLower() in -Om1 mode to avoid buildup of | 4085 // TODO(stichnot): Use postLower() in -Om1 mode to avoid buildup of |
| 4087 // infinite weight temporaries. | 4086 // infinite weight temporaries. |
| 4088 } | 4087 } |
| 4089 | 4088 |
| 4090 lowerAssign(InstAssign::create(Func, Dest, T)); | 4089 lowerAssign(InstAssign::create(Func, Dest, T)); |
| 4091 } | 4090 } |
| 4092 | 4091 |
| 4093 // The following pattern occurs often in lowered C and C++ code: | 4092 // The following pattern occurs often in lowered C and C++ code: |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4317 llvm::isa<ConstantRelocatable>(Offset)); | 4316 llvm::isa<ConstantRelocatable>(Offset)); |
| 4318 } | 4317 } |
| 4319 Mem = OperandX8632Mem::create(Func, Ty, Base, Offset); | 4318 Mem = OperandX8632Mem::create(Func, Ty, Base, Offset); |
| 4320 } | 4319 } |
| 4321 return llvm::cast<OperandX8632Mem>(legalize(Mem)); | 4320 return llvm::cast<OperandX8632Mem>(legalize(Mem)); |
| 4322 } | 4321 } |
| 4323 | 4322 |
| 4324 Variable *TargetX8632::makeReg(Type Type, int32_t RegNum) { | 4323 Variable *TargetX8632::makeReg(Type Type, int32_t RegNum) { |
| 4325 // There aren't any 64-bit integer registers for x86-32. | 4324 // There aren't any 64-bit integer registers for x86-32. |
| 4326 assert(Type != IceType_i64); | 4325 assert(Type != IceType_i64); |
| 4327 Variable *Reg = Func->makeVariable(Type, Context.getNode()); | 4326 Variable *Reg = Func->makeVariable(Type); |
| 4328 if (RegNum == Variable::NoRegister) | 4327 if (RegNum == Variable::NoRegister) |
| 4329 Reg->setWeightInfinite(); | 4328 Reg->setWeightInfinite(); |
| 4330 else | 4329 else |
| 4331 Reg->setRegNum(RegNum); | 4330 Reg->setRegNum(RegNum); |
| 4332 return Reg; | 4331 return Reg; |
| 4333 } | 4332 } |
| 4334 | 4333 |
| 4335 void TargetX8632::postLower() { | 4334 void TargetX8632::postLower() { |
| 4336 if (Ctx->getOptLevel() != Opt_m1) | 4335 if (Ctx->getOptLevel() != Opt_m1) |
| 4337 return; | 4336 return; |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4552 Str << "\t.align\t" << Align << "\n"; | 4551 Str << "\t.align\t" << Align << "\n"; |
| 4553 Str << MangledName << ":\n"; | 4552 Str << MangledName << ":\n"; |
| 4554 for (SizeT i = 0; i < Size; ++i) { | 4553 for (SizeT i = 0; i < Size; ++i) { |
| 4555 Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n"; | 4554 Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n"; |
| 4556 } | 4555 } |
| 4557 Str << "\t.size\t" << MangledName << ", " << Size << "\n"; | 4556 Str << "\t.size\t" << MangledName << ", " << Size << "\n"; |
| 4558 } | 4557 } |
| 4559 } | 4558 } |
| 4560 | 4559 |
| 4561 } // end of namespace Ice | 4560 } // end of namespace Ice |
| OLD | NEW |