OLD | NEW |
1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===// | 1 //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 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 /// \file | 10 /// \file |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 CondARM32::Cond C1, C2; | 129 CondARM32::Cond C1, C2; |
130 } TableIcmp64[] = { | 130 } TableIcmp64[] = { |
131 #define X(val, is_signed, swapped64, C_32, C1_64, C2_64) \ | 131 #define X(val, is_signed, swapped64, C_32, C1_64, C2_64) \ |
132 { is_signed, swapped64, CondARM32::C1_64, CondARM32::C2_64 } \ | 132 { is_signed, swapped64, CondARM32::C1_64, CondARM32::C2_64 } \ |
133 , | 133 , |
134 ICMPARM32_TABLE | 134 ICMPARM32_TABLE |
135 #undef X | 135 #undef X |
136 }; | 136 }; |
137 | 137 |
138 CondARM32::Cond getIcmp32Mapping(InstIcmp::ICond Cond) { | 138 CondARM32::Cond getIcmp32Mapping(InstIcmp::ICond Cond) { |
139 size_t Index = static_cast<size_t>(Cond); | 139 assert(Cond < llvm::array_lengthof(TableIcmp32)); |
140 assert(Index < llvm::array_lengthof(TableIcmp32)); | 140 return TableIcmp32[Cond].Mapping; |
141 return TableIcmp32[Index].Mapping; | |
142 } | 141 } |
143 | 142 |
144 // In some cases, there are x-macros tables for both high-level and low-level | 143 // In some cases, there are x-macros tables for both high-level and low-level |
145 // instructions/operands that use the same enum key value. The tables are kept | 144 // instructions/operands that use the same enum key value. The tables are kept |
146 // separate to maintain a proper separation between abstraction layers. There | 145 // separate to maintain a proper separation between abstraction layers. There |
147 // is a risk that the tables could get out of sync if enum values are reordered | 146 // is a risk that the tables could get out of sync if enum values are reordered |
148 // or if entries are added or deleted. The following anonymous namespaces use | 147 // or if entries are added or deleted. The following anonymous namespaces use |
149 // static_asserts to ensure everything is kept in sync. | 148 // static_asserts to ensure everything is kept in sync. |
150 | 149 |
151 // Validate the enum values in ICMPARM32_TABLE. | 150 // Validate the enum values in ICMPARM32_TABLE. |
(...skipping 3793 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3945 if (Cond.WhenTrue1 != CondARM32::kNone) { | 3944 if (Cond.WhenTrue1 != CondARM32::kNone) { |
3946 _mov_redefined(T, _1, Cond.WhenTrue1); | 3945 _mov_redefined(T, _1, Cond.WhenTrue1); |
3947 } | 3946 } |
3948 | 3947 |
3949 _mov(Dest, T); | 3948 _mov(Dest, T); |
3950 } | 3949 } |
3951 | 3950 |
3952 TargetARM32::CondWhenTrue | 3951 TargetARM32::CondWhenTrue |
3953 TargetARM32::lowerInt64IcmpCond(InstIcmp::ICond Condition, Operand *Src0, | 3952 TargetARM32::lowerInt64IcmpCond(InstIcmp::ICond Condition, Operand *Src0, |
3954 Operand *Src1) { | 3953 Operand *Src1) { |
3955 size_t Index = static_cast<size_t>(Condition); | 3954 assert(Condition < llvm::array_lengthof(TableIcmp64)); |
3956 assert(Index < llvm::array_lengthof(TableIcmp64)); | |
3957 | 3955 |
3958 Int32Operands SrcsLo(loOperand(Src0), loOperand(Src1)); | 3956 Int32Operands SrcsLo(loOperand(Src0), loOperand(Src1)); |
3959 Int32Operands SrcsHi(hiOperand(Src0), hiOperand(Src1)); | 3957 Int32Operands SrcsHi(hiOperand(Src0), hiOperand(Src1)); |
3960 assert(SrcsLo.hasConstOperand() == SrcsHi.hasConstOperand()); | 3958 assert(SrcsLo.hasConstOperand() == SrcsHi.hasConstOperand()); |
3961 assert(SrcsLo.swappedOperands() == SrcsHi.swappedOperands()); | 3959 assert(SrcsLo.swappedOperands() == SrcsHi.swappedOperands()); |
3962 | 3960 |
3963 if (SrcsLo.hasConstOperand()) { | 3961 if (SrcsLo.hasConstOperand()) { |
3964 const uint32_t ValueLo = SrcsLo.getConstantValue(); | 3962 const uint32_t ValueLo = SrcsLo.getConstantValue(); |
3965 const uint32_t ValueHi = SrcsHi.getConstantValue(); | 3963 const uint32_t ValueHi = SrcsHi.getConstantValue(); |
3966 const uint64_t Value = (static_cast<uint64_t>(ValueHi) << 32) | ValueLo; | 3964 const uint64_t Value = (static_cast<uint64_t>(ValueHi) << 32) | ValueLo; |
3967 if ((Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) && | 3965 if ((Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) && |
3968 Value == 0) { | 3966 Value == 0) { |
3969 Variable *T = makeReg(IceType_i32); | 3967 Variable *T = makeReg(IceType_i32); |
3970 Variable *Src0LoR = SrcsLo.src0R(this); | 3968 Variable *Src0LoR = SrcsLo.src0R(this); |
3971 Variable *Src0HiR = SrcsHi.src0R(this); | 3969 Variable *Src0HiR = SrcsHi.src0R(this); |
3972 _orrs(T, Src0LoR, Src0HiR); | 3970 _orrs(T, Src0LoR, Src0HiR); |
3973 Context.insert<InstFakeUse>(T); | 3971 Context.insert<InstFakeUse>(T); |
3974 return CondWhenTrue(TableIcmp64[Index].C1); | 3972 return CondWhenTrue(TableIcmp64[Condition].C1); |
3975 } | 3973 } |
3976 | 3974 |
3977 Variable *Src0RLo = SrcsLo.src0R(this); | 3975 Variable *Src0RLo = SrcsLo.src0R(this); |
3978 Variable *Src0RHi = SrcsHi.src0R(this); | 3976 Variable *Src0RHi = SrcsHi.src0R(this); |
3979 Operand *Src1RFLo = SrcsLo.src1RF(this); | 3977 Operand *Src1RFLo = SrcsLo.src1RF(this); |
3980 Operand *Src1RFHi = ValueLo == ValueHi ? Src1RFLo : SrcsHi.src1RF(this); | 3978 Operand *Src1RFHi = ValueLo == ValueHi ? Src1RFLo : SrcsHi.src1RF(this); |
3981 | 3979 |
3982 const bool UseRsb = TableIcmp64[Index].Swapped != SrcsLo.swappedOperands(); | 3980 const bool UseRsb = |
| 3981 TableIcmp64[Condition].Swapped != SrcsLo.swappedOperands(); |
3983 | 3982 |
3984 if (UseRsb) { | 3983 if (UseRsb) { |
3985 if (TableIcmp64[Index].IsSigned) { | 3984 if (TableIcmp64[Condition].IsSigned) { |
3986 Variable *T = makeReg(IceType_i32); | 3985 Variable *T = makeReg(IceType_i32); |
3987 _rsbs(T, Src0RLo, Src1RFLo); | 3986 _rsbs(T, Src0RLo, Src1RFLo); |
3988 Context.insert<InstFakeUse>(T); | 3987 Context.insert<InstFakeUse>(T); |
3989 | 3988 |
3990 T = makeReg(IceType_i32); | 3989 T = makeReg(IceType_i32); |
3991 _rscs(T, Src0RHi, Src1RFHi); | 3990 _rscs(T, Src0RHi, Src1RFHi); |
3992 // We need to add a FakeUse here because liveness gets mad at us (Def | 3991 // We need to add a FakeUse here because liveness gets mad at us (Def |
3993 // without Use.) Note that flag-setting instructions are considered to | 3992 // without Use.) Note that flag-setting instructions are considered to |
3994 // have side effects and, therefore, are not DCE'ed. | 3993 // have side effects and, therefore, are not DCE'ed. |
3995 Context.insert<InstFakeUse>(T); | 3994 Context.insert<InstFakeUse>(T); |
3996 } else { | 3995 } else { |
3997 Variable *T = makeReg(IceType_i32); | 3996 Variable *T = makeReg(IceType_i32); |
3998 _rsbs(T, Src0RHi, Src1RFHi); | 3997 _rsbs(T, Src0RHi, Src1RFHi); |
3999 Context.insert<InstFakeUse>(T); | 3998 Context.insert<InstFakeUse>(T); |
4000 | 3999 |
4001 T = makeReg(IceType_i32); | 4000 T = makeReg(IceType_i32); |
4002 _rsbs(T, Src0RLo, Src1RFLo, CondARM32::EQ); | 4001 _rsbs(T, Src0RLo, Src1RFLo, CondARM32::EQ); |
4003 Context.insert<InstFakeUse>(T); | 4002 Context.insert<InstFakeUse>(T); |
4004 } | 4003 } |
4005 } else { | 4004 } else { |
4006 if (TableIcmp64[Index].IsSigned) { | 4005 if (TableIcmp64[Condition].IsSigned) { |
4007 _cmp(Src0RLo, Src1RFLo); | 4006 _cmp(Src0RLo, Src1RFLo); |
4008 Variable *T = makeReg(IceType_i32); | 4007 Variable *T = makeReg(IceType_i32); |
4009 _sbcs(T, Src0RHi, Src1RFHi); | 4008 _sbcs(T, Src0RHi, Src1RFHi); |
4010 Context.insert<InstFakeUse>(T); | 4009 Context.insert<InstFakeUse>(T); |
4011 } else { | 4010 } else { |
4012 _cmp(Src0RHi, Src1RFHi); | 4011 _cmp(Src0RHi, Src1RFHi); |
4013 _cmp(Src0RLo, Src1RFLo, CondARM32::EQ); | 4012 _cmp(Src0RLo, Src1RFLo, CondARM32::EQ); |
4014 } | 4013 } |
4015 } | 4014 } |
4016 | 4015 |
4017 return CondWhenTrue(TableIcmp64[Index].C1); | 4016 return CondWhenTrue(TableIcmp64[Condition].C1); |
4018 } | 4017 } |
4019 | 4018 |
4020 Variable *Src0RLo, *Src0RHi; | 4019 Variable *Src0RLo, *Src0RHi; |
4021 Operand *Src1RFLo, *Src1RFHi; | 4020 Operand *Src1RFLo, *Src1RFHi; |
4022 if (TableIcmp64[Index].Swapped) { | 4021 if (TableIcmp64[Condition].Swapped) { |
4023 Src0RLo = legalizeToReg(loOperand(Src1)); | 4022 Src0RLo = legalizeToReg(loOperand(Src1)); |
4024 Src0RHi = legalizeToReg(hiOperand(Src1)); | 4023 Src0RHi = legalizeToReg(hiOperand(Src1)); |
4025 Src1RFLo = legalizeToReg(loOperand(Src0)); | 4024 Src1RFLo = legalizeToReg(loOperand(Src0)); |
4026 Src1RFHi = legalizeToReg(hiOperand(Src0)); | 4025 Src1RFHi = legalizeToReg(hiOperand(Src0)); |
4027 } else { | 4026 } else { |
4028 Src0RLo = legalizeToReg(loOperand(Src0)); | 4027 Src0RLo = legalizeToReg(loOperand(Src0)); |
4029 Src0RHi = legalizeToReg(hiOperand(Src0)); | 4028 Src0RHi = legalizeToReg(hiOperand(Src0)); |
4030 Src1RFLo = legalizeToReg(loOperand(Src1)); | 4029 Src1RFLo = legalizeToReg(loOperand(Src1)); |
4031 Src1RFHi = legalizeToReg(hiOperand(Src1)); | 4030 Src1RFHi = legalizeToReg(hiOperand(Src1)); |
4032 } | 4031 } |
(...skipping 20 matching lines...) Expand all Loading... |
4053 // that's nice in that it's just as short but has fewer dependencies for | 4052 // that's nice in that it's just as short but has fewer dependencies for |
4054 // better ILP at the cost of more registers. | 4053 // better ILP at the cost of more registers. |
4055 // | 4054 // |
4056 // Otherwise for signed/unsigned <, <=, etc. LLVM uses a sequence with two | 4055 // Otherwise for signed/unsigned <, <=, etc. LLVM uses a sequence with two |
4057 // unconditional mov #0, two cmps, two conditional mov #1, and one | 4056 // unconditional mov #0, two cmps, two conditional mov #1, and one |
4058 // conditional reg mov. That has few dependencies for good ILP, but is a | 4057 // conditional reg mov. That has few dependencies for good ILP, but is a |
4059 // longer sequence. | 4058 // longer sequence. |
4060 // | 4059 // |
4061 // So, we are going with the GCC version since it's usually better (except | 4060 // So, we are going with the GCC version since it's usually better (except |
4062 // perhaps for eq/ne). We could revisit special-casing eq/ne later. | 4061 // perhaps for eq/ne). We could revisit special-casing eq/ne later. |
4063 if (TableIcmp64[Index].IsSigned) { | 4062 if (TableIcmp64[Condition].IsSigned) { |
4064 Variable *ScratchReg = makeReg(IceType_i32); | 4063 Variable *ScratchReg = makeReg(IceType_i32); |
4065 _cmp(Src0RLo, Src1RFLo); | 4064 _cmp(Src0RLo, Src1RFLo); |
4066 _sbcs(ScratchReg, Src0RHi, Src1RFHi); | 4065 _sbcs(ScratchReg, Src0RHi, Src1RFHi); |
4067 // ScratchReg isn't going to be used, but we need the side-effect of | 4066 // ScratchReg isn't going to be used, but we need the side-effect of |
4068 // setting flags from this operation. | 4067 // setting flags from this operation. |
4069 Context.insert<InstFakeUse>(ScratchReg); | 4068 Context.insert<InstFakeUse>(ScratchReg); |
4070 } else { | 4069 } else { |
4071 _cmp(Src0RHi, Src1RFHi); | 4070 _cmp(Src0RHi, Src1RFHi); |
4072 _cmp(Src0RLo, Src1RFLo, CondARM32::EQ); | 4071 _cmp(Src0RLo, Src1RFLo, CondARM32::EQ); |
4073 } | 4072 } |
4074 return CondWhenTrue(TableIcmp64[Index].C1); | 4073 return CondWhenTrue(TableIcmp64[Condition].C1); |
4075 } | 4074 } |
4076 | 4075 |
4077 TargetARM32::CondWhenTrue | 4076 TargetARM32::CondWhenTrue |
4078 TargetARM32::lowerInt32IcmpCond(InstIcmp::ICond Condition, Operand *Src0, | 4077 TargetARM32::lowerInt32IcmpCond(InstIcmp::ICond Condition, Operand *Src0, |
4079 Operand *Src1) { | 4078 Operand *Src1) { |
4080 Int32Operands Srcs(Src0, Src1); | 4079 Int32Operands Srcs(Src0, Src1); |
4081 if (!Srcs.hasConstOperand()) { | 4080 if (!Srcs.hasConstOperand()) { |
4082 | 4081 |
4083 Variable *Src0R = Srcs.src0R(this); | 4082 Variable *Src0R = Srcs.src0R(this); |
4084 Operand *Src1RF = Srcs.src1RF(this); | 4083 Operand *Src1RF = Srcs.src1RF(this); |
(...skipping 2439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6524 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 6523 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
6525 } | 6524 } |
6526 | 6525 |
6527 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM]; | 6526 llvm::SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM]; |
6528 llvm::SmallBitVector | 6527 llvm::SmallBitVector |
6529 TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; | 6528 TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; |
6530 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 6529 llvm::SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
6531 | 6530 |
6532 } // end of namespace ARM32 | 6531 } // end of namespace ARM32 |
6533 } // end of namespace Ice | 6532 } // end of namespace Ice |
OLD | NEW |