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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 78 #undef X | 78 #undef X |
| 79 }; | 79 }; |
| 80 const size_t TableIcmp64Size = llvm::array_lengthof(TableIcmp64); | 80 const size_t TableIcmp64Size = llvm::array_lengthof(TableIcmp64); |
| 81 | 81 |
| 82 InstX8632Br::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) { | 82 InstX8632Br::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) { |
| 83 size_t Index = static_cast<size_t>(Cond); | 83 size_t Index = static_cast<size_t>(Cond); |
| 84 assert(Index < TableIcmp32Size); | 84 assert(Index < TableIcmp32Size); |
| 85 return TableIcmp32[Index].Mapping; | 85 return TableIcmp32[Index].Mapping; |
| 86 } | 86 } |
| 87 | 87 |
| 88 // Returns the type name as a valid assembly label. | |
| 89 IceString typeAsmLabel(Type Ty) { | |
| 90 IceString Result; | |
| 91 llvm::raw_string_ostream BaseOS(Result); | |
|
Jim Stichnoth
2014/06/27 18:30:16
I'd like to avoid unnecessarily building LLVM stre
wala
2014/06/27 21:09:19
To avoid snprintf, this function could emit the va
Karl
2014/07/01 20:31:55
I find this statement about not using raw_string_o
| |
| 92 Ostream OS(&BaseOS); | |
| 93 unsigned NumElements = typeNumElements(Ty); | |
| 94 if (NumElements > 1) { | |
| 95 OS << "v" << NumElements; | |
| 96 } | |
| 97 OS << typeElementType(Ty); | |
| 98 return BaseOS.str(); | |
| 99 } | |
| 100 | |
| 88 // In some cases, there are x-macros tables for both high-level and | 101 // In some cases, there are x-macros tables for both high-level and |
| 89 // low-level instructions/operands that use the same enum key value. | 102 // low-level instructions/operands that use the same enum key value. |
| 90 // The tables are kept separate to maintain a proper separation | 103 // The tables are kept separate to maintain a proper separation |
| 91 // between abstraction layers. There is a risk that the tables | 104 // between abstraction layers. There is a risk that the tables |
| 92 // could get out of sync if enum values are reordered or if entries | 105 // could get out of sync if enum values are reordered or if entries |
| 93 // are added or deleted. This dummy function uses static_assert to | 106 // are added or deleted. This dummy function uses static_assert to |
| 94 // ensure everything is kept in sync. | 107 // ensure everything is kept in sync. |
| 95 void xMacroIntegrityCheck() { | 108 void xMacroIntegrityCheck() { |
| 96 // Validate the enum values in FCMPX8632_TABLE. | 109 // Validate the enum values in FCMPX8632_TABLE. |
| 97 { | 110 { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 153 { | 166 { |
| 154 // Define a temporary set of enum values based on low-level | 167 // Define a temporary set of enum values based on low-level |
| 155 // table entries. | 168 // table entries. |
| 156 enum _tmp_enum { | 169 enum _tmp_enum { |
| 157 #define X(tag, cvt, sdss, width) _tmp_##tag, | 170 #define X(tag, cvt, sdss, width) _tmp_##tag, |
| 158 ICETYPEX8632_TABLE | 171 ICETYPEX8632_TABLE |
| 159 #undef X | 172 #undef X |
| 160 _num | 173 _num |
| 161 }; | 174 }; |
| 162 // Define a set of constants based on high-level table entries. | 175 // Define a set of constants based on high-level table entries. |
| 163 #define X(tag, size, align, str) static const int _table1_##tag = tag; | 176 #define X(tag, size, align, elts, elty, str) \ |
| 177 static const int _table1_##tag = tag; | |
| 164 ICETYPE_TABLE; | 178 ICETYPE_TABLE; |
| 165 #undef X | 179 #undef X |
| 166 // Define a set of constants based on low-level table entries, | 180 // Define a set of constants based on low-level table entries, |
| 167 // and ensure the table entry keys are consistent. | 181 // and ensure the table entry keys are consistent. |
| 168 #define X(tag, cvt, sdss, width) \ | 182 #define X(tag, cvt, sdss, width) \ |
| 169 static const int _table2_##tag = _tmp_##tag; \ | 183 static const int _table2_##tag = _tmp_##tag; \ |
| 170 STATIC_ASSERT(_table1_##tag == _table2_##tag); | 184 STATIC_ASSERT(_table1_##tag == _table2_##tag); |
| 171 ICETYPEX8632_TABLE; | 185 ICETYPEX8632_TABLE; |
| 172 #undef X | 186 #undef X |
| 173 // Repeat the static asserts with respect to the high-level | 187 // Repeat the static asserts with respect to the high-level |
| 174 // table entries in case the high-level table has extra entries. | 188 // table entries in case the high-level table has extra entries. |
| 175 #define X(tag, size, align, str) STATIC_ASSERT(_table1_##tag == _table2_##tag); | 189 #define X(tag, size, align, elts, elty, str) \ |
| 190 STATIC_ASSERT(_table1_##tag == _table2_##tag); | |
| 176 ICETYPE_TABLE; | 191 ICETYPE_TABLE; |
| 177 #undef X | 192 #undef X |
| 178 } | 193 } |
| 179 } | 194 } |
| 180 | 195 |
| 181 } // end of anonymous namespace | 196 } // end of anonymous namespace |
| 182 | 197 |
| 183 TargetX8632::TargetX8632(Cfg *Func) | 198 TargetX8632::TargetX8632(Cfg *Func) |
| 184 : TargetLowering(Func), IsEbpBasedFrame(false), FrameSizeLocals(0), | 199 : TargetLowering(Func), IsEbpBasedFrame(false), FrameSizeLocals(0), |
| 185 LocalsSizeBytes(0), NextLabelNumber(0), ComputedLiveRanges(false), | 200 LocalsSizeBytes(0), NextLabelNumber(0), ComputedLiveRanges(false), |
| (...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 674 typedef ConstantDouble IceType; | 689 typedef ConstantDouble IceType; |
| 675 static const Type Ty = IceType_f64; | 690 static const Type Ty = IceType_f64; |
| 676 static const char *TypeName; | 691 static const char *TypeName; |
| 677 static const char *AsmTag; | 692 static const char *AsmTag; |
| 678 static const char *PrintfString; | 693 static const char *PrintfString; |
| 679 }; | 694 }; |
| 680 const char *PoolTypeConverter<double>::TypeName = "double"; | 695 const char *PoolTypeConverter<double>::TypeName = "double"; |
| 681 const char *PoolTypeConverter<double>::AsmTag = ".quad"; | 696 const char *PoolTypeConverter<double>::AsmTag = ".quad"; |
| 682 const char *PoolTypeConverter<double>::PrintfString = "0x%llx"; | 697 const char *PoolTypeConverter<double>::PrintfString = "0x%llx"; |
| 683 | 698 |
| 684 template <typename T> void TargetX8632::emitConstantPool() const { | 699 template <typename T> void TargetX8632::emitScalarConstantPool() const { |
| 685 Ostream &Str = Ctx->getStrEmit(); | 700 Ostream &Str = Ctx->getStrEmit(); |
| 686 Type Ty = T::Ty; | 701 Type Ty = T::Ty; |
| 687 SizeT Align = typeAlignInBytes(Ty); | 702 SizeT Align = typeAlignInBytes(Ty); |
| 688 ConstantList Pool = Ctx->getConstantPool(Ty); | 703 ConstantList Pool = Ctx->getConstantPool(Ty); |
| 689 | 704 |
| 690 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align | 705 Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",@progbits," << Align |
| 691 << "\n"; | 706 << "\n"; |
| 692 Str << "\t.align\t" << Align << "\n"; | 707 Str << "\t.align\t" << Align << "\n"; |
| 693 for (ConstantList::const_iterator I = Pool.begin(), E = Pool.end(); I != E; | 708 for (ConstantList::const_iterator I = Pool.begin(), E = Pool.end(); I != E; |
| 694 ++I) { | 709 ++I) { |
| 695 typename T::IceType *Const = llvm::cast<typename T::IceType>(*I); | 710 typename T::IceType *Const = llvm::cast<typename T::IceType>(*I); |
| 696 typename T::PrimitiveFpType Value = Const->getValue(); | 711 typename T::PrimitiveFpType Value = Const->getValue(); |
| 697 // Use memcpy() to copy bits from Value into RawValue in a way | 712 // Use memcpy() to copy bits from Value into RawValue in a way |
| 698 // that avoids breaking strict-aliasing rules. | 713 // that avoids breaking strict-aliasing rules. |
| 699 typename T::PrimitiveIntType RawValue; | 714 typename T::PrimitiveIntType RawValue; |
| 700 memcpy(&RawValue, &Value, sizeof(Value)); | 715 memcpy(&RawValue, &Value, sizeof(Value)); |
| 701 char buf[30]; | 716 char buf[30]; |
| 702 int CharsPrinted = | 717 int CharsPrinted = |
| 703 snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue); | 718 snprintf(buf, llvm::array_lengthof(buf), T::PrintfString, RawValue); |
| 704 assert(CharsPrinted >= 0 && | 719 assert(CharsPrinted >= 0 && |
| 705 (size_t)CharsPrinted < llvm::array_lengthof(buf)); | 720 (size_t)CharsPrinted < llvm::array_lengthof(buf)); |
| 706 (void)CharsPrinted; // avoid warnings if asserts are disabled | 721 (void)CharsPrinted; // avoid warnings if asserts are disabled |
| 707 Str << "L$" << Ty << "$" << Const->getPoolEntryID() << ":\n"; | 722 Str << "L$" << Ty << "$" << Const->getPoolEntryID() << ":\n"; |
| 708 Str << "\t" << T::AsmTag << "\t" << buf << "\t# " << T::TypeName << " " | 723 Str << "\t" << T::AsmTag << "\t" << buf << "\t# " << T::TypeName << " " |
| 709 << Value << "\n"; | 724 << Value << "\n"; |
| 710 } | 725 } |
| 711 } | 726 } |
| 712 | 727 |
| 728 void TargetX8632::emitVectorConstantPool() const { | |
| 729 Ostream &Str = Ctx->getStrEmit(); | |
|
jvoung (off chromium)
2014/06/26 23:33:46
You could just make a local variable "Align = 16"
Jim Stichnoth
2014/06/27 18:30:16
Is it appropriate to reuse VECT128_BYTES for this
wala
2014/06/27 21:09:19
I'll do this, and then explain that we naturally a
| |
| 730 Str << "\t.section\t.rodata.cst" << 16 << ",\"aM\",@progbits," << 16 << "\n"; | |
| 731 Str << "\t.align\t" << 16 << "\n"; | |
| 732 | |
| 733 // Emit each (128 bit) vector. | |
| 734 ConstantList Vectors = Ctx->getConstantPool(IceType_v8i16); | |
|
jvoung (off chromium)
2014/06/26 23:33:46
Could add a comment that all non-i1 vectors are in
wala
2014/06/27 21:09:19
I will add the comment. I'm unsure how to avoid th
| |
| 735 for (ConstantList::const_iterator I = Vectors.begin(), E = Vectors.end(); | |
| 736 I != E; ++I) { | |
| 737 ConstantVector *Vector = llvm::cast<ConstantVector>(*I); | |
| 738 Vect128 Value = Vector->getValue(); | |
| 739 assert(Value.size() == VECT128_BYTES); | |
| 740 const char *Data = Value.data(); | |
| 741 Str << "L$" << typeAsmLabel(Vector->getType()) << "$" | |
| 742 << Vector->getPoolEntryID() << ":\n"; | |
| 743 for (unsigned Element = 0; Element != 4; ++Element) { | |
| 744 uint32_t RawValue; | |
| 745 memcpy(&RawValue, &Data[4 * Element], 4); | |
| 746 char buf[30]; | |
| 747 int CharsPrinted = | |
| 748 snprintf(buf, llvm::array_lengthof(buf), "0x%x", RawValue); | |
| 749 assert(CharsPrinted >= 0 && | |
| 750 (size_t)CharsPrinted < llvm::array_lengthof(buf)); | |
| 751 Str << "\t" | |
| 752 << ".long" | |
| 753 << "\t" << buf << "\t" | |
| 754 << "\n"; | |
| 755 } | |
| 756 } | |
| 757 | |
| 758 // Emit each I1 vector expanded to a 128 bit constant. | |
| 759 ConstantList BitVectors = Ctx->getConstantPool(IceType_v4i1); | |
| 760 for (ConstantList::const_iterator I = BitVectors.begin(), | |
| 761 E = BitVectors.end(); | |
| 762 I != E; ++I) { | |
| 763 ConstantBitVector *BitVector = llvm::cast<ConstantBitVector>(*I); | |
| 764 BitVect Value = BitVector->getValue(); | |
| 765 Str << "L$" << typeAsmLabel(BitVector->getType()) << "$" | |
| 766 << BitVector->getPoolEntryID() << ":\n"; | |
| 767 const char *AsmString = NULL; | |
| 768 switch (BitVector->getType()) { | |
| 769 default: | |
| 770 llvm_unreachable("Unknown type"); | |
| 771 case IceType_v4i1: | |
| 772 AsmString = ".long"; | |
| 773 break; | |
| 774 case IceType_v8i1: | |
| 775 AsmString = ".short"; | |
| 776 break; | |
| 777 case IceType_v16i1: | |
| 778 AsmString = ".byte"; | |
| 779 break; | |
| 780 } | |
| 781 unsigned NumElements = Value.size(); | |
| 782 for (unsigned Element = 0; Element != NumElements; ++Element) { | |
| 783 Str << "\t" << AsmString << "\t" | |
| 784 << "0x"; | |
| 785 Str << (Value[Element] ? "1" : "0"); | |
| 786 Str << "\t" | |
| 787 << "\n"; | |
| 788 } | |
| 789 } | |
| 790 } | |
| 791 | |
| 713 void TargetX8632::emitConstants() const { | 792 void TargetX8632::emitConstants() const { |
| 714 emitConstantPool<PoolTypeConverter<float> >(); | 793 emitScalarConstantPool<PoolTypeConverter<float> >(); |
| 715 emitConstantPool<PoolTypeConverter<double> >(); | 794 emitScalarConstantPool<PoolTypeConverter<double> >(); |
| 795 emitVectorConstantPool(); | |
| 716 | 796 |
| 717 // No need to emit constants from the int pool since (for x86) they | 797 // No need to emit constants from the int pool since (for x86) they |
| 718 // are embedded as immediates in the instructions. | 798 // are embedded as immediates in the instructions. |
| 719 } | 799 } |
| 720 | 800 |
| 721 void TargetX8632::split64(Variable *Var) { | 801 void TargetX8632::split64(Variable *Var) { |
| 722 switch (Var->getType()) { | 802 switch (Var->getType()) { |
| 723 default: | 803 default: |
| 724 return; | 804 return; |
| 725 case IceType_i64: | 805 case IceType_i64: |
| (...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1290 } | 1370 } |
| 1291 StackOffset += typeWidthInBytesOnStack(Arg->getType()); | 1371 StackOffset += typeWidthInBytesOnStack(Arg->getType()); |
| 1292 } | 1372 } |
| 1293 // Generate the call instruction. Assign its result to a temporary | 1373 // Generate the call instruction. Assign its result to a temporary |
| 1294 // with high register allocation weight. | 1374 // with high register allocation weight. |
| 1295 Variable *Dest = Instr->getDest(); | 1375 Variable *Dest = Instr->getDest(); |
| 1296 Variable *eax = NULL; // doubles as RegLo as necessary | 1376 Variable *eax = NULL; // doubles as RegLo as necessary |
| 1297 Variable *edx = NULL; | 1377 Variable *edx = NULL; |
| 1298 if (Dest) { | 1378 if (Dest) { |
| 1299 switch (Dest->getType()) { | 1379 switch (Dest->getType()) { |
| 1380 case IceType_v4i1: | |
| 1381 case IceType_v8i1: | |
| 1382 case IceType_v16i1: | |
| 1383 case IceType_v16i8: | |
| 1384 case IceType_v8i16: | |
| 1385 case IceType_v4i32: | |
| 1386 case IceType_v4f32: | |
| 1300 case IceType_NUM: | 1387 case IceType_NUM: |
| 1301 llvm_unreachable("Invalid Call dest type"); | 1388 llvm_unreachable("Invalid Call dest type"); |
| 1302 break; | 1389 break; |
| 1303 case IceType_void: | 1390 case IceType_void: |
| 1304 break; | 1391 break; |
| 1305 case IceType_i1: | 1392 case IceType_i1: |
| 1306 case IceType_i8: | 1393 case IceType_i8: |
| 1307 case IceType_i16: | 1394 case IceType_i16: |
| 1308 case IceType_i32: | 1395 case IceType_i32: |
| 1309 eax = makeReg(Dest->getType(), Reg_eax); | 1396 eax = makeReg(Dest->getType(), Reg_eax); |
| (...skipping 954 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2264 if (Inst->hasRetValue()) { | 2351 if (Inst->hasRetValue()) { |
| 2265 Operand *Src0 = legalize(Inst->getRetValue()); | 2352 Operand *Src0 = legalize(Inst->getRetValue()); |
| 2266 if (Src0->getType() == IceType_i64) { | 2353 if (Src0->getType() == IceType_i64) { |
| 2267 Variable *eax = legalizeToVar(loOperand(Src0), false, Reg_eax); | 2354 Variable *eax = legalizeToVar(loOperand(Src0), false, Reg_eax); |
| 2268 Variable *edx = legalizeToVar(hiOperand(Src0), false, Reg_edx); | 2355 Variable *edx = legalizeToVar(hiOperand(Src0), false, Reg_edx); |
| 2269 Reg = eax; | 2356 Reg = eax; |
| 2270 Context.insert(InstFakeUse::create(Func, edx)); | 2357 Context.insert(InstFakeUse::create(Func, edx)); |
| 2271 } else if (Src0->getType() == IceType_f32 || | 2358 } else if (Src0->getType() == IceType_f32 || |
| 2272 Src0->getType() == IceType_f64) { | 2359 Src0->getType() == IceType_f64) { |
| 2273 _fld(Src0); | 2360 _fld(Src0); |
| 2361 } else if (typeNumElements(Src0->getType()) > 1) { | |
| 2362 Reg = legalizeToVar(Src0, false, Reg_xmm0); | |
| 2274 } else { | 2363 } else { |
| 2275 _mov(Reg, Src0, Reg_eax); | 2364 _mov(Reg, Src0, Reg_eax); |
| 2276 } | 2365 } |
| 2277 } | 2366 } |
| 2278 _ret(Reg); | 2367 _ret(Reg); |
| 2279 // Add a fake use of esp to make sure esp stays alive for the entire | 2368 // Add a fake use of esp to make sure esp stays alive for the entire |
| 2280 // function. Otherwise post-call esp adjustments get dead-code | 2369 // function. Otherwise post-call esp adjustments get dead-code |
| 2281 // eliminated. TODO: Are there more places where the fake use | 2370 // eliminated. TODO: Are there more places where the fake use |
| 2282 // should be inserted? E.g. "void f(int n){while(1) g(n);}" may not | 2371 // should be inserted? E.g. "void f(int n){while(1) g(n);}" may not |
| 2283 // have a ret instruction. | 2372 // have a ret instruction. |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2385 _br(Inst->getLabelDefault()); | 2474 _br(Inst->getLabelDefault()); |
| 2386 } | 2475 } |
| 2387 | 2476 |
| 2388 void TargetX8632::lowerUnreachable(const InstUnreachable * /*Inst*/) { | 2477 void TargetX8632::lowerUnreachable(const InstUnreachable * /*Inst*/) { |
| 2389 const SizeT MaxSrcs = 0; | 2478 const SizeT MaxSrcs = 0; |
| 2390 Variable *Dest = NULL; | 2479 Variable *Dest = NULL; |
| 2391 InstCall *Call = makeHelperCall("ice_unreachable", Dest, MaxSrcs); | 2480 InstCall *Call = makeHelperCall("ice_unreachable", Dest, MaxSrcs); |
| 2392 lowerCall(Call); | 2481 lowerCall(Call); |
| 2393 } | 2482 } |
| 2394 | 2483 |
| 2484 // Helper for legalize() to emit the right code to lower an operand to a | |
| 2485 // register of the appropriate type. | |
| 2486 Variable *TargetX8632::copyToReg(Operand *Src, int32_t RegNum) { | |
| 2487 Type Ty = Src->getType(); | |
| 2488 Variable *Reg = makeReg(Ty, RegNum); | |
| 2489 if (typeNumElements(Ty) > 1) { | |
|
jvoung (off chromium)
2014/06/26 23:33:46
Maybe there should be some inlineable "isVectorTyp
wala
2014/06/27 21:09:19
I agree.
| |
| 2490 _movp(Reg, Src); | |
| 2491 } else { | |
| 2492 _mov(Reg, Src); | |
| 2493 } | |
| 2494 return Reg; | |
| 2495 } | |
| 2496 | |
| 2395 Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed, | 2497 Operand *TargetX8632::legalize(Operand *From, LegalMask Allowed, |
| 2396 bool AllowOverlap, int32_t RegNum) { | 2498 bool AllowOverlap, int32_t RegNum) { |
| 2397 // Assert that a physical register is allowed. To date, all calls | 2499 // Assert that a physical register is allowed. To date, all calls |
| 2398 // to legalize() allow a physical register. If a physical register | 2500 // to legalize() allow a physical register. If a physical register |
| 2399 // needs to be explicitly disallowed, then new code will need to be | 2501 // needs to be explicitly disallowed, then new code will need to be |
| 2400 // written to force a spill. | 2502 // written to force a spill. |
| 2401 assert(Allowed & Legal_Reg); | 2503 assert(Allowed & Legal_Reg); |
| 2402 // If we're asking for a specific physical register, make sure we're | 2504 // If we're asking for a specific physical register, make sure we're |
| 2403 // not allowing any other operand kinds. (This could be future | 2505 // not allowing any other operand kinds. (This could be future |
| 2404 // work, e.g. allow the shl shift amount to be either an immediate | 2506 // work, e.g. allow the shl shift amount to be either an immediate |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 2417 if (Index) { | 2519 if (Index) { |
| 2418 RegIndex = legalizeToVar(Index, true); | 2520 RegIndex = legalizeToVar(Index, true); |
| 2419 } | 2521 } |
| 2420 if (Base != RegBase || Index != RegIndex) { | 2522 if (Base != RegBase || Index != RegIndex) { |
| 2421 From = OperandX8632Mem::create( | 2523 From = OperandX8632Mem::create( |
| 2422 Func, Mem->getType(), RegBase, Mem->getOffset(), RegIndex, | 2524 Func, Mem->getType(), RegBase, Mem->getOffset(), RegIndex, |
| 2423 Mem->getShift(), Mem->getSegmentRegister()); | 2525 Mem->getShift(), Mem->getSegmentRegister()); |
| 2424 } | 2526 } |
| 2425 | 2527 |
| 2426 if (!(Allowed & Legal_Mem)) { | 2528 if (!(Allowed & Legal_Mem)) { |
| 2427 Variable *Reg = makeReg(From->getType(), RegNum); | 2529 From = copyToReg(From, RegNum); |
| 2428 _mov(Reg, From, RegNum); | |
| 2429 From = Reg; | |
| 2430 } | 2530 } |
| 2431 return From; | 2531 return From; |
| 2432 } | 2532 } |
| 2433 if (llvm::isa<Constant>(From)) { | 2533 if (llvm::isa<Constant>(From)) { |
| 2434 if (llvm::isa<ConstantUndef>(From)) { | 2534 if (llvm::isa<ConstantUndef>(From)) { |
| 2435 // Lower undefs to zero. Another option is to lower undefs to an | 2535 // Lower undefs to zero. Another option is to lower undefs to an |
| 2436 // uninitialized register; however, using an uninitialized register | 2536 // uninitialized register; however, using an uninitialized register |
| 2437 // results in less predictable code. | 2537 // results in less predictable code. |
| 2438 // | 2538 // |
| 2439 // If in the future the implementation is changed to lower undef | 2539 // If in the future the implementation is changed to lower undef |
| 2440 // values to uninitialized registers, a FakeDef will be needed: | 2540 // values to uninitialized registers, a FakeDef will be needed: |
| 2441 // Context.insert(InstFakeDef::create(Func, Reg)); | 2541 // Context.insert(InstFakeDef::create(Func, Reg)); |
| 2442 // This is in order to ensure that the live range of Reg is not | 2542 // This is in order to ensure that the live range of Reg is not |
| 2443 // overestimated. If the constant being lowered is a 64 bit value, | 2543 // overestimated. If the constant being lowered is a 64 bit value, |
| 2444 // then the result should be split and the lo and hi components will | 2544 // then the result should be split and the lo and hi components will |
| 2445 // need to go in uninitialized registers. | 2545 // need to go in uninitialized registers. |
| 2446 From = Ctx->getConstantZero(From->getType()); | 2546 From = Ctx->getConstantZero(From->getType()); |
| 2447 } | 2547 } |
| 2448 bool NeedsReg = | 2548 bool NeedsReg = |
| 2449 !(Allowed & Legal_Imm) || | 2549 !(Allowed & Legal_Imm) || |
| 2450 // ConstantFloat and ConstantDouble are actually memory operands. | 2550 // ConstantFloat, ConstantDouble, and vector constants are |
| 2551 // actually memory operands. | |
| 2451 (!(Allowed & Legal_Mem) && | 2552 (!(Allowed & Legal_Mem) && |
| 2452 (From->getType() == IceType_f32 || From->getType() == IceType_f64)); | 2553 (From->getType() == IceType_f32 || From->getType() == IceType_f64 || |
| 2554 typeNumElements(From->getType()) > 1)); | |
| 2453 if (NeedsReg) { | 2555 if (NeedsReg) { |
| 2454 Variable *Reg = makeReg(From->getType(), RegNum); | 2556 From = copyToReg(From, RegNum); |
| 2455 _mov(Reg, From); | |
| 2456 From = Reg; | |
| 2457 } | 2557 } |
| 2458 return From; | 2558 return From; |
| 2459 } | 2559 } |
| 2460 if (Variable *Var = llvm::dyn_cast<Variable>(From)) { | 2560 if (Variable *Var = llvm::dyn_cast<Variable>(From)) { |
| 2461 // We need a new physical register for the operand if: | 2561 // We need a new physical register for the operand if: |
| 2462 // Mem is not allowed and Var->getRegNum() is unknown, or | 2562 // Mem is not allowed and Var->getRegNum() is unknown, or |
| 2463 // RegNum is required and Var->getRegNum() doesn't match. | 2563 // RegNum is required and Var->getRegNum() doesn't match. |
| 2464 if ((!(Allowed & Legal_Mem) && !Var->hasReg()) || | 2564 if ((!(Allowed & Legal_Mem) && !Var->hasReg()) || |
| 2465 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) { | 2565 (RegNum != Variable::NoRegister && RegNum != Var->getRegNum())) { |
| 2466 Variable *Reg = makeReg(From->getType(), RegNum); | 2566 Variable *Reg = copyToReg(From, RegNum); |
| 2467 if (RegNum == Variable::NoRegister) { | 2567 if (RegNum == Variable::NoRegister) { |
| 2468 Reg->setPreferredRegister(Var, AllowOverlap); | 2568 Reg->setPreferredRegister(Var, AllowOverlap); |
| 2469 } | 2569 } |
| 2470 _mov(Reg, From); | |
| 2471 From = Reg; | 2570 From = Reg; |
| 2472 } | 2571 } |
| 2473 return From; | 2572 return From; |
| 2474 } | 2573 } |
| 2475 llvm_unreachable("Unhandled operand kind in legalize()"); | 2574 llvm_unreachable("Unhandled operand kind in legalize()"); |
| 2476 return From; | 2575 return From; |
| 2477 } | 2576 } |
| 2478 | 2577 |
| 2479 // Provide a trivial wrapper to legalize() for this common usage. | 2578 // Provide a trivial wrapper to legalize() for this common usage. |
| 2480 Variable *TargetX8632::legalizeToVar(Operand *From, bool AllowOverlap, | 2579 Variable *TargetX8632::legalizeToVar(Operand *From, bool AllowOverlap, |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2562 } | 2661 } |
| 2563 assert(AvailableTypedRegisters.any()); | 2662 assert(AvailableTypedRegisters.any()); |
| 2564 int32_t RegNum = AvailableTypedRegisters.find_first(); | 2663 int32_t RegNum = AvailableTypedRegisters.find_first(); |
| 2565 Var->setRegNum(RegNum); | 2664 Var->setRegNum(RegNum); |
| 2566 AvailableRegisters[RegNum] = false; | 2665 AvailableRegisters[RegNum] = false; |
| 2567 } | 2666 } |
| 2568 } | 2667 } |
| 2569 } | 2668 } |
| 2570 } | 2669 } |
| 2571 | 2670 |
| 2671 template <> void ConstantInteger::emit(GlobalContext *Ctx) const { | |
| 2672 Ostream &Str = Ctx->getStrEmit(); | |
| 2673 Str << getValue(); | |
| 2674 } | |
| 2675 | |
| 2572 template <> void ConstantFloat::emit(GlobalContext *Ctx) const { | 2676 template <> void ConstantFloat::emit(GlobalContext *Ctx) const { |
| 2573 Ostream &Str = Ctx->getStrEmit(); | 2677 Ostream &Str = Ctx->getStrEmit(); |
| 2574 // It would be better to prefix with ".L$" instead of "L$", but | 2678 // It would be better to prefix with ".L$" instead of "L$", but |
| 2575 // llvm-mc doesn't parse "dword ptr [.L$foo]". | 2679 // llvm-mc doesn't parse "dword ptr [.L$foo]". |
| 2576 Str << "dword ptr [L$" << IceType_f32 << "$" << getPoolEntryID() << "]"; | 2680 Str << "dword ptr [L$" << IceType_f32 << "$" << getPoolEntryID() << "]"; |
| 2577 } | 2681 } |
| 2578 | 2682 |
| 2579 template <> void ConstantDouble::emit(GlobalContext *Ctx) const { | 2683 template <> void ConstantDouble::emit(GlobalContext *Ctx) const { |
| 2580 Ostream &Str = Ctx->getStrEmit(); | 2684 Ostream &Str = Ctx->getStrEmit(); |
| 2581 Str << "qword ptr [L$" << IceType_f64 << "$" << getPoolEntryID() << "]"; | 2685 Str << "qword ptr [L$" << IceType_f64 << "$" << getPoolEntryID() << "]"; |
| 2582 } | 2686 } |
| 2583 | 2687 |
| 2688 template <> void ConstantVector::emit(GlobalContext *Ctx) const { | |
| 2689 Ostream &Str = Ctx->getStrEmit(); | |
| 2690 Str << "xmmword ptr [L$" << typeAsmLabel(getType()) << "$" << getPoolEntryID() | |
| 2691 << "]"; | |
| 2692 } | |
| 2693 | |
| 2694 template <> void ConstantBitVector::emit(GlobalContext *Ctx) const { | |
| 2695 Ostream &Str = Ctx->getStrEmit(); | |
| 2696 Str << "xmmword ptr [L$" << typeAsmLabel(getType()) << "$" << getPoolEntryID() | |
| 2697 << "]"; | |
| 2698 } | |
| 2699 | |
| 2584 } // end of namespace Ice | 2700 } // end of namespace Ice |
| OLD | NEW |