| 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 |