| 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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 const struct TableFcmp_ { | 54 const struct TableFcmp_ { |
| 55 uint32_t Default; | 55 uint32_t Default; |
| 56 bool SwapScalarOperands; | 56 bool SwapScalarOperands; |
| 57 CondX86::BrCond C1, C2; | 57 CondX86::BrCond C1, C2; |
| 58 bool SwapVectorOperands; | 58 bool SwapVectorOperands; |
| 59 CondX86::CmppsCond Predicate; | 59 CondX86::CmppsCond Predicate; |
| 60 } TableFcmp[] = { | 60 } TableFcmp[] = { |
| 61 #define X(val, dflt, swapS, C1, C2, swapV, pred) \ | 61 #define X(val, dflt, swapS, C1, C2, swapV, pred) \ |
| 62 { dflt, swapS, CondX86::C1, CondX86::C2, swapV, CondX86::pred } \ | 62 { dflt, swapS, CondX86::C1, CondX86::C2, swapV, CondX86::pred } \ |
| 63 , | 63 , |
| 64 FCMPX8632_TABLE | 64 FCMPX8632_TABLE |
| 65 #undef X | 65 #undef X |
| 66 }; | 66 }; |
| 67 const size_t TableFcmpSize = llvm::array_lengthof(TableFcmp); | 67 const size_t TableFcmpSize = llvm::array_lengthof(TableFcmp); |
| 68 | 68 |
| 69 // The following table summarizes the logic for lowering the icmp instruction | 69 // The following table summarizes the logic for lowering the icmp instruction |
| 70 // for i32 and narrower types. Each icmp condition has a clear mapping to an | 70 // for i32 and narrower types. Each icmp condition has a clear mapping to an |
| 71 // x86 conditional branch instruction. | 71 // x86 conditional branch instruction. |
| 72 | 72 |
| 73 const struct TableIcmp32_ { | 73 const struct TableIcmp32_ { |
| 74 CondX86::BrCond Mapping; | 74 CondX86::BrCond Mapping; |
| 75 } TableIcmp32[] = { | 75 } TableIcmp32[] = { |
| 76 #define X(val, C_32, C1_64, C2_64, C3_64) \ | 76 #define X(val, C_32, C1_64, C2_64, C3_64) \ |
| 77 { CondX86::C_32 } \ | 77 { CondX86::C_32 } \ |
| 78 , | 78 , |
| 79 ICMPX8632_TABLE | 79 ICMPX8632_TABLE |
| 80 #undef X | 80 #undef X |
| 81 }; | 81 }; |
| 82 const size_t TableIcmp32Size = llvm::array_lengthof(TableIcmp32); | 82 const size_t TableIcmp32Size = llvm::array_lengthof(TableIcmp32); |
| 83 | 83 |
| 84 // The following table summarizes the logic for lowering the icmp instruction | 84 // The following table summarizes the logic for lowering the icmp instruction |
| 85 // for the i64 type. For Eq and Ne, two separate 32-bit comparisons and | 85 // for the i64 type. For Eq and Ne, two separate 32-bit comparisons and |
| 86 // conditional branches are needed. For the other conditions, three separate | 86 // conditional branches are needed. For the other conditions, three separate |
| 87 // conditional branches are needed. | 87 // conditional branches are needed. |
| 88 const struct TableIcmp64_ { | 88 const struct TableIcmp64_ { |
| 89 CondX86::BrCond C1, C2, C3; | 89 CondX86::BrCond C1, C2, C3; |
| 90 } TableIcmp64[] = { | 90 } TableIcmp64[] = { |
| 91 #define X(val, C_32, C1_64, C2_64, C3_64) \ | 91 #define X(val, C_32, C1_64, C2_64, C3_64) \ |
| 92 { CondX86::C1_64, CondX86::C2_64, CondX86::C3_64 } \ | 92 { CondX86::C1_64, CondX86::C2_64, CondX86::C3_64 } \ |
| 93 , | 93 , |
| 94 ICMPX8632_TABLE | 94 ICMPX8632_TABLE |
| 95 #undef X | 95 #undef X |
| 96 }; | 96 }; |
| 97 const size_t TableIcmp64Size = llvm::array_lengthof(TableIcmp64); | 97 const size_t TableIcmp64Size = llvm::array_lengthof(TableIcmp64); |
| 98 | 98 |
| 99 CondX86::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) { | 99 CondX86::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) { |
| 100 size_t Index = static_cast<size_t>(Cond); | 100 size_t Index = static_cast<size_t>(Cond); |
| 101 assert(Index < TableIcmp32Size); | 101 assert(Index < TableIcmp32Size); |
| 102 return TableIcmp32[Index].Mapping; | 102 return TableIcmp32[Index].Mapping; |
| 103 } | 103 } |
| 104 | 104 |
| 105 const struct TableTypeX8632Attributes_ { | 105 const struct TableTypeX8632Attributes_ { |
| 106 Type InVectorElementType; | 106 Type InVectorElementType; |
| 107 } TableTypeX8632Attributes[] = { | 107 } TableTypeX8632Attributes[] = { |
| 108 #define X(tag, elementty, cvt, sdss, pack, width, fld) \ | 108 #define X(tag, elementty, cvt, sdss, pack, width, fld) \ |
| 109 { elementty } \ | 109 { elementty } \ |
| 110 , | 110 , |
| 111 ICETYPEX8632_TABLE | 111 ICETYPEX8632_TABLE |
| 112 #undef X | 112 #undef X |
| 113 }; | 113 }; |
| 114 const size_t TableTypeX8632AttributesSize = | 114 const size_t TableTypeX8632AttributesSize = |
| 115 llvm::array_lengthof(TableTypeX8632Attributes); | 115 llvm::array_lengthof(TableTypeX8632Attributes); |
| 116 | 116 |
| 117 // Return the type which the elements of the vector have in the X86 | 117 // Return the type which the elements of the vector have in the X86 |
| 118 // representation of the vector. | 118 // representation of the vector. |
| 119 Type getInVectorElementType(Type Ty) { | 119 Type getInVectorElementType(Type Ty) { |
| 120 assert(isVectorType(Ty)); | 120 assert(isVectorType(Ty)); |
| 121 size_t Index = static_cast<size_t>(Ty); | 121 size_t Index = static_cast<size_t>(Ty); |
| 122 (void)Index; | 122 (void)Index; |
| 123 assert(Index < TableTypeX8632AttributesSize); | 123 assert(Index < TableTypeX8632AttributesSize); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 148 } | 148 } |
| 149 | 149 |
| 150 // Value is in bytes. Return Value adjusted to the next highest multiple | 150 // Value is in bytes. Return Value adjusted to the next highest multiple |
| 151 // of the stack alignment. | 151 // of the stack alignment. |
| 152 uint32_t applyStackAlignment(uint32_t Value) { | 152 uint32_t applyStackAlignment(uint32_t Value) { |
| 153 return applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES); | 153 return applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES); |
| 154 } | 154 } |
| 155 | 155 |
| 156 // Instruction set options | 156 // Instruction set options |
| 157 namespace cl = ::llvm::cl; | 157 namespace cl = ::llvm::cl; |
| 158 cl::opt<TargetX8632::X86InstructionSet> | 158 cl::opt<TargetX8632::X86InstructionSet> CLInstructionSet( |
| 159 CLInstructionSet("mattr", cl::desc("X86 target attributes"), | 159 "mattr", cl::desc("X86 target attributes"), cl::init(TargetX8632::SSE2), |
| 160 cl::init(TargetX8632::SSE2), | 160 cl::values(clEnumValN(TargetX8632::SSE2, "sse2", |
| 161 cl::values(clEnumValN(TargetX8632::SSE2, "sse2", | 161 "Enable SSE2 instructions (default)"), |
| 162 "Enable SSE2 instructions (default)"), | 162 clEnumValN(TargetX8632::SSE4_1, "sse4.1", |
| 163 clEnumValN(TargetX8632::SSE4_1, "sse4.1", | 163 "Enable SSE 4.1 instructions"), |
| 164 "Enable SSE 4.1 instructions"), | 164 clEnumValEnd)); |
| 165 clEnumValEnd)); | |
| 166 | 165 |
| 167 // In some cases, there are x-macros tables for both high-level and | 166 // In some cases, there are x-macros tables for both high-level and |
| 168 // low-level instructions/operands that use the same enum key value. | 167 // low-level instructions/operands that use the same enum key value. |
| 169 // The tables are kept separate to maintain a proper separation | 168 // The tables are kept separate to maintain a proper separation |
| 170 // between abstraction layers. There is a risk that the tables could | 169 // between abstraction layers. There is a risk that the tables could |
| 171 // get out of sync if enum values are reordered or if entries are | 170 // get out of sync if enum values are reordered or if entries are |
| 172 // added or deleted. The following dummy namespaces use | 171 // added or deleted. The following dummy namespaces use |
| 173 // static_asserts to ensure everything is kept in sync. | 172 // static_asserts to ensure everything is kept in sync. |
| 174 | 173 |
| 175 // Validate the enum values in FCMPX8632_TABLE. | 174 // Validate the enum values in FCMPX8632_TABLE. |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 if (InstX8632Br *Br = llvm::dyn_cast<InstX8632Br>(I)) { | 446 if (InstX8632Br *Br = llvm::dyn_cast<InstX8632Br>(I)) { |
| 448 return Br->optimizeBranch(NextNode); | 447 return Br->optimizeBranch(NextNode); |
| 449 } | 448 } |
| 450 return false; | 449 return false; |
| 451 } | 450 } |
| 452 | 451 |
| 453 IceString TargetX8632::RegNames[] = { | 452 IceString TargetX8632::RegNames[] = { |
| 454 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ | 453 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ |
| 455 frameptr, isI8, isInt, isFP) \ | 454 frameptr, isI8, isInt, isFP) \ |
| 456 name, | 455 name, |
| 457 REGX8632_TABLE | 456 REGX8632_TABLE |
| 458 #undef X | 457 #undef X |
| 459 }; | 458 }; |
| 460 | 459 |
| 461 Variable *TargetX8632::getPhysicalRegister(SizeT RegNum, Type Ty) { | 460 Variable *TargetX8632::getPhysicalRegister(SizeT RegNum, Type Ty) { |
| 462 if (Ty == IceType_void) | 461 if (Ty == IceType_void) |
| 463 Ty = IceType_i32; | 462 Ty = IceType_i32; |
| 464 if (PhysicalRegisters[Ty].empty()) | 463 if (PhysicalRegisters[Ty].empty()) |
| 465 PhysicalRegisters[Ty].resize(RegX8632::Reg_NUM); | 464 PhysicalRegisters[Ty].resize(RegX8632::Reg_NUM); |
| 466 assert(RegNum < PhysicalRegisters[Ty].size()); | 465 assert(RegNum < PhysicalRegisters[Ty].size()); |
| 467 Variable *Reg = PhysicalRegisters[Ty][RegNum]; | 466 Variable *Reg = PhysicalRegisters[Ty][RegNum]; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 478 } | 477 } |
| 479 return Reg; | 478 return Reg; |
| 480 } | 479 } |
| 481 | 480 |
| 482 IceString TargetX8632::getRegName(SizeT RegNum, Type Ty) const { | 481 IceString TargetX8632::getRegName(SizeT RegNum, Type Ty) const { |
| 483 assert(RegNum < RegX8632::Reg_NUM); | 482 assert(RegNum < RegX8632::Reg_NUM); |
| 484 static IceString RegNames8[] = { | 483 static IceString RegNames8[] = { |
| 485 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ | 484 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ |
| 486 frameptr, isI8, isInt, isFP) \ | 485 frameptr, isI8, isInt, isFP) \ |
| 487 name8, | 486 name8, |
| 488 REGX8632_TABLE | 487 REGX8632_TABLE |
| 489 #undef X | 488 #undef X |
| 490 }; | 489 }; |
| 491 static IceString RegNames16[] = { | 490 static IceString RegNames16[] = { |
| 492 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ | 491 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \ |
| 493 frameptr, isI8, isInt, isFP) \ | 492 frameptr, isI8, isInt, isFP) \ |
| 494 name16, | 493 name16, |
| 495 REGX8632_TABLE | 494 REGX8632_TABLE |
| 496 #undef X | 495 #undef X |
| 497 }; | 496 }; |
| 498 switch (Ty) { | 497 switch (Ty) { |
| 499 case IceType_i1: | 498 case IceType_i1: |
| 500 case IceType_i8: | 499 case IceType_i8: |
| 501 return RegNames8[RegNum]; | 500 return RegNames8[RegNum]; |
| 502 case IceType_i16: | 501 case IceType_i16: |
| 503 return RegNames16[RegNum]; | 502 return RegNames16[RegNum]; |
| 504 default: | 503 default: |
| 505 return RegNames[RegNum]; | 504 return RegNames[RegNum]; |
| (...skipping 2249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2755 // | 2754 // |
| 2756 // insertelement into index 2 (result is stored in T): | 2755 // insertelement into index 2 (result is stored in T): |
| 2757 // T := SourceVectRM | 2756 // T := SourceVectRM |
| 2758 // ElementR := ElementR[0, 0] T[0, 3] | 2757 // ElementR := ElementR[0, 0] T[0, 3] |
| 2759 // T := T[0, 1] ElementR[0, 3] | 2758 // T := T[0, 1] ElementR[0, 3] |
| 2760 // | 2759 // |
| 2761 // insertelement into index 3 (result is stored in T): | 2760 // insertelement into index 3 (result is stored in T): |
| 2762 // T := SourceVectRM | 2761 // T := SourceVectRM |
| 2763 // ElementR := ElementR[0, 0] T[0, 2] | 2762 // ElementR := ElementR[0, 0] T[0, 2] |
| 2764 // T := T[0, 1] ElementR[3, 0] | 2763 // T := T[0, 1] ElementR[3, 0] |
| 2765 const unsigned char Mask1[3] = { 0, 192, 128 }; | 2764 const unsigned char Mask1[3] = {0, 192, 128}; |
| 2766 const unsigned char Mask2[3] = { 227, 196, 52 }; | 2765 const unsigned char Mask2[3] = {227, 196, 52}; |
| 2767 | 2766 |
| 2768 Constant *Mask1Constant = Ctx->getConstantInt32(Mask1[Index - 1]); | 2767 Constant *Mask1Constant = Ctx->getConstantInt32(Mask1[Index - 1]); |
| 2769 Constant *Mask2Constant = Ctx->getConstantInt32(Mask2[Index - 1]); | 2768 Constant *Mask2Constant = Ctx->getConstantInt32(Mask2[Index - 1]); |
| 2770 | 2769 |
| 2771 if (Index == 1) { | 2770 if (Index == 1) { |
| 2772 _shufps(ElementR, SourceVectRM, Mask1Constant); | 2771 _shufps(ElementR, SourceVectRM, Mask1Constant); |
| 2773 _shufps(ElementR, SourceVectRM, Mask2Constant); | 2772 _shufps(ElementR, SourceVectRM, Mask2Constant); |
| 2774 _movp(Inst->getDest(), ElementR); | 2773 _movp(Inst->getDest(), ElementR); |
| 2775 } else { | 2774 } else { |
| 2776 Variable *T = makeReg(Ty); | 2775 Variable *T = makeReg(Ty); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2799 Variable *T = makeReg(Ty); | 2798 Variable *T = makeReg(Ty); |
| 2800 _movp(T, Slot); | 2799 _movp(T, Slot); |
| 2801 _movp(Inst->getDest(), T); | 2800 _movp(Inst->getDest(), T); |
| 2802 } | 2801 } |
| 2803 } | 2802 } |
| 2804 | 2803 |
| 2805 void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { | 2804 void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { |
| 2806 switch (Instr->getIntrinsicInfo().ID) { | 2805 switch (Instr->getIntrinsicInfo().ID) { |
| 2807 case Intrinsics::AtomicCmpxchg: { | 2806 case Intrinsics::AtomicCmpxchg: { |
| 2808 if (!Intrinsics::VerifyMemoryOrder( | 2807 if (!Intrinsics::VerifyMemoryOrder( |
| 2809 llvm::cast<ConstantInteger32>(Instr->getArg(3))->getValue())) { | 2808 llvm::cast<ConstantInteger32>(Instr->getArg(3))->getValue())) { |
| 2810 Func->setError("Unexpected memory ordering (success) for AtomicCmpxchg"); | 2809 Func->setError("Unexpected memory ordering (success) for AtomicCmpxchg"); |
| 2811 return; | 2810 return; |
| 2812 } | 2811 } |
| 2813 if (!Intrinsics::VerifyMemoryOrder( | 2812 if (!Intrinsics::VerifyMemoryOrder( |
| 2814 llvm::cast<ConstantInteger32>(Instr->getArg(4))->getValue())) { | 2813 llvm::cast<ConstantInteger32>(Instr->getArg(4))->getValue())) { |
| 2815 Func->setError("Unexpected memory ordering (failure) for AtomicCmpxchg"); | 2814 Func->setError("Unexpected memory ordering (failure) for AtomicCmpxchg"); |
| 2816 return; | 2815 return; |
| 2817 } | 2816 } |
| 2818 Variable *DestPrev = Instr->getDest(); | 2817 Variable *DestPrev = Instr->getDest(); |
| 2819 Operand *PtrToMem = Instr->getArg(0); | 2818 Operand *PtrToMem = Instr->getArg(0); |
| 2820 Operand *Expected = Instr->getArg(1); | 2819 Operand *Expected = Instr->getArg(1); |
| 2821 Operand *Desired = Instr->getArg(2); | 2820 Operand *Desired = Instr->getArg(2); |
| 2822 if (tryOptimizedCmpxchgCmpBr(DestPrev, PtrToMem, Expected, Desired)) | 2821 if (tryOptimizedCmpxchgCmpBr(DestPrev, PtrToMem, Expected, Desired)) |
| 2823 return; | 2822 return; |
| 2824 lowerAtomicCmpxchg(DestPrev, PtrToMem, Expected, Desired); | 2823 lowerAtomicCmpxchg(DestPrev, PtrToMem, Expected, Desired); |
| 2825 return; | 2824 return; |
| 2826 } | 2825 } |
| 2827 case Intrinsics::AtomicFence: | 2826 case Intrinsics::AtomicFence: |
| 2828 if (!Intrinsics::VerifyMemoryOrder( | 2827 if (!Intrinsics::VerifyMemoryOrder( |
| 2829 llvm::cast<ConstantInteger32>(Instr->getArg(0))->getValue())) { | 2828 llvm::cast<ConstantInteger32>(Instr->getArg(0))->getValue())) { |
| 2830 Func->setError("Unexpected memory ordering for AtomicFence"); | 2829 Func->setError("Unexpected memory ordering for AtomicFence"); |
| 2831 return; | 2830 return; |
| 2832 } | 2831 } |
| 2833 _mfence(); | 2832 _mfence(); |
| 2834 return; | 2833 return; |
| 2835 case Intrinsics::AtomicFenceAll: | 2834 case Intrinsics::AtomicFenceAll: |
| 2836 // NOTE: FenceAll should prevent and load/store from being moved | 2835 // NOTE: FenceAll should prevent and load/store from being moved |
| 2837 // across the fence (both atomic and non-atomic). The InstX8632Mfence | 2836 // across the fence (both atomic and non-atomic). The InstX8632Mfence |
| 2838 // instruction is currently marked coarsely as "HasSideEffects". | 2837 // instruction is currently marked coarsely as "HasSideEffects". |
| 2839 _mfence(); | 2838 _mfence(); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2865 return; | 2864 return; |
| 2866 } | 2865 } |
| 2867 // The PNaCl ABI requires the byte size to be a compile-time constant. | 2866 // The PNaCl ABI requires the byte size to be a compile-time constant. |
| 2868 Func->setError("AtomicIsLockFree byte size should be compile-time const"); | 2867 Func->setError("AtomicIsLockFree byte size should be compile-time const"); |
| 2869 return; | 2868 return; |
| 2870 } | 2869 } |
| 2871 case Intrinsics::AtomicLoad: { | 2870 case Intrinsics::AtomicLoad: { |
| 2872 // We require the memory address to be naturally aligned. | 2871 // We require the memory address to be naturally aligned. |
| 2873 // Given that is the case, then normal loads are atomic. | 2872 // Given that is the case, then normal loads are atomic. |
| 2874 if (!Intrinsics::VerifyMemoryOrder( | 2873 if (!Intrinsics::VerifyMemoryOrder( |
| 2875 llvm::cast<ConstantInteger32>(Instr->getArg(1))->getValue())) { | 2874 llvm::cast<ConstantInteger32>(Instr->getArg(1))->getValue())) { |
| 2876 Func->setError("Unexpected memory ordering for AtomicLoad"); | 2875 Func->setError("Unexpected memory ordering for AtomicLoad"); |
| 2877 return; | 2876 return; |
| 2878 } | 2877 } |
| 2879 Variable *Dest = Instr->getDest(); | 2878 Variable *Dest = Instr->getDest(); |
| 2880 if (Dest->getType() == IceType_i64) { | 2879 if (Dest->getType() == IceType_i64) { |
| 2881 // Follow what GCC does and use a movq instead of what lowerLoad() | 2880 // Follow what GCC does and use a movq instead of what lowerLoad() |
| 2882 // normally does (split the load into two). | 2881 // normally does (split the load into two). |
| 2883 // Thus, this skips load/arithmetic op folding. Load/arithmetic folding | 2882 // Thus, this skips load/arithmetic op folding. Load/arithmetic folding |
| 2884 // can't happen anyway, since this is x86-32 and integer arithmetic only | 2883 // can't happen anyway, since this is x86-32 and integer arithmetic only |
| 2885 // happens on 32-bit quantities. | 2884 // happens on 32-bit quantities. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2898 lowerLoad(Load); | 2897 lowerLoad(Load); |
| 2899 // Make sure the atomic load isn't elided when unused, by adding a FakeUse. | 2898 // Make sure the atomic load isn't elided when unused, by adding a FakeUse. |
| 2900 // Since lowerLoad may fuse the load w/ an arithmetic instruction, | 2899 // Since lowerLoad may fuse the load w/ an arithmetic instruction, |
| 2901 // insert the FakeUse on the last-inserted instruction's dest. | 2900 // insert the FakeUse on the last-inserted instruction's dest. |
| 2902 Context.insert( | 2901 Context.insert( |
| 2903 InstFakeUse::create(Func, Context.getLastInserted()->getDest())); | 2902 InstFakeUse::create(Func, Context.getLastInserted()->getDest())); |
| 2904 return; | 2903 return; |
| 2905 } | 2904 } |
| 2906 case Intrinsics::AtomicRMW: | 2905 case Intrinsics::AtomicRMW: |
| 2907 if (!Intrinsics::VerifyMemoryOrder( | 2906 if (!Intrinsics::VerifyMemoryOrder( |
| 2908 llvm::cast<ConstantInteger32>(Instr->getArg(3))->getValue())) { | 2907 llvm::cast<ConstantInteger32>(Instr->getArg(3))->getValue())) { |
| 2909 Func->setError("Unexpected memory ordering for AtomicRMW"); | 2908 Func->setError("Unexpected memory ordering for AtomicRMW"); |
| 2910 return; | 2909 return; |
| 2911 } | 2910 } |
| 2912 lowerAtomicRMW(Instr->getDest(), | 2911 lowerAtomicRMW(Instr->getDest(), |
| 2913 static_cast<uint32_t>(llvm::cast<ConstantInteger32>( | 2912 static_cast<uint32_t>(llvm::cast<ConstantInteger32>( |
| 2914 Instr->getArg(0))->getValue()), | 2913 Instr->getArg(0))->getValue()), |
| 2915 Instr->getArg(1), Instr->getArg(2)); | 2914 Instr->getArg(1), Instr->getArg(2)); |
| 2916 return; | 2915 return; |
| 2917 case Intrinsics::AtomicStore: { | 2916 case Intrinsics::AtomicStore: { |
| 2918 if (!Intrinsics::VerifyMemoryOrder( | 2917 if (!Intrinsics::VerifyMemoryOrder( |
| 2919 llvm::cast<ConstantInteger32>(Instr->getArg(2))->getValue())) { | 2918 llvm::cast<ConstantInteger32>(Instr->getArg(2))->getValue())) { |
| 2920 Func->setError("Unexpected memory ordering for AtomicStore"); | 2919 Func->setError("Unexpected memory ordering for AtomicStore"); |
| 2921 return; | 2920 return; |
| 2922 } | 2921 } |
| 2923 // We require the memory address to be naturally aligned. | 2922 // We require the memory address to be naturally aligned. |
| 2924 // Given that is the case, then normal stores are atomic. | 2923 // Given that is the case, then normal stores are atomic. |
| 2925 // Add a fence after the store to make it visible. | 2924 // Add a fence after the store to make it visible. |
| 2926 Operand *Value = Instr->getArg(0); | 2925 Operand *Value = Instr->getArg(0); |
| 2927 Operand *Ptr = Instr->getArg(1); | 2926 Operand *Ptr = Instr->getArg(1); |
| 2928 if (Value->getType() == IceType_i64) { | 2927 if (Value->getType() == IceType_i64) { |
| 2929 // Use a movq instead of what lowerStore() normally does | 2928 // Use a movq instead of what lowerStore() normally does |
| (...skipping 1640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4570 return; | 4569 return; |
| 4571 | 4570 |
| 4572 Ostream &Str = Ctx->getStrEmit(); | 4571 Ostream &Str = Ctx->getStrEmit(); |
| 4573 | 4572 |
| 4574 const VariableDeclaration::InitializerListType &Initializers = | 4573 const VariableDeclaration::InitializerListType &Initializers = |
| 4575 Var.getInitializers(); | 4574 Var.getInitializers(); |
| 4576 | 4575 |
| 4577 // If external and not initialized, this must be a cross test. | 4576 // If external and not initialized, this must be a cross test. |
| 4578 // Don't generate a declaration for such cases. | 4577 // Don't generate a declaration for such cases. |
| 4579 bool IsExternal = Var.isExternal() || Ctx->getFlags().DisableInternal; | 4578 bool IsExternal = Var.isExternal() || Ctx->getFlags().DisableInternal; |
| 4580 if (IsExternal && !Var.hasInitializer()) return; | 4579 if (IsExternal && !Var.hasInitializer()) |
| 4580 return; |
| 4581 | 4581 |
| 4582 bool HasNonzeroInitializer = Var.hasNonzeroInitializer(); | 4582 bool HasNonzeroInitializer = Var.hasNonzeroInitializer(); |
| 4583 bool IsConstant = Var.getIsConstant(); | 4583 bool IsConstant = Var.getIsConstant(); |
| 4584 uint32_t Align = Var.getAlignment(); | 4584 uint32_t Align = Var.getAlignment(); |
| 4585 SizeT Size = Var.getNumBytes(); | 4585 SizeT Size = Var.getNumBytes(); |
| 4586 IceString MangledName = Var.mangleName(Ctx); | 4586 IceString MangledName = Var.mangleName(Ctx); |
| 4587 IceString SectionSuffix = ""; | 4587 IceString SectionSuffix = ""; |
| 4588 if (Ctx->getFlags().DataSections) | 4588 if (Ctx->getFlags().DataSections) |
| 4589 SectionSuffix = "." + MangledName; | 4589 SectionSuffix = "." + MangledName; |
| 4590 | 4590 |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4711 Writer->writeConstantPool<ConstantFloat>(IceType_f32); | 4711 Writer->writeConstantPool<ConstantFloat>(IceType_f32); |
| 4712 Writer->writeConstantPool<ConstantDouble>(IceType_f64); | 4712 Writer->writeConstantPool<ConstantDouble>(IceType_f64); |
| 4713 } else { | 4713 } else { |
| 4714 OstreamLocker L(Ctx); | 4714 OstreamLocker L(Ctx); |
| 4715 emitConstantPool<PoolTypeConverter<float>>(Ctx); | 4715 emitConstantPool<PoolTypeConverter<float>>(Ctx); |
| 4716 emitConstantPool<PoolTypeConverter<double>>(Ctx); | 4716 emitConstantPool<PoolTypeConverter<double>>(Ctx); |
| 4717 } | 4717 } |
| 4718 } | 4718 } |
| 4719 | 4719 |
| 4720 } // end of namespace Ice | 4720 } // end of namespace Ice |
| OLD | NEW |