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 2838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2849 OperandX8632Mem *Loc = | 2849 OperandX8632Mem *Loc = |
2850 getMemoryOperandForStackSlot(InVectorElementTy, Slot, Offset); | 2850 getMemoryOperandForStackSlot(InVectorElementTy, Slot, Offset); |
2851 _store(legalizeToVar(ElementToInsertNotLegalized), Loc); | 2851 _store(legalizeToVar(ElementToInsertNotLegalized), Loc); |
2852 | 2852 |
2853 Variable *T = makeReg(Ty); | 2853 Variable *T = makeReg(Ty); |
2854 _movp(T, Slot); | 2854 _movp(T, Slot); |
2855 _movp(Inst->getDest(), T); | 2855 _movp(Inst->getDest(), T); |
2856 } | 2856 } |
2857 } | 2857 } |
2858 | 2858 |
| 2859 namespace { |
| 2860 |
| 2861 // Converts a ConstantInteger32 operand into its constant value, or |
| 2862 // MemoryOrderInvalid if the operand is not a ConstantInteger32. |
| 2863 uint64_t getConstantMemoryOrder(Operand *Opnd) { |
| 2864 if (auto Integer = llvm::dyn_cast<ConstantInteger32>(Opnd)) |
| 2865 return Integer->getValue(); |
| 2866 return Intrinsics::MemoryOrderInvalid; |
| 2867 } |
| 2868 |
| 2869 } // end of anonymous namespace |
| 2870 |
2859 void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { | 2871 void TargetX8632::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { |
2860 switch (Instr->getIntrinsicInfo().ID) { | 2872 switch (Intrinsics::IntrinsicID ID = Instr->getIntrinsicInfo().ID) { |
2861 case Intrinsics::AtomicCmpxchg: { | 2873 case Intrinsics::AtomicCmpxchg: { |
2862 if (!Intrinsics::VerifyMemoryOrder( | 2874 if (!Intrinsics::isMemoryOrderValid( |
2863 llvm::cast<ConstantInteger32>(Instr->getArg(3))->getValue())) { | 2875 ID, getConstantMemoryOrder(Instr->getArg(3)), |
2864 Func->setError("Unexpected memory ordering (success) for AtomicCmpxchg"); | 2876 getConstantMemoryOrder(Instr->getArg(4)))) { |
2865 return; | 2877 Func->setError("Unexpected memory ordering for AtomicCmpxchg"); |
2866 } | |
2867 if (!Intrinsics::VerifyMemoryOrder( | |
2868 llvm::cast<ConstantInteger32>(Instr->getArg(4))->getValue())) { | |
2869 Func->setError("Unexpected memory ordering (failure) for AtomicCmpxchg"); | |
2870 return; | 2878 return; |
2871 } | 2879 } |
2872 Variable *DestPrev = Instr->getDest(); | 2880 Variable *DestPrev = Instr->getDest(); |
2873 Operand *PtrToMem = Instr->getArg(0); | 2881 Operand *PtrToMem = Instr->getArg(0); |
2874 Operand *Expected = Instr->getArg(1); | 2882 Operand *Expected = Instr->getArg(1); |
2875 Operand *Desired = Instr->getArg(2); | 2883 Operand *Desired = Instr->getArg(2); |
2876 if (tryOptimizedCmpxchgCmpBr(DestPrev, PtrToMem, Expected, Desired)) | 2884 if (tryOptimizedCmpxchgCmpBr(DestPrev, PtrToMem, Expected, Desired)) |
2877 return; | 2885 return; |
2878 lowerAtomicCmpxchg(DestPrev, PtrToMem, Expected, Desired); | 2886 lowerAtomicCmpxchg(DestPrev, PtrToMem, Expected, Desired); |
2879 return; | 2887 return; |
2880 } | 2888 } |
2881 case Intrinsics::AtomicFence: | 2889 case Intrinsics::AtomicFence: |
2882 if (!Intrinsics::VerifyMemoryOrder( | 2890 if (!Intrinsics::isMemoryOrderValid( |
2883 llvm::cast<ConstantInteger32>(Instr->getArg(0))->getValue())) { | 2891 ID, getConstantMemoryOrder(Instr->getArg(0)))) { |
2884 Func->setError("Unexpected memory ordering for AtomicFence"); | 2892 Func->setError("Unexpected memory ordering for AtomicFence"); |
2885 return; | 2893 return; |
2886 } | 2894 } |
2887 _mfence(); | 2895 _mfence(); |
2888 return; | 2896 return; |
2889 case Intrinsics::AtomicFenceAll: | 2897 case Intrinsics::AtomicFenceAll: |
2890 // NOTE: FenceAll should prevent and load/store from being moved | 2898 // NOTE: FenceAll should prevent and load/store from being moved |
2891 // across the fence (both atomic and non-atomic). The InstX8632Mfence | 2899 // across the fence (both atomic and non-atomic). The InstX8632Mfence |
2892 // instruction is currently marked coarsely as "HasSideEffects". | 2900 // instruction is currently marked coarsely as "HasSideEffects". |
2893 _mfence(); | 2901 _mfence(); |
(...skipping 24 matching lines...) Expand all Loading... |
2918 _mov(Dest, Result); | 2926 _mov(Dest, Result); |
2919 return; | 2927 return; |
2920 } | 2928 } |
2921 // The PNaCl ABI requires the byte size to be a compile-time constant. | 2929 // The PNaCl ABI requires the byte size to be a compile-time constant. |
2922 Func->setError("AtomicIsLockFree byte size should be compile-time const"); | 2930 Func->setError("AtomicIsLockFree byte size should be compile-time const"); |
2923 return; | 2931 return; |
2924 } | 2932 } |
2925 case Intrinsics::AtomicLoad: { | 2933 case Intrinsics::AtomicLoad: { |
2926 // We require the memory address to be naturally aligned. | 2934 // We require the memory address to be naturally aligned. |
2927 // Given that is the case, then normal loads are atomic. | 2935 // Given that is the case, then normal loads are atomic. |
2928 if (!Intrinsics::VerifyMemoryOrder( | 2936 if (!Intrinsics::isMemoryOrderValid( |
2929 llvm::cast<ConstantInteger32>(Instr->getArg(1))->getValue())) { | 2937 ID, getConstantMemoryOrder(Instr->getArg(1)))) { |
2930 Func->setError("Unexpected memory ordering for AtomicLoad"); | 2938 Func->setError("Unexpected memory ordering for AtomicLoad"); |
2931 return; | 2939 return; |
2932 } | 2940 } |
2933 Variable *Dest = Instr->getDest(); | 2941 Variable *Dest = Instr->getDest(); |
2934 if (Dest->getType() == IceType_i64) { | 2942 if (Dest->getType() == IceType_i64) { |
2935 // Follow what GCC does and use a movq instead of what lowerLoad() | 2943 // Follow what GCC does and use a movq instead of what lowerLoad() |
2936 // normally does (split the load into two). | 2944 // normally does (split the load into two). |
2937 // Thus, this skips load/arithmetic op folding. Load/arithmetic folding | 2945 // Thus, this skips load/arithmetic op folding. Load/arithmetic folding |
2938 // can't happen anyway, since this is x86-32 and integer arithmetic only | 2946 // can't happen anyway, since this is x86-32 and integer arithmetic only |
2939 // happens on 32-bit quantities. | 2947 // happens on 32-bit quantities. |
(...skipping 11 matching lines...) Expand all Loading... |
2951 InstLoad *Load = InstLoad::create(Func, Dest, Instr->getArg(0)); | 2959 InstLoad *Load = InstLoad::create(Func, Dest, Instr->getArg(0)); |
2952 lowerLoad(Load); | 2960 lowerLoad(Load); |
2953 // Make sure the atomic load isn't elided when unused, by adding a FakeUse. | 2961 // Make sure the atomic load isn't elided when unused, by adding a FakeUse. |
2954 // Since lowerLoad may fuse the load w/ an arithmetic instruction, | 2962 // Since lowerLoad may fuse the load w/ an arithmetic instruction, |
2955 // insert the FakeUse on the last-inserted instruction's dest. | 2963 // insert the FakeUse on the last-inserted instruction's dest. |
2956 Context.insert( | 2964 Context.insert( |
2957 InstFakeUse::create(Func, Context.getLastInserted()->getDest())); | 2965 InstFakeUse::create(Func, Context.getLastInserted()->getDest())); |
2958 return; | 2966 return; |
2959 } | 2967 } |
2960 case Intrinsics::AtomicRMW: | 2968 case Intrinsics::AtomicRMW: |
2961 if (!Intrinsics::VerifyMemoryOrder( | 2969 if (!Intrinsics::isMemoryOrderValid( |
2962 llvm::cast<ConstantInteger32>(Instr->getArg(3))->getValue())) { | 2970 ID, getConstantMemoryOrder(Instr->getArg(3)))) { |
2963 Func->setError("Unexpected memory ordering for AtomicRMW"); | 2971 Func->setError("Unexpected memory ordering for AtomicRMW"); |
2964 return; | 2972 return; |
2965 } | 2973 } |
2966 lowerAtomicRMW(Instr->getDest(), | 2974 lowerAtomicRMW(Instr->getDest(), |
2967 static_cast<uint32_t>(llvm::cast<ConstantInteger32>( | 2975 static_cast<uint32_t>(llvm::cast<ConstantInteger32>( |
2968 Instr->getArg(0))->getValue()), | 2976 Instr->getArg(0))->getValue()), |
2969 Instr->getArg(1), Instr->getArg(2)); | 2977 Instr->getArg(1), Instr->getArg(2)); |
2970 return; | 2978 return; |
2971 case Intrinsics::AtomicStore: { | 2979 case Intrinsics::AtomicStore: { |
2972 if (!Intrinsics::VerifyMemoryOrder( | 2980 if (!Intrinsics::isMemoryOrderValid( |
2973 llvm::cast<ConstantInteger32>(Instr->getArg(2))->getValue())) { | 2981 ID, getConstantMemoryOrder(Instr->getArg(2)))) { |
2974 Func->setError("Unexpected memory ordering for AtomicStore"); | 2982 Func->setError("Unexpected memory ordering for AtomicStore"); |
2975 return; | 2983 return; |
2976 } | 2984 } |
2977 // We require the memory address to be naturally aligned. | 2985 // We require the memory address to be naturally aligned. |
2978 // Given that is the case, then normal stores are atomic. | 2986 // Given that is the case, then normal stores are atomic. |
2979 // Add a fence after the store to make it visible. | 2987 // Add a fence after the store to make it visible. |
2980 Operand *Value = Instr->getArg(0); | 2988 Operand *Value = Instr->getArg(0); |
2981 Operand *Ptr = Instr->getArg(1); | 2989 Operand *Ptr = Instr->getArg(1); |
2982 if (Value->getType() == IceType_i64) { | 2990 if (Value->getType() == IceType_i64) { |
2983 // Use a movq instead of what lowerStore() normally does | 2991 // Use a movq instead of what lowerStore() normally does |
(...skipping 1494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4478 OperandX8632Mem *TargetX8632::FormMemoryOperand(Operand *Operand, Type Ty) { | 4486 OperandX8632Mem *TargetX8632::FormMemoryOperand(Operand *Operand, Type Ty) { |
4479 OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand); | 4487 OperandX8632Mem *Mem = llvm::dyn_cast<OperandX8632Mem>(Operand); |
4480 // It may be the case that address mode optimization already creates | 4488 // It may be the case that address mode optimization already creates |
4481 // an OperandX8632Mem, so in that case it wouldn't need another level | 4489 // an OperandX8632Mem, so in that case it wouldn't need another level |
4482 // of transformation. | 4490 // of transformation. |
4483 if (!Mem) { | 4491 if (!Mem) { |
4484 Variable *Base = llvm::dyn_cast<Variable>(Operand); | 4492 Variable *Base = llvm::dyn_cast<Variable>(Operand); |
4485 Constant *Offset = llvm::dyn_cast<Constant>(Operand); | 4493 Constant *Offset = llvm::dyn_cast<Constant>(Operand); |
4486 assert(Base || Offset); | 4494 assert(Base || Offset); |
4487 if (Offset) { | 4495 if (Offset) { |
| 4496 // Make sure Offset is not undef. |
| 4497 Offset = llvm::cast<Constant>(legalize(Offset)); |
4488 assert(llvm::isa<ConstantInteger32>(Offset) || | 4498 assert(llvm::isa<ConstantInteger32>(Offset) || |
4489 llvm::isa<ConstantRelocatable>(Offset)); | 4499 llvm::isa<ConstantRelocatable>(Offset)); |
4490 } | 4500 } |
4491 Mem = OperandX8632Mem::create(Func, Ty, Base, Offset); | 4501 Mem = OperandX8632Mem::create(Func, Ty, Base, Offset); |
4492 } | 4502 } |
4493 return llvm::cast<OperandX8632Mem>(legalize(Mem)); | 4503 return llvm::cast<OperandX8632Mem>(legalize(Mem)); |
4494 } | 4504 } |
4495 | 4505 |
4496 Variable *TargetX8632::makeReg(Type Type, int32_t RegNum) { | 4506 Variable *TargetX8632::makeReg(Type Type, int32_t RegNum) { |
4497 // There aren't any 64-bit integer registers for x86-32. | 4507 // There aren't any 64-bit integer registers for x86-32. |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4788 case FT_Asm: | 4798 case FT_Asm: |
4789 case FT_Iasm: { | 4799 case FT_Iasm: { |
4790 OstreamLocker L(Ctx); | 4800 OstreamLocker L(Ctx); |
4791 emitConstantPool<PoolTypeConverter<float>>(Ctx); | 4801 emitConstantPool<PoolTypeConverter<float>>(Ctx); |
4792 emitConstantPool<PoolTypeConverter<double>>(Ctx); | 4802 emitConstantPool<PoolTypeConverter<double>>(Ctx); |
4793 } break; | 4803 } break; |
4794 } | 4804 } |
4795 } | 4805 } |
4796 | 4806 |
4797 } // end of namespace Ice | 4807 } // end of namespace Ice |
OLD | NEW |