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 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 | 117 |
118 namespace { | 118 namespace { |
119 | 119 |
120 // The following table summarizes the logic for lowering the icmp instruction | 120 // The following table summarizes the logic for lowering the icmp instruction |
121 // for i32 and narrower types. Each icmp condition has a clear mapping to an | 121 // for i32 and narrower types. Each icmp condition has a clear mapping to an |
122 // ARM32 conditional move instruction. | 122 // ARM32 conditional move instruction. |
123 | 123 |
124 const struct TableIcmp32_ { | 124 const struct TableIcmp32_ { |
125 CondARM32::Cond Mapping; | 125 CondARM32::Cond Mapping; |
126 } TableIcmp32[] = { | 126 } TableIcmp32[] = { |
127 #define X(val, is_signed, swapped64, C_32, C1_64, C2_64) \ | 127 #define X(val, is_signed, swapped64, C_32, C1_64, C2_64, C_V, INV_V, NEG_V) \ |
128 { CondARM32::C_32 } \ | 128 { CondARM32::C_32 } \ |
129 , | 129 , |
130 ICMPARM32_TABLE | 130 ICMPARM32_TABLE |
131 #undef X | 131 #undef X |
132 }; | 132 }; |
133 | 133 |
134 // The following table summarizes the logic for lowering the icmp instruction | 134 // The following table summarizes the logic for lowering the icmp instruction |
135 // for the i64 type. Two conditional moves are needed for setting to 1 or 0. | 135 // for the i64 type. Two conditional moves are needed for setting to 1 or 0. |
136 // The operands may need to be swapped, and there is a slight difference for | 136 // The operands may need to be swapped, and there is a slight difference for |
137 // signed vs unsigned (comparing hi vs lo first, and using cmp vs sbc). | 137 // signed vs unsigned (comparing hi vs lo first, and using cmp vs sbc). |
138 const struct TableIcmp64_ { | 138 const struct TableIcmp64_ { |
139 bool IsSigned; | 139 bool IsSigned; |
140 bool Swapped; | 140 bool Swapped; |
141 CondARM32::Cond C1, C2; | 141 CondARM32::Cond C1, C2; |
142 } TableIcmp64[] = { | 142 } TableIcmp64[] = { |
143 #define X(val, is_signed, swapped64, C_32, C1_64, C2_64) \ | 143 #define X(val, is_signed, swapped64, C_32, C1_64, C2_64, C_V, INV_V, NEG_V) \ |
144 { is_signed, swapped64, CondARM32::C1_64, CondARM32::C2_64 } \ | 144 { is_signed, swapped64, CondARM32::C1_64, CondARM32::C2_64 } \ |
145 , | 145 , |
146 ICMPARM32_TABLE | 146 ICMPARM32_TABLE |
147 #undef X | 147 #undef X |
148 }; | 148 }; |
149 | 149 |
150 CondARM32::Cond getIcmp32Mapping(InstIcmp::ICond Cond) { | 150 CondARM32::Cond getIcmp32Mapping(InstIcmp::ICond Cond) { |
151 assert(Cond < llvm::array_lengthof(TableIcmp32)); | 151 assert(Cond < llvm::array_lengthof(TableIcmp32)); |
152 return TableIcmp32[Cond].Mapping; | 152 return TableIcmp32[Cond].Mapping; |
153 } | 153 } |
154 | 154 |
155 // In some cases, there are x-macros tables for both high-level and low-level | 155 // In some cases, there are x-macros tables for both high-level and low-level |
156 // instructions/operands that use the same enum key value. The tables are kept | 156 // instructions/operands that use the same enum key value. The tables are kept |
157 // separate to maintain a proper separation between abstraction layers. There | 157 // separate to maintain a proper separation between abstraction layers. There |
158 // is a risk that the tables could get out of sync if enum values are reordered | 158 // is a risk that the tables could get out of sync if enum values are reordered |
159 // or if entries are added or deleted. The following anonymous namespaces use | 159 // or if entries are added or deleted. The following anonymous namespaces use |
160 // static_asserts to ensure everything is kept in sync. | 160 // static_asserts to ensure everything is kept in sync. |
161 | 161 |
162 // Validate the enum values in ICMPARM32_TABLE. | 162 // Validate the enum values in ICMPARM32_TABLE. |
163 namespace { | 163 namespace { |
164 // Define a temporary set of enum values based on low-level table entries. | 164 // Define a temporary set of enum values based on low-level table entries. |
165 enum _icmp_ll_enum { | 165 enum _icmp_ll_enum { |
166 #define X(val, signed, swapped64, C_32, C1_64, C2_64) _icmp_ll_##val, | 166 #define X(val, is_signed, swapped64, C_32, C1_64, C2_64, C_V, INV_V, NEG_V) \ |
| 167 _icmp_ll_##val, |
167 ICMPARM32_TABLE | 168 ICMPARM32_TABLE |
168 #undef X | 169 #undef X |
169 _num | 170 _num |
170 }; | 171 }; |
171 // Define a set of constants based on high-level table entries. | 172 // Define a set of constants based on high-level table entries. |
172 #define X(tag, str) static constexpr int _icmp_hl_##tag = InstIcmp::tag; | 173 #define X(tag, str) static constexpr int _icmp_hl_##tag = InstIcmp::tag; |
173 ICEINSTICMP_TABLE | 174 ICEINSTICMP_TABLE |
174 #undef X | 175 #undef X |
175 // Define a set of constants based on low-level table entries, and ensure the | 176 // Define a set of constants based on low-level table entries, and ensure the |
176 // table entry keys are consistent. | 177 // table entry keys are consistent. |
177 #define X(val, signed, swapped64, C_32, C1_64, C2_64) \ | 178 #define X(val, is_signed, swapped64, C_32, C1_64, C2_64, C_V, INV_V, NEG_V) \ |
178 static_assert( \ | 179 static_assert( \ |
179 _icmp_ll_##val == _icmp_hl_##val, \ | 180 _icmp_ll_##val == _icmp_hl_##val, \ |
180 "Inconsistency between ICMPARM32_TABLE and ICEINSTICMP_TABLE: " #val); | 181 "Inconsistency between ICMPARM32_TABLE and ICEINSTICMP_TABLE: " #val); |
181 ICMPARM32_TABLE | 182 ICMPARM32_TABLE |
182 #undef X | 183 #undef X |
183 // Repeat the static asserts with respect to the high-level table entries in | 184 // Repeat the static asserts with respect to the high-level table entries in |
184 // case the high-level table has extra entries. | 185 // case the high-level table has extra entries. |
185 #define X(tag, str) \ | 186 #define X(tag, str) \ |
186 static_assert( \ | 187 static_assert( \ |
187 _icmp_hl_##tag == _icmp_ll_##tag, \ | 188 _icmp_hl_##tag == _icmp_ll_##tag, \ |
(...skipping 634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
822 Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_setjmp); | 823 Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_setjmp); |
823 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, | 824 auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper, |
824 NoTailCall, IsTargetHelperCall); | 825 NoTailCall, IsTargetHelperCall); |
825 Call->addArg(IntrinsicCall->getArg(0)); | 826 Call->addArg(IntrinsicCall->getArg(0)); |
826 Instr->setDeleted(); | 827 Instr->setDeleted(); |
827 return; | 828 return; |
828 } | 829 } |
829 } | 830 } |
830 llvm::report_fatal_error("Control flow should never have reached here."); | 831 llvm::report_fatal_error("Control flow should never have reached here."); |
831 } | 832 } |
832 case Inst::Icmp: { | |
833 Variable *Dest = Instr->getDest(); | |
834 const Type DestTy = Dest->getType(); | |
835 if (isVectorType(DestTy)) { | |
836 auto *CmpInstr = llvm::cast<InstIcmp>(Instr); | |
837 const auto Condition = CmpInstr->getCondition(); | |
838 scalarizeInstruction( | |
839 Dest, | |
840 [this, Condition](Variable *Dest, Variable *Src0, Variable *Src1) { | |
841 return Context.insert<InstIcmp>(Condition, Dest, Src0, Src1); | |
842 }, | |
843 CmpInstr->getSrc(0), CmpInstr->getSrc(1)); | |
844 CmpInstr->setDeleted(); | |
845 } | |
846 return; | |
847 } | |
848 case Inst::Fcmp: { | |
849 Variable *Dest = Instr->getDest(); | |
850 const Type DestTy = Dest->getType(); | |
851 if (isVectorType(DestTy)) { | |
852 auto *CmpInstr = llvm::cast<InstFcmp>(Instr); | |
853 const auto Condition = CmpInstr->getCondition(); | |
854 scalarizeInstruction( | |
855 Dest, | |
856 [this, Condition](Variable *Dest, Variable *Src0, Variable *Src1) { | |
857 return Context.insert<InstFcmp>(Condition, Dest, Src0, Src1); | |
858 }, | |
859 CmpInstr->getSrc(0), CmpInstr->getSrc(1)); | |
860 CmpInstr->setDeleted(); | |
861 } | |
862 return; | |
863 } | |
864 } | 833 } |
865 } | 834 } |
866 | 835 |
867 void TargetARM32::findMaxStackOutArgsSize() { | 836 void TargetARM32::findMaxStackOutArgsSize() { |
868 // MinNeededOutArgsBytes should be updated if the Target ever creates a | 837 // MinNeededOutArgsBytes should be updated if the Target ever creates a |
869 // high-level InstCall that requires more stack bytes. | 838 // high-level InstCall that requires more stack bytes. |
870 constexpr size_t MinNeededOutArgsBytes = 0; | 839 constexpr size_t MinNeededOutArgsBytes = 0; |
871 MaxOutArgsSizeBytes = MinNeededOutArgsBytes; | 840 MaxOutArgsSizeBytes = MinNeededOutArgsBytes; |
872 for (CfgNode *Node : Func->getNodes()) { | 841 for (CfgNode *Node : Func->getNodes()) { |
873 Context.init(Node); | 842 Context.init(Node); |
(...skipping 3370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4244 _mov(Dest, T); | 4213 _mov(Dest, T); |
4245 return; | 4214 return; |
4246 } | 4215 } |
4247 assert(false && "extractelement requires a constant index"); | 4216 assert(false && "extractelement requires a constant index"); |
4248 } | 4217 } |
4249 | 4218 |
4250 namespace { | 4219 namespace { |
4251 // Validates FCMPARM32_TABLE's declaration w.r.t. InstFcmp::FCondition ordering | 4220 // Validates FCMPARM32_TABLE's declaration w.r.t. InstFcmp::FCondition ordering |
4252 // (and naming). | 4221 // (and naming). |
4253 enum { | 4222 enum { |
4254 #define X(val, CC0, CC1) _fcmp_ll_##val, | 4223 #define X(val, CC0, CC1, CC0_V, CC1_V, INV_V, NEG_V) _fcmp_ll_##val, |
4255 FCMPARM32_TABLE | 4224 FCMPARM32_TABLE |
4256 #undef X | 4225 #undef X |
4257 _fcmp_ll_NUM | 4226 _fcmp_ll_NUM |
4258 }; | 4227 }; |
4259 | 4228 |
4260 enum { | 4229 enum { |
4261 #define X(tag, str) _fcmp_hl_##tag = InstFcmp::tag, | 4230 #define X(tag, str) _fcmp_hl_##tag = InstFcmp::tag, |
4262 ICEINSTFCMP_TABLE | 4231 ICEINSTFCMP_TABLE |
4263 #undef X | 4232 #undef X |
4264 _fcmp_hl_NUM | 4233 _fcmp_hl_NUM |
4265 }; | 4234 }; |
4266 | 4235 |
4267 static_assert((uint32_t)_fcmp_hl_NUM == (uint32_t)_fcmp_ll_NUM, | 4236 static_assert((uint32_t)_fcmp_hl_NUM == (uint32_t)_fcmp_ll_NUM, |
4268 "Inconsistency between high-level and low-level fcmp tags."); | 4237 "Inconsistency between high-level and low-level fcmp tags."); |
4269 #define X(tag, str) \ | 4238 #define X(tag, str) \ |
4270 static_assert( \ | 4239 static_assert( \ |
4271 (uint32_t)_fcmp_hl_##tag == (uint32_t)_fcmp_ll_##tag, \ | 4240 (uint32_t)_fcmp_hl_##tag == (uint32_t)_fcmp_ll_##tag, \ |
4272 "Inconsistency between high-level and low-level fcmp tag " #tag); | 4241 "Inconsistency between high-level and low-level fcmp tag " #tag); |
4273 ICEINSTFCMP_TABLE | 4242 ICEINSTFCMP_TABLE |
4274 #undef X | 4243 #undef X |
4275 | 4244 |
4276 struct { | 4245 struct { |
4277 CondARM32::Cond CC0; | 4246 CondARM32::Cond CC0; |
4278 CondARM32::Cond CC1; | 4247 CondARM32::Cond CC1; |
4279 } TableFcmp[] = { | 4248 } TableFcmp[] = { |
4280 #define X(val, CC0, CC1) \ | 4249 #define X(val, CC0, CC1, CC0_V, CC1_V, INV_V, NEG_V) \ |
4281 { CondARM32::CC0, CondARM32::CC1 } \ | 4250 { CondARM32::CC0, CondARM32::CC1 } \ |
4282 , | 4251 , |
4283 FCMPARM32_TABLE | 4252 FCMPARM32_TABLE |
4284 #undef X | 4253 #undef X |
4285 }; | 4254 }; |
4286 | 4255 |
4287 bool isFloatingPointZero(const Operand *Src) { | 4256 bool isFloatingPointZero(const Operand *Src) { |
4288 if (const auto *F32 = llvm::dyn_cast<const ConstantFloat>(Src)) { | 4257 if (const auto *F32 = llvm::dyn_cast<const ConstantFloat>(Src)) { |
4289 return Utils::isPositiveZero(F32->getValue()); | 4258 return Utils::isPositiveZero(F32->getValue()); |
4290 } | 4259 } |
(...skipping 24 matching lines...) Expand all Loading... |
4315 } | 4284 } |
4316 _vmrs(); | 4285 _vmrs(); |
4317 assert(Condition < llvm::array_lengthof(TableFcmp)); | 4286 assert(Condition < llvm::array_lengthof(TableFcmp)); |
4318 return CondWhenTrue(TableFcmp[Condition].CC0, TableFcmp[Condition].CC1); | 4287 return CondWhenTrue(TableFcmp[Condition].CC0, TableFcmp[Condition].CC1); |
4319 } | 4288 } |
4320 } | 4289 } |
4321 } | 4290 } |
4322 | 4291 |
4323 void TargetARM32::lowerFcmp(const InstFcmp *Instr) { | 4292 void TargetARM32::lowerFcmp(const InstFcmp *Instr) { |
4324 Variable *Dest = Instr->getDest(); | 4293 Variable *Dest = Instr->getDest(); |
4325 if (isVectorType(Dest->getType())) { | 4294 const Type DestTy = Dest->getType(); |
4326 UnimplementedLoweringError(this, Instr); | 4295 |
| 4296 if (isVectorType(DestTy)) { |
| 4297 if (Instr->getCondition() == InstFcmp::False) { |
| 4298 constexpr Type SafeTypeForMovingConstant = IceType_v4i32; |
| 4299 auto *T = makeReg(SafeTypeForMovingConstant); |
| 4300 _mov(T, llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0))); |
| 4301 _mov(Dest, T); |
| 4302 return; |
| 4303 } |
| 4304 |
| 4305 if (Instr->getCondition() == InstFcmp::True) { |
| 4306 constexpr Type SafeTypeForMovingConstant = IceType_v4i32; |
| 4307 auto *T = makeReg(SafeTypeForMovingConstant); |
| 4308 _mov(T, llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(1))); |
| 4309 _mov(Dest, T); |
| 4310 return; |
| 4311 } |
| 4312 |
| 4313 Variable *T0; |
| 4314 Variable *T1; |
| 4315 bool Negate = false; |
| 4316 auto *Src0 = legalizeToReg(Instr->getSrc(0)); |
| 4317 auto *Src1 = legalizeToReg(Instr->getSrc(1)); |
| 4318 |
| 4319 switch (Instr->getCondition()) { |
| 4320 default: |
| 4321 llvm::report_fatal_error("Unhandled fp comparison."); |
| 4322 #define _Vcnone(Tptr, S0, S1) \ |
| 4323 do { \ |
| 4324 *(Tptr) = nullptr; \ |
| 4325 } while (0) |
| 4326 #define _Vceq(Tptr, S0, S1) \ |
| 4327 do { \ |
| 4328 *(Tptr) = makeReg(DestTy); \ |
| 4329 _vceq(*(Tptr), S0, S1); \ |
| 4330 } while (0) |
| 4331 #define _Vcge(Tptr, S0, S1) \ |
| 4332 do { \ |
| 4333 *(Tptr) = makeReg(DestTy); \ |
| 4334 _vcge(*(Tptr), S0, S1)->setSignType(InstARM32::FS_Signed); \ |
| 4335 } while (0) |
| 4336 #define _Vcgt(Tptr, S0, S1) \ |
| 4337 do { \ |
| 4338 *(Tptr) = makeReg(DestTy); \ |
| 4339 _vcgt(*(Tptr), S0, S1)->setSignType(InstARM32::FS_Signed); \ |
| 4340 } while (0) |
| 4341 #define X(val, CC0, CC1, CC0_V, CC1_V, INV_V, NEG_V) \ |
| 4342 case InstFcmp::val: { \ |
| 4343 _Vc##CC0_V(&T0, (INV_V) ? Src1 : Src0, (INV_V) ? Src0 : Src1); \ |
| 4344 _Vc##CC1_V(&T1, (INV_V) ? Src0 : Src1, (INV_V) ? Src1 : Src0); \ |
| 4345 Negate = NEG_V; \ |
| 4346 } break; |
| 4347 FCMPARM32_TABLE |
| 4348 #undef X |
| 4349 #undef _Vcgt |
| 4350 #undef _Vcge |
| 4351 #undef _Vceq |
| 4352 #undef _Vcnone |
| 4353 } |
| 4354 assert(T0 != nullptr); |
| 4355 Variable *T = T0; |
| 4356 if (T1 != nullptr) { |
| 4357 T = makeReg(DestTy); |
| 4358 _vorr(T, T0, T1); |
| 4359 } |
| 4360 |
| 4361 if (Negate) { |
| 4362 auto *TNeg = makeReg(DestTy); |
| 4363 _vmvn(TNeg, T); |
| 4364 T = TNeg; |
| 4365 } |
| 4366 |
| 4367 _mov(Dest, T); |
4327 return; | 4368 return; |
4328 } | 4369 } |
4329 | 4370 |
4330 Variable *T = makeReg(IceType_i1); | 4371 Variable *T = makeReg(IceType_i1); |
4331 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); | 4372 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); |
4332 Operand *_0 = | 4373 Operand *_0 = |
4333 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); | 4374 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
4334 | 4375 |
4335 CondWhenTrue Cond = lowerFcmpCond(Instr); | 4376 CondWhenTrue Cond = lowerFcmpCond(Instr); |
4336 | 4377 |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4614 return lowerInt8AndInt16IcmpCond(Condition, Src0, Src1); | 4655 return lowerInt8AndInt16IcmpCond(Condition, Src0, Src1); |
4615 case IceType_i32: | 4656 case IceType_i32: |
4616 return lowerInt32IcmpCond(Condition, Src0, Src1); | 4657 return lowerInt32IcmpCond(Condition, Src0, Src1); |
4617 case IceType_i64: | 4658 case IceType_i64: |
4618 return lowerInt64IcmpCond(Condition, Src0, Src1); | 4659 return lowerInt64IcmpCond(Condition, Src0, Src1); |
4619 } | 4660 } |
4620 } | 4661 } |
4621 | 4662 |
4622 void TargetARM32::lowerIcmp(const InstIcmp *Instr) { | 4663 void TargetARM32::lowerIcmp(const InstIcmp *Instr) { |
4623 Variable *Dest = Instr->getDest(); | 4664 Variable *Dest = Instr->getDest(); |
| 4665 const Type DestTy = Dest->getType(); |
4624 | 4666 |
4625 if (isVectorType(Dest->getType())) { | 4667 if (isVectorType(DestTy)) { |
4626 UnimplementedLoweringError(this, Instr); | 4668 auto *T = makeReg(DestTy); |
| 4669 auto *Src0 = legalizeToReg(Instr->getSrc(0)); |
| 4670 auto *Src1 = legalizeToReg(Instr->getSrc(1)); |
| 4671 const Type SrcTy = Src0->getType(); |
| 4672 |
| 4673 bool NeedsShl = false; |
| 4674 Type NewTypeAfterShl; |
| 4675 SizeT ShAmt; |
| 4676 switch (SrcTy) { |
| 4677 default: |
| 4678 break; |
| 4679 case IceType_v16i1: |
| 4680 NeedsShl = true; |
| 4681 NewTypeAfterShl = IceType_v16i8; |
| 4682 ShAmt = 7; |
| 4683 break; |
| 4684 case IceType_v8i1: |
| 4685 NeedsShl = true; |
| 4686 NewTypeAfterShl = IceType_v8i16; |
| 4687 ShAmt = 15; |
| 4688 break; |
| 4689 case IceType_v4i1: |
| 4690 NeedsShl = true; |
| 4691 NewTypeAfterShl = IceType_v4i32; |
| 4692 ShAmt = 31; |
| 4693 break; |
| 4694 } |
| 4695 |
| 4696 if (NeedsShl) { |
| 4697 auto *Imm = llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(ShAmt)); |
| 4698 auto *Src0T = makeReg(NewTypeAfterShl); |
| 4699 auto *Src0Shl = makeReg(NewTypeAfterShl); |
| 4700 _mov(Src0T, Src0); |
| 4701 _vshl(Src0Shl, Src0T, Imm); |
| 4702 Src0 = Src0Shl; |
| 4703 |
| 4704 auto *Src1T = makeReg(NewTypeAfterShl); |
| 4705 auto *Src1Shl = makeReg(NewTypeAfterShl); |
| 4706 _mov(Src1T, Src1); |
| 4707 _vshl(Src1Shl, Src1T, Imm); |
| 4708 Src1 = Src1Shl; |
| 4709 } |
| 4710 |
| 4711 switch (Instr->getCondition()) { |
| 4712 default: |
| 4713 llvm::report_fatal_error("Unhandled integer comparison."); |
| 4714 #define _Vceq(T, S0, S1, Signed) _vceq(T, S0, S1) |
| 4715 #define _Vcge(T, S0, S1, Signed) \ |
| 4716 _vcge(T, S0, S1) \ |
| 4717 ->setSignType(Signed ? InstARM32::FS_Signed : InstARM32::FS_Unsigned) |
| 4718 #define _Vcgt(T, S0, S1, Signed) \ |
| 4719 _vcgt(T, S0, S1) \ |
| 4720 ->setSignType(Signed ? InstARM32::FS_Signed : InstARM32::FS_Unsigned) |
| 4721 #define X(val, is_signed, swapped64, C_32, C1_64, C2_64, C_V, INV_V, NEG_V) \ |
| 4722 case InstIcmp::val: { \ |
| 4723 _Vc##C_V(T, (INV_V) ? Src1 : Src0, (INV_V) ? Src0 : Src1, is_signed); \ |
| 4724 if (NEG_V) { \ |
| 4725 auto *TInv = makeReg(DestTy); \ |
| 4726 _vmvn(TInv, T); \ |
| 4727 T = TInv; \ |
| 4728 } \ |
| 4729 } break; |
| 4730 ICMPARM32_TABLE |
| 4731 #undef X |
| 4732 #undef _Vcgt |
| 4733 #undef _Vcge |
| 4734 #undef _Vceq |
| 4735 } |
| 4736 _mov(Dest, T); |
4627 return; | 4737 return; |
4628 } | 4738 } |
4629 | 4739 |
4630 Operand *_0 = | 4740 Operand *_0 = |
4631 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); | 4741 legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex); |
4632 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); | 4742 Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex); |
4633 Variable *T = makeReg(IceType_i1); | 4743 Variable *T = makeReg(IceType_i1); |
4634 | 4744 |
4635 _mov(T, _0); | 4745 _mov(T, _0); |
4636 CondWhenTrue Cond = lowerIcmpCond(Instr); | 4746 CondWhenTrue Cond = lowerIcmpCond(Instr); |
(...skipping 2357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6994 // However, for compatibility with current NaCl LLVM, don't claim that. | 7104 // However, for compatibility with current NaCl LLVM, don't claim that. |
6995 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; | 7105 Str << ".eabi_attribute 14, 3 @ Tag_ABI_PCS_R9_use: Not used\n"; |
6996 } | 7106 } |
6997 | 7107 |
6998 SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM]; | 7108 SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM]; |
6999 SmallBitVector TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; | 7109 SmallBitVector TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM]; |
7000 SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; | 7110 SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM]; |
7001 | 7111 |
7002 } // end of namespace ARM32 | 7112 } // end of namespace ARM32 |
7003 } // end of namespace Ice | 7113 } // end of namespace Ice |
OLD | NEW |