xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceTargetLoweringARM32.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceTargetLoweringARM32.cpp - ARM32 lowering ------------===//
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker //                        The Subzero Code Generator
4*03ce13f7SAndroid Build Coastguard Worker //
5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*03ce13f7SAndroid Build Coastguard Worker //
8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*03ce13f7SAndroid Build Coastguard Worker ///
10*03ce13f7SAndroid Build Coastguard Worker /// \file
11*03ce13f7SAndroid Build Coastguard Worker /// \brief Implements the TargetLoweringARM32 class, which consists almost
12*03ce13f7SAndroid Build Coastguard Worker /// entirely of the lowering sequence for each high-level instruction.
13*03ce13f7SAndroid Build Coastguard Worker ///
14*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*03ce13f7SAndroid Build Coastguard Worker #include "IceTargetLoweringARM32.h"
16*03ce13f7SAndroid Build Coastguard Worker 
17*03ce13f7SAndroid Build Coastguard Worker #include "IceCfg.h"
18*03ce13f7SAndroid Build Coastguard Worker #include "IceCfgNode.h"
19*03ce13f7SAndroid Build Coastguard Worker #include "IceClFlags.h"
20*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h"
21*03ce13f7SAndroid Build Coastguard Worker #include "IceELFObjectWriter.h"
22*03ce13f7SAndroid Build Coastguard Worker #include "IceGlobalInits.h"
23*03ce13f7SAndroid Build Coastguard Worker #include "IceInstARM32.def"
24*03ce13f7SAndroid Build Coastguard Worker #include "IceInstARM32.h"
25*03ce13f7SAndroid Build Coastguard Worker #include "IceInstVarIter.h"
26*03ce13f7SAndroid Build Coastguard Worker #include "IceLiveness.h"
27*03ce13f7SAndroid Build Coastguard Worker #include "IceOperand.h"
28*03ce13f7SAndroid Build Coastguard Worker #include "IcePhiLoweringImpl.h"
29*03ce13f7SAndroid Build Coastguard Worker #include "IceRegistersARM32.h"
30*03ce13f7SAndroid Build Coastguard Worker #include "IceTargetLoweringARM32.def"
31*03ce13f7SAndroid Build Coastguard Worker #include "IceUtils.h"
32*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/MathExtras.h"
33*03ce13f7SAndroid Build Coastguard Worker 
34*03ce13f7SAndroid Build Coastguard Worker #include <algorithm>
35*03ce13f7SAndroid Build Coastguard Worker #include <array>
36*03ce13f7SAndroid Build Coastguard Worker #include <utility>
37*03ce13f7SAndroid Build Coastguard Worker 
38*03ce13f7SAndroid Build Coastguard Worker namespace ARM32 {
createTargetLowering(::Ice::Cfg * Func)39*03ce13f7SAndroid Build Coastguard Worker std::unique_ptr<::Ice::TargetLowering> createTargetLowering(::Ice::Cfg *Func) {
40*03ce13f7SAndroid Build Coastguard Worker   return ::Ice::ARM32::TargetARM32::create(Func);
41*03ce13f7SAndroid Build Coastguard Worker }
42*03ce13f7SAndroid Build Coastguard Worker 
43*03ce13f7SAndroid Build Coastguard Worker std::unique_ptr<::Ice::TargetDataLowering>
createTargetDataLowering(::Ice::GlobalContext * Ctx)44*03ce13f7SAndroid Build Coastguard Worker createTargetDataLowering(::Ice::GlobalContext *Ctx) {
45*03ce13f7SAndroid Build Coastguard Worker   return ::Ice::ARM32::TargetDataARM32::create(Ctx);
46*03ce13f7SAndroid Build Coastguard Worker }
47*03ce13f7SAndroid Build Coastguard Worker 
48*03ce13f7SAndroid Build Coastguard Worker std::unique_ptr<::Ice::TargetHeaderLowering>
createTargetHeaderLowering(::Ice::GlobalContext * Ctx)49*03ce13f7SAndroid Build Coastguard Worker createTargetHeaderLowering(::Ice::GlobalContext *Ctx) {
50*03ce13f7SAndroid Build Coastguard Worker   return ::Ice::ARM32::TargetHeaderARM32::create(Ctx);
51*03ce13f7SAndroid Build Coastguard Worker }
52*03ce13f7SAndroid Build Coastguard Worker 
staticInit(::Ice::GlobalContext * Ctx)53*03ce13f7SAndroid Build Coastguard Worker void staticInit(::Ice::GlobalContext *Ctx) {
54*03ce13f7SAndroid Build Coastguard Worker   ::Ice::ARM32::TargetARM32::staticInit(Ctx);
55*03ce13f7SAndroid Build Coastguard Worker }
56*03ce13f7SAndroid Build Coastguard Worker 
shouldBePooled(const::Ice::Constant * C)57*03ce13f7SAndroid Build Coastguard Worker bool shouldBePooled(const ::Ice::Constant *C) {
58*03ce13f7SAndroid Build Coastguard Worker   return ::Ice::ARM32::TargetARM32::shouldBePooled(C);
59*03ce13f7SAndroid Build Coastguard Worker }
60*03ce13f7SAndroid Build Coastguard Worker 
getPointerType()61*03ce13f7SAndroid Build Coastguard Worker ::Ice::Type getPointerType() {
62*03ce13f7SAndroid Build Coastguard Worker   return ::Ice::ARM32::TargetARM32::getPointerType();
63*03ce13f7SAndroid Build Coastguard Worker }
64*03ce13f7SAndroid Build Coastguard Worker 
65*03ce13f7SAndroid Build Coastguard Worker } // end of namespace ARM32
66*03ce13f7SAndroid Build Coastguard Worker 
67*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
68*03ce13f7SAndroid Build Coastguard Worker namespace ARM32 {
69*03ce13f7SAndroid Build Coastguard Worker 
70*03ce13f7SAndroid Build Coastguard Worker namespace {
71*03ce13f7SAndroid Build Coastguard Worker 
72*03ce13f7SAndroid Build Coastguard Worker /// SizeOf is used to obtain the size of an initializer list as a constexpr
73*03ce13f7SAndroid Build Coastguard Worker /// expression. This is only needed until our C++ library is updated to
74*03ce13f7SAndroid Build Coastguard Worker /// C++ 14 -- which defines constexpr members to std::initializer_list.
75*03ce13f7SAndroid Build Coastguard Worker class SizeOf {
76*03ce13f7SAndroid Build Coastguard Worker   SizeOf(const SizeOf &) = delete;
77*03ce13f7SAndroid Build Coastguard Worker   SizeOf &operator=(const SizeOf &) = delete;
78*03ce13f7SAndroid Build Coastguard Worker 
79*03ce13f7SAndroid Build Coastguard Worker public:
SizeOf()80*03ce13f7SAndroid Build Coastguard Worker   constexpr SizeOf() : Size(0) {}
81*03ce13f7SAndroid Build Coastguard Worker   template <typename... T>
SizeOf(T...)82*03ce13f7SAndroid Build Coastguard Worker   explicit constexpr SizeOf(T...) : Size(__length<T...>::value) {}
size() const83*03ce13f7SAndroid Build Coastguard Worker   constexpr SizeT size() const { return Size; }
84*03ce13f7SAndroid Build Coastguard Worker 
85*03ce13f7SAndroid Build Coastguard Worker private:
86*03ce13f7SAndroid Build Coastguard Worker   template <typename T, typename... U> struct __length {
87*03ce13f7SAndroid Build Coastguard Worker     static constexpr std::size_t value = 1 + __length<U...>::value;
88*03ce13f7SAndroid Build Coastguard Worker   };
89*03ce13f7SAndroid Build Coastguard Worker 
90*03ce13f7SAndroid Build Coastguard Worker   template <typename T> struct __length<T> {
91*03ce13f7SAndroid Build Coastguard Worker     static constexpr std::size_t value = 1;
92*03ce13f7SAndroid Build Coastguard Worker   };
93*03ce13f7SAndroid Build Coastguard Worker 
94*03ce13f7SAndroid Build Coastguard Worker   const std::size_t Size;
95*03ce13f7SAndroid Build Coastguard Worker };
96*03ce13f7SAndroid Build Coastguard Worker 
97*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
98*03ce13f7SAndroid Build Coastguard Worker 
99*03ce13f7SAndroid Build Coastguard Worker // Defines the RegARM32::Table table with register information.
100*03ce13f7SAndroid Build Coastguard Worker RegARM32::RegTableType RegARM32::RegTable[RegARM32::Reg_NUM] = {
101*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr,   \
102*03ce13f7SAndroid Build Coastguard Worker           isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init)       \
103*03ce13f7SAndroid Build Coastguard Worker   {name,      encode,                                                          \
104*03ce13f7SAndroid Build Coastguard Worker    cc_arg,    scratch,                                                         \
105*03ce13f7SAndroid Build Coastguard Worker    preserved, stackptr,                                                        \
106*03ce13f7SAndroid Build Coastguard Worker    frameptr,  isGPR,                                                           \
107*03ce13f7SAndroid Build Coastguard Worker    isInt,     isI64Pair,                                                       \
108*03ce13f7SAndroid Build Coastguard Worker    isFP32,    isFP64,                                                          \
109*03ce13f7SAndroid Build Coastguard Worker    isVec128,  (SizeOf alias_init).size(),                                      \
110*03ce13f7SAndroid Build Coastguard Worker    alias_init},
111*03ce13f7SAndroid Build Coastguard Worker     REGARM32_TABLE
112*03ce13f7SAndroid Build Coastguard Worker #undef X
113*03ce13f7SAndroid Build Coastguard Worker };
114*03ce13f7SAndroid Build Coastguard Worker 
115*03ce13f7SAndroid Build Coastguard Worker namespace {
116*03ce13f7SAndroid Build Coastguard Worker 
117*03ce13f7SAndroid Build Coastguard Worker // The following table summarizes the logic for lowering the icmp instruction
118*03ce13f7SAndroid Build Coastguard Worker // for i32 and narrower types. Each icmp condition has a clear mapping to an
119*03ce13f7SAndroid Build Coastguard Worker // ARM32 conditional move instruction.
120*03ce13f7SAndroid Build Coastguard Worker 
121*03ce13f7SAndroid Build Coastguard Worker const struct TableIcmp32_ {
122*03ce13f7SAndroid Build Coastguard Worker   CondARM32::Cond Mapping;
123*03ce13f7SAndroid Build Coastguard Worker } TableIcmp32[] = {
124*03ce13f7SAndroid Build Coastguard Worker #define X(val, is_signed, swapped64, C_32, C1_64, C2_64, C_V, INV_V, NEG_V)    \
125*03ce13f7SAndroid Build Coastguard Worker   {CondARM32::C_32},
126*03ce13f7SAndroid Build Coastguard Worker     ICMPARM32_TABLE
127*03ce13f7SAndroid Build Coastguard Worker #undef X
128*03ce13f7SAndroid Build Coastguard Worker };
129*03ce13f7SAndroid Build Coastguard Worker 
130*03ce13f7SAndroid Build Coastguard Worker // The following table summarizes the logic for lowering the icmp instruction
131*03ce13f7SAndroid Build Coastguard Worker // for the i64 type. Two conditional moves are needed for setting to 1 or 0.
132*03ce13f7SAndroid Build Coastguard Worker // The operands may need to be swapped, and there is a slight difference for
133*03ce13f7SAndroid Build Coastguard Worker // signed vs unsigned (comparing hi vs lo first, and using cmp vs sbc).
134*03ce13f7SAndroid Build Coastguard Worker const struct TableIcmp64_ {
135*03ce13f7SAndroid Build Coastguard Worker   bool IsSigned;
136*03ce13f7SAndroid Build Coastguard Worker   bool Swapped;
137*03ce13f7SAndroid Build Coastguard Worker   CondARM32::Cond C1, C2;
138*03ce13f7SAndroid Build Coastguard Worker } TableIcmp64[] = {
139*03ce13f7SAndroid Build Coastguard Worker #define X(val, is_signed, swapped64, C_32, C1_64, C2_64, C_V, INV_V, NEG_V)    \
140*03ce13f7SAndroid Build Coastguard Worker   {is_signed, swapped64, CondARM32::C1_64, CondARM32::C2_64},
141*03ce13f7SAndroid Build Coastguard Worker     ICMPARM32_TABLE
142*03ce13f7SAndroid Build Coastguard Worker #undef X
143*03ce13f7SAndroid Build Coastguard Worker };
144*03ce13f7SAndroid Build Coastguard Worker 
getIcmp32Mapping(InstIcmp::ICond Cond)145*03ce13f7SAndroid Build Coastguard Worker CondARM32::Cond getIcmp32Mapping(InstIcmp::ICond Cond) {
146*03ce13f7SAndroid Build Coastguard Worker   assert(Cond < llvm::array_lengthof(TableIcmp32));
147*03ce13f7SAndroid Build Coastguard Worker   return TableIcmp32[Cond].Mapping;
148*03ce13f7SAndroid Build Coastguard Worker }
149*03ce13f7SAndroid Build Coastguard Worker 
150*03ce13f7SAndroid Build Coastguard Worker // In some cases, there are x-macros tables for both high-level and low-level
151*03ce13f7SAndroid Build Coastguard Worker // instructions/operands that use the same enum key value. The tables are kept
152*03ce13f7SAndroid Build Coastguard Worker // separate to maintain a proper separation between abstraction layers. There
153*03ce13f7SAndroid Build Coastguard Worker // is a risk that the tables could get out of sync if enum values are reordered
154*03ce13f7SAndroid Build Coastguard Worker // or if entries are added or deleted. The following anonymous namespaces use
155*03ce13f7SAndroid Build Coastguard Worker // static_asserts to ensure everything is kept in sync.
156*03ce13f7SAndroid Build Coastguard Worker 
157*03ce13f7SAndroid Build Coastguard Worker // Validate the enum values in ICMPARM32_TABLE.
158*03ce13f7SAndroid Build Coastguard Worker namespace {
159*03ce13f7SAndroid Build Coastguard Worker // Define a temporary set of enum values based on low-level table entries.
160*03ce13f7SAndroid Build Coastguard Worker enum _icmp_ll_enum {
161*03ce13f7SAndroid Build Coastguard Worker #define X(val, is_signed, swapped64, C_32, C1_64, C2_64, C_V, INV_V, NEG_V)    \
162*03ce13f7SAndroid Build Coastguard Worker   _icmp_ll_##val,
163*03ce13f7SAndroid Build Coastguard Worker   ICMPARM32_TABLE
164*03ce13f7SAndroid Build Coastguard Worker #undef X
165*03ce13f7SAndroid Build Coastguard Worker       _num
166*03ce13f7SAndroid Build Coastguard Worker };
167*03ce13f7SAndroid Build Coastguard Worker // Define a set of constants based on high-level table entries.
168*03ce13f7SAndroid Build Coastguard Worker #define X(tag, reverse, str)                                                   \
169*03ce13f7SAndroid Build Coastguard Worker   static constexpr int _icmp_hl_##tag = InstIcmp::tag;
170*03ce13f7SAndroid Build Coastguard Worker ICEINSTICMP_TABLE
171*03ce13f7SAndroid Build Coastguard Worker #undef X
172*03ce13f7SAndroid Build Coastguard Worker // Define a set of constants based on low-level table entries, and ensure the
173*03ce13f7SAndroid Build Coastguard Worker // table entry keys are consistent.
174*03ce13f7SAndroid Build Coastguard Worker #define X(val, is_signed, swapped64, C_32, C1_64, C2_64, C_V, INV_V, NEG_V)    \
175*03ce13f7SAndroid Build Coastguard Worker   static_assert(                                                               \
176*03ce13f7SAndroid Build Coastguard Worker       _icmp_ll_##val == _icmp_hl_##val,                                        \
177*03ce13f7SAndroid Build Coastguard Worker       "Inconsistency between ICMPARM32_TABLE and ICEINSTICMP_TABLE: " #val);
178*03ce13f7SAndroid Build Coastguard Worker ICMPARM32_TABLE
179*03ce13f7SAndroid Build Coastguard Worker #undef X
180*03ce13f7SAndroid Build Coastguard Worker // Repeat the static asserts with respect to the high-level table entries in
181*03ce13f7SAndroid Build Coastguard Worker // case the high-level table has extra entries.
182*03ce13f7SAndroid Build Coastguard Worker #define X(tag, reverse, str)                                                   \
183*03ce13f7SAndroid Build Coastguard Worker   static_assert(                                                               \
184*03ce13f7SAndroid Build Coastguard Worker       _icmp_hl_##tag == _icmp_ll_##tag,                                        \
185*03ce13f7SAndroid Build Coastguard Worker       "Inconsistency between ICMPARM32_TABLE and ICEINSTICMP_TABLE: " #tag);
186*03ce13f7SAndroid Build Coastguard Worker ICEINSTICMP_TABLE
187*03ce13f7SAndroid Build Coastguard Worker #undef X
188*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
189*03ce13f7SAndroid Build Coastguard Worker 
190*03ce13f7SAndroid Build Coastguard Worker // Stack alignment
191*03ce13f7SAndroid Build Coastguard Worker const uint32_t ARM32_STACK_ALIGNMENT_BYTES = 16;
192*03ce13f7SAndroid Build Coastguard Worker 
193*03ce13f7SAndroid Build Coastguard Worker // Value is in bytes. Return Value adjusted to the next highest multiple of the
194*03ce13f7SAndroid Build Coastguard Worker // stack alignment.
applyStackAlignment(uint32_t Value)195*03ce13f7SAndroid Build Coastguard Worker uint32_t applyStackAlignment(uint32_t Value) {
196*03ce13f7SAndroid Build Coastguard Worker   return Utils::applyAlignment(Value, ARM32_STACK_ALIGNMENT_BYTES);
197*03ce13f7SAndroid Build Coastguard Worker }
198*03ce13f7SAndroid Build Coastguard Worker 
199*03ce13f7SAndroid Build Coastguard Worker // Value is in bytes. Return Value adjusted to the next highest multiple of the
200*03ce13f7SAndroid Build Coastguard Worker // stack alignment required for the given type.
applyStackAlignmentTy(uint32_t Value,Type Ty)201*03ce13f7SAndroid Build Coastguard Worker uint32_t applyStackAlignmentTy(uint32_t Value, Type Ty) {
202*03ce13f7SAndroid Build Coastguard Worker   // Use natural alignment, except that normally (non-NaCl) ARM only aligns
203*03ce13f7SAndroid Build Coastguard Worker   // vectors to 8 bytes.
204*03ce13f7SAndroid Build Coastguard Worker   // TODO(jvoung): Check this ...
205*03ce13f7SAndroid Build Coastguard Worker   size_t typeAlignInBytes = typeWidthInBytes(Ty);
206*03ce13f7SAndroid Build Coastguard Worker   if (isVectorType(Ty))
207*03ce13f7SAndroid Build Coastguard Worker     typeAlignInBytes = 8;
208*03ce13f7SAndroid Build Coastguard Worker   return Utils::applyAlignment(Value, typeAlignInBytes);
209*03ce13f7SAndroid Build Coastguard Worker }
210*03ce13f7SAndroid Build Coastguard Worker 
211*03ce13f7SAndroid Build Coastguard Worker // Conservatively check if at compile time we know that the operand is
212*03ce13f7SAndroid Build Coastguard Worker // definitely a non-zero integer.
isGuaranteedNonzeroInt(const Operand * Op)213*03ce13f7SAndroid Build Coastguard Worker bool isGuaranteedNonzeroInt(const Operand *Op) {
214*03ce13f7SAndroid Build Coastguard Worker   if (auto *Const = llvm::dyn_cast_or_null<ConstantInteger32>(Op)) {
215*03ce13f7SAndroid Build Coastguard Worker     return Const->getValue() != 0;
216*03ce13f7SAndroid Build Coastguard Worker   }
217*03ce13f7SAndroid Build Coastguard Worker   return false;
218*03ce13f7SAndroid Build Coastguard Worker }
219*03ce13f7SAndroid Build Coastguard Worker 
220*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
221*03ce13f7SAndroid Build Coastguard Worker 
TargetARM32Features(const ClFlags & Flags)222*03ce13f7SAndroid Build Coastguard Worker TargetARM32Features::TargetARM32Features(const ClFlags &Flags) {
223*03ce13f7SAndroid Build Coastguard Worker   static_assert(
224*03ce13f7SAndroid Build Coastguard Worker       (ARM32InstructionSet::End - ARM32InstructionSet::Begin) ==
225*03ce13f7SAndroid Build Coastguard Worker           (TargetInstructionSet::ARM32InstructionSet_End -
226*03ce13f7SAndroid Build Coastguard Worker            TargetInstructionSet::ARM32InstructionSet_Begin),
227*03ce13f7SAndroid Build Coastguard Worker       "ARM32InstructionSet range different from TargetInstructionSet");
228*03ce13f7SAndroid Build Coastguard Worker   if (Flags.getTargetInstructionSet() !=
229*03ce13f7SAndroid Build Coastguard Worker       TargetInstructionSet::BaseInstructionSet) {
230*03ce13f7SAndroid Build Coastguard Worker     InstructionSet = static_cast<ARM32InstructionSet>(
231*03ce13f7SAndroid Build Coastguard Worker         (Flags.getTargetInstructionSet() -
232*03ce13f7SAndroid Build Coastguard Worker          TargetInstructionSet::ARM32InstructionSet_Begin) +
233*03ce13f7SAndroid Build Coastguard Worker         ARM32InstructionSet::Begin);
234*03ce13f7SAndroid Build Coastguard Worker   }
235*03ce13f7SAndroid Build Coastguard Worker }
236*03ce13f7SAndroid Build Coastguard Worker 
237*03ce13f7SAndroid Build Coastguard Worker namespace {
238*03ce13f7SAndroid Build Coastguard Worker constexpr SizeT NumGPRArgs =
239*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr,   \
240*03ce13f7SAndroid Build Coastguard Worker           isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init)       \
241*03ce13f7SAndroid Build Coastguard Worker   +(((cc_arg) > 0) ? 1 : 0)
242*03ce13f7SAndroid Build Coastguard Worker     REGARM32_GPR_TABLE
243*03ce13f7SAndroid Build Coastguard Worker #undef X
244*03ce13f7SAndroid Build Coastguard Worker     ;
245*03ce13f7SAndroid Build Coastguard Worker std::array<RegNumT, NumGPRArgs> GPRArgInitializer;
246*03ce13f7SAndroid Build Coastguard Worker 
247*03ce13f7SAndroid Build Coastguard Worker constexpr SizeT NumI64Args =
248*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr,   \
249*03ce13f7SAndroid Build Coastguard Worker           isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init)       \
250*03ce13f7SAndroid Build Coastguard Worker   +(((cc_arg) > 0) ? 1 : 0)
251*03ce13f7SAndroid Build Coastguard Worker     REGARM32_I64PAIR_TABLE
252*03ce13f7SAndroid Build Coastguard Worker #undef X
253*03ce13f7SAndroid Build Coastguard Worker     ;
254*03ce13f7SAndroid Build Coastguard Worker std::array<RegNumT, NumI64Args> I64ArgInitializer;
255*03ce13f7SAndroid Build Coastguard Worker 
256*03ce13f7SAndroid Build Coastguard Worker constexpr SizeT NumFP32Args =
257*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr,   \
258*03ce13f7SAndroid Build Coastguard Worker           isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init)       \
259*03ce13f7SAndroid Build Coastguard Worker   +(((cc_arg) > 0) ? 1 : 0)
260*03ce13f7SAndroid Build Coastguard Worker     REGARM32_FP32_TABLE
261*03ce13f7SAndroid Build Coastguard Worker #undef X
262*03ce13f7SAndroid Build Coastguard Worker     ;
263*03ce13f7SAndroid Build Coastguard Worker std::array<RegNumT, NumFP32Args> FP32ArgInitializer;
264*03ce13f7SAndroid Build Coastguard Worker 
265*03ce13f7SAndroid Build Coastguard Worker constexpr SizeT NumFP64Args =
266*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr,   \
267*03ce13f7SAndroid Build Coastguard Worker           isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init)       \
268*03ce13f7SAndroid Build Coastguard Worker   +(((cc_arg) > 0) ? 1 : 0)
269*03ce13f7SAndroid Build Coastguard Worker     REGARM32_FP64_TABLE
270*03ce13f7SAndroid Build Coastguard Worker #undef X
271*03ce13f7SAndroid Build Coastguard Worker     ;
272*03ce13f7SAndroid Build Coastguard Worker std::array<RegNumT, NumFP64Args> FP64ArgInitializer;
273*03ce13f7SAndroid Build Coastguard Worker 
274*03ce13f7SAndroid Build Coastguard Worker constexpr SizeT NumVec128Args =
275*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr,   \
276*03ce13f7SAndroid Build Coastguard Worker           isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init)       \
277*03ce13f7SAndroid Build Coastguard Worker   +(((cc_arg > 0)) ? 1 : 0)
278*03ce13f7SAndroid Build Coastguard Worker     REGARM32_VEC128_TABLE
279*03ce13f7SAndroid Build Coastguard Worker #undef X
280*03ce13f7SAndroid Build Coastguard Worker     ;
281*03ce13f7SAndroid Build Coastguard Worker std::array<RegNumT, NumVec128Args> Vec128ArgInitializer;
282*03ce13f7SAndroid Build Coastguard Worker 
getRegClassName(RegClass C)283*03ce13f7SAndroid Build Coastguard Worker const char *getRegClassName(RegClass C) {
284*03ce13f7SAndroid Build Coastguard Worker   auto ClassNum = static_cast<RegARM32::RegClassARM32>(C);
285*03ce13f7SAndroid Build Coastguard Worker   assert(ClassNum < RegARM32::RCARM32_NUM);
286*03ce13f7SAndroid Build Coastguard Worker   switch (ClassNum) {
287*03ce13f7SAndroid Build Coastguard Worker   default:
288*03ce13f7SAndroid Build Coastguard Worker     assert(C < RC_Target);
289*03ce13f7SAndroid Build Coastguard Worker     return regClassString(C);
290*03ce13f7SAndroid Build Coastguard Worker   // Add handling of new register classes below.
291*03ce13f7SAndroid Build Coastguard Worker   case RegARM32::RCARM32_QtoS:
292*03ce13f7SAndroid Build Coastguard Worker     return "QtoS";
293*03ce13f7SAndroid Build Coastguard Worker   }
294*03ce13f7SAndroid Build Coastguard Worker }
295*03ce13f7SAndroid Build Coastguard Worker 
296*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
297*03ce13f7SAndroid Build Coastguard Worker 
TargetARM32(Cfg * Func)298*03ce13f7SAndroid Build Coastguard Worker TargetARM32::TargetARM32(Cfg *Func)
299*03ce13f7SAndroid Build Coastguard Worker     : TargetLowering(Func), CPUFeatures(getFlags()) {}
300*03ce13f7SAndroid Build Coastguard Worker 
staticInit(GlobalContext * Ctx)301*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::staticInit(GlobalContext *Ctx) {
302*03ce13f7SAndroid Build Coastguard Worker   RegNumT::setLimit(RegARM32::Reg_NUM);
303*03ce13f7SAndroid Build Coastguard Worker   // Limit this size (or do all bitsets need to be the same width)???
304*03ce13f7SAndroid Build Coastguard Worker   SmallBitVector IntegerRegisters(RegARM32::Reg_NUM);
305*03ce13f7SAndroid Build Coastguard Worker   SmallBitVector I64PairRegisters(RegARM32::Reg_NUM);
306*03ce13f7SAndroid Build Coastguard Worker   SmallBitVector Float32Registers(RegARM32::Reg_NUM);
307*03ce13f7SAndroid Build Coastguard Worker   SmallBitVector Float64Registers(RegARM32::Reg_NUM);
308*03ce13f7SAndroid Build Coastguard Worker   SmallBitVector VectorRegisters(RegARM32::Reg_NUM);
309*03ce13f7SAndroid Build Coastguard Worker   SmallBitVector QtoSRegisters(RegARM32::Reg_NUM);
310*03ce13f7SAndroid Build Coastguard Worker   SmallBitVector InvalidRegisters(RegARM32::Reg_NUM);
311*03ce13f7SAndroid Build Coastguard Worker   const unsigned EncodedReg_q8 = RegARM32::RegTable[RegARM32::Reg_q8].Encoding;
312*03ce13f7SAndroid Build Coastguard Worker   for (int i = 0; i < RegARM32::Reg_NUM; ++i) {
313*03ce13f7SAndroid Build Coastguard Worker     const auto &Entry = RegARM32::RegTable[i];
314*03ce13f7SAndroid Build Coastguard Worker     IntegerRegisters[i] = Entry.IsInt;
315*03ce13f7SAndroid Build Coastguard Worker     I64PairRegisters[i] = Entry.IsI64Pair;
316*03ce13f7SAndroid Build Coastguard Worker     Float32Registers[i] = Entry.IsFP32;
317*03ce13f7SAndroid Build Coastguard Worker     Float64Registers[i] = Entry.IsFP64;
318*03ce13f7SAndroid Build Coastguard Worker     VectorRegisters[i] = Entry.IsVec128;
319*03ce13f7SAndroid Build Coastguard Worker     RegisterAliases[i].resize(RegARM32::Reg_NUM);
320*03ce13f7SAndroid Build Coastguard Worker     // TODO(eholk): It would be better to store a QtoS flag in the
321*03ce13f7SAndroid Build Coastguard Worker     // IceRegistersARM32 table than to compare their encodings here.
322*03ce13f7SAndroid Build Coastguard Worker     QtoSRegisters[i] = Entry.IsVec128 && Entry.Encoding < EncodedReg_q8;
323*03ce13f7SAndroid Build Coastguard Worker     for (int j = 0; j < Entry.NumAliases; ++j) {
324*03ce13f7SAndroid Build Coastguard Worker       assert(i == j || !RegisterAliases[i][Entry.Aliases[j]]);
325*03ce13f7SAndroid Build Coastguard Worker       RegisterAliases[i].set(Entry.Aliases[j]);
326*03ce13f7SAndroid Build Coastguard Worker     }
327*03ce13f7SAndroid Build Coastguard Worker     assert(RegisterAliases[i][i]);
328*03ce13f7SAndroid Build Coastguard Worker     if (Entry.CCArg <= 0) {
329*03ce13f7SAndroid Build Coastguard Worker       continue;
330*03ce13f7SAndroid Build Coastguard Worker     }
331*03ce13f7SAndroid Build Coastguard Worker     const auto RegNum = RegNumT::fromInt(i);
332*03ce13f7SAndroid Build Coastguard Worker     if (Entry.IsGPR) {
333*03ce13f7SAndroid Build Coastguard Worker       GPRArgInitializer[Entry.CCArg - 1] = RegNum;
334*03ce13f7SAndroid Build Coastguard Worker     } else if (Entry.IsI64Pair) {
335*03ce13f7SAndroid Build Coastguard Worker       I64ArgInitializer[Entry.CCArg - 1] = RegNum;
336*03ce13f7SAndroid Build Coastguard Worker     } else if (Entry.IsFP32) {
337*03ce13f7SAndroid Build Coastguard Worker       FP32ArgInitializer[Entry.CCArg - 1] = RegNum;
338*03ce13f7SAndroid Build Coastguard Worker     } else if (Entry.IsFP64) {
339*03ce13f7SAndroid Build Coastguard Worker       FP64ArgInitializer[Entry.CCArg - 1] = RegNum;
340*03ce13f7SAndroid Build Coastguard Worker     } else if (Entry.IsVec128) {
341*03ce13f7SAndroid Build Coastguard Worker       Vec128ArgInitializer[Entry.CCArg - 1] = RegNum;
342*03ce13f7SAndroid Build Coastguard Worker     }
343*03ce13f7SAndroid Build Coastguard Worker   }
344*03ce13f7SAndroid Build Coastguard Worker   TypeToRegisterSet[IceType_void] = InvalidRegisters;
345*03ce13f7SAndroid Build Coastguard Worker   TypeToRegisterSet[IceType_i1] = IntegerRegisters;
346*03ce13f7SAndroid Build Coastguard Worker   TypeToRegisterSet[IceType_i8] = IntegerRegisters;
347*03ce13f7SAndroid Build Coastguard Worker   TypeToRegisterSet[IceType_i16] = IntegerRegisters;
348*03ce13f7SAndroid Build Coastguard Worker   TypeToRegisterSet[IceType_i32] = IntegerRegisters;
349*03ce13f7SAndroid Build Coastguard Worker   TypeToRegisterSet[IceType_i64] = I64PairRegisters;
350*03ce13f7SAndroid Build Coastguard Worker   TypeToRegisterSet[IceType_f32] = Float32Registers;
351*03ce13f7SAndroid Build Coastguard Worker   TypeToRegisterSet[IceType_f64] = Float64Registers;
352*03ce13f7SAndroid Build Coastguard Worker   TypeToRegisterSet[IceType_v4i1] = VectorRegisters;
353*03ce13f7SAndroid Build Coastguard Worker   TypeToRegisterSet[IceType_v8i1] = VectorRegisters;
354*03ce13f7SAndroid Build Coastguard Worker   TypeToRegisterSet[IceType_v16i1] = VectorRegisters;
355*03ce13f7SAndroid Build Coastguard Worker   TypeToRegisterSet[IceType_v16i8] = VectorRegisters;
356*03ce13f7SAndroid Build Coastguard Worker   TypeToRegisterSet[IceType_v8i16] = VectorRegisters;
357*03ce13f7SAndroid Build Coastguard Worker   TypeToRegisterSet[IceType_v4i32] = VectorRegisters;
358*03ce13f7SAndroid Build Coastguard Worker   TypeToRegisterSet[IceType_v4f32] = VectorRegisters;
359*03ce13f7SAndroid Build Coastguard Worker   TypeToRegisterSet[RegARM32::RCARM32_QtoS] = QtoSRegisters;
360*03ce13f7SAndroid Build Coastguard Worker 
361*03ce13f7SAndroid Build Coastguard Worker   for (size_t i = 0; i < llvm::array_lengthof(TypeToRegisterSet); ++i)
362*03ce13f7SAndroid Build Coastguard Worker     TypeToRegisterSetUnfiltered[i] = TypeToRegisterSet[i];
363*03ce13f7SAndroid Build Coastguard Worker 
364*03ce13f7SAndroid Build Coastguard Worker   filterTypeToRegisterSet(
365*03ce13f7SAndroid Build Coastguard Worker       Ctx, RegARM32::Reg_NUM, TypeToRegisterSet,
366*03ce13f7SAndroid Build Coastguard Worker       llvm::array_lengthof(TypeToRegisterSet),
367*03ce13f7SAndroid Build Coastguard Worker       [](RegNumT RegNum) -> std::string {
368*03ce13f7SAndroid Build Coastguard Worker         // This function simply removes ", " from the
369*03ce13f7SAndroid Build Coastguard Worker         // register name.
370*03ce13f7SAndroid Build Coastguard Worker         std::string Name = RegARM32::getRegName(RegNum);
371*03ce13f7SAndroid Build Coastguard Worker         constexpr const char RegSeparator[] = ", ";
372*03ce13f7SAndroid Build Coastguard Worker         constexpr size_t RegSeparatorWidth =
373*03ce13f7SAndroid Build Coastguard Worker             llvm::array_lengthof(RegSeparator) - 1;
374*03ce13f7SAndroid Build Coastguard Worker         for (size_t Pos = Name.find(RegSeparator); Pos != std::string::npos;
375*03ce13f7SAndroid Build Coastguard Worker              Pos = Name.find(RegSeparator)) {
376*03ce13f7SAndroid Build Coastguard Worker           Name.replace(Pos, RegSeparatorWidth, "");
377*03ce13f7SAndroid Build Coastguard Worker         }
378*03ce13f7SAndroid Build Coastguard Worker         return Name;
379*03ce13f7SAndroid Build Coastguard Worker       },
380*03ce13f7SAndroid Build Coastguard Worker       getRegClassName);
381*03ce13f7SAndroid Build Coastguard Worker }
382*03ce13f7SAndroid Build Coastguard Worker 
383*03ce13f7SAndroid Build Coastguard Worker namespace {
copyRegAllocFromInfWeightVariable64On32(const VarList & Vars)384*03ce13f7SAndroid Build Coastguard Worker void copyRegAllocFromInfWeightVariable64On32(const VarList &Vars) {
385*03ce13f7SAndroid Build Coastguard Worker   for (Variable *Var : Vars) {
386*03ce13f7SAndroid Build Coastguard Worker     auto *Var64 = llvm::dyn_cast<Variable64On32>(Var);
387*03ce13f7SAndroid Build Coastguard Worker     if (!Var64) {
388*03ce13f7SAndroid Build Coastguard Worker       // This is not the variable we are looking for.
389*03ce13f7SAndroid Build Coastguard Worker       continue;
390*03ce13f7SAndroid Build Coastguard Worker     }
391*03ce13f7SAndroid Build Coastguard Worker     // only allow infinite-weight i64 temporaries to be register allocated.
392*03ce13f7SAndroid Build Coastguard Worker     assert(!Var64->hasReg() || Var64->mustHaveReg());
393*03ce13f7SAndroid Build Coastguard Worker     if (!Var64->hasReg()) {
394*03ce13f7SAndroid Build Coastguard Worker       continue;
395*03ce13f7SAndroid Build Coastguard Worker     }
396*03ce13f7SAndroid Build Coastguard Worker     const auto FirstReg =
397*03ce13f7SAndroid Build Coastguard Worker         RegNumT::fixme(RegARM32::getI64PairFirstGPRNum(Var->getRegNum()));
398*03ce13f7SAndroid Build Coastguard Worker     // This assumes little endian.
399*03ce13f7SAndroid Build Coastguard Worker     Variable *Lo = Var64->getLo();
400*03ce13f7SAndroid Build Coastguard Worker     Variable *Hi = Var64->getHi();
401*03ce13f7SAndroid Build Coastguard Worker     assert(Lo->hasReg() == Hi->hasReg());
402*03ce13f7SAndroid Build Coastguard Worker     if (Lo->hasReg()) {
403*03ce13f7SAndroid Build Coastguard Worker       continue;
404*03ce13f7SAndroid Build Coastguard Worker     }
405*03ce13f7SAndroid Build Coastguard Worker     Lo->setRegNum(FirstReg);
406*03ce13f7SAndroid Build Coastguard Worker     Lo->setMustHaveReg();
407*03ce13f7SAndroid Build Coastguard Worker     Hi->setRegNum(RegNumT::fixme(FirstReg + 1));
408*03ce13f7SAndroid Build Coastguard Worker     Hi->setMustHaveReg();
409*03ce13f7SAndroid Build Coastguard Worker   }
410*03ce13f7SAndroid Build Coastguard Worker }
411*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
412*03ce13f7SAndroid Build Coastguard Worker 
getCallStackArgumentsSizeBytes(const InstCall * Call)413*03ce13f7SAndroid Build Coastguard Worker uint32_t TargetARM32::getCallStackArgumentsSizeBytes(const InstCall *Call) {
414*03ce13f7SAndroid Build Coastguard Worker   TargetARM32::CallingConv CC;
415*03ce13f7SAndroid Build Coastguard Worker   RegNumT DummyReg;
416*03ce13f7SAndroid Build Coastguard Worker   size_t OutArgsSizeBytes = 0;
417*03ce13f7SAndroid Build Coastguard Worker   for (SizeT i = 0, NumArgs = Call->getNumArgs(); i < NumArgs; ++i) {
418*03ce13f7SAndroid Build Coastguard Worker     Operand *Arg = legalizeUndef(Call->getArg(i));
419*03ce13f7SAndroid Build Coastguard Worker     const Type Ty = Arg->getType();
420*03ce13f7SAndroid Build Coastguard Worker     if (isScalarIntegerType(Ty)) {
421*03ce13f7SAndroid Build Coastguard Worker       if (CC.argInGPR(Ty, &DummyReg)) {
422*03ce13f7SAndroid Build Coastguard Worker         continue;
423*03ce13f7SAndroid Build Coastguard Worker       }
424*03ce13f7SAndroid Build Coastguard Worker     } else {
425*03ce13f7SAndroid Build Coastguard Worker       if (CC.argInVFP(Ty, &DummyReg)) {
426*03ce13f7SAndroid Build Coastguard Worker         continue;
427*03ce13f7SAndroid Build Coastguard Worker       }
428*03ce13f7SAndroid Build Coastguard Worker     }
429*03ce13f7SAndroid Build Coastguard Worker 
430*03ce13f7SAndroid Build Coastguard Worker     OutArgsSizeBytes = applyStackAlignmentTy(OutArgsSizeBytes, Ty);
431*03ce13f7SAndroid Build Coastguard Worker     OutArgsSizeBytes += typeWidthInBytesOnStack(Ty);
432*03ce13f7SAndroid Build Coastguard Worker   }
433*03ce13f7SAndroid Build Coastguard Worker 
434*03ce13f7SAndroid Build Coastguard Worker   return applyStackAlignment(OutArgsSizeBytes);
435*03ce13f7SAndroid Build Coastguard Worker }
436*03ce13f7SAndroid Build Coastguard Worker 
genTargetHelperCallFor(Inst * Instr)437*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::genTargetHelperCallFor(Inst *Instr) {
438*03ce13f7SAndroid Build Coastguard Worker   constexpr bool NoTailCall = false;
439*03ce13f7SAndroid Build Coastguard Worker   constexpr bool IsTargetHelperCall = true;
440*03ce13f7SAndroid Build Coastguard Worker 
441*03ce13f7SAndroid Build Coastguard Worker   switch (Instr->getKind()) {
442*03ce13f7SAndroid Build Coastguard Worker   default:
443*03ce13f7SAndroid Build Coastguard Worker     return;
444*03ce13f7SAndroid Build Coastguard Worker   case Inst::Arithmetic: {
445*03ce13f7SAndroid Build Coastguard Worker     Variable *Dest = Instr->getDest();
446*03ce13f7SAndroid Build Coastguard Worker     const Type DestTy = Dest->getType();
447*03ce13f7SAndroid Build Coastguard Worker     const InstArithmetic::OpKind Op =
448*03ce13f7SAndroid Build Coastguard Worker         llvm::cast<InstArithmetic>(Instr)->getOp();
449*03ce13f7SAndroid Build Coastguard Worker     if (isVectorType(DestTy)) {
450*03ce13f7SAndroid Build Coastguard Worker       switch (Op) {
451*03ce13f7SAndroid Build Coastguard Worker       default:
452*03ce13f7SAndroid Build Coastguard Worker         break;
453*03ce13f7SAndroid Build Coastguard Worker       case InstArithmetic::Fdiv:
454*03ce13f7SAndroid Build Coastguard Worker       case InstArithmetic::Frem:
455*03ce13f7SAndroid Build Coastguard Worker       case InstArithmetic::Sdiv:
456*03ce13f7SAndroid Build Coastguard Worker       case InstArithmetic::Srem:
457*03ce13f7SAndroid Build Coastguard Worker       case InstArithmetic::Udiv:
458*03ce13f7SAndroid Build Coastguard Worker       case InstArithmetic::Urem:
459*03ce13f7SAndroid Build Coastguard Worker         scalarizeArithmetic(Op, Dest, Instr->getSrc(0), Instr->getSrc(1));
460*03ce13f7SAndroid Build Coastguard Worker         Instr->setDeleted();
461*03ce13f7SAndroid Build Coastguard Worker         return;
462*03ce13f7SAndroid Build Coastguard Worker       }
463*03ce13f7SAndroid Build Coastguard Worker     }
464*03ce13f7SAndroid Build Coastguard Worker     switch (DestTy) {
465*03ce13f7SAndroid Build Coastguard Worker     default:
466*03ce13f7SAndroid Build Coastguard Worker       return;
467*03ce13f7SAndroid Build Coastguard Worker     case IceType_i64: {
468*03ce13f7SAndroid Build Coastguard Worker       // Technically, ARM has its own aeabi routines, but we can use the
469*03ce13f7SAndroid Build Coastguard Worker       // non-aeabi routine as well. LLVM uses __aeabi_ldivmod for div, but uses
470*03ce13f7SAndroid Build Coastguard Worker       // the more standard __moddi3 for rem.
471*03ce13f7SAndroid Build Coastguard Worker       RuntimeHelper HelperID = RuntimeHelper::H_Num;
472*03ce13f7SAndroid Build Coastguard Worker       switch (Op) {
473*03ce13f7SAndroid Build Coastguard Worker       default:
474*03ce13f7SAndroid Build Coastguard Worker         return;
475*03ce13f7SAndroid Build Coastguard Worker       case InstArithmetic::Udiv:
476*03ce13f7SAndroid Build Coastguard Worker         HelperID = RuntimeHelper::H_udiv_i64;
477*03ce13f7SAndroid Build Coastguard Worker         break;
478*03ce13f7SAndroid Build Coastguard Worker       case InstArithmetic::Sdiv:
479*03ce13f7SAndroid Build Coastguard Worker         HelperID = RuntimeHelper::H_sdiv_i64;
480*03ce13f7SAndroid Build Coastguard Worker         break;
481*03ce13f7SAndroid Build Coastguard Worker       case InstArithmetic::Urem:
482*03ce13f7SAndroid Build Coastguard Worker         HelperID = RuntimeHelper::H_urem_i64;
483*03ce13f7SAndroid Build Coastguard Worker         break;
484*03ce13f7SAndroid Build Coastguard Worker       case InstArithmetic::Srem:
485*03ce13f7SAndroid Build Coastguard Worker         HelperID = RuntimeHelper::H_srem_i64;
486*03ce13f7SAndroid Build Coastguard Worker         break;
487*03ce13f7SAndroid Build Coastguard Worker       }
488*03ce13f7SAndroid Build Coastguard Worker       Operand *TargetHelper = Ctx->getRuntimeHelperFunc(HelperID);
489*03ce13f7SAndroid Build Coastguard Worker       ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem;
490*03ce13f7SAndroid Build Coastguard Worker       constexpr SizeT MaxArgs = 2;
491*03ce13f7SAndroid Build Coastguard Worker       auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
492*03ce13f7SAndroid Build Coastguard Worker                                             NoTailCall, IsTargetHelperCall);
493*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Instr->getSrc(0));
494*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Instr->getSrc(1));
495*03ce13f7SAndroid Build Coastguard Worker       Instr->setDeleted();
496*03ce13f7SAndroid Build Coastguard Worker       return;
497*03ce13f7SAndroid Build Coastguard Worker     }
498*03ce13f7SAndroid Build Coastguard Worker     case IceType_i32:
499*03ce13f7SAndroid Build Coastguard Worker     case IceType_i16:
500*03ce13f7SAndroid Build Coastguard Worker     case IceType_i8: {
501*03ce13f7SAndroid Build Coastguard Worker       const bool HasHWDiv = hasCPUFeature(TargetARM32Features::HWDivArm);
502*03ce13f7SAndroid Build Coastguard Worker       InstCast::OpKind CastKind;
503*03ce13f7SAndroid Build Coastguard Worker       RuntimeHelper HelperID = RuntimeHelper::H_Num;
504*03ce13f7SAndroid Build Coastguard Worker       switch (Op) {
505*03ce13f7SAndroid Build Coastguard Worker       default:
506*03ce13f7SAndroid Build Coastguard Worker         return;
507*03ce13f7SAndroid Build Coastguard Worker       case InstArithmetic::Udiv:
508*03ce13f7SAndroid Build Coastguard Worker         HelperID = HasHWDiv ? RuntimeHelper::H_Num : RuntimeHelper::H_udiv_i32;
509*03ce13f7SAndroid Build Coastguard Worker         CastKind = InstCast::Zext;
510*03ce13f7SAndroid Build Coastguard Worker         break;
511*03ce13f7SAndroid Build Coastguard Worker       case InstArithmetic::Sdiv:
512*03ce13f7SAndroid Build Coastguard Worker         HelperID = HasHWDiv ? RuntimeHelper::H_Num : RuntimeHelper::H_sdiv_i32;
513*03ce13f7SAndroid Build Coastguard Worker         CastKind = InstCast::Sext;
514*03ce13f7SAndroid Build Coastguard Worker         break;
515*03ce13f7SAndroid Build Coastguard Worker       case InstArithmetic::Urem:
516*03ce13f7SAndroid Build Coastguard Worker         HelperID = HasHWDiv ? RuntimeHelper::H_Num : RuntimeHelper::H_urem_i32;
517*03ce13f7SAndroid Build Coastguard Worker         CastKind = InstCast::Zext;
518*03ce13f7SAndroid Build Coastguard Worker         break;
519*03ce13f7SAndroid Build Coastguard Worker       case InstArithmetic::Srem:
520*03ce13f7SAndroid Build Coastguard Worker         HelperID = HasHWDiv ? RuntimeHelper::H_Num : RuntimeHelper::H_srem_i32;
521*03ce13f7SAndroid Build Coastguard Worker         CastKind = InstCast::Sext;
522*03ce13f7SAndroid Build Coastguard Worker         break;
523*03ce13f7SAndroid Build Coastguard Worker       }
524*03ce13f7SAndroid Build Coastguard Worker       if (HelperID == RuntimeHelper::H_Num) {
525*03ce13f7SAndroid Build Coastguard Worker         // HelperID should only ever be undefined when the processor does not
526*03ce13f7SAndroid Build Coastguard Worker         // have a hardware divider. If any other helpers are ever introduced,
527*03ce13f7SAndroid Build Coastguard Worker         // the following assert will have to be modified.
528*03ce13f7SAndroid Build Coastguard Worker         assert(HasHWDiv);
529*03ce13f7SAndroid Build Coastguard Worker         return;
530*03ce13f7SAndroid Build Coastguard Worker       }
531*03ce13f7SAndroid Build Coastguard Worker       Operand *Src0 = Instr->getSrc(0);
532*03ce13f7SAndroid Build Coastguard Worker       Operand *Src1 = Instr->getSrc(1);
533*03ce13f7SAndroid Build Coastguard Worker       if (DestTy != IceType_i32) {
534*03ce13f7SAndroid Build Coastguard Worker         // Src0 and Src1 have to be zero-, or signed-extended to i32. For Src0,
535*03ce13f7SAndroid Build Coastguard Worker         // we just insert a InstCast right before the call to the helper.
536*03ce13f7SAndroid Build Coastguard Worker         Variable *Src0_32 = Func->makeVariable(IceType_i32);
537*03ce13f7SAndroid Build Coastguard Worker         Context.insert<InstCast>(CastKind, Src0_32, Src0);
538*03ce13f7SAndroid Build Coastguard Worker         Src0 = Src0_32;
539*03ce13f7SAndroid Build Coastguard Worker 
540*03ce13f7SAndroid Build Coastguard Worker         // For extending Src1, we will just insert an InstCast if Src1 is not a
541*03ce13f7SAndroid Build Coastguard Worker         // Constant. If it is, then we extend it here, and not during program
542*03ce13f7SAndroid Build Coastguard Worker         // runtime. This allows preambleDivRem to optimize-out the div-by-0
543*03ce13f7SAndroid Build Coastguard Worker         // check.
544*03ce13f7SAndroid Build Coastguard Worker         if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) {
545*03ce13f7SAndroid Build Coastguard Worker           const int32_t ShAmt = (DestTy == IceType_i16) ? 16 : 24;
546*03ce13f7SAndroid Build Coastguard Worker           int32_t NewC = C->getValue();
547*03ce13f7SAndroid Build Coastguard Worker           if (CastKind == InstCast::Zext) {
548*03ce13f7SAndroid Build Coastguard Worker             NewC &= ~(0x80000000l >> ShAmt);
549*03ce13f7SAndroid Build Coastguard Worker           } else {
550*03ce13f7SAndroid Build Coastguard Worker             NewC = (NewC << ShAmt) >> ShAmt;
551*03ce13f7SAndroid Build Coastguard Worker           }
552*03ce13f7SAndroid Build Coastguard Worker           Src1 = Ctx->getConstantInt32(NewC);
553*03ce13f7SAndroid Build Coastguard Worker         } else {
554*03ce13f7SAndroid Build Coastguard Worker           Variable *Src1_32 = Func->makeVariable(IceType_i32);
555*03ce13f7SAndroid Build Coastguard Worker           Context.insert<InstCast>(CastKind, Src1_32, Src1);
556*03ce13f7SAndroid Build Coastguard Worker           Src1 = Src1_32;
557*03ce13f7SAndroid Build Coastguard Worker         }
558*03ce13f7SAndroid Build Coastguard Worker       }
559*03ce13f7SAndroid Build Coastguard Worker       Operand *TargetHelper = Ctx->getRuntimeHelperFunc(HelperID);
560*03ce13f7SAndroid Build Coastguard Worker       ARM32HelpersPreamble[TargetHelper] = &TargetARM32::preambleDivRem;
561*03ce13f7SAndroid Build Coastguard Worker       constexpr SizeT MaxArgs = 2;
562*03ce13f7SAndroid Build Coastguard Worker       auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
563*03ce13f7SAndroid Build Coastguard Worker                                             NoTailCall, IsTargetHelperCall);
564*03ce13f7SAndroid Build Coastguard Worker       assert(Src0->getType() == IceType_i32);
565*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Src0);
566*03ce13f7SAndroid Build Coastguard Worker       assert(Src1->getType() == IceType_i32);
567*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Src1);
568*03ce13f7SAndroid Build Coastguard Worker       Instr->setDeleted();
569*03ce13f7SAndroid Build Coastguard Worker       return;
570*03ce13f7SAndroid Build Coastguard Worker     }
571*03ce13f7SAndroid Build Coastguard Worker     case IceType_f64:
572*03ce13f7SAndroid Build Coastguard Worker     case IceType_f32: {
573*03ce13f7SAndroid Build Coastguard Worker       if (Op != InstArithmetic::Frem) {
574*03ce13f7SAndroid Build Coastguard Worker         return;
575*03ce13f7SAndroid Build Coastguard Worker       }
576*03ce13f7SAndroid Build Coastguard Worker       constexpr SizeT MaxArgs = 2;
577*03ce13f7SAndroid Build Coastguard Worker       Operand *TargetHelper = Ctx->getRuntimeHelperFunc(
578*03ce13f7SAndroid Build Coastguard Worker           DestTy == IceType_f32 ? RuntimeHelper::H_frem_f32
579*03ce13f7SAndroid Build Coastguard Worker                                 : RuntimeHelper::H_frem_f64);
580*03ce13f7SAndroid Build Coastguard Worker       auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
581*03ce13f7SAndroid Build Coastguard Worker                                             NoTailCall, IsTargetHelperCall);
582*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Instr->getSrc(0));
583*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Instr->getSrc(1));
584*03ce13f7SAndroid Build Coastguard Worker       Instr->setDeleted();
585*03ce13f7SAndroid Build Coastguard Worker       return;
586*03ce13f7SAndroid Build Coastguard Worker     }
587*03ce13f7SAndroid Build Coastguard Worker     }
588*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Control flow should never have reached here.");
589*03ce13f7SAndroid Build Coastguard Worker   }
590*03ce13f7SAndroid Build Coastguard Worker   case Inst::Cast: {
591*03ce13f7SAndroid Build Coastguard Worker     Variable *Dest = Instr->getDest();
592*03ce13f7SAndroid Build Coastguard Worker     Operand *Src0 = Instr->getSrc(0);
593*03ce13f7SAndroid Build Coastguard Worker     const Type DestTy = Dest->getType();
594*03ce13f7SAndroid Build Coastguard Worker     const Type SrcTy = Src0->getType();
595*03ce13f7SAndroid Build Coastguard Worker     auto *CastInstr = llvm::cast<InstCast>(Instr);
596*03ce13f7SAndroid Build Coastguard Worker     const InstCast::OpKind CastKind = CastInstr->getCastKind();
597*03ce13f7SAndroid Build Coastguard Worker 
598*03ce13f7SAndroid Build Coastguard Worker     switch (CastKind) {
599*03ce13f7SAndroid Build Coastguard Worker     default:
600*03ce13f7SAndroid Build Coastguard Worker       return;
601*03ce13f7SAndroid Build Coastguard Worker     case InstCast::Fptosi:
602*03ce13f7SAndroid Build Coastguard Worker     case InstCast::Fptoui: {
603*03ce13f7SAndroid Build Coastguard Worker       if (DestTy != IceType_i64) {
604*03ce13f7SAndroid Build Coastguard Worker         return;
605*03ce13f7SAndroid Build Coastguard Worker       }
606*03ce13f7SAndroid Build Coastguard Worker       const bool DestIsSigned = CastKind == InstCast::Fptosi;
607*03ce13f7SAndroid Build Coastguard Worker       const bool Src0IsF32 = isFloat32Asserting32Or64(SrcTy);
608*03ce13f7SAndroid Build Coastguard Worker       Operand *TargetHelper = Ctx->getRuntimeHelperFunc(
609*03ce13f7SAndroid Build Coastguard Worker           Src0IsF32 ? (DestIsSigned ? RuntimeHelper::H_fptosi_f32_i64
610*03ce13f7SAndroid Build Coastguard Worker                                     : RuntimeHelper::H_fptoui_f32_i64)
611*03ce13f7SAndroid Build Coastguard Worker                     : (DestIsSigned ? RuntimeHelper::H_fptosi_f64_i64
612*03ce13f7SAndroid Build Coastguard Worker                                     : RuntimeHelper::H_fptoui_f64_i64));
613*03ce13f7SAndroid Build Coastguard Worker       static constexpr SizeT MaxArgs = 1;
614*03ce13f7SAndroid Build Coastguard Worker       auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
615*03ce13f7SAndroid Build Coastguard Worker                                             NoTailCall, IsTargetHelperCall);
616*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Src0);
617*03ce13f7SAndroid Build Coastguard Worker       Instr->setDeleted();
618*03ce13f7SAndroid Build Coastguard Worker       return;
619*03ce13f7SAndroid Build Coastguard Worker     }
620*03ce13f7SAndroid Build Coastguard Worker     case InstCast::Sitofp:
621*03ce13f7SAndroid Build Coastguard Worker     case InstCast::Uitofp: {
622*03ce13f7SAndroid Build Coastguard Worker       if (SrcTy != IceType_i64) {
623*03ce13f7SAndroid Build Coastguard Worker         return;
624*03ce13f7SAndroid Build Coastguard Worker       }
625*03ce13f7SAndroid Build Coastguard Worker       const bool SourceIsSigned = CastKind == InstCast::Sitofp;
626*03ce13f7SAndroid Build Coastguard Worker       const bool DestIsF32 = isFloat32Asserting32Or64(Dest->getType());
627*03ce13f7SAndroid Build Coastguard Worker       Operand *TargetHelper = Ctx->getRuntimeHelperFunc(
628*03ce13f7SAndroid Build Coastguard Worker           DestIsF32 ? (SourceIsSigned ? RuntimeHelper::H_sitofp_i64_f32
629*03ce13f7SAndroid Build Coastguard Worker                                       : RuntimeHelper::H_uitofp_i64_f32)
630*03ce13f7SAndroid Build Coastguard Worker                     : (SourceIsSigned ? RuntimeHelper::H_sitofp_i64_f64
631*03ce13f7SAndroid Build Coastguard Worker                                       : RuntimeHelper::H_uitofp_i64_f64));
632*03ce13f7SAndroid Build Coastguard Worker       static constexpr SizeT MaxArgs = 1;
633*03ce13f7SAndroid Build Coastguard Worker       auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
634*03ce13f7SAndroid Build Coastguard Worker                                             NoTailCall, IsTargetHelperCall);
635*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Src0);
636*03ce13f7SAndroid Build Coastguard Worker       Instr->setDeleted();
637*03ce13f7SAndroid Build Coastguard Worker       return;
638*03ce13f7SAndroid Build Coastguard Worker     }
639*03ce13f7SAndroid Build Coastguard Worker     case InstCast::Bitcast: {
640*03ce13f7SAndroid Build Coastguard Worker       if (DestTy == SrcTy) {
641*03ce13f7SAndroid Build Coastguard Worker         return;
642*03ce13f7SAndroid Build Coastguard Worker       }
643*03ce13f7SAndroid Build Coastguard Worker       Variable *CallDest = Dest;
644*03ce13f7SAndroid Build Coastguard Worker       RuntimeHelper HelperID = RuntimeHelper::H_Num;
645*03ce13f7SAndroid Build Coastguard Worker       switch (DestTy) {
646*03ce13f7SAndroid Build Coastguard Worker       default:
647*03ce13f7SAndroid Build Coastguard Worker         return;
648*03ce13f7SAndroid Build Coastguard Worker       case IceType_i8:
649*03ce13f7SAndroid Build Coastguard Worker         assert(SrcTy == IceType_v8i1);
650*03ce13f7SAndroid Build Coastguard Worker         HelperID = RuntimeHelper::H_bitcast_8xi1_i8;
651*03ce13f7SAndroid Build Coastguard Worker         CallDest = Func->makeVariable(IceType_i32);
652*03ce13f7SAndroid Build Coastguard Worker         break;
653*03ce13f7SAndroid Build Coastguard Worker       case IceType_i16:
654*03ce13f7SAndroid Build Coastguard Worker         assert(SrcTy == IceType_v16i1);
655*03ce13f7SAndroid Build Coastguard Worker         HelperID = RuntimeHelper::H_bitcast_16xi1_i16;
656*03ce13f7SAndroid Build Coastguard Worker         CallDest = Func->makeVariable(IceType_i32);
657*03ce13f7SAndroid Build Coastguard Worker         break;
658*03ce13f7SAndroid Build Coastguard Worker       case IceType_v8i1: {
659*03ce13f7SAndroid Build Coastguard Worker         assert(SrcTy == IceType_i8);
660*03ce13f7SAndroid Build Coastguard Worker         HelperID = RuntimeHelper::H_bitcast_i8_8xi1;
661*03ce13f7SAndroid Build Coastguard Worker         Variable *Src0AsI32 = Func->makeVariable(stackSlotType());
662*03ce13f7SAndroid Build Coastguard Worker         // Arguments to functions are required to be at least 32 bits wide.
663*03ce13f7SAndroid Build Coastguard Worker         Context.insert<InstCast>(InstCast::Zext, Src0AsI32, Src0);
664*03ce13f7SAndroid Build Coastguard Worker         Src0 = Src0AsI32;
665*03ce13f7SAndroid Build Coastguard Worker       } break;
666*03ce13f7SAndroid Build Coastguard Worker       case IceType_v16i1: {
667*03ce13f7SAndroid Build Coastguard Worker         assert(SrcTy == IceType_i16);
668*03ce13f7SAndroid Build Coastguard Worker         HelperID = RuntimeHelper::H_bitcast_i16_16xi1;
669*03ce13f7SAndroid Build Coastguard Worker         Variable *Src0AsI32 = Func->makeVariable(stackSlotType());
670*03ce13f7SAndroid Build Coastguard Worker         // Arguments to functions are required to be at least 32 bits wide.
671*03ce13f7SAndroid Build Coastguard Worker         Context.insert<InstCast>(InstCast::Zext, Src0AsI32, Src0);
672*03ce13f7SAndroid Build Coastguard Worker         Src0 = Src0AsI32;
673*03ce13f7SAndroid Build Coastguard Worker       } break;
674*03ce13f7SAndroid Build Coastguard Worker       }
675*03ce13f7SAndroid Build Coastguard Worker       constexpr SizeT MaxSrcs = 1;
676*03ce13f7SAndroid Build Coastguard Worker       InstCall *Call = makeHelperCall(HelperID, CallDest, MaxSrcs);
677*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Src0);
678*03ce13f7SAndroid Build Coastguard Worker       Context.insert(Call);
679*03ce13f7SAndroid Build Coastguard Worker       // The PNaCl ABI disallows i8/i16 return types, so truncate the helper
680*03ce13f7SAndroid Build Coastguard Worker       // call result to the appropriate type as necessary.
681*03ce13f7SAndroid Build Coastguard Worker       if (CallDest->getType() != Dest->getType())
682*03ce13f7SAndroid Build Coastguard Worker         Context.insert<InstCast>(InstCast::Trunc, Dest, CallDest);
683*03ce13f7SAndroid Build Coastguard Worker       Instr->setDeleted();
684*03ce13f7SAndroid Build Coastguard Worker       return;
685*03ce13f7SAndroid Build Coastguard Worker     }
686*03ce13f7SAndroid Build Coastguard Worker     case InstCast::Trunc: {
687*03ce13f7SAndroid Build Coastguard Worker       if (DestTy == SrcTy) {
688*03ce13f7SAndroid Build Coastguard Worker         return;
689*03ce13f7SAndroid Build Coastguard Worker       }
690*03ce13f7SAndroid Build Coastguard Worker       if (!isVectorType(SrcTy)) {
691*03ce13f7SAndroid Build Coastguard Worker         return;
692*03ce13f7SAndroid Build Coastguard Worker       }
693*03ce13f7SAndroid Build Coastguard Worker       assert(typeNumElements(DestTy) == typeNumElements(SrcTy));
694*03ce13f7SAndroid Build Coastguard Worker       assert(typeElementType(DestTy) == IceType_i1);
695*03ce13f7SAndroid Build Coastguard Worker       assert(isVectorIntegerType(SrcTy));
696*03ce13f7SAndroid Build Coastguard Worker       return;
697*03ce13f7SAndroid Build Coastguard Worker     }
698*03ce13f7SAndroid Build Coastguard Worker     case InstCast::Sext:
699*03ce13f7SAndroid Build Coastguard Worker     case InstCast::Zext: {
700*03ce13f7SAndroid Build Coastguard Worker       if (DestTy == SrcTy) {
701*03ce13f7SAndroid Build Coastguard Worker         return;
702*03ce13f7SAndroid Build Coastguard Worker       }
703*03ce13f7SAndroid Build Coastguard Worker       if (!isVectorType(DestTy)) {
704*03ce13f7SAndroid Build Coastguard Worker         return;
705*03ce13f7SAndroid Build Coastguard Worker       }
706*03ce13f7SAndroid Build Coastguard Worker       assert(typeNumElements(DestTy) == typeNumElements(SrcTy));
707*03ce13f7SAndroid Build Coastguard Worker       assert(typeElementType(SrcTy) == IceType_i1);
708*03ce13f7SAndroid Build Coastguard Worker       assert(isVectorIntegerType(DestTy));
709*03ce13f7SAndroid Build Coastguard Worker       return;
710*03ce13f7SAndroid Build Coastguard Worker     }
711*03ce13f7SAndroid Build Coastguard Worker     }
712*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Control flow should never have reached here.");
713*03ce13f7SAndroid Build Coastguard Worker   }
714*03ce13f7SAndroid Build Coastguard Worker   case Inst::Intrinsic: {
715*03ce13f7SAndroid Build Coastguard Worker     Variable *Dest = Instr->getDest();
716*03ce13f7SAndroid Build Coastguard Worker     auto *Intrinsic = llvm::cast<InstIntrinsic>(Instr);
717*03ce13f7SAndroid Build Coastguard Worker     Intrinsics::IntrinsicID ID = Intrinsic->getIntrinsicID();
718*03ce13f7SAndroid Build Coastguard Worker     switch (ID) {
719*03ce13f7SAndroid Build Coastguard Worker     default:
720*03ce13f7SAndroid Build Coastguard Worker       return;
721*03ce13f7SAndroid Build Coastguard Worker     case Intrinsics::Ctpop: {
722*03ce13f7SAndroid Build Coastguard Worker       Operand *Src0 = Intrinsic->getArg(0);
723*03ce13f7SAndroid Build Coastguard Worker       Operand *TargetHelper =
724*03ce13f7SAndroid Build Coastguard Worker           Ctx->getRuntimeHelperFunc(isInt32Asserting32Or64(Src0->getType())
725*03ce13f7SAndroid Build Coastguard Worker                                         ? RuntimeHelper::H_call_ctpop_i32
726*03ce13f7SAndroid Build Coastguard Worker                                         : RuntimeHelper::H_call_ctpop_i64);
727*03ce13f7SAndroid Build Coastguard Worker       static constexpr SizeT MaxArgs = 1;
728*03ce13f7SAndroid Build Coastguard Worker       auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
729*03ce13f7SAndroid Build Coastguard Worker                                             NoTailCall, IsTargetHelperCall);
730*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Src0);
731*03ce13f7SAndroid Build Coastguard Worker       Instr->setDeleted();
732*03ce13f7SAndroid Build Coastguard Worker       if (Src0->getType() == IceType_i64) {
733*03ce13f7SAndroid Build Coastguard Worker         ARM32HelpersPostamble[TargetHelper] = &TargetARM32::postambleCtpop64;
734*03ce13f7SAndroid Build Coastguard Worker       }
735*03ce13f7SAndroid Build Coastguard Worker       return;
736*03ce13f7SAndroid Build Coastguard Worker     }
737*03ce13f7SAndroid Build Coastguard Worker     case Intrinsics::Longjmp: {
738*03ce13f7SAndroid Build Coastguard Worker       static constexpr SizeT MaxArgs = 2;
739*03ce13f7SAndroid Build Coastguard Worker       static constexpr Variable *NoDest = nullptr;
740*03ce13f7SAndroid Build Coastguard Worker       Operand *TargetHelper =
741*03ce13f7SAndroid Build Coastguard Worker           Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_longjmp);
742*03ce13f7SAndroid Build Coastguard Worker       auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper,
743*03ce13f7SAndroid Build Coastguard Worker                                             NoTailCall, IsTargetHelperCall);
744*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Intrinsic->getArg(0));
745*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Intrinsic->getArg(1));
746*03ce13f7SAndroid Build Coastguard Worker       Instr->setDeleted();
747*03ce13f7SAndroid Build Coastguard Worker       return;
748*03ce13f7SAndroid Build Coastguard Worker     }
749*03ce13f7SAndroid Build Coastguard Worker     case Intrinsics::Memcpy: {
750*03ce13f7SAndroid Build Coastguard Worker       // In the future, we could potentially emit an inline memcpy/memset, etc.
751*03ce13f7SAndroid Build Coastguard Worker       // for intrinsic calls w/ a known length.
752*03ce13f7SAndroid Build Coastguard Worker       static constexpr SizeT MaxArgs = 3;
753*03ce13f7SAndroid Build Coastguard Worker       static constexpr Variable *NoDest = nullptr;
754*03ce13f7SAndroid Build Coastguard Worker       Operand *TargetHelper =
755*03ce13f7SAndroid Build Coastguard Worker           Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_memcpy);
756*03ce13f7SAndroid Build Coastguard Worker       auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper,
757*03ce13f7SAndroid Build Coastguard Worker                                             NoTailCall, IsTargetHelperCall);
758*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Intrinsic->getArg(0));
759*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Intrinsic->getArg(1));
760*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Intrinsic->getArg(2));
761*03ce13f7SAndroid Build Coastguard Worker       Instr->setDeleted();
762*03ce13f7SAndroid Build Coastguard Worker       return;
763*03ce13f7SAndroid Build Coastguard Worker     }
764*03ce13f7SAndroid Build Coastguard Worker     case Intrinsics::Memmove: {
765*03ce13f7SAndroid Build Coastguard Worker       static constexpr SizeT MaxArgs = 3;
766*03ce13f7SAndroid Build Coastguard Worker       static constexpr Variable *NoDest = nullptr;
767*03ce13f7SAndroid Build Coastguard Worker       Operand *TargetHelper =
768*03ce13f7SAndroid Build Coastguard Worker           Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_memmove);
769*03ce13f7SAndroid Build Coastguard Worker       auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper,
770*03ce13f7SAndroid Build Coastguard Worker                                             NoTailCall, IsTargetHelperCall);
771*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Intrinsic->getArg(0));
772*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Intrinsic->getArg(1));
773*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Intrinsic->getArg(2));
774*03ce13f7SAndroid Build Coastguard Worker       Instr->setDeleted();
775*03ce13f7SAndroid Build Coastguard Worker       return;
776*03ce13f7SAndroid Build Coastguard Worker     }
777*03ce13f7SAndroid Build Coastguard Worker     case Intrinsics::Memset: {
778*03ce13f7SAndroid Build Coastguard Worker       // The value operand needs to be extended to a stack slot size because the
779*03ce13f7SAndroid Build Coastguard Worker       // PNaCl ABI requires arguments to be at least 32 bits wide.
780*03ce13f7SAndroid Build Coastguard Worker       Operand *ValOp = Intrinsic->getArg(1);
781*03ce13f7SAndroid Build Coastguard Worker       assert(ValOp->getType() == IceType_i8);
782*03ce13f7SAndroid Build Coastguard Worker       Variable *ValExt = Func->makeVariable(stackSlotType());
783*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstCast>(InstCast::Zext, ValExt, ValOp);
784*03ce13f7SAndroid Build Coastguard Worker 
785*03ce13f7SAndroid Build Coastguard Worker       // Technically, ARM has its own __aeabi_memset, but we can use plain
786*03ce13f7SAndroid Build Coastguard Worker       // memset too. The value and size argument need to be flipped if we ever
787*03ce13f7SAndroid Build Coastguard Worker       // decide to use __aeabi_memset.
788*03ce13f7SAndroid Build Coastguard Worker       static constexpr SizeT MaxArgs = 3;
789*03ce13f7SAndroid Build Coastguard Worker       static constexpr Variable *NoDest = nullptr;
790*03ce13f7SAndroid Build Coastguard Worker       Operand *TargetHelper =
791*03ce13f7SAndroid Build Coastguard Worker           Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_memset);
792*03ce13f7SAndroid Build Coastguard Worker       auto *Call = Context.insert<InstCall>(MaxArgs, NoDest, TargetHelper,
793*03ce13f7SAndroid Build Coastguard Worker                                             NoTailCall, IsTargetHelperCall);
794*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Intrinsic->getArg(0));
795*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(ValExt);
796*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Intrinsic->getArg(2));
797*03ce13f7SAndroid Build Coastguard Worker       Instr->setDeleted();
798*03ce13f7SAndroid Build Coastguard Worker       return;
799*03ce13f7SAndroid Build Coastguard Worker     }
800*03ce13f7SAndroid Build Coastguard Worker     case Intrinsics::Setjmp: {
801*03ce13f7SAndroid Build Coastguard Worker       static constexpr SizeT MaxArgs = 1;
802*03ce13f7SAndroid Build Coastguard Worker       Operand *TargetHelper =
803*03ce13f7SAndroid Build Coastguard Worker           Ctx->getRuntimeHelperFunc(RuntimeHelper::H_call_setjmp);
804*03ce13f7SAndroid Build Coastguard Worker       auto *Call = Context.insert<InstCall>(MaxArgs, Dest, TargetHelper,
805*03ce13f7SAndroid Build Coastguard Worker                                             NoTailCall, IsTargetHelperCall);
806*03ce13f7SAndroid Build Coastguard Worker       Call->addArg(Intrinsic->getArg(0));
807*03ce13f7SAndroid Build Coastguard Worker       Instr->setDeleted();
808*03ce13f7SAndroid Build Coastguard Worker       return;
809*03ce13f7SAndroid Build Coastguard Worker     }
810*03ce13f7SAndroid Build Coastguard Worker     }
811*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Control flow should never have reached here.");
812*03ce13f7SAndroid Build Coastguard Worker   }
813*03ce13f7SAndroid Build Coastguard Worker   }
814*03ce13f7SAndroid Build Coastguard Worker }
815*03ce13f7SAndroid Build Coastguard Worker 
findMaxStackOutArgsSize()816*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::findMaxStackOutArgsSize() {
817*03ce13f7SAndroid Build Coastguard Worker   // MinNeededOutArgsBytes should be updated if the Target ever creates a
818*03ce13f7SAndroid Build Coastguard Worker   // high-level InstCall that requires more stack bytes.
819*03ce13f7SAndroid Build Coastguard Worker   constexpr size_t MinNeededOutArgsBytes = 0;
820*03ce13f7SAndroid Build Coastguard Worker   MaxOutArgsSizeBytes = MinNeededOutArgsBytes;
821*03ce13f7SAndroid Build Coastguard Worker   for (CfgNode *Node : Func->getNodes()) {
822*03ce13f7SAndroid Build Coastguard Worker     Context.init(Node);
823*03ce13f7SAndroid Build Coastguard Worker     while (!Context.atEnd()) {
824*03ce13f7SAndroid Build Coastguard Worker       PostIncrLoweringContext PostIncrement(Context);
825*03ce13f7SAndroid Build Coastguard Worker       Inst *CurInstr = iteratorToInst(Context.getCur());
826*03ce13f7SAndroid Build Coastguard Worker       if (auto *Call = llvm::dyn_cast<InstCall>(CurInstr)) {
827*03ce13f7SAndroid Build Coastguard Worker         SizeT OutArgsSizeBytes = getCallStackArgumentsSizeBytes(Call);
828*03ce13f7SAndroid Build Coastguard Worker         MaxOutArgsSizeBytes = std::max(MaxOutArgsSizeBytes, OutArgsSizeBytes);
829*03ce13f7SAndroid Build Coastguard Worker       }
830*03ce13f7SAndroid Build Coastguard Worker     }
831*03ce13f7SAndroid Build Coastguard Worker   }
832*03ce13f7SAndroid Build Coastguard Worker }
833*03ce13f7SAndroid Build Coastguard Worker 
834*03ce13f7SAndroid Build Coastguard Worker GlobalString
createGotoffRelocation(const ConstantRelocatable * CR)835*03ce13f7SAndroid Build Coastguard Worker TargetARM32::createGotoffRelocation(const ConstantRelocatable *CR) {
836*03ce13f7SAndroid Build Coastguard Worker   GlobalString CRName = CR->getName();
837*03ce13f7SAndroid Build Coastguard Worker   GlobalString CRGotoffName =
838*03ce13f7SAndroid Build Coastguard Worker       Ctx->getGlobalString("GOTOFF$" + Func->getFunctionName() + "$" + CRName);
839*03ce13f7SAndroid Build Coastguard Worker   if (KnownGotoffs.count(CRGotoffName) == 0) {
840*03ce13f7SAndroid Build Coastguard Worker     constexpr bool SuppressMangling = true;
841*03ce13f7SAndroid Build Coastguard Worker     auto *Global =
842*03ce13f7SAndroid Build Coastguard Worker         VariableDeclaration::create(Func->getGlobalPool(), SuppressMangling);
843*03ce13f7SAndroid Build Coastguard Worker     Global->setIsConstant(true);
844*03ce13f7SAndroid Build Coastguard Worker     Global->setName(CRName);
845*03ce13f7SAndroid Build Coastguard Worker     Func->getGlobalPool()->willNotBeEmitted(Global);
846*03ce13f7SAndroid Build Coastguard Worker 
847*03ce13f7SAndroid Build Coastguard Worker     auto *Gotoff =
848*03ce13f7SAndroid Build Coastguard Worker         VariableDeclaration::create(Func->getGlobalPool(), SuppressMangling);
849*03ce13f7SAndroid Build Coastguard Worker     constexpr auto GotFixup = R_ARM_GOTOFF32;
850*03ce13f7SAndroid Build Coastguard Worker     Gotoff->setIsConstant(true);
851*03ce13f7SAndroid Build Coastguard Worker     Gotoff->addInitializer(VariableDeclaration::RelocInitializer::create(
852*03ce13f7SAndroid Build Coastguard Worker         Func->getGlobalPool(), Global, {RelocOffset::create(Ctx, 0)},
853*03ce13f7SAndroid Build Coastguard Worker         GotFixup));
854*03ce13f7SAndroid Build Coastguard Worker     Gotoff->setName(CRGotoffName);
855*03ce13f7SAndroid Build Coastguard Worker     Func->addGlobal(Gotoff);
856*03ce13f7SAndroid Build Coastguard Worker     KnownGotoffs.emplace(CRGotoffName);
857*03ce13f7SAndroid Build Coastguard Worker   }
858*03ce13f7SAndroid Build Coastguard Worker   return CRGotoffName;
859*03ce13f7SAndroid Build Coastguard Worker }
860*03ce13f7SAndroid Build Coastguard Worker 
translateO2()861*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::translateO2() {
862*03ce13f7SAndroid Build Coastguard Worker   TimerMarker T(TimerStack::TT_O2, Func);
863*03ce13f7SAndroid Build Coastguard Worker 
864*03ce13f7SAndroid Build Coastguard Worker   genTargetHelperCalls();
865*03ce13f7SAndroid Build Coastguard Worker   findMaxStackOutArgsSize();
866*03ce13f7SAndroid Build Coastguard Worker 
867*03ce13f7SAndroid Build Coastguard Worker   // Do not merge Alloca instructions, and lay out the stack.
868*03ce13f7SAndroid Build Coastguard Worker   static constexpr bool SortAndCombineAllocas = true;
869*03ce13f7SAndroid Build Coastguard Worker   Func->processAllocas(SortAndCombineAllocas);
870*03ce13f7SAndroid Build Coastguard Worker   Func->dump("After Alloca processing");
871*03ce13f7SAndroid Build Coastguard Worker 
872*03ce13f7SAndroid Build Coastguard Worker   if (!getFlags().getEnablePhiEdgeSplit()) {
873*03ce13f7SAndroid Build Coastguard Worker     // Lower Phi instructions.
874*03ce13f7SAndroid Build Coastguard Worker     Func->placePhiLoads();
875*03ce13f7SAndroid Build Coastguard Worker     if (Func->hasError())
876*03ce13f7SAndroid Build Coastguard Worker       return;
877*03ce13f7SAndroid Build Coastguard Worker     Func->placePhiStores();
878*03ce13f7SAndroid Build Coastguard Worker     if (Func->hasError())
879*03ce13f7SAndroid Build Coastguard Worker       return;
880*03ce13f7SAndroid Build Coastguard Worker     Func->deletePhis();
881*03ce13f7SAndroid Build Coastguard Worker     if (Func->hasError())
882*03ce13f7SAndroid Build Coastguard Worker       return;
883*03ce13f7SAndroid Build Coastguard Worker     Func->dump("After Phi lowering");
884*03ce13f7SAndroid Build Coastguard Worker   }
885*03ce13f7SAndroid Build Coastguard Worker 
886*03ce13f7SAndroid Build Coastguard Worker   // Address mode optimization.
887*03ce13f7SAndroid Build Coastguard Worker   Func->getVMetadata()->init(VMK_SingleDefs);
888*03ce13f7SAndroid Build Coastguard Worker   Func->doAddressOpt();
889*03ce13f7SAndroid Build Coastguard Worker   Func->materializeVectorShuffles();
890*03ce13f7SAndroid Build Coastguard Worker 
891*03ce13f7SAndroid Build Coastguard Worker   // Argument lowering
892*03ce13f7SAndroid Build Coastguard Worker   Func->doArgLowering();
893*03ce13f7SAndroid Build Coastguard Worker 
894*03ce13f7SAndroid Build Coastguard Worker   // Target lowering. This requires liveness analysis for some parts of the
895*03ce13f7SAndroid Build Coastguard Worker   // lowering decisions, such as compare/branch fusing. If non-lightweight
896*03ce13f7SAndroid Build Coastguard Worker   // liveness analysis is used, the instructions need to be renumbered first.
897*03ce13f7SAndroid Build Coastguard Worker   // TODO: This renumbering should only be necessary if we're actually
898*03ce13f7SAndroid Build Coastguard Worker   // calculating live intervals, which we only do for register allocation.
899*03ce13f7SAndroid Build Coastguard Worker   Func->renumberInstructions();
900*03ce13f7SAndroid Build Coastguard Worker   if (Func->hasError())
901*03ce13f7SAndroid Build Coastguard Worker     return;
902*03ce13f7SAndroid Build Coastguard Worker 
903*03ce13f7SAndroid Build Coastguard Worker   // TODO: It should be sufficient to use the fastest liveness calculation,
904*03ce13f7SAndroid Build Coastguard Worker   // i.e. livenessLightweight(). However, for some reason that slows down the
905*03ce13f7SAndroid Build Coastguard Worker   // rest of the translation. Investigate.
906*03ce13f7SAndroid Build Coastguard Worker   Func->liveness(Liveness_Basic);
907*03ce13f7SAndroid Build Coastguard Worker   if (Func->hasError())
908*03ce13f7SAndroid Build Coastguard Worker     return;
909*03ce13f7SAndroid Build Coastguard Worker   Func->dump("After ARM32 address mode opt");
910*03ce13f7SAndroid Build Coastguard Worker 
911*03ce13f7SAndroid Build Coastguard Worker   Func->genCode();
912*03ce13f7SAndroid Build Coastguard Worker   if (Func->hasError())
913*03ce13f7SAndroid Build Coastguard Worker     return;
914*03ce13f7SAndroid Build Coastguard Worker   Func->dump("After ARM32 codegen");
915*03ce13f7SAndroid Build Coastguard Worker 
916*03ce13f7SAndroid Build Coastguard Worker   // Register allocation. This requires instruction renumbering and full
917*03ce13f7SAndroid Build Coastguard Worker   // liveness analysis.
918*03ce13f7SAndroid Build Coastguard Worker   Func->renumberInstructions();
919*03ce13f7SAndroid Build Coastguard Worker   if (Func->hasError())
920*03ce13f7SAndroid Build Coastguard Worker     return;
921*03ce13f7SAndroid Build Coastguard Worker   Func->liveness(Liveness_Intervals);
922*03ce13f7SAndroid Build Coastguard Worker   if (Func->hasError())
923*03ce13f7SAndroid Build Coastguard Worker     return;
924*03ce13f7SAndroid Build Coastguard Worker   // The post-codegen dump is done here, after liveness analysis and associated
925*03ce13f7SAndroid Build Coastguard Worker   // cleanup, to make the dump cleaner and more useful.
926*03ce13f7SAndroid Build Coastguard Worker   Func->dump("After initial ARM32 codegen");
927*03ce13f7SAndroid Build Coastguard Worker   // Validate the live range computations. The expensive validation call is
928*03ce13f7SAndroid Build Coastguard Worker   // deliberately only made when assertions are enabled.
929*03ce13f7SAndroid Build Coastguard Worker   assert(Func->validateLiveness());
930*03ce13f7SAndroid Build Coastguard Worker   Func->getVMetadata()->init(VMK_All);
931*03ce13f7SAndroid Build Coastguard Worker   regAlloc(RAK_Global);
932*03ce13f7SAndroid Build Coastguard Worker   if (Func->hasError())
933*03ce13f7SAndroid Build Coastguard Worker     return;
934*03ce13f7SAndroid Build Coastguard Worker 
935*03ce13f7SAndroid Build Coastguard Worker   copyRegAllocFromInfWeightVariable64On32(Func->getVariables());
936*03ce13f7SAndroid Build Coastguard Worker   Func->dump("After linear scan regalloc");
937*03ce13f7SAndroid Build Coastguard Worker 
938*03ce13f7SAndroid Build Coastguard Worker   if (getFlags().getEnablePhiEdgeSplit()) {
939*03ce13f7SAndroid Build Coastguard Worker     Func->advancedPhiLowering();
940*03ce13f7SAndroid Build Coastguard Worker     Func->dump("After advanced Phi lowering");
941*03ce13f7SAndroid Build Coastguard Worker   }
942*03ce13f7SAndroid Build Coastguard Worker 
943*03ce13f7SAndroid Build Coastguard Worker   ForbidTemporaryWithoutReg _(this);
944*03ce13f7SAndroid Build Coastguard Worker 
945*03ce13f7SAndroid Build Coastguard Worker   // Stack frame mapping.
946*03ce13f7SAndroid Build Coastguard Worker   Func->genFrame();
947*03ce13f7SAndroid Build Coastguard Worker   if (Func->hasError())
948*03ce13f7SAndroid Build Coastguard Worker     return;
949*03ce13f7SAndroid Build Coastguard Worker   Func->dump("After stack frame mapping");
950*03ce13f7SAndroid Build Coastguard Worker 
951*03ce13f7SAndroid Build Coastguard Worker   postLowerLegalization();
952*03ce13f7SAndroid Build Coastguard Worker   if (Func->hasError())
953*03ce13f7SAndroid Build Coastguard Worker     return;
954*03ce13f7SAndroid Build Coastguard Worker   Func->dump("After postLowerLegalization");
955*03ce13f7SAndroid Build Coastguard Worker 
956*03ce13f7SAndroid Build Coastguard Worker   Func->contractEmptyNodes();
957*03ce13f7SAndroid Build Coastguard Worker   Func->reorderNodes();
958*03ce13f7SAndroid Build Coastguard Worker 
959*03ce13f7SAndroid Build Coastguard Worker   // Branch optimization. This needs to be done just before code emission. In
960*03ce13f7SAndroid Build Coastguard Worker   // particular, no transformations that insert or reorder CfgNodes should be
961*03ce13f7SAndroid Build Coastguard Worker   // done after branch optimization. We go ahead and do it before nop insertion
962*03ce13f7SAndroid Build Coastguard Worker   // to reduce the amount of work needed for searching for opportunities.
963*03ce13f7SAndroid Build Coastguard Worker   Func->doBranchOpt();
964*03ce13f7SAndroid Build Coastguard Worker   Func->dump("After branch optimization");
965*03ce13f7SAndroid Build Coastguard Worker }
966*03ce13f7SAndroid Build Coastguard Worker 
translateOm1()967*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::translateOm1() {
968*03ce13f7SAndroid Build Coastguard Worker   TimerMarker T(TimerStack::TT_Om1, Func);
969*03ce13f7SAndroid Build Coastguard Worker 
970*03ce13f7SAndroid Build Coastguard Worker   genTargetHelperCalls();
971*03ce13f7SAndroid Build Coastguard Worker   findMaxStackOutArgsSize();
972*03ce13f7SAndroid Build Coastguard Worker 
973*03ce13f7SAndroid Build Coastguard Worker   // Do not merge Alloca instructions, and lay out the stack.
974*03ce13f7SAndroid Build Coastguard Worker   static constexpr bool DontSortAndCombineAllocas = false;
975*03ce13f7SAndroid Build Coastguard Worker   Func->processAllocas(DontSortAndCombineAllocas);
976*03ce13f7SAndroid Build Coastguard Worker   Func->dump("After Alloca processing");
977*03ce13f7SAndroid Build Coastguard Worker 
978*03ce13f7SAndroid Build Coastguard Worker   Func->placePhiLoads();
979*03ce13f7SAndroid Build Coastguard Worker   if (Func->hasError())
980*03ce13f7SAndroid Build Coastguard Worker     return;
981*03ce13f7SAndroid Build Coastguard Worker   Func->placePhiStores();
982*03ce13f7SAndroid Build Coastguard Worker   if (Func->hasError())
983*03ce13f7SAndroid Build Coastguard Worker     return;
984*03ce13f7SAndroid Build Coastguard Worker   Func->deletePhis();
985*03ce13f7SAndroid Build Coastguard Worker   if (Func->hasError())
986*03ce13f7SAndroid Build Coastguard Worker     return;
987*03ce13f7SAndroid Build Coastguard Worker   Func->dump("After Phi lowering");
988*03ce13f7SAndroid Build Coastguard Worker 
989*03ce13f7SAndroid Build Coastguard Worker   Func->doArgLowering();
990*03ce13f7SAndroid Build Coastguard Worker 
991*03ce13f7SAndroid Build Coastguard Worker   Func->genCode();
992*03ce13f7SAndroid Build Coastguard Worker   if (Func->hasError())
993*03ce13f7SAndroid Build Coastguard Worker     return;
994*03ce13f7SAndroid Build Coastguard Worker   Func->dump("After initial ARM32 codegen");
995*03ce13f7SAndroid Build Coastguard Worker 
996*03ce13f7SAndroid Build Coastguard Worker   regAlloc(RAK_InfOnly);
997*03ce13f7SAndroid Build Coastguard Worker   if (Func->hasError())
998*03ce13f7SAndroid Build Coastguard Worker     return;
999*03ce13f7SAndroid Build Coastguard Worker 
1000*03ce13f7SAndroid Build Coastguard Worker   copyRegAllocFromInfWeightVariable64On32(Func->getVariables());
1001*03ce13f7SAndroid Build Coastguard Worker   Func->dump("After regalloc of infinite-weight variables");
1002*03ce13f7SAndroid Build Coastguard Worker 
1003*03ce13f7SAndroid Build Coastguard Worker   ForbidTemporaryWithoutReg _(this);
1004*03ce13f7SAndroid Build Coastguard Worker 
1005*03ce13f7SAndroid Build Coastguard Worker   Func->genFrame();
1006*03ce13f7SAndroid Build Coastguard Worker   if (Func->hasError())
1007*03ce13f7SAndroid Build Coastguard Worker     return;
1008*03ce13f7SAndroid Build Coastguard Worker   Func->dump("After stack frame mapping");
1009*03ce13f7SAndroid Build Coastguard Worker 
1010*03ce13f7SAndroid Build Coastguard Worker   postLowerLegalization();
1011*03ce13f7SAndroid Build Coastguard Worker   if (Func->hasError())
1012*03ce13f7SAndroid Build Coastguard Worker     return;
1013*03ce13f7SAndroid Build Coastguard Worker   Func->dump("After postLowerLegalization");
1014*03ce13f7SAndroid Build Coastguard Worker }
1015*03ce13f7SAndroid Build Coastguard Worker 
getStackAlignment() const1016*03ce13f7SAndroid Build Coastguard Worker uint32_t TargetARM32::getStackAlignment() const {
1017*03ce13f7SAndroid Build Coastguard Worker   return ARM32_STACK_ALIGNMENT_BYTES;
1018*03ce13f7SAndroid Build Coastguard Worker }
1019*03ce13f7SAndroid Build Coastguard Worker 
doBranchOpt(Inst * I,const CfgNode * NextNode)1020*03ce13f7SAndroid Build Coastguard Worker bool TargetARM32::doBranchOpt(Inst *I, const CfgNode *NextNode) {
1021*03ce13f7SAndroid Build Coastguard Worker   if (auto *Br = llvm::dyn_cast<InstARM32Br>(I)) {
1022*03ce13f7SAndroid Build Coastguard Worker     return Br->optimizeBranch(NextNode);
1023*03ce13f7SAndroid Build Coastguard Worker   }
1024*03ce13f7SAndroid Build Coastguard Worker   return false;
1025*03ce13f7SAndroid Build Coastguard Worker }
1026*03ce13f7SAndroid Build Coastguard Worker 
getRegName(RegNumT RegNum,Type Ty) const1027*03ce13f7SAndroid Build Coastguard Worker const char *TargetARM32::getRegName(RegNumT RegNum, Type Ty) const {
1028*03ce13f7SAndroid Build Coastguard Worker   (void)Ty;
1029*03ce13f7SAndroid Build Coastguard Worker   return RegARM32::getRegName(RegNum);
1030*03ce13f7SAndroid Build Coastguard Worker }
1031*03ce13f7SAndroid Build Coastguard Worker 
getPhysicalRegister(RegNumT RegNum,Type Ty)1032*03ce13f7SAndroid Build Coastguard Worker Variable *TargetARM32::getPhysicalRegister(RegNumT RegNum, Type Ty) {
1033*03ce13f7SAndroid Build Coastguard Worker   static const Type DefaultType[] = {
1034*03ce13f7SAndroid Build Coastguard Worker #define X(val, encode, name, cc_arg, scratch, preserved, stackptr, frameptr,   \
1035*03ce13f7SAndroid Build Coastguard Worker           isGPR, isInt, isI64Pair, isFP32, isFP64, isVec128, alias_init)       \
1036*03ce13f7SAndroid Build Coastguard Worker   (isFP32)                                                                     \
1037*03ce13f7SAndroid Build Coastguard Worker       ? IceType_f32                                                            \
1038*03ce13f7SAndroid Build Coastguard Worker       : ((isFP64) ? IceType_f64 : ((isVec128 ? IceType_v4i32 : IceType_i32))),
1039*03ce13f7SAndroid Build Coastguard Worker       REGARM32_TABLE
1040*03ce13f7SAndroid Build Coastguard Worker #undef X
1041*03ce13f7SAndroid Build Coastguard Worker   };
1042*03ce13f7SAndroid Build Coastguard Worker 
1043*03ce13f7SAndroid Build Coastguard Worker   if (Ty == IceType_void) {
1044*03ce13f7SAndroid Build Coastguard Worker     assert(unsigned(RegNum) < llvm::array_lengthof(DefaultType));
1045*03ce13f7SAndroid Build Coastguard Worker     Ty = DefaultType[RegNum];
1046*03ce13f7SAndroid Build Coastguard Worker   }
1047*03ce13f7SAndroid Build Coastguard Worker   if (PhysicalRegisters[Ty].empty())
1048*03ce13f7SAndroid Build Coastguard Worker     PhysicalRegisters[Ty].resize(RegARM32::Reg_NUM);
1049*03ce13f7SAndroid Build Coastguard Worker   assert(unsigned(RegNum) < PhysicalRegisters[Ty].size());
1050*03ce13f7SAndroid Build Coastguard Worker   Variable *Reg = PhysicalRegisters[Ty][RegNum];
1051*03ce13f7SAndroid Build Coastguard Worker   if (Reg == nullptr) {
1052*03ce13f7SAndroid Build Coastguard Worker     Reg = Func->makeVariable(Ty);
1053*03ce13f7SAndroid Build Coastguard Worker     Reg->setRegNum(RegNum);
1054*03ce13f7SAndroid Build Coastguard Worker     PhysicalRegisters[Ty][RegNum] = Reg;
1055*03ce13f7SAndroid Build Coastguard Worker     // Specially mark a named physical register as an "argument" so that it is
1056*03ce13f7SAndroid Build Coastguard Worker     // considered live upon function entry.  Otherwise it's possible to get
1057*03ce13f7SAndroid Build Coastguard Worker     // liveness validation errors for saving callee-save registers.
1058*03ce13f7SAndroid Build Coastguard Worker     Func->addImplicitArg(Reg);
1059*03ce13f7SAndroid Build Coastguard Worker     // Don't bother tracking the live range of a named physical register.
1060*03ce13f7SAndroid Build Coastguard Worker     Reg->setIgnoreLiveness();
1061*03ce13f7SAndroid Build Coastguard Worker   }
1062*03ce13f7SAndroid Build Coastguard Worker   return Reg;
1063*03ce13f7SAndroid Build Coastguard Worker }
1064*03ce13f7SAndroid Build Coastguard Worker 
emitJumpTable(const Cfg * Func,const InstJumpTable * JumpTable) const1065*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::emitJumpTable(const Cfg *Func,
1066*03ce13f7SAndroid Build Coastguard Worker                                 const InstJumpTable *JumpTable) const {
1067*03ce13f7SAndroid Build Coastguard Worker   (void)Func;
1068*03ce13f7SAndroid Build Coastguard Worker   (void)JumpTable;
1069*03ce13f7SAndroid Build Coastguard Worker   UnimplementedError(getFlags());
1070*03ce13f7SAndroid Build Coastguard Worker }
1071*03ce13f7SAndroid Build Coastguard Worker 
emitVariable(const Variable * Var) const1072*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::emitVariable(const Variable *Var) const {
1073*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::dump())
1074*03ce13f7SAndroid Build Coastguard Worker     return;
1075*03ce13f7SAndroid Build Coastguard Worker   Ostream &Str = Ctx->getStrEmit();
1076*03ce13f7SAndroid Build Coastguard Worker   if (Var->hasReg()) {
1077*03ce13f7SAndroid Build Coastguard Worker     Str << getRegName(Var->getRegNum(), Var->getType());
1078*03ce13f7SAndroid Build Coastguard Worker     return;
1079*03ce13f7SAndroid Build Coastguard Worker   }
1080*03ce13f7SAndroid Build Coastguard Worker   if (Var->mustHaveReg()) {
1081*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Infinite-weight Variable (" + Var->getName() +
1082*03ce13f7SAndroid Build Coastguard Worker                              ") has no register assigned - function " +
1083*03ce13f7SAndroid Build Coastguard Worker                              Func->getFunctionName());
1084*03ce13f7SAndroid Build Coastguard Worker   }
1085*03ce13f7SAndroid Build Coastguard Worker   assert(!Var->isRematerializable());
1086*03ce13f7SAndroid Build Coastguard Worker   int32_t Offset = Var->getStackOffset();
1087*03ce13f7SAndroid Build Coastguard Worker   auto BaseRegNum = Var->getBaseRegNum();
1088*03ce13f7SAndroid Build Coastguard Worker   if (BaseRegNum.hasNoValue()) {
1089*03ce13f7SAndroid Build Coastguard Worker     BaseRegNum = getFrameOrStackReg();
1090*03ce13f7SAndroid Build Coastguard Worker   }
1091*03ce13f7SAndroid Build Coastguard Worker   const Type VarTy = Var->getType();
1092*03ce13f7SAndroid Build Coastguard Worker   Str << "[" << getRegName(BaseRegNum, VarTy);
1093*03ce13f7SAndroid Build Coastguard Worker   if (Offset != 0) {
1094*03ce13f7SAndroid Build Coastguard Worker     Str << ", #" << Offset;
1095*03ce13f7SAndroid Build Coastguard Worker   }
1096*03ce13f7SAndroid Build Coastguard Worker   Str << "]";
1097*03ce13f7SAndroid Build Coastguard Worker }
1098*03ce13f7SAndroid Build Coastguard Worker 
CallingConv()1099*03ce13f7SAndroid Build Coastguard Worker TargetARM32::CallingConv::CallingConv()
1100*03ce13f7SAndroid Build Coastguard Worker     : GPRegsUsed(RegARM32::Reg_NUM),
1101*03ce13f7SAndroid Build Coastguard Worker       GPRArgs(GPRArgInitializer.rbegin(), GPRArgInitializer.rend()),
1102*03ce13f7SAndroid Build Coastguard Worker       I64Args(I64ArgInitializer.rbegin(), I64ArgInitializer.rend()),
1103*03ce13f7SAndroid Build Coastguard Worker       VFPRegsUsed(RegARM32::Reg_NUM),
1104*03ce13f7SAndroid Build Coastguard Worker       FP32Args(FP32ArgInitializer.rbegin(), FP32ArgInitializer.rend()),
1105*03ce13f7SAndroid Build Coastguard Worker       FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()),
1106*03ce13f7SAndroid Build Coastguard Worker       Vec128Args(Vec128ArgInitializer.rbegin(), Vec128ArgInitializer.rend()) {}
1107*03ce13f7SAndroid Build Coastguard Worker 
argInGPR(Type Ty,RegNumT * Reg)1108*03ce13f7SAndroid Build Coastguard Worker bool TargetARM32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) {
1109*03ce13f7SAndroid Build Coastguard Worker   CfgVector<RegNumT> *Source;
1110*03ce13f7SAndroid Build Coastguard Worker 
1111*03ce13f7SAndroid Build Coastguard Worker   switch (Ty) {
1112*03ce13f7SAndroid Build Coastguard Worker   default: {
1113*03ce13f7SAndroid Build Coastguard Worker     assert(isScalarIntegerType(Ty));
1114*03ce13f7SAndroid Build Coastguard Worker     Source = &GPRArgs;
1115*03ce13f7SAndroid Build Coastguard Worker   } break;
1116*03ce13f7SAndroid Build Coastguard Worker   case IceType_i64: {
1117*03ce13f7SAndroid Build Coastguard Worker     Source = &I64Args;
1118*03ce13f7SAndroid Build Coastguard Worker   } break;
1119*03ce13f7SAndroid Build Coastguard Worker   }
1120*03ce13f7SAndroid Build Coastguard Worker 
1121*03ce13f7SAndroid Build Coastguard Worker   discardUnavailableGPRsAndTheirAliases(Source);
1122*03ce13f7SAndroid Build Coastguard Worker 
1123*03ce13f7SAndroid Build Coastguard Worker   if (Source->empty()) {
1124*03ce13f7SAndroid Build Coastguard Worker     GPRegsUsed.set();
1125*03ce13f7SAndroid Build Coastguard Worker     return false;
1126*03ce13f7SAndroid Build Coastguard Worker   }
1127*03ce13f7SAndroid Build Coastguard Worker 
1128*03ce13f7SAndroid Build Coastguard Worker   *Reg = Source->back();
1129*03ce13f7SAndroid Build Coastguard Worker   // Note that we don't Source->pop_back() here. This is intentional. Notice how
1130*03ce13f7SAndroid Build Coastguard Worker   // we mark all of Reg's aliases as Used. So, for the next argument,
1131*03ce13f7SAndroid Build Coastguard Worker   // Source->back() is marked as unavailable, and it is thus implicitly popped
1132*03ce13f7SAndroid Build Coastguard Worker   // from the stack.
1133*03ce13f7SAndroid Build Coastguard Worker   GPRegsUsed |= RegisterAliases[*Reg];
1134*03ce13f7SAndroid Build Coastguard Worker   return true;
1135*03ce13f7SAndroid Build Coastguard Worker }
1136*03ce13f7SAndroid Build Coastguard Worker 
1137*03ce13f7SAndroid Build Coastguard Worker // GPR are not packed when passing parameters. Thus, a function foo(i32, i64,
1138*03ce13f7SAndroid Build Coastguard Worker // i32) will have the first argument in r0, the second in r1-r2, and the third
1139*03ce13f7SAndroid Build Coastguard Worker // on the stack. To model this behavior, whenever we pop a register from Regs,
1140*03ce13f7SAndroid Build Coastguard Worker // we remove all of its aliases from the pool of available GPRs. This has the
1141*03ce13f7SAndroid Build Coastguard Worker // effect of computing the "closure" on the GPR registers.
discardUnavailableGPRsAndTheirAliases(CfgVector<RegNumT> * Regs)1142*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::CallingConv::discardUnavailableGPRsAndTheirAliases(
1143*03ce13f7SAndroid Build Coastguard Worker     CfgVector<RegNumT> *Regs) {
1144*03ce13f7SAndroid Build Coastguard Worker   while (!Regs->empty() && GPRegsUsed[Regs->back()]) {
1145*03ce13f7SAndroid Build Coastguard Worker     GPRegsUsed |= RegisterAliases[Regs->back()];
1146*03ce13f7SAndroid Build Coastguard Worker     Regs->pop_back();
1147*03ce13f7SAndroid Build Coastguard Worker   }
1148*03ce13f7SAndroid Build Coastguard Worker }
1149*03ce13f7SAndroid Build Coastguard Worker 
argInVFP(Type Ty,RegNumT * Reg)1150*03ce13f7SAndroid Build Coastguard Worker bool TargetARM32::CallingConv::argInVFP(Type Ty, RegNumT *Reg) {
1151*03ce13f7SAndroid Build Coastguard Worker   CfgVector<RegNumT> *Source;
1152*03ce13f7SAndroid Build Coastguard Worker 
1153*03ce13f7SAndroid Build Coastguard Worker   switch (Ty) {
1154*03ce13f7SAndroid Build Coastguard Worker   default: {
1155*03ce13f7SAndroid Build Coastguard Worker     assert(isVectorType(Ty));
1156*03ce13f7SAndroid Build Coastguard Worker     Source = &Vec128Args;
1157*03ce13f7SAndroid Build Coastguard Worker   } break;
1158*03ce13f7SAndroid Build Coastguard Worker   case IceType_f32: {
1159*03ce13f7SAndroid Build Coastguard Worker     Source = &FP32Args;
1160*03ce13f7SAndroid Build Coastguard Worker   } break;
1161*03ce13f7SAndroid Build Coastguard Worker   case IceType_f64: {
1162*03ce13f7SAndroid Build Coastguard Worker     Source = &FP64Args;
1163*03ce13f7SAndroid Build Coastguard Worker   } break;
1164*03ce13f7SAndroid Build Coastguard Worker   }
1165*03ce13f7SAndroid Build Coastguard Worker 
1166*03ce13f7SAndroid Build Coastguard Worker   discardUnavailableVFPRegs(Source);
1167*03ce13f7SAndroid Build Coastguard Worker 
1168*03ce13f7SAndroid Build Coastguard Worker   if (Source->empty()) {
1169*03ce13f7SAndroid Build Coastguard Worker     VFPRegsUsed.set();
1170*03ce13f7SAndroid Build Coastguard Worker     return false;
1171*03ce13f7SAndroid Build Coastguard Worker   }
1172*03ce13f7SAndroid Build Coastguard Worker 
1173*03ce13f7SAndroid Build Coastguard Worker   *Reg = Source->back();
1174*03ce13f7SAndroid Build Coastguard Worker   VFPRegsUsed |= RegisterAliases[*Reg];
1175*03ce13f7SAndroid Build Coastguard Worker   return true;
1176*03ce13f7SAndroid Build Coastguard Worker }
1177*03ce13f7SAndroid Build Coastguard Worker 
1178*03ce13f7SAndroid Build Coastguard Worker // Arguments in VFP registers are not packed, so we don't mark the popped
1179*03ce13f7SAndroid Build Coastguard Worker // registers' aliases as unavailable.
discardUnavailableVFPRegs(CfgVector<RegNumT> * Regs)1180*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::CallingConv::discardUnavailableVFPRegs(
1181*03ce13f7SAndroid Build Coastguard Worker     CfgVector<RegNumT> *Regs) {
1182*03ce13f7SAndroid Build Coastguard Worker   while (!Regs->empty() && VFPRegsUsed[Regs->back()]) {
1183*03ce13f7SAndroid Build Coastguard Worker     Regs->pop_back();
1184*03ce13f7SAndroid Build Coastguard Worker   }
1185*03ce13f7SAndroid Build Coastguard Worker }
1186*03ce13f7SAndroid Build Coastguard Worker 
lowerArguments()1187*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerArguments() {
1188*03ce13f7SAndroid Build Coastguard Worker   VarList &Args = Func->getArgs();
1189*03ce13f7SAndroid Build Coastguard Worker   TargetARM32::CallingConv CC;
1190*03ce13f7SAndroid Build Coastguard Worker 
1191*03ce13f7SAndroid Build Coastguard Worker   // For each register argument, replace Arg in the argument list with the home
1192*03ce13f7SAndroid Build Coastguard Worker   // register. Then generate an instruction in the prolog to copy the home
1193*03ce13f7SAndroid Build Coastguard Worker   // register to the assigned location of Arg.
1194*03ce13f7SAndroid Build Coastguard Worker   Context.init(Func->getEntryNode());
1195*03ce13f7SAndroid Build Coastguard Worker   Context.setInsertPoint(Context.getCur());
1196*03ce13f7SAndroid Build Coastguard Worker 
1197*03ce13f7SAndroid Build Coastguard Worker   for (SizeT I = 0, E = Args.size(); I < E; ++I) {
1198*03ce13f7SAndroid Build Coastguard Worker     Variable *Arg = Args[I];
1199*03ce13f7SAndroid Build Coastguard Worker     Type Ty = Arg->getType();
1200*03ce13f7SAndroid Build Coastguard Worker     RegNumT RegNum;
1201*03ce13f7SAndroid Build Coastguard Worker     if (isScalarIntegerType(Ty)) {
1202*03ce13f7SAndroid Build Coastguard Worker       if (!CC.argInGPR(Ty, &RegNum)) {
1203*03ce13f7SAndroid Build Coastguard Worker         continue;
1204*03ce13f7SAndroid Build Coastguard Worker       }
1205*03ce13f7SAndroid Build Coastguard Worker     } else {
1206*03ce13f7SAndroid Build Coastguard Worker       if (!CC.argInVFP(Ty, &RegNum)) {
1207*03ce13f7SAndroid Build Coastguard Worker         continue;
1208*03ce13f7SAndroid Build Coastguard Worker       }
1209*03ce13f7SAndroid Build Coastguard Worker     }
1210*03ce13f7SAndroid Build Coastguard Worker 
1211*03ce13f7SAndroid Build Coastguard Worker     Variable *RegisterArg = Func->makeVariable(Ty);
1212*03ce13f7SAndroid Build Coastguard Worker     if (BuildDefs::dump()) {
1213*03ce13f7SAndroid Build Coastguard Worker       RegisterArg->setName(Func, "home_reg:" + Arg->getName());
1214*03ce13f7SAndroid Build Coastguard Worker     }
1215*03ce13f7SAndroid Build Coastguard Worker     RegisterArg->setIsArg();
1216*03ce13f7SAndroid Build Coastguard Worker     Arg->setIsArg(false);
1217*03ce13f7SAndroid Build Coastguard Worker     Args[I] = RegisterArg;
1218*03ce13f7SAndroid Build Coastguard Worker     switch (Ty) {
1219*03ce13f7SAndroid Build Coastguard Worker     default: {
1220*03ce13f7SAndroid Build Coastguard Worker       RegisterArg->setRegNum(RegNum);
1221*03ce13f7SAndroid Build Coastguard Worker     } break;
1222*03ce13f7SAndroid Build Coastguard Worker     case IceType_i64: {
1223*03ce13f7SAndroid Build Coastguard Worker       auto *RegisterArg64 = llvm::cast<Variable64On32>(RegisterArg);
1224*03ce13f7SAndroid Build Coastguard Worker       RegisterArg64->initHiLo(Func);
1225*03ce13f7SAndroid Build Coastguard Worker       RegisterArg64->getLo()->setRegNum(
1226*03ce13f7SAndroid Build Coastguard Worker           RegNumT::fixme(RegARM32::getI64PairFirstGPRNum(RegNum)));
1227*03ce13f7SAndroid Build Coastguard Worker       RegisterArg64->getHi()->setRegNum(
1228*03ce13f7SAndroid Build Coastguard Worker           RegNumT::fixme(RegARM32::getI64PairSecondGPRNum(RegNum)));
1229*03ce13f7SAndroid Build Coastguard Worker     } break;
1230*03ce13f7SAndroid Build Coastguard Worker     }
1231*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstAssign>(Arg, RegisterArg);
1232*03ce13f7SAndroid Build Coastguard Worker   }
1233*03ce13f7SAndroid Build Coastguard Worker }
1234*03ce13f7SAndroid Build Coastguard Worker 
1235*03ce13f7SAndroid Build Coastguard Worker // Helper function for addProlog().
1236*03ce13f7SAndroid Build Coastguard Worker //
1237*03ce13f7SAndroid Build Coastguard Worker // This assumes Arg is an argument passed on the stack. This sets the frame
1238*03ce13f7SAndroid Build Coastguard Worker // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an
1239*03ce13f7SAndroid Build Coastguard Worker // I64 arg that has been split into Lo and Hi components, it calls itself
1240*03ce13f7SAndroid Build Coastguard Worker // recursively on the components, taking care to handle Lo first because of the
1241*03ce13f7SAndroid Build Coastguard Worker // little-endian architecture. Lastly, this function generates an instruction
1242*03ce13f7SAndroid Build Coastguard Worker // to copy Arg into its assigned register if applicable.
finishArgumentLowering(Variable * Arg,Variable * FramePtr,size_t BasicFrameOffset,size_t * InArgsSizeBytes)1243*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::finishArgumentLowering(Variable *Arg, Variable *FramePtr,
1244*03ce13f7SAndroid Build Coastguard Worker                                          size_t BasicFrameOffset,
1245*03ce13f7SAndroid Build Coastguard Worker                                          size_t *InArgsSizeBytes) {
1246*03ce13f7SAndroid Build Coastguard Worker   const Type Ty = Arg->getType();
1247*03ce13f7SAndroid Build Coastguard Worker   *InArgsSizeBytes = applyStackAlignmentTy(*InArgsSizeBytes, Ty);
1248*03ce13f7SAndroid Build Coastguard Worker 
1249*03ce13f7SAndroid Build Coastguard Worker   if (auto *Arg64On32 = llvm::dyn_cast<Variable64On32>(Arg)) {
1250*03ce13f7SAndroid Build Coastguard Worker     Variable *const Lo = Arg64On32->getLo();
1251*03ce13f7SAndroid Build Coastguard Worker     Variable *const Hi = Arg64On32->getHi();
1252*03ce13f7SAndroid Build Coastguard Worker     finishArgumentLowering(Lo, FramePtr, BasicFrameOffset, InArgsSizeBytes);
1253*03ce13f7SAndroid Build Coastguard Worker     finishArgumentLowering(Hi, FramePtr, BasicFrameOffset, InArgsSizeBytes);
1254*03ce13f7SAndroid Build Coastguard Worker     return;
1255*03ce13f7SAndroid Build Coastguard Worker   }
1256*03ce13f7SAndroid Build Coastguard Worker   assert(Ty != IceType_i64);
1257*03ce13f7SAndroid Build Coastguard Worker 
1258*03ce13f7SAndroid Build Coastguard Worker   const int32_t ArgStackOffset = BasicFrameOffset + *InArgsSizeBytes;
1259*03ce13f7SAndroid Build Coastguard Worker   *InArgsSizeBytes += typeWidthInBytesOnStack(Ty);
1260*03ce13f7SAndroid Build Coastguard Worker 
1261*03ce13f7SAndroid Build Coastguard Worker   if (!Arg->hasReg()) {
1262*03ce13f7SAndroid Build Coastguard Worker     Arg->setStackOffset(ArgStackOffset);
1263*03ce13f7SAndroid Build Coastguard Worker     return;
1264*03ce13f7SAndroid Build Coastguard Worker   }
1265*03ce13f7SAndroid Build Coastguard Worker 
1266*03ce13f7SAndroid Build Coastguard Worker   // If the argument variable has been assigned a register, we need to copy the
1267*03ce13f7SAndroid Build Coastguard Worker   // value from the stack slot.
1268*03ce13f7SAndroid Build Coastguard Worker   Variable *Parameter = Func->makeVariable(Ty);
1269*03ce13f7SAndroid Build Coastguard Worker   Parameter->setMustNotHaveReg();
1270*03ce13f7SAndroid Build Coastguard Worker   Parameter->setStackOffset(ArgStackOffset);
1271*03ce13f7SAndroid Build Coastguard Worker   _mov(Arg, Parameter);
1272*03ce13f7SAndroid Build Coastguard Worker }
1273*03ce13f7SAndroid Build Coastguard Worker 
stackSlotType()1274*03ce13f7SAndroid Build Coastguard Worker Type TargetARM32::stackSlotType() { return IceType_i32; }
1275*03ce13f7SAndroid Build Coastguard Worker 
addProlog(CfgNode * Node)1276*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::addProlog(CfgNode *Node) {
1277*03ce13f7SAndroid Build Coastguard Worker   // Stack frame layout:
1278*03ce13f7SAndroid Build Coastguard Worker   //
1279*03ce13f7SAndroid Build Coastguard Worker   // +------------------------+
1280*03ce13f7SAndroid Build Coastguard Worker   // | 1. preserved registers |
1281*03ce13f7SAndroid Build Coastguard Worker   // +------------------------+
1282*03ce13f7SAndroid Build Coastguard Worker   // | 2. padding             |
1283*03ce13f7SAndroid Build Coastguard Worker   // +------------------------+ <--- FramePointer (if used)
1284*03ce13f7SAndroid Build Coastguard Worker   // | 3. global spill area   |
1285*03ce13f7SAndroid Build Coastguard Worker   // +------------------------+
1286*03ce13f7SAndroid Build Coastguard Worker   // | 4. padding             |
1287*03ce13f7SAndroid Build Coastguard Worker   // +------------------------+
1288*03ce13f7SAndroid Build Coastguard Worker   // | 5. local spill area    |
1289*03ce13f7SAndroid Build Coastguard Worker   // +------------------------+
1290*03ce13f7SAndroid Build Coastguard Worker   // | 6. padding             |
1291*03ce13f7SAndroid Build Coastguard Worker   // +------------------------+
1292*03ce13f7SAndroid Build Coastguard Worker   // | 7. allocas (variable)  |
1293*03ce13f7SAndroid Build Coastguard Worker   // +------------------------+
1294*03ce13f7SAndroid Build Coastguard Worker   // | 8. padding             |
1295*03ce13f7SAndroid Build Coastguard Worker   // +------------------------+
1296*03ce13f7SAndroid Build Coastguard Worker   // | 9. out args            |
1297*03ce13f7SAndroid Build Coastguard Worker   // +------------------------+ <--- StackPointer
1298*03ce13f7SAndroid Build Coastguard Worker   //
1299*03ce13f7SAndroid Build Coastguard Worker   // The following variables record the size in bytes of the given areas:
1300*03ce13f7SAndroid Build Coastguard Worker   //  * PreservedRegsSizeBytes: area 1
1301*03ce13f7SAndroid Build Coastguard Worker   //  * SpillAreaPaddingBytes:  area 2
1302*03ce13f7SAndroid Build Coastguard Worker   //  * GlobalsSize:            area 3
1303*03ce13f7SAndroid Build Coastguard Worker   //  * GlobalsAndSubsequentPaddingSize: areas 3 - 4
1304*03ce13f7SAndroid Build Coastguard Worker   //  * LocalsSpillAreaSize:    area 5
1305*03ce13f7SAndroid Build Coastguard Worker   //  * SpillAreaSizeBytes:     areas 2 - 6, and 9
1306*03ce13f7SAndroid Build Coastguard Worker   //  * MaxOutArgsSizeBytes:    area 9
1307*03ce13f7SAndroid Build Coastguard Worker   //
1308*03ce13f7SAndroid Build Coastguard Worker   // Determine stack frame offsets for each Variable without a register
1309*03ce13f7SAndroid Build Coastguard Worker   // assignment.  This can be done as one variable per stack slot.  Or, do
1310*03ce13f7SAndroid Build Coastguard Worker   // coalescing by running the register allocator again with an infinite set of
1311*03ce13f7SAndroid Build Coastguard Worker   // registers (as a side effect, this gives variables a second chance at
1312*03ce13f7SAndroid Build Coastguard Worker   // physical register assignment).
1313*03ce13f7SAndroid Build Coastguard Worker   //
1314*03ce13f7SAndroid Build Coastguard Worker   // A middle ground approach is to leverage sparsity and allocate one block of
1315*03ce13f7SAndroid Build Coastguard Worker   // space on the frame for globals (variables with multi-block lifetime), and
1316*03ce13f7SAndroid Build Coastguard Worker   // one block to share for locals (single-block lifetime).
1317*03ce13f7SAndroid Build Coastguard Worker 
1318*03ce13f7SAndroid Build Coastguard Worker   Context.init(Node);
1319*03ce13f7SAndroid Build Coastguard Worker   Context.setInsertPoint(Context.getCur());
1320*03ce13f7SAndroid Build Coastguard Worker 
1321*03ce13f7SAndroid Build Coastguard Worker   SmallBitVector CalleeSaves = getRegisterSet(RegSet_CalleeSave, RegSet_None);
1322*03ce13f7SAndroid Build Coastguard Worker   RegsUsed = SmallBitVector(CalleeSaves.size());
1323*03ce13f7SAndroid Build Coastguard Worker   VarList SortedSpilledVariables;
1324*03ce13f7SAndroid Build Coastguard Worker   size_t GlobalsSize = 0;
1325*03ce13f7SAndroid Build Coastguard Worker   // If there is a separate locals area, this represents that area. Otherwise
1326*03ce13f7SAndroid Build Coastguard Worker   // it counts any variable not counted by GlobalsSize.
1327*03ce13f7SAndroid Build Coastguard Worker   SpillAreaSizeBytes = 0;
1328*03ce13f7SAndroid Build Coastguard Worker   // If there is a separate locals area, this specifies the alignment for it.
1329*03ce13f7SAndroid Build Coastguard Worker   uint32_t LocalsSlotsAlignmentBytes = 0;
1330*03ce13f7SAndroid Build Coastguard Worker   // The entire spill locations area gets aligned to largest natural alignment
1331*03ce13f7SAndroid Build Coastguard Worker   // of the variables that have a spill slot.
1332*03ce13f7SAndroid Build Coastguard Worker   uint32_t SpillAreaAlignmentBytes = 0;
1333*03ce13f7SAndroid Build Coastguard Worker   // For now, we don't have target-specific variables that need special
1334*03ce13f7SAndroid Build Coastguard Worker   // treatment (no stack-slot-linked SpillVariable type).
1335*03ce13f7SAndroid Build Coastguard Worker   std::function<bool(Variable *)> TargetVarHook = [](Variable *Var) {
1336*03ce13f7SAndroid Build Coastguard Worker     static constexpr bool AssignStackSlot = false;
1337*03ce13f7SAndroid Build Coastguard Worker     static constexpr bool DontAssignStackSlot = !AssignStackSlot;
1338*03ce13f7SAndroid Build Coastguard Worker     if (llvm::isa<Variable64On32>(Var)) {
1339*03ce13f7SAndroid Build Coastguard Worker       return DontAssignStackSlot;
1340*03ce13f7SAndroid Build Coastguard Worker     }
1341*03ce13f7SAndroid Build Coastguard Worker     return AssignStackSlot;
1342*03ce13f7SAndroid Build Coastguard Worker   };
1343*03ce13f7SAndroid Build Coastguard Worker 
1344*03ce13f7SAndroid Build Coastguard Worker   // Compute the list of spilled variables and bounds for GlobalsSize, etc.
1345*03ce13f7SAndroid Build Coastguard Worker   getVarStackSlotParams(SortedSpilledVariables, RegsUsed, &GlobalsSize,
1346*03ce13f7SAndroid Build Coastguard Worker                         &SpillAreaSizeBytes, &SpillAreaAlignmentBytes,
1347*03ce13f7SAndroid Build Coastguard Worker                         &LocalsSlotsAlignmentBytes, TargetVarHook);
1348*03ce13f7SAndroid Build Coastguard Worker   uint32_t LocalsSpillAreaSize = SpillAreaSizeBytes;
1349*03ce13f7SAndroid Build Coastguard Worker   SpillAreaSizeBytes += GlobalsSize;
1350*03ce13f7SAndroid Build Coastguard Worker 
1351*03ce13f7SAndroid Build Coastguard Worker   // Add push instructions for preserved registers. On ARM, "push" can push a
1352*03ce13f7SAndroid Build Coastguard Worker   // whole list of GPRs via a bitmask (0-15). Unlike x86, ARM also has
1353*03ce13f7SAndroid Build Coastguard Worker   // callee-saved float/vector registers.
1354*03ce13f7SAndroid Build Coastguard Worker   //
1355*03ce13f7SAndroid Build Coastguard Worker   // The "vpush" instruction can handle a whole list of float/vector registers,
1356*03ce13f7SAndroid Build Coastguard Worker   // but it only handles contiguous sequences of registers by specifying the
1357*03ce13f7SAndroid Build Coastguard Worker   // start and the length.
1358*03ce13f7SAndroid Build Coastguard Worker   PreservedGPRs.reserve(CalleeSaves.size());
1359*03ce13f7SAndroid Build Coastguard Worker   PreservedSRegs.reserve(CalleeSaves.size());
1360*03ce13f7SAndroid Build Coastguard Worker 
1361*03ce13f7SAndroid Build Coastguard Worker   // Consider FP and LR as callee-save / used as needed.
1362*03ce13f7SAndroid Build Coastguard Worker   if (UsesFramePointer) {
1363*03ce13f7SAndroid Build Coastguard Worker     if (RegsUsed[RegARM32::Reg_fp]) {
1364*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error("Frame pointer has been used.");
1365*03ce13f7SAndroid Build Coastguard Worker     }
1366*03ce13f7SAndroid Build Coastguard Worker     CalleeSaves[RegARM32::Reg_fp] = true;
1367*03ce13f7SAndroid Build Coastguard Worker     RegsUsed[RegARM32::Reg_fp] = true;
1368*03ce13f7SAndroid Build Coastguard Worker   }
1369*03ce13f7SAndroid Build Coastguard Worker   if (!MaybeLeafFunc) {
1370*03ce13f7SAndroid Build Coastguard Worker     CalleeSaves[RegARM32::Reg_lr] = true;
1371*03ce13f7SAndroid Build Coastguard Worker     RegsUsed[RegARM32::Reg_lr] = true;
1372*03ce13f7SAndroid Build Coastguard Worker   }
1373*03ce13f7SAndroid Build Coastguard Worker 
1374*03ce13f7SAndroid Build Coastguard Worker   // Make two passes over the used registers. The first pass records all the
1375*03ce13f7SAndroid Build Coastguard Worker   // used registers -- and their aliases. Then, we figure out which GPRs and
1376*03ce13f7SAndroid Build Coastguard Worker   // VFP S registers should be saved. We don't bother saving D/Q registers
1377*03ce13f7SAndroid Build Coastguard Worker   // because their uses are recorded as S regs uses.
1378*03ce13f7SAndroid Build Coastguard Worker   SmallBitVector ToPreserve(RegARM32::Reg_NUM);
1379*03ce13f7SAndroid Build Coastguard Worker   for (SizeT i = 0; i < CalleeSaves.size(); ++i) {
1380*03ce13f7SAndroid Build Coastguard Worker     if (CalleeSaves[i] && RegsUsed[i]) {
1381*03ce13f7SAndroid Build Coastguard Worker       ToPreserve |= RegisterAliases[i];
1382*03ce13f7SAndroid Build Coastguard Worker     }
1383*03ce13f7SAndroid Build Coastguard Worker   }
1384*03ce13f7SAndroid Build Coastguard Worker 
1385*03ce13f7SAndroid Build Coastguard Worker   uint32_t NumCallee = 0;
1386*03ce13f7SAndroid Build Coastguard Worker   size_t PreservedRegsSizeBytes = 0;
1387*03ce13f7SAndroid Build Coastguard Worker 
1388*03ce13f7SAndroid Build Coastguard Worker   // RegClasses is a tuple of
1389*03ce13f7SAndroid Build Coastguard Worker   //
1390*03ce13f7SAndroid Build Coastguard Worker   // <First Register in Class, Last Register in Class, Vector of Save Registers>
1391*03ce13f7SAndroid Build Coastguard Worker   //
1392*03ce13f7SAndroid Build Coastguard Worker   // We use this tuple to figure out which register we should push/pop during
1393*03ce13f7SAndroid Build Coastguard Worker   // prolog/epilog.
1394*03ce13f7SAndroid Build Coastguard Worker   using RegClassType = std::tuple<uint32_t, uint32_t, VarList *>;
1395*03ce13f7SAndroid Build Coastguard Worker   const RegClassType RegClasses[] = {
1396*03ce13f7SAndroid Build Coastguard Worker       RegClassType(RegARM32::Reg_GPR_First, RegARM32::Reg_GPR_Last,
1397*03ce13f7SAndroid Build Coastguard Worker                    &PreservedGPRs),
1398*03ce13f7SAndroid Build Coastguard Worker       RegClassType(RegARM32::Reg_SREG_First, RegARM32::Reg_SREG_Last,
1399*03ce13f7SAndroid Build Coastguard Worker                    &PreservedSRegs)};
1400*03ce13f7SAndroid Build Coastguard Worker   for (const auto &RegClass : RegClasses) {
1401*03ce13f7SAndroid Build Coastguard Worker     const uint32_t FirstRegInClass = std::get<0>(RegClass);
1402*03ce13f7SAndroid Build Coastguard Worker     const uint32_t LastRegInClass = std::get<1>(RegClass);
1403*03ce13f7SAndroid Build Coastguard Worker     VarList *const PreservedRegsInClass = std::get<2>(RegClass);
1404*03ce13f7SAndroid Build Coastguard Worker     for (uint32_t Reg = FirstRegInClass; Reg <= LastRegInClass; ++Reg) {
1405*03ce13f7SAndroid Build Coastguard Worker       if (!ToPreserve[Reg]) {
1406*03ce13f7SAndroid Build Coastguard Worker         continue;
1407*03ce13f7SAndroid Build Coastguard Worker       }
1408*03ce13f7SAndroid Build Coastguard Worker       ++NumCallee;
1409*03ce13f7SAndroid Build Coastguard Worker       Variable *PhysicalRegister = getPhysicalRegister(RegNumT::fromInt(Reg));
1410*03ce13f7SAndroid Build Coastguard Worker       PreservedRegsSizeBytes +=
1411*03ce13f7SAndroid Build Coastguard Worker           typeWidthInBytesOnStack(PhysicalRegister->getType());
1412*03ce13f7SAndroid Build Coastguard Worker       PreservedRegsInClass->push_back(PhysicalRegister);
1413*03ce13f7SAndroid Build Coastguard Worker     }
1414*03ce13f7SAndroid Build Coastguard Worker   }
1415*03ce13f7SAndroid Build Coastguard Worker 
1416*03ce13f7SAndroid Build Coastguard Worker   Ctx->statsUpdateRegistersSaved(NumCallee);
1417*03ce13f7SAndroid Build Coastguard Worker   if (!PreservedSRegs.empty())
1418*03ce13f7SAndroid Build Coastguard Worker     _push(PreservedSRegs);
1419*03ce13f7SAndroid Build Coastguard Worker   if (!PreservedGPRs.empty())
1420*03ce13f7SAndroid Build Coastguard Worker     _push(PreservedGPRs);
1421*03ce13f7SAndroid Build Coastguard Worker 
1422*03ce13f7SAndroid Build Coastguard Worker   // Generate "mov FP, SP" if needed.
1423*03ce13f7SAndroid Build Coastguard Worker   if (UsesFramePointer) {
1424*03ce13f7SAndroid Build Coastguard Worker     Variable *FP = getPhysicalRegister(RegARM32::Reg_fp);
1425*03ce13f7SAndroid Build Coastguard Worker     Variable *SP = getPhysicalRegister(RegARM32::Reg_sp);
1426*03ce13f7SAndroid Build Coastguard Worker     _mov(FP, SP);
1427*03ce13f7SAndroid Build Coastguard Worker     // Keep FP live for late-stage liveness analysis (e.g. asm-verbose mode).
1428*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(FP);
1429*03ce13f7SAndroid Build Coastguard Worker   }
1430*03ce13f7SAndroid Build Coastguard Worker 
1431*03ce13f7SAndroid Build Coastguard Worker   // Align the variables area. SpillAreaPaddingBytes is the size of the region
1432*03ce13f7SAndroid Build Coastguard Worker   // after the preserved registers and before the spill areas.
1433*03ce13f7SAndroid Build Coastguard Worker   // LocalsSlotsPaddingBytes is the amount of padding between the globals and
1434*03ce13f7SAndroid Build Coastguard Worker   // locals area if they are separate.
1435*03ce13f7SAndroid Build Coastguard Worker   assert(SpillAreaAlignmentBytes <= ARM32_STACK_ALIGNMENT_BYTES);
1436*03ce13f7SAndroid Build Coastguard Worker   assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes);
1437*03ce13f7SAndroid Build Coastguard Worker   uint32_t SpillAreaPaddingBytes = 0;
1438*03ce13f7SAndroid Build Coastguard Worker   uint32_t LocalsSlotsPaddingBytes = 0;
1439*03ce13f7SAndroid Build Coastguard Worker   alignStackSpillAreas(PreservedRegsSizeBytes, SpillAreaAlignmentBytes,
1440*03ce13f7SAndroid Build Coastguard Worker                        GlobalsSize, LocalsSlotsAlignmentBytes,
1441*03ce13f7SAndroid Build Coastguard Worker                        &SpillAreaPaddingBytes, &LocalsSlotsPaddingBytes);
1442*03ce13f7SAndroid Build Coastguard Worker   SpillAreaSizeBytes += SpillAreaPaddingBytes + LocalsSlotsPaddingBytes;
1443*03ce13f7SAndroid Build Coastguard Worker   uint32_t GlobalsAndSubsequentPaddingSize =
1444*03ce13f7SAndroid Build Coastguard Worker       GlobalsSize + LocalsSlotsPaddingBytes;
1445*03ce13f7SAndroid Build Coastguard Worker 
1446*03ce13f7SAndroid Build Coastguard Worker   // Adds the out args space to the stack, and align SP if necessary.
1447*03ce13f7SAndroid Build Coastguard Worker   if (!NeedsStackAlignment) {
1448*03ce13f7SAndroid Build Coastguard Worker     SpillAreaSizeBytes += MaxOutArgsSizeBytes;
1449*03ce13f7SAndroid Build Coastguard Worker   } else {
1450*03ce13f7SAndroid Build Coastguard Worker     uint32_t StackOffset = PreservedRegsSizeBytes;
1451*03ce13f7SAndroid Build Coastguard Worker     uint32_t StackSize = applyStackAlignment(StackOffset + SpillAreaSizeBytes);
1452*03ce13f7SAndroid Build Coastguard Worker     StackSize = applyStackAlignment(StackSize + MaxOutArgsSizeBytes);
1453*03ce13f7SAndroid Build Coastguard Worker     SpillAreaSizeBytes = StackSize - StackOffset;
1454*03ce13f7SAndroid Build Coastguard Worker   }
1455*03ce13f7SAndroid Build Coastguard Worker 
1456*03ce13f7SAndroid Build Coastguard Worker   // Combine fixed alloca with SpillAreaSize.
1457*03ce13f7SAndroid Build Coastguard Worker   SpillAreaSizeBytes += FixedAllocaSizeBytes;
1458*03ce13f7SAndroid Build Coastguard Worker 
1459*03ce13f7SAndroid Build Coastguard Worker   // Generate "sub sp, SpillAreaSizeBytes"
1460*03ce13f7SAndroid Build Coastguard Worker   if (SpillAreaSizeBytes) {
1461*03ce13f7SAndroid Build Coastguard Worker     Variable *SP = getPhysicalRegister(RegARM32::Reg_sp);
1462*03ce13f7SAndroid Build Coastguard Worker     // Use the scratch register if needed to legalize the immediate.
1463*03ce13f7SAndroid Build Coastguard Worker     Operand *SubAmount = legalize(Ctx->getConstantInt32(SpillAreaSizeBytes),
1464*03ce13f7SAndroid Build Coastguard Worker                                   Legal_Reg | Legal_Flex, getReservedTmpReg());
1465*03ce13f7SAndroid Build Coastguard Worker     _sub(SP, SP, SubAmount);
1466*03ce13f7SAndroid Build Coastguard Worker     if (FixedAllocaAlignBytes > ARM32_STACK_ALIGNMENT_BYTES) {
1467*03ce13f7SAndroid Build Coastguard Worker       alignRegisterPow2(SP, FixedAllocaAlignBytes);
1468*03ce13f7SAndroid Build Coastguard Worker     }
1469*03ce13f7SAndroid Build Coastguard Worker   }
1470*03ce13f7SAndroid Build Coastguard Worker 
1471*03ce13f7SAndroid Build Coastguard Worker   Ctx->statsUpdateFrameBytes(SpillAreaSizeBytes);
1472*03ce13f7SAndroid Build Coastguard Worker 
1473*03ce13f7SAndroid Build Coastguard Worker   // Fill in stack offsets for stack args, and copy args into registers for
1474*03ce13f7SAndroid Build Coastguard Worker   // those that were register-allocated. Args are pushed right to left, so
1475*03ce13f7SAndroid Build Coastguard Worker   // Arg[0] is closest to the stack/frame pointer.
1476*03ce13f7SAndroid Build Coastguard Worker   Variable *FramePtr = getPhysicalRegister(getFrameOrStackReg());
1477*03ce13f7SAndroid Build Coastguard Worker   size_t BasicFrameOffset = PreservedRegsSizeBytes;
1478*03ce13f7SAndroid Build Coastguard Worker   if (!UsesFramePointer)
1479*03ce13f7SAndroid Build Coastguard Worker     BasicFrameOffset += SpillAreaSizeBytes;
1480*03ce13f7SAndroid Build Coastguard Worker 
1481*03ce13f7SAndroid Build Coastguard Worker   const VarList &Args = Func->getArgs();
1482*03ce13f7SAndroid Build Coastguard Worker   size_t InArgsSizeBytes = 0;
1483*03ce13f7SAndroid Build Coastguard Worker   TargetARM32::CallingConv CC;
1484*03ce13f7SAndroid Build Coastguard Worker   for (Variable *Arg : Args) {
1485*03ce13f7SAndroid Build Coastguard Worker     RegNumT DummyReg;
1486*03ce13f7SAndroid Build Coastguard Worker     const Type Ty = Arg->getType();
1487*03ce13f7SAndroid Build Coastguard Worker 
1488*03ce13f7SAndroid Build Coastguard Worker     // Skip arguments passed in registers.
1489*03ce13f7SAndroid Build Coastguard Worker     if (isScalarIntegerType(Ty)) {
1490*03ce13f7SAndroid Build Coastguard Worker       if (CC.argInGPR(Ty, &DummyReg)) {
1491*03ce13f7SAndroid Build Coastguard Worker         continue;
1492*03ce13f7SAndroid Build Coastguard Worker       }
1493*03ce13f7SAndroid Build Coastguard Worker     } else {
1494*03ce13f7SAndroid Build Coastguard Worker       if (CC.argInVFP(Ty, &DummyReg)) {
1495*03ce13f7SAndroid Build Coastguard Worker         continue;
1496*03ce13f7SAndroid Build Coastguard Worker       }
1497*03ce13f7SAndroid Build Coastguard Worker     }
1498*03ce13f7SAndroid Build Coastguard Worker     finishArgumentLowering(Arg, FramePtr, BasicFrameOffset, &InArgsSizeBytes);
1499*03ce13f7SAndroid Build Coastguard Worker   }
1500*03ce13f7SAndroid Build Coastguard Worker 
1501*03ce13f7SAndroid Build Coastguard Worker   // Fill in stack offsets for locals.
1502*03ce13f7SAndroid Build Coastguard Worker   assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes,
1503*03ce13f7SAndroid Build Coastguard Worker                       SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize,
1504*03ce13f7SAndroid Build Coastguard Worker                       UsesFramePointer);
1505*03ce13f7SAndroid Build Coastguard Worker   this->HasComputedFrame = true;
1506*03ce13f7SAndroid Build Coastguard Worker 
1507*03ce13f7SAndroid Build Coastguard Worker   if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) {
1508*03ce13f7SAndroid Build Coastguard Worker     OstreamLocker _(Func->getContext());
1509*03ce13f7SAndroid Build Coastguard Worker     Ostream &Str = Func->getContext()->getStrDump();
1510*03ce13f7SAndroid Build Coastguard Worker 
1511*03ce13f7SAndroid Build Coastguard Worker     Str << "Stack layout:\n";
1512*03ce13f7SAndroid Build Coastguard Worker     uint32_t SPAdjustmentPaddingSize =
1513*03ce13f7SAndroid Build Coastguard Worker         SpillAreaSizeBytes - LocalsSpillAreaSize -
1514*03ce13f7SAndroid Build Coastguard Worker         GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes -
1515*03ce13f7SAndroid Build Coastguard Worker         MaxOutArgsSizeBytes;
1516*03ce13f7SAndroid Build Coastguard Worker     Str << " in-args = " << InArgsSizeBytes << " bytes\n"
1517*03ce13f7SAndroid Build Coastguard Worker         << " preserved registers = " << PreservedRegsSizeBytes << " bytes\n"
1518*03ce13f7SAndroid Build Coastguard Worker         << " spill area padding = " << SpillAreaPaddingBytes << " bytes\n"
1519*03ce13f7SAndroid Build Coastguard Worker         << " globals spill area = " << GlobalsSize << " bytes\n"
1520*03ce13f7SAndroid Build Coastguard Worker         << " globals-locals spill areas intermediate padding = "
1521*03ce13f7SAndroid Build Coastguard Worker         << GlobalsAndSubsequentPaddingSize - GlobalsSize << " bytes\n"
1522*03ce13f7SAndroid Build Coastguard Worker         << " locals spill area = " << LocalsSpillAreaSize << " bytes\n"
1523*03ce13f7SAndroid Build Coastguard Worker         << " SP alignment padding = " << SPAdjustmentPaddingSize << " bytes\n";
1524*03ce13f7SAndroid Build Coastguard Worker 
1525*03ce13f7SAndroid Build Coastguard Worker     Str << "Stack details:\n"
1526*03ce13f7SAndroid Build Coastguard Worker         << " SP adjustment = " << SpillAreaSizeBytes << " bytes\n"
1527*03ce13f7SAndroid Build Coastguard Worker         << " spill area alignment = " << SpillAreaAlignmentBytes << " bytes\n"
1528*03ce13f7SAndroid Build Coastguard Worker         << " outgoing args size = " << MaxOutArgsSizeBytes << " bytes\n"
1529*03ce13f7SAndroid Build Coastguard Worker         << " locals spill area alignment = " << LocalsSlotsAlignmentBytes
1530*03ce13f7SAndroid Build Coastguard Worker         << " bytes\n"
1531*03ce13f7SAndroid Build Coastguard Worker         << " is FP based = " << UsesFramePointer << "\n";
1532*03ce13f7SAndroid Build Coastguard Worker   }
1533*03ce13f7SAndroid Build Coastguard Worker }
1534*03ce13f7SAndroid Build Coastguard Worker 
addEpilog(CfgNode * Node)1535*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::addEpilog(CfgNode *Node) {
1536*03ce13f7SAndroid Build Coastguard Worker   InstList &Insts = Node->getInsts();
1537*03ce13f7SAndroid Build Coastguard Worker   InstList::reverse_iterator RI, E;
1538*03ce13f7SAndroid Build Coastguard Worker   for (RI = Insts.rbegin(), E = Insts.rend(); RI != E; ++RI) {
1539*03ce13f7SAndroid Build Coastguard Worker     if (llvm::isa<InstARM32Ret>(*RI))
1540*03ce13f7SAndroid Build Coastguard Worker       break;
1541*03ce13f7SAndroid Build Coastguard Worker   }
1542*03ce13f7SAndroid Build Coastguard Worker   if (RI == E)
1543*03ce13f7SAndroid Build Coastguard Worker     return;
1544*03ce13f7SAndroid Build Coastguard Worker 
1545*03ce13f7SAndroid Build Coastguard Worker   // Convert the reverse_iterator position into its corresponding (forward)
1546*03ce13f7SAndroid Build Coastguard Worker   // iterator position.
1547*03ce13f7SAndroid Build Coastguard Worker   InstList::iterator InsertPoint = reverseToForwardIterator(RI);
1548*03ce13f7SAndroid Build Coastguard Worker   --InsertPoint;
1549*03ce13f7SAndroid Build Coastguard Worker   Context.init(Node);
1550*03ce13f7SAndroid Build Coastguard Worker   Context.setInsertPoint(InsertPoint);
1551*03ce13f7SAndroid Build Coastguard Worker 
1552*03ce13f7SAndroid Build Coastguard Worker   Variable *SP = getPhysicalRegister(RegARM32::Reg_sp);
1553*03ce13f7SAndroid Build Coastguard Worker   if (UsesFramePointer) {
1554*03ce13f7SAndroid Build Coastguard Worker     Variable *FP = getPhysicalRegister(RegARM32::Reg_fp);
1555*03ce13f7SAndroid Build Coastguard Worker     // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake
1556*03ce13f7SAndroid Build Coastguard Worker     // use of SP before the assignment of SP=FP keeps previous SP adjustments
1557*03ce13f7SAndroid Build Coastguard Worker     // from being dead-code eliminated.
1558*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(SP);
1559*03ce13f7SAndroid Build Coastguard Worker     _mov_redefined(SP, FP);
1560*03ce13f7SAndroid Build Coastguard Worker   } else {
1561*03ce13f7SAndroid Build Coastguard Worker     // add SP, SpillAreaSizeBytes
1562*03ce13f7SAndroid Build Coastguard Worker     if (SpillAreaSizeBytes) {
1563*03ce13f7SAndroid Build Coastguard Worker       // Use the scratch register if needed to legalize the immediate.
1564*03ce13f7SAndroid Build Coastguard Worker       Operand *AddAmount =
1565*03ce13f7SAndroid Build Coastguard Worker           legalize(Ctx->getConstantInt32(SpillAreaSizeBytes),
1566*03ce13f7SAndroid Build Coastguard Worker                    Legal_Reg | Legal_Flex, getReservedTmpReg());
1567*03ce13f7SAndroid Build Coastguard Worker       _add(SP, SP, AddAmount);
1568*03ce13f7SAndroid Build Coastguard Worker     }
1569*03ce13f7SAndroid Build Coastguard Worker   }
1570*03ce13f7SAndroid Build Coastguard Worker 
1571*03ce13f7SAndroid Build Coastguard Worker   if (!PreservedGPRs.empty())
1572*03ce13f7SAndroid Build Coastguard Worker     _pop(PreservedGPRs);
1573*03ce13f7SAndroid Build Coastguard Worker   if (!PreservedSRegs.empty())
1574*03ce13f7SAndroid Build Coastguard Worker     _pop(PreservedSRegs);
1575*03ce13f7SAndroid Build Coastguard Worker }
1576*03ce13f7SAndroid Build Coastguard Worker 
isLegalMemOffset(Type Ty,int32_t Offset) const1577*03ce13f7SAndroid Build Coastguard Worker bool TargetARM32::isLegalMemOffset(Type Ty, int32_t Offset) const {
1578*03ce13f7SAndroid Build Coastguard Worker   constexpr bool ZeroExt = false;
1579*03ce13f7SAndroid Build Coastguard Worker   return OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset);
1580*03ce13f7SAndroid Build Coastguard Worker }
1581*03ce13f7SAndroid Build Coastguard Worker 
newBaseRegister(Variable * Base,int32_t Offset,RegNumT ScratchRegNum)1582*03ce13f7SAndroid Build Coastguard Worker Variable *TargetARM32::PostLoweringLegalizer::newBaseRegister(
1583*03ce13f7SAndroid Build Coastguard Worker     Variable *Base, int32_t Offset, RegNumT ScratchRegNum) {
1584*03ce13f7SAndroid Build Coastguard Worker   // Legalize will likely need a movw/movt combination, but if the top bits are
1585*03ce13f7SAndroid Build Coastguard Worker   // all 0 from negating the offset and subtracting, we could use that instead.
1586*03ce13f7SAndroid Build Coastguard Worker   const bool ShouldSub = Offset != 0 && (-Offset & 0xFFFF0000) == 0;
1587*03ce13f7SAndroid Build Coastguard Worker   Variable *ScratchReg = Target->makeReg(IceType_i32, ScratchRegNum);
1588*03ce13f7SAndroid Build Coastguard Worker   if (ShouldSub) {
1589*03ce13f7SAndroid Build Coastguard Worker     Operand *OffsetVal =
1590*03ce13f7SAndroid Build Coastguard Worker         Target->legalize(Target->Ctx->getConstantInt32(-Offset),
1591*03ce13f7SAndroid Build Coastguard Worker                          Legal_Reg | Legal_Flex, ScratchRegNum);
1592*03ce13f7SAndroid Build Coastguard Worker     Target->_sub(ScratchReg, Base, OffsetVal);
1593*03ce13f7SAndroid Build Coastguard Worker   } else {
1594*03ce13f7SAndroid Build Coastguard Worker     Operand *OffsetVal =
1595*03ce13f7SAndroid Build Coastguard Worker         Target->legalize(Target->Ctx->getConstantInt32(Offset),
1596*03ce13f7SAndroid Build Coastguard Worker                          Legal_Reg | Legal_Flex, ScratchRegNum);
1597*03ce13f7SAndroid Build Coastguard Worker     Target->_add(ScratchReg, Base, OffsetVal);
1598*03ce13f7SAndroid Build Coastguard Worker   }
1599*03ce13f7SAndroid Build Coastguard Worker 
1600*03ce13f7SAndroid Build Coastguard Worker   if (ScratchRegNum == Target->getReservedTmpReg()) {
1601*03ce13f7SAndroid Build Coastguard Worker     const bool BaseIsStackOrFramePtr =
1602*03ce13f7SAndroid Build Coastguard Worker         Base->getRegNum() == Target->getFrameOrStackReg();
1603*03ce13f7SAndroid Build Coastguard Worker     // There is currently no code path that would trigger this assertion, so we
1604*03ce13f7SAndroid Build Coastguard Worker     // leave this assertion here in case it is ever violated. This is not a
1605*03ce13f7SAndroid Build Coastguard Worker     // fatal error (thus the use of assert() and not llvm::report_fatal_error)
1606*03ce13f7SAndroid Build Coastguard Worker     // as the program compiled by subzero will still work correctly.
1607*03ce13f7SAndroid Build Coastguard Worker     assert(BaseIsStackOrFramePtr);
1608*03ce13f7SAndroid Build Coastguard Worker     // Side-effect: updates TempBase to reflect the new Temporary.
1609*03ce13f7SAndroid Build Coastguard Worker     if (BaseIsStackOrFramePtr) {
1610*03ce13f7SAndroid Build Coastguard Worker       TempBaseReg = ScratchReg;
1611*03ce13f7SAndroid Build Coastguard Worker       TempBaseOffset = Offset;
1612*03ce13f7SAndroid Build Coastguard Worker     } else {
1613*03ce13f7SAndroid Build Coastguard Worker       TempBaseReg = nullptr;
1614*03ce13f7SAndroid Build Coastguard Worker       TempBaseOffset = 0;
1615*03ce13f7SAndroid Build Coastguard Worker     }
1616*03ce13f7SAndroid Build Coastguard Worker   }
1617*03ce13f7SAndroid Build Coastguard Worker 
1618*03ce13f7SAndroid Build Coastguard Worker   return ScratchReg;
1619*03ce13f7SAndroid Build Coastguard Worker }
1620*03ce13f7SAndroid Build Coastguard Worker 
createMemOperand(Type Ty,Variable * Base,int32_t Offset,bool AllowOffsets)1621*03ce13f7SAndroid Build Coastguard Worker OperandARM32Mem *TargetARM32::PostLoweringLegalizer::createMemOperand(
1622*03ce13f7SAndroid Build Coastguard Worker     Type Ty, Variable *Base, int32_t Offset, bool AllowOffsets) {
1623*03ce13f7SAndroid Build Coastguard Worker   assert(!Base->isRematerializable());
1624*03ce13f7SAndroid Build Coastguard Worker   if (Offset == 0 || (AllowOffsets && Target->isLegalMemOffset(Ty, Offset))) {
1625*03ce13f7SAndroid Build Coastguard Worker     return OperandARM32Mem::create(
1626*03ce13f7SAndroid Build Coastguard Worker         Target->Func, Ty, Base,
1627*03ce13f7SAndroid Build Coastguard Worker         llvm::cast<ConstantInteger32>(Target->Ctx->getConstantInt32(Offset)),
1628*03ce13f7SAndroid Build Coastguard Worker         OperandARM32Mem::Offset);
1629*03ce13f7SAndroid Build Coastguard Worker   }
1630*03ce13f7SAndroid Build Coastguard Worker 
1631*03ce13f7SAndroid Build Coastguard Worker   if (!AllowOffsets || TempBaseReg == nullptr) {
1632*03ce13f7SAndroid Build Coastguard Worker     newBaseRegister(Base, Offset, Target->getReservedTmpReg());
1633*03ce13f7SAndroid Build Coastguard Worker   }
1634*03ce13f7SAndroid Build Coastguard Worker 
1635*03ce13f7SAndroid Build Coastguard Worker   int32_t OffsetDiff = Offset - TempBaseOffset;
1636*03ce13f7SAndroid Build Coastguard Worker   assert(AllowOffsets || OffsetDiff == 0);
1637*03ce13f7SAndroid Build Coastguard Worker 
1638*03ce13f7SAndroid Build Coastguard Worker   if (!Target->isLegalMemOffset(Ty, OffsetDiff)) {
1639*03ce13f7SAndroid Build Coastguard Worker     newBaseRegister(Base, Offset, Target->getReservedTmpReg());
1640*03ce13f7SAndroid Build Coastguard Worker     OffsetDiff = 0;
1641*03ce13f7SAndroid Build Coastguard Worker   }
1642*03ce13f7SAndroid Build Coastguard Worker 
1643*03ce13f7SAndroid Build Coastguard Worker   assert(!TempBaseReg->isRematerializable());
1644*03ce13f7SAndroid Build Coastguard Worker   return OperandARM32Mem::create(
1645*03ce13f7SAndroid Build Coastguard Worker       Target->Func, Ty, TempBaseReg,
1646*03ce13f7SAndroid Build Coastguard Worker       llvm::cast<ConstantInteger32>(Target->Ctx->getConstantInt32(OffsetDiff)),
1647*03ce13f7SAndroid Build Coastguard Worker       OperandARM32Mem::Offset);
1648*03ce13f7SAndroid Build Coastguard Worker }
1649*03ce13f7SAndroid Build Coastguard Worker 
resetTempBaseIfClobberedBy(const Inst * Instr)1650*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::PostLoweringLegalizer::resetTempBaseIfClobberedBy(
1651*03ce13f7SAndroid Build Coastguard Worker     const Inst *Instr) {
1652*03ce13f7SAndroid Build Coastguard Worker   bool ClobbersTempBase = false;
1653*03ce13f7SAndroid Build Coastguard Worker   if (TempBaseReg != nullptr) {
1654*03ce13f7SAndroid Build Coastguard Worker     Variable *Dest = Instr->getDest();
1655*03ce13f7SAndroid Build Coastguard Worker     if (llvm::isa<InstARM32Call>(Instr)) {
1656*03ce13f7SAndroid Build Coastguard Worker       // The following assertion is an invariant, so we remove it from the if
1657*03ce13f7SAndroid Build Coastguard Worker       // test. If the invariant is ever broken/invalidated/changed, remember
1658*03ce13f7SAndroid Build Coastguard Worker       // to add it back to the if condition.
1659*03ce13f7SAndroid Build Coastguard Worker       assert(TempBaseReg->getRegNum() == Target->getReservedTmpReg());
1660*03ce13f7SAndroid Build Coastguard Worker       // The linker may need to clobber IP if the call is too far from PC. Thus,
1661*03ce13f7SAndroid Build Coastguard Worker       // we assume IP will be overwritten.
1662*03ce13f7SAndroid Build Coastguard Worker       ClobbersTempBase = true;
1663*03ce13f7SAndroid Build Coastguard Worker     } else if (Dest != nullptr &&
1664*03ce13f7SAndroid Build Coastguard Worker                Dest->getRegNum() == TempBaseReg->getRegNum()) {
1665*03ce13f7SAndroid Build Coastguard Worker       // Register redefinition.
1666*03ce13f7SAndroid Build Coastguard Worker       ClobbersTempBase = true;
1667*03ce13f7SAndroid Build Coastguard Worker     }
1668*03ce13f7SAndroid Build Coastguard Worker   }
1669*03ce13f7SAndroid Build Coastguard Worker 
1670*03ce13f7SAndroid Build Coastguard Worker   if (ClobbersTempBase) {
1671*03ce13f7SAndroid Build Coastguard Worker     TempBaseReg = nullptr;
1672*03ce13f7SAndroid Build Coastguard Worker     TempBaseOffset = 0;
1673*03ce13f7SAndroid Build Coastguard Worker   }
1674*03ce13f7SAndroid Build Coastguard Worker }
1675*03ce13f7SAndroid Build Coastguard Worker 
legalizeMov(InstARM32Mov * MovInstr)1676*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::PostLoweringLegalizer::legalizeMov(InstARM32Mov *MovInstr) {
1677*03ce13f7SAndroid Build Coastguard Worker   Variable *Dest = MovInstr->getDest();
1678*03ce13f7SAndroid Build Coastguard Worker   assert(Dest != nullptr);
1679*03ce13f7SAndroid Build Coastguard Worker   Type DestTy = Dest->getType();
1680*03ce13f7SAndroid Build Coastguard Worker   assert(DestTy != IceType_i64);
1681*03ce13f7SAndroid Build Coastguard Worker 
1682*03ce13f7SAndroid Build Coastguard Worker   Operand *Src = MovInstr->getSrc(0);
1683*03ce13f7SAndroid Build Coastguard Worker   Type SrcTy = Src->getType();
1684*03ce13f7SAndroid Build Coastguard Worker   (void)SrcTy;
1685*03ce13f7SAndroid Build Coastguard Worker   assert(SrcTy != IceType_i64);
1686*03ce13f7SAndroid Build Coastguard Worker 
1687*03ce13f7SAndroid Build Coastguard Worker   if (MovInstr->isMultiDest() || MovInstr->isMultiSource())
1688*03ce13f7SAndroid Build Coastguard Worker     return;
1689*03ce13f7SAndroid Build Coastguard Worker 
1690*03ce13f7SAndroid Build Coastguard Worker   bool Legalized = false;
1691*03ce13f7SAndroid Build Coastguard Worker   if (!Dest->hasReg()) {
1692*03ce13f7SAndroid Build Coastguard Worker     auto *SrcR = llvm::cast<Variable>(Src);
1693*03ce13f7SAndroid Build Coastguard Worker     assert(SrcR->hasReg());
1694*03ce13f7SAndroid Build Coastguard Worker     assert(!SrcR->isRematerializable());
1695*03ce13f7SAndroid Build Coastguard Worker     const int32_t Offset = Dest->getStackOffset();
1696*03ce13f7SAndroid Build Coastguard Worker     // This is a _mov(Mem(), Variable), i.e., a store.
1697*03ce13f7SAndroid Build Coastguard Worker     Target->_str(SrcR, createMemOperand(DestTy, StackOrFrameReg, Offset),
1698*03ce13f7SAndroid Build Coastguard Worker                  MovInstr->getPredicate());
1699*03ce13f7SAndroid Build Coastguard Worker     // _str() does not have a Dest, so we add a fake-def(Dest).
1700*03ce13f7SAndroid Build Coastguard Worker     Target->Context.insert<InstFakeDef>(Dest);
1701*03ce13f7SAndroid Build Coastguard Worker     Legalized = true;
1702*03ce13f7SAndroid Build Coastguard Worker   } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) {
1703*03ce13f7SAndroid Build Coastguard Worker     if (Var->isRematerializable()) {
1704*03ce13f7SAndroid Build Coastguard Worker       // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable).
1705*03ce13f7SAndroid Build Coastguard Worker 
1706*03ce13f7SAndroid Build Coastguard Worker       // ExtraOffset is only needed for frame-pointer based frames as we have
1707*03ce13f7SAndroid Build Coastguard Worker       // to account for spill storage.
1708*03ce13f7SAndroid Build Coastguard Worker       const int32_t ExtraOffset = (Var->getRegNum() == Target->getFrameReg())
1709*03ce13f7SAndroid Build Coastguard Worker                                       ? Target->getFrameFixedAllocaOffset()
1710*03ce13f7SAndroid Build Coastguard Worker                                       : 0;
1711*03ce13f7SAndroid Build Coastguard Worker 
1712*03ce13f7SAndroid Build Coastguard Worker       const int32_t Offset = Var->getStackOffset() + ExtraOffset;
1713*03ce13f7SAndroid Build Coastguard Worker       Variable *Base = Target->getPhysicalRegister(Var->getRegNum());
1714*03ce13f7SAndroid Build Coastguard Worker       Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum());
1715*03ce13f7SAndroid Build Coastguard Worker       Target->_mov(Dest, T);
1716*03ce13f7SAndroid Build Coastguard Worker       Legalized = true;
1717*03ce13f7SAndroid Build Coastguard Worker     } else {
1718*03ce13f7SAndroid Build Coastguard Worker       if (!Var->hasReg()) {
1719*03ce13f7SAndroid Build Coastguard Worker         // This is a _mov(Variable, Mem()), i.e., a load.
1720*03ce13f7SAndroid Build Coastguard Worker         const int32_t Offset = Var->getStackOffset();
1721*03ce13f7SAndroid Build Coastguard Worker         Target->_ldr(Dest, createMemOperand(DestTy, StackOrFrameReg, Offset),
1722*03ce13f7SAndroid Build Coastguard Worker                      MovInstr->getPredicate());
1723*03ce13f7SAndroid Build Coastguard Worker         Legalized = true;
1724*03ce13f7SAndroid Build Coastguard Worker       }
1725*03ce13f7SAndroid Build Coastguard Worker     }
1726*03ce13f7SAndroid Build Coastguard Worker   }
1727*03ce13f7SAndroid Build Coastguard Worker 
1728*03ce13f7SAndroid Build Coastguard Worker   if (Legalized) {
1729*03ce13f7SAndroid Build Coastguard Worker     if (MovInstr->isDestRedefined()) {
1730*03ce13f7SAndroid Build Coastguard Worker       Target->_set_dest_redefined();
1731*03ce13f7SAndroid Build Coastguard Worker     }
1732*03ce13f7SAndroid Build Coastguard Worker     MovInstr->setDeleted();
1733*03ce13f7SAndroid Build Coastguard Worker   }
1734*03ce13f7SAndroid Build Coastguard Worker }
1735*03ce13f7SAndroid Build Coastguard Worker 
1736*03ce13f7SAndroid Build Coastguard Worker // ARM32 address modes:
1737*03ce13f7SAndroid Build Coastguard Worker //  ld/st i[8|16|32]: [reg], [reg +/- imm12], [pc +/- imm12],
1738*03ce13f7SAndroid Build Coastguard Worker //                    [reg +/- reg << shamt5]
1739*03ce13f7SAndroid Build Coastguard Worker //  ld/st f[32|64]  : [reg], [reg +/- imm8] , [pc +/- imm8]
1740*03ce13f7SAndroid Build Coastguard Worker //  ld/st vectors   : [reg]
1741*03ce13f7SAndroid Build Coastguard Worker //
1742*03ce13f7SAndroid Build Coastguard Worker // For now, we don't handle address modes with Relocatables.
1743*03ce13f7SAndroid Build Coastguard Worker namespace {
1744*03ce13f7SAndroid Build Coastguard Worker // MemTraits contains per-type valid address mode information.
1745*03ce13f7SAndroid Build Coastguard Worker #define X(tag, elementty, int_width, fp_width, uvec_width, svec_width, sbits,  \
1746*03ce13f7SAndroid Build Coastguard Worker           ubits, rraddr, shaddr)                                               \
1747*03ce13f7SAndroid Build Coastguard Worker   static_assert(!(shaddr) || rraddr, "Check ICETYPEARM32_TABLE::" #tag);
1748*03ce13f7SAndroid Build Coastguard Worker ICETYPEARM32_TABLE
1749*03ce13f7SAndroid Build Coastguard Worker #undef X
1750*03ce13f7SAndroid Build Coastguard Worker 
1751*03ce13f7SAndroid Build Coastguard Worker static const struct {
1752*03ce13f7SAndroid Build Coastguard Worker   int32_t ValidImmMask;
1753*03ce13f7SAndroid Build Coastguard Worker   bool CanHaveImm;
1754*03ce13f7SAndroid Build Coastguard Worker   bool CanHaveIndex;
1755*03ce13f7SAndroid Build Coastguard Worker   bool CanHaveShiftedIndex;
1756*03ce13f7SAndroid Build Coastguard Worker } MemTraits[] = {
1757*03ce13f7SAndroid Build Coastguard Worker #define X(tag, elementty, int_width, fp_width, uvec_width, svec_width, sbits,  \
1758*03ce13f7SAndroid Build Coastguard Worker           ubits, rraddr, shaddr)                                               \
1759*03ce13f7SAndroid Build Coastguard Worker   {                                                                            \
1760*03ce13f7SAndroid Build Coastguard Worker       (1 << ubits) - 1,                                                        \
1761*03ce13f7SAndroid Build Coastguard Worker       (ubits) > 0,                                                             \
1762*03ce13f7SAndroid Build Coastguard Worker       rraddr,                                                                  \
1763*03ce13f7SAndroid Build Coastguard Worker       shaddr,                                                                  \
1764*03ce13f7SAndroid Build Coastguard Worker   },
1765*03ce13f7SAndroid Build Coastguard Worker     ICETYPEARM32_TABLE
1766*03ce13f7SAndroid Build Coastguard Worker #undef X
1767*03ce13f7SAndroid Build Coastguard Worker };
1768*03ce13f7SAndroid Build Coastguard Worker static constexpr SizeT MemTraitsSize = llvm::array_lengthof(MemTraits);
1769*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
1770*03ce13f7SAndroid Build Coastguard Worker 
1771*03ce13f7SAndroid Build Coastguard Worker OperandARM32Mem *
legalizeMemOperand(OperandARM32Mem * Mem,bool AllowOffsets)1772*03ce13f7SAndroid Build Coastguard Worker TargetARM32::PostLoweringLegalizer::legalizeMemOperand(OperandARM32Mem *Mem,
1773*03ce13f7SAndroid Build Coastguard Worker                                                        bool AllowOffsets) {
1774*03ce13f7SAndroid Build Coastguard Worker   assert(!Mem->isRegReg() || !Mem->getIndex()->isRematerializable());
1775*03ce13f7SAndroid Build Coastguard Worker   assert(Mem->isRegReg() || Target->isLegalMemOffset(
1776*03ce13f7SAndroid Build Coastguard Worker                                 Mem->getType(), Mem->getOffset()->getValue()));
1777*03ce13f7SAndroid Build Coastguard Worker 
1778*03ce13f7SAndroid Build Coastguard Worker   bool Legalized = false;
1779*03ce13f7SAndroid Build Coastguard Worker   Variable *Base = Mem->getBase();
1780*03ce13f7SAndroid Build Coastguard Worker   int32_t Offset = Mem->isRegReg() ? 0 : Mem->getOffset()->getValue();
1781*03ce13f7SAndroid Build Coastguard Worker   if (Base->isRematerializable()) {
1782*03ce13f7SAndroid Build Coastguard Worker     const int32_t ExtraOffset = (Base->getRegNum() == Target->getFrameReg())
1783*03ce13f7SAndroid Build Coastguard Worker                                     ? Target->getFrameFixedAllocaOffset()
1784*03ce13f7SAndroid Build Coastguard Worker                                     : 0;
1785*03ce13f7SAndroid Build Coastguard Worker     Offset += Base->getStackOffset() + ExtraOffset;
1786*03ce13f7SAndroid Build Coastguard Worker     Base = Target->getPhysicalRegister(Base->getRegNum());
1787*03ce13f7SAndroid Build Coastguard Worker     assert(!Base->isRematerializable());
1788*03ce13f7SAndroid Build Coastguard Worker     Legalized = true;
1789*03ce13f7SAndroid Build Coastguard Worker   }
1790*03ce13f7SAndroid Build Coastguard Worker 
1791*03ce13f7SAndroid Build Coastguard Worker   if (!Legalized) {
1792*03ce13f7SAndroid Build Coastguard Worker     return nullptr;
1793*03ce13f7SAndroid Build Coastguard Worker   }
1794*03ce13f7SAndroid Build Coastguard Worker 
1795*03ce13f7SAndroid Build Coastguard Worker   if (!Mem->isRegReg()) {
1796*03ce13f7SAndroid Build Coastguard Worker     return createMemOperand(Mem->getType(), Base, Offset, AllowOffsets);
1797*03ce13f7SAndroid Build Coastguard Worker   }
1798*03ce13f7SAndroid Build Coastguard Worker 
1799*03ce13f7SAndroid Build Coastguard Worker   assert(MemTraits[Mem->getType()].CanHaveIndex);
1800*03ce13f7SAndroid Build Coastguard Worker 
1801*03ce13f7SAndroid Build Coastguard Worker   if (Offset != 0) {
1802*03ce13f7SAndroid Build Coastguard Worker     if (TempBaseReg == nullptr) {
1803*03ce13f7SAndroid Build Coastguard Worker       Base = newBaseRegister(Base, Offset, Target->getReservedTmpReg());
1804*03ce13f7SAndroid Build Coastguard Worker     } else {
1805*03ce13f7SAndroid Build Coastguard Worker       uint32_t Imm8, Rotate;
1806*03ce13f7SAndroid Build Coastguard Worker       const int32_t OffsetDiff = Offset - TempBaseOffset;
1807*03ce13f7SAndroid Build Coastguard Worker       if (OffsetDiff == 0) {
1808*03ce13f7SAndroid Build Coastguard Worker         Base = TempBaseReg;
1809*03ce13f7SAndroid Build Coastguard Worker       } else if (OperandARM32FlexImm::canHoldImm(OffsetDiff, &Rotate, &Imm8)) {
1810*03ce13f7SAndroid Build Coastguard Worker         auto *OffsetDiffF = OperandARM32FlexImm::create(
1811*03ce13f7SAndroid Build Coastguard Worker             Target->Func, IceType_i32, Imm8, Rotate);
1812*03ce13f7SAndroid Build Coastguard Worker         Target->_add(TempBaseReg, TempBaseReg, OffsetDiffF);
1813*03ce13f7SAndroid Build Coastguard Worker         TempBaseOffset += OffsetDiff;
1814*03ce13f7SAndroid Build Coastguard Worker         Base = TempBaseReg;
1815*03ce13f7SAndroid Build Coastguard Worker       } else if (OperandARM32FlexImm::canHoldImm(-OffsetDiff, &Rotate, &Imm8)) {
1816*03ce13f7SAndroid Build Coastguard Worker         auto *OffsetDiffF = OperandARM32FlexImm::create(
1817*03ce13f7SAndroid Build Coastguard Worker             Target->Func, IceType_i32, Imm8, Rotate);
1818*03ce13f7SAndroid Build Coastguard Worker         Target->_sub(TempBaseReg, TempBaseReg, OffsetDiffF);
1819*03ce13f7SAndroid Build Coastguard Worker         TempBaseOffset += OffsetDiff;
1820*03ce13f7SAndroid Build Coastguard Worker         Base = TempBaseReg;
1821*03ce13f7SAndroid Build Coastguard Worker       } else {
1822*03ce13f7SAndroid Build Coastguard Worker         Base = newBaseRegister(Base, Offset, Target->getReservedTmpReg());
1823*03ce13f7SAndroid Build Coastguard Worker       }
1824*03ce13f7SAndroid Build Coastguard Worker     }
1825*03ce13f7SAndroid Build Coastguard Worker   }
1826*03ce13f7SAndroid Build Coastguard Worker 
1827*03ce13f7SAndroid Build Coastguard Worker   return OperandARM32Mem::create(Target->Func, Mem->getType(), Base,
1828*03ce13f7SAndroid Build Coastguard Worker                                  Mem->getIndex(), Mem->getShiftOp(),
1829*03ce13f7SAndroid Build Coastguard Worker                                  Mem->getShiftAmt(), Mem->getAddrMode());
1830*03ce13f7SAndroid Build Coastguard Worker }
1831*03ce13f7SAndroid Build Coastguard Worker 
postLowerLegalization()1832*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::postLowerLegalization() {
1833*03ce13f7SAndroid Build Coastguard Worker   // If a stack variable's frame offset doesn't fit, convert from:
1834*03ce13f7SAndroid Build Coastguard Worker   //   ldr X, OFF[SP]
1835*03ce13f7SAndroid Build Coastguard Worker   // to:
1836*03ce13f7SAndroid Build Coastguard Worker   //   movw/movt TMP, OFF_PART
1837*03ce13f7SAndroid Build Coastguard Worker   //   add TMP, TMP, SP
1838*03ce13f7SAndroid Build Coastguard Worker   //   ldr X, OFF_MORE[TMP]
1839*03ce13f7SAndroid Build Coastguard Worker   //
1840*03ce13f7SAndroid Build Coastguard Worker   // This is safe because we have reserved TMP, and add for ARM does not
1841*03ce13f7SAndroid Build Coastguard Worker   // clobber the flags register.
1842*03ce13f7SAndroid Build Coastguard Worker   Func->dump("Before postLowerLegalization");
1843*03ce13f7SAndroid Build Coastguard Worker   assert(hasComputedFrame());
1844*03ce13f7SAndroid Build Coastguard Worker   // Do a fairly naive greedy clustering for now. Pick the first stack slot
1845*03ce13f7SAndroid Build Coastguard Worker   // that's out of bounds and make a new base reg using the architecture's temp
1846*03ce13f7SAndroid Build Coastguard Worker   // register. If that works for the next slot, then great. Otherwise, create a
1847*03ce13f7SAndroid Build Coastguard Worker   // new base register, clobbering the previous base register. Never share a
1848*03ce13f7SAndroid Build Coastguard Worker   // base reg across different basic blocks. This isn't ideal if local and
1849*03ce13f7SAndroid Build Coastguard Worker   // multi-block variables are far apart and their references are interspersed.
1850*03ce13f7SAndroid Build Coastguard Worker   // It may help to be more coordinated about assign stack slot numbers and may
1851*03ce13f7SAndroid Build Coastguard Worker   // help to assign smaller offsets to higher-weight variables so that they
1852*03ce13f7SAndroid Build Coastguard Worker   // don't depend on this legalization.
1853*03ce13f7SAndroid Build Coastguard Worker   for (CfgNode *Node : Func->getNodes()) {
1854*03ce13f7SAndroid Build Coastguard Worker     Context.init(Node);
1855*03ce13f7SAndroid Build Coastguard Worker     // One legalizer per basic block, otherwise we would share the Temporary
1856*03ce13f7SAndroid Build Coastguard Worker     // Base Register between basic blocks.
1857*03ce13f7SAndroid Build Coastguard Worker     PostLoweringLegalizer Legalizer(this);
1858*03ce13f7SAndroid Build Coastguard Worker     while (!Context.atEnd()) {
1859*03ce13f7SAndroid Build Coastguard Worker       PostIncrLoweringContext PostIncrement(Context);
1860*03ce13f7SAndroid Build Coastguard Worker       Inst *CurInstr = iteratorToInst(Context.getCur());
1861*03ce13f7SAndroid Build Coastguard Worker 
1862*03ce13f7SAndroid Build Coastguard Worker       // Check if the previous TempBaseReg is clobbered, and reset if needed.
1863*03ce13f7SAndroid Build Coastguard Worker       Legalizer.resetTempBaseIfClobberedBy(CurInstr);
1864*03ce13f7SAndroid Build Coastguard Worker 
1865*03ce13f7SAndroid Build Coastguard Worker       if (auto *MovInstr = llvm::dyn_cast<InstARM32Mov>(CurInstr)) {
1866*03ce13f7SAndroid Build Coastguard Worker         Legalizer.legalizeMov(MovInstr);
1867*03ce13f7SAndroid Build Coastguard Worker       } else if (auto *LdrInstr = llvm::dyn_cast<InstARM32Ldr>(CurInstr)) {
1868*03ce13f7SAndroid Build Coastguard Worker         if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand(
1869*03ce13f7SAndroid Build Coastguard Worker                 llvm::cast<OperandARM32Mem>(LdrInstr->getSrc(0)))) {
1870*03ce13f7SAndroid Build Coastguard Worker           _ldr(CurInstr->getDest(), LegalMem, LdrInstr->getPredicate());
1871*03ce13f7SAndroid Build Coastguard Worker           CurInstr->setDeleted();
1872*03ce13f7SAndroid Build Coastguard Worker         }
1873*03ce13f7SAndroid Build Coastguard Worker       } else if (auto *LdrexInstr = llvm::dyn_cast<InstARM32Ldrex>(CurInstr)) {
1874*03ce13f7SAndroid Build Coastguard Worker         constexpr bool DisallowOffsetsBecauseLdrex = false;
1875*03ce13f7SAndroid Build Coastguard Worker         if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand(
1876*03ce13f7SAndroid Build Coastguard Worker                 llvm::cast<OperandARM32Mem>(LdrexInstr->getSrc(0)),
1877*03ce13f7SAndroid Build Coastguard Worker                 DisallowOffsetsBecauseLdrex)) {
1878*03ce13f7SAndroid Build Coastguard Worker           _ldrex(CurInstr->getDest(), LegalMem, LdrexInstr->getPredicate());
1879*03ce13f7SAndroid Build Coastguard Worker           CurInstr->setDeleted();
1880*03ce13f7SAndroid Build Coastguard Worker         }
1881*03ce13f7SAndroid Build Coastguard Worker       } else if (auto *StrInstr = llvm::dyn_cast<InstARM32Str>(CurInstr)) {
1882*03ce13f7SAndroid Build Coastguard Worker         if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand(
1883*03ce13f7SAndroid Build Coastguard Worker                 llvm::cast<OperandARM32Mem>(StrInstr->getSrc(1)))) {
1884*03ce13f7SAndroid Build Coastguard Worker           _str(llvm::cast<Variable>(CurInstr->getSrc(0)), LegalMem,
1885*03ce13f7SAndroid Build Coastguard Worker                StrInstr->getPredicate());
1886*03ce13f7SAndroid Build Coastguard Worker           CurInstr->setDeleted();
1887*03ce13f7SAndroid Build Coastguard Worker         }
1888*03ce13f7SAndroid Build Coastguard Worker       } else if (auto *StrexInstr = llvm::dyn_cast<InstARM32Strex>(CurInstr)) {
1889*03ce13f7SAndroid Build Coastguard Worker         constexpr bool DisallowOffsetsBecauseStrex = false;
1890*03ce13f7SAndroid Build Coastguard Worker         if (OperandARM32Mem *LegalMem = Legalizer.legalizeMemOperand(
1891*03ce13f7SAndroid Build Coastguard Worker                 llvm::cast<OperandARM32Mem>(StrexInstr->getSrc(1)),
1892*03ce13f7SAndroid Build Coastguard Worker                 DisallowOffsetsBecauseStrex)) {
1893*03ce13f7SAndroid Build Coastguard Worker           _strex(CurInstr->getDest(), llvm::cast<Variable>(CurInstr->getSrc(0)),
1894*03ce13f7SAndroid Build Coastguard Worker                  LegalMem, StrexInstr->getPredicate());
1895*03ce13f7SAndroid Build Coastguard Worker           CurInstr->setDeleted();
1896*03ce13f7SAndroid Build Coastguard Worker         }
1897*03ce13f7SAndroid Build Coastguard Worker       }
1898*03ce13f7SAndroid Build Coastguard Worker 
1899*03ce13f7SAndroid Build Coastguard Worker       // Sanity-check: the Legalizer will either have no Temp, or it will be
1900*03ce13f7SAndroid Build Coastguard Worker       // bound to IP.
1901*03ce13f7SAndroid Build Coastguard Worker       Legalizer.assertNoTempOrAssignedToIP();
1902*03ce13f7SAndroid Build Coastguard Worker     }
1903*03ce13f7SAndroid Build Coastguard Worker   }
1904*03ce13f7SAndroid Build Coastguard Worker }
1905*03ce13f7SAndroid Build Coastguard Worker 
loOperand(Operand * Operand)1906*03ce13f7SAndroid Build Coastguard Worker Operand *TargetARM32::loOperand(Operand *Operand) {
1907*03ce13f7SAndroid Build Coastguard Worker   assert(Operand->getType() == IceType_i64);
1908*03ce13f7SAndroid Build Coastguard Worker   if (Operand->getType() != IceType_i64)
1909*03ce13f7SAndroid Build Coastguard Worker     return Operand;
1910*03ce13f7SAndroid Build Coastguard Worker   if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand))
1911*03ce13f7SAndroid Build Coastguard Worker     return Var64On32->getLo();
1912*03ce13f7SAndroid Build Coastguard Worker   if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand))
1913*03ce13f7SAndroid Build Coastguard Worker     return Ctx->getConstantInt32(static_cast<uint32_t>(Const->getValue()));
1914*03ce13f7SAndroid Build Coastguard Worker   if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) {
1915*03ce13f7SAndroid Build Coastguard Worker     // Conservatively disallow memory operands with side-effects (pre/post
1916*03ce13f7SAndroid Build Coastguard Worker     // increment) in case of duplication.
1917*03ce13f7SAndroid Build Coastguard Worker     assert(Mem->getAddrMode() == OperandARM32Mem::Offset ||
1918*03ce13f7SAndroid Build Coastguard Worker            Mem->getAddrMode() == OperandARM32Mem::NegOffset);
1919*03ce13f7SAndroid Build Coastguard Worker     if (Mem->isRegReg()) {
1920*03ce13f7SAndroid Build Coastguard Worker       Variable *IndexR = legalizeToReg(Mem->getIndex());
1921*03ce13f7SAndroid Build Coastguard Worker       return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(), IndexR,
1922*03ce13f7SAndroid Build Coastguard Worker                                      Mem->getShiftOp(), Mem->getShiftAmt(),
1923*03ce13f7SAndroid Build Coastguard Worker                                      Mem->getAddrMode());
1924*03ce13f7SAndroid Build Coastguard Worker     } else {
1925*03ce13f7SAndroid Build Coastguard Worker       return OperandARM32Mem::create(Func, IceType_i32, Mem->getBase(),
1926*03ce13f7SAndroid Build Coastguard Worker                                      Mem->getOffset(), Mem->getAddrMode());
1927*03ce13f7SAndroid Build Coastguard Worker     }
1928*03ce13f7SAndroid Build Coastguard Worker   }
1929*03ce13f7SAndroid Build Coastguard Worker   llvm::report_fatal_error("Unsupported operand type");
1930*03ce13f7SAndroid Build Coastguard Worker   return nullptr;
1931*03ce13f7SAndroid Build Coastguard Worker }
1932*03ce13f7SAndroid Build Coastguard Worker 
hiOperand(Operand * Operand)1933*03ce13f7SAndroid Build Coastguard Worker Operand *TargetARM32::hiOperand(Operand *Operand) {
1934*03ce13f7SAndroid Build Coastguard Worker   assert(Operand->getType() == IceType_i64);
1935*03ce13f7SAndroid Build Coastguard Worker   if (Operand->getType() != IceType_i64)
1936*03ce13f7SAndroid Build Coastguard Worker     return Operand;
1937*03ce13f7SAndroid Build Coastguard Worker   if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand))
1938*03ce13f7SAndroid Build Coastguard Worker     return Var64On32->getHi();
1939*03ce13f7SAndroid Build Coastguard Worker   if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) {
1940*03ce13f7SAndroid Build Coastguard Worker     return Ctx->getConstantInt32(
1941*03ce13f7SAndroid Build Coastguard Worker         static_cast<uint32_t>(Const->getValue() >> 32));
1942*03ce13f7SAndroid Build Coastguard Worker   }
1943*03ce13f7SAndroid Build Coastguard Worker   if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand)) {
1944*03ce13f7SAndroid Build Coastguard Worker     // Conservatively disallow memory operands with side-effects in case of
1945*03ce13f7SAndroid Build Coastguard Worker     // duplication.
1946*03ce13f7SAndroid Build Coastguard Worker     assert(Mem->getAddrMode() == OperandARM32Mem::Offset ||
1947*03ce13f7SAndroid Build Coastguard Worker            Mem->getAddrMode() == OperandARM32Mem::NegOffset);
1948*03ce13f7SAndroid Build Coastguard Worker     const Type SplitType = IceType_i32;
1949*03ce13f7SAndroid Build Coastguard Worker     if (Mem->isRegReg()) {
1950*03ce13f7SAndroid Build Coastguard Worker       // We have to make a temp variable T, and add 4 to either Base or Index.
1951*03ce13f7SAndroid Build Coastguard Worker       // The Index may be shifted, so adding 4 can mean something else. Thus,
1952*03ce13f7SAndroid Build Coastguard Worker       // prefer T := Base + 4, and use T as the new Base.
1953*03ce13f7SAndroid Build Coastguard Worker       Variable *Base = Mem->getBase();
1954*03ce13f7SAndroid Build Coastguard Worker       Constant *Four = Ctx->getConstantInt32(4);
1955*03ce13f7SAndroid Build Coastguard Worker       Variable *NewBase = Func->makeVariable(Base->getType());
1956*03ce13f7SAndroid Build Coastguard Worker       lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, NewBase,
1957*03ce13f7SAndroid Build Coastguard Worker                                              Base, Four));
1958*03ce13f7SAndroid Build Coastguard Worker       Variable *BaseR = legalizeToReg(NewBase);
1959*03ce13f7SAndroid Build Coastguard Worker       Variable *IndexR = legalizeToReg(Mem->getIndex());
1960*03ce13f7SAndroid Build Coastguard Worker       return OperandARM32Mem::create(Func, SplitType, BaseR, IndexR,
1961*03ce13f7SAndroid Build Coastguard Worker                                      Mem->getShiftOp(), Mem->getShiftAmt(),
1962*03ce13f7SAndroid Build Coastguard Worker                                      Mem->getAddrMode());
1963*03ce13f7SAndroid Build Coastguard Worker     } else {
1964*03ce13f7SAndroid Build Coastguard Worker       Variable *Base = Mem->getBase();
1965*03ce13f7SAndroid Build Coastguard Worker       ConstantInteger32 *Offset = Mem->getOffset();
1966*03ce13f7SAndroid Build Coastguard Worker       assert(!Utils::WouldOverflowAdd(Offset->getValue(), 4));
1967*03ce13f7SAndroid Build Coastguard Worker       int32_t NextOffsetVal = Offset->getValue() + 4;
1968*03ce13f7SAndroid Build Coastguard Worker       constexpr bool ZeroExt = false;
1969*03ce13f7SAndroid Build Coastguard Worker       if (!OperandARM32Mem::canHoldOffset(SplitType, ZeroExt, NextOffsetVal)) {
1970*03ce13f7SAndroid Build Coastguard Worker         // We have to make a temp variable and add 4 to either Base or Offset.
1971*03ce13f7SAndroid Build Coastguard Worker         // If we add 4 to Offset, this will convert a non-RegReg addressing
1972*03ce13f7SAndroid Build Coastguard Worker         // mode into a RegReg addressing mode. Since NaCl sandboxing disallows
1973*03ce13f7SAndroid Build Coastguard Worker         // RegReg addressing modes, prefer adding to base and replacing
1974*03ce13f7SAndroid Build Coastguard Worker         // instead. Thus we leave the old offset alone.
1975*03ce13f7SAndroid Build Coastguard Worker         Constant *_4 = Ctx->getConstantInt32(4);
1976*03ce13f7SAndroid Build Coastguard Worker         Variable *NewBase = Func->makeVariable(Base->getType());
1977*03ce13f7SAndroid Build Coastguard Worker         lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add,
1978*03ce13f7SAndroid Build Coastguard Worker                                                NewBase, Base, _4));
1979*03ce13f7SAndroid Build Coastguard Worker         Base = NewBase;
1980*03ce13f7SAndroid Build Coastguard Worker       } else {
1981*03ce13f7SAndroid Build Coastguard Worker         Offset =
1982*03ce13f7SAndroid Build Coastguard Worker             llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(NextOffsetVal));
1983*03ce13f7SAndroid Build Coastguard Worker       }
1984*03ce13f7SAndroid Build Coastguard Worker       Variable *BaseR = legalizeToReg(Base);
1985*03ce13f7SAndroid Build Coastguard Worker       return OperandARM32Mem::create(Func, SplitType, BaseR, Offset,
1986*03ce13f7SAndroid Build Coastguard Worker                                      Mem->getAddrMode());
1987*03ce13f7SAndroid Build Coastguard Worker     }
1988*03ce13f7SAndroid Build Coastguard Worker   }
1989*03ce13f7SAndroid Build Coastguard Worker   llvm::report_fatal_error("Unsupported operand type");
1990*03ce13f7SAndroid Build Coastguard Worker   return nullptr;
1991*03ce13f7SAndroid Build Coastguard Worker }
1992*03ce13f7SAndroid Build Coastguard Worker 
getRegisterSet(RegSetMask Include,RegSetMask Exclude) const1993*03ce13f7SAndroid Build Coastguard Worker SmallBitVector TargetARM32::getRegisterSet(RegSetMask Include,
1994*03ce13f7SAndroid Build Coastguard Worker                                            RegSetMask Exclude) const {
1995*03ce13f7SAndroid Build Coastguard Worker   SmallBitVector Registers(RegARM32::Reg_NUM);
1996*03ce13f7SAndroid Build Coastguard Worker 
1997*03ce13f7SAndroid Build Coastguard Worker   for (uint32_t i = 0; i < RegARM32::Reg_NUM; ++i) {
1998*03ce13f7SAndroid Build Coastguard Worker     const auto &Entry = RegARM32::RegTable[i];
1999*03ce13f7SAndroid Build Coastguard Worker     if (Entry.Scratch && (Include & RegSet_CallerSave))
2000*03ce13f7SAndroid Build Coastguard Worker       Registers[i] = true;
2001*03ce13f7SAndroid Build Coastguard Worker     if (Entry.Preserved && (Include & RegSet_CalleeSave))
2002*03ce13f7SAndroid Build Coastguard Worker       Registers[i] = true;
2003*03ce13f7SAndroid Build Coastguard Worker     if (Entry.StackPtr && (Include & RegSet_StackPointer))
2004*03ce13f7SAndroid Build Coastguard Worker       Registers[i] = true;
2005*03ce13f7SAndroid Build Coastguard Worker     if (Entry.FramePtr && (Include & RegSet_FramePointer))
2006*03ce13f7SAndroid Build Coastguard Worker       Registers[i] = true;
2007*03ce13f7SAndroid Build Coastguard Worker     if (Entry.Scratch && (Exclude & RegSet_CallerSave))
2008*03ce13f7SAndroid Build Coastguard Worker       Registers[i] = false;
2009*03ce13f7SAndroid Build Coastguard Worker     if (Entry.Preserved && (Exclude & RegSet_CalleeSave))
2010*03ce13f7SAndroid Build Coastguard Worker       Registers[i] = false;
2011*03ce13f7SAndroid Build Coastguard Worker     if (Entry.StackPtr && (Exclude & RegSet_StackPointer))
2012*03ce13f7SAndroid Build Coastguard Worker       Registers[i] = false;
2013*03ce13f7SAndroid Build Coastguard Worker     if (Entry.FramePtr && (Exclude & RegSet_FramePointer))
2014*03ce13f7SAndroid Build Coastguard Worker       Registers[i] = false;
2015*03ce13f7SAndroid Build Coastguard Worker   }
2016*03ce13f7SAndroid Build Coastguard Worker 
2017*03ce13f7SAndroid Build Coastguard Worker   return Registers;
2018*03ce13f7SAndroid Build Coastguard Worker }
2019*03ce13f7SAndroid Build Coastguard Worker 
lowerAlloca(const InstAlloca * Instr)2020*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerAlloca(const InstAlloca *Instr) {
2021*03ce13f7SAndroid Build Coastguard Worker   // Conservatively require the stack to be aligned. Some stack adjustment
2022*03ce13f7SAndroid Build Coastguard Worker   // operations implemented below assume that the stack is aligned before the
2023*03ce13f7SAndroid Build Coastguard Worker   // alloca. All the alloca code ensures that the stack alignment is preserved
2024*03ce13f7SAndroid Build Coastguard Worker   // after the alloca. The stack alignment restriction can be relaxed in some
2025*03ce13f7SAndroid Build Coastguard Worker   // cases.
2026*03ce13f7SAndroid Build Coastguard Worker   NeedsStackAlignment = true;
2027*03ce13f7SAndroid Build Coastguard Worker 
2028*03ce13f7SAndroid Build Coastguard Worker   // For default align=0, set it to the real value 1, to avoid any
2029*03ce13f7SAndroid Build Coastguard Worker   // bit-manipulation problems below.
2030*03ce13f7SAndroid Build Coastguard Worker   const uint32_t AlignmentParam = std::max(1u, Instr->getAlignInBytes());
2031*03ce13f7SAndroid Build Coastguard Worker 
2032*03ce13f7SAndroid Build Coastguard Worker   // LLVM enforces power of 2 alignment.
2033*03ce13f7SAndroid Build Coastguard Worker   assert(llvm::isPowerOf2_32(AlignmentParam));
2034*03ce13f7SAndroid Build Coastguard Worker   assert(llvm::isPowerOf2_32(ARM32_STACK_ALIGNMENT_BYTES));
2035*03ce13f7SAndroid Build Coastguard Worker 
2036*03ce13f7SAndroid Build Coastguard Worker   const uint32_t Alignment =
2037*03ce13f7SAndroid Build Coastguard Worker       std::max(AlignmentParam, ARM32_STACK_ALIGNMENT_BYTES);
2038*03ce13f7SAndroid Build Coastguard Worker   const bool OverAligned = Alignment > ARM32_STACK_ALIGNMENT_BYTES;
2039*03ce13f7SAndroid Build Coastguard Worker   const bool OptM1 = Func->getOptLevel() == Opt_m1;
2040*03ce13f7SAndroid Build Coastguard Worker   const bool AllocaWithKnownOffset = Instr->getKnownFrameOffset();
2041*03ce13f7SAndroid Build Coastguard Worker   const bool UseFramePointer =
2042*03ce13f7SAndroid Build Coastguard Worker       hasFramePointer() || OverAligned || !AllocaWithKnownOffset || OptM1;
2043*03ce13f7SAndroid Build Coastguard Worker 
2044*03ce13f7SAndroid Build Coastguard Worker   if (UseFramePointer)
2045*03ce13f7SAndroid Build Coastguard Worker     setHasFramePointer();
2046*03ce13f7SAndroid Build Coastguard Worker 
2047*03ce13f7SAndroid Build Coastguard Worker   Variable *SP = getPhysicalRegister(RegARM32::Reg_sp);
2048*03ce13f7SAndroid Build Coastguard Worker   if (OverAligned) {
2049*03ce13f7SAndroid Build Coastguard Worker     alignRegisterPow2(SP, Alignment);
2050*03ce13f7SAndroid Build Coastguard Worker   }
2051*03ce13f7SAndroid Build Coastguard Worker 
2052*03ce13f7SAndroid Build Coastguard Worker   Variable *Dest = Instr->getDest();
2053*03ce13f7SAndroid Build Coastguard Worker   Operand *TotalSize = Instr->getSizeInBytes();
2054*03ce13f7SAndroid Build Coastguard Worker 
2055*03ce13f7SAndroid Build Coastguard Worker   if (const auto *ConstantTotalSize =
2056*03ce13f7SAndroid Build Coastguard Worker           llvm::dyn_cast<ConstantInteger32>(TotalSize)) {
2057*03ce13f7SAndroid Build Coastguard Worker     const uint32_t Value =
2058*03ce13f7SAndroid Build Coastguard Worker         Utils::applyAlignment(ConstantTotalSize->getValue(), Alignment);
2059*03ce13f7SAndroid Build Coastguard Worker     // Constant size alloca.
2060*03ce13f7SAndroid Build Coastguard Worker     if (!UseFramePointer) {
2061*03ce13f7SAndroid Build Coastguard Worker       // If we don't need a Frame Pointer, this alloca has a known offset to the
2062*03ce13f7SAndroid Build Coastguard Worker       // stack pointer. We don't need adjust the stack pointer, nor assign any
2063*03ce13f7SAndroid Build Coastguard Worker       // value to Dest, as Dest is rematerializable.
2064*03ce13f7SAndroid Build Coastguard Worker       assert(Dest->isRematerializable());
2065*03ce13f7SAndroid Build Coastguard Worker       FixedAllocaSizeBytes += Value;
2066*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeDef>(Dest);
2067*03ce13f7SAndroid Build Coastguard Worker       return;
2068*03ce13f7SAndroid Build Coastguard Worker     }
2069*03ce13f7SAndroid Build Coastguard Worker 
2070*03ce13f7SAndroid Build Coastguard Worker     // If a frame pointer is required, then we need to store the alloca'd result
2071*03ce13f7SAndroid Build Coastguard Worker     // in Dest.
2072*03ce13f7SAndroid Build Coastguard Worker     Operand *SubAmountRF =
2073*03ce13f7SAndroid Build Coastguard Worker         legalize(Ctx->getConstantInt32(Value), Legal_Reg | Legal_Flex);
2074*03ce13f7SAndroid Build Coastguard Worker     _sub(SP, SP, SubAmountRF);
2075*03ce13f7SAndroid Build Coastguard Worker   } else {
2076*03ce13f7SAndroid Build Coastguard Worker     // Non-constant sizes need to be adjusted to the next highest multiple of
2077*03ce13f7SAndroid Build Coastguard Worker     // the required alignment at runtime.
2078*03ce13f7SAndroid Build Coastguard Worker     TotalSize = legalize(TotalSize, Legal_Reg | Legal_Flex);
2079*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(IceType_i32);
2080*03ce13f7SAndroid Build Coastguard Worker     _mov(T, TotalSize);
2081*03ce13f7SAndroid Build Coastguard Worker     Operand *AddAmount = legalize(Ctx->getConstantInt32(Alignment - 1));
2082*03ce13f7SAndroid Build Coastguard Worker     _add(T, T, AddAmount);
2083*03ce13f7SAndroid Build Coastguard Worker     alignRegisterPow2(T, Alignment);
2084*03ce13f7SAndroid Build Coastguard Worker     _sub(SP, SP, T);
2085*03ce13f7SAndroid Build Coastguard Worker   }
2086*03ce13f7SAndroid Build Coastguard Worker 
2087*03ce13f7SAndroid Build Coastguard Worker   // Adds back a few bytes to SP to account for the out args area.
2088*03ce13f7SAndroid Build Coastguard Worker   Variable *T = SP;
2089*03ce13f7SAndroid Build Coastguard Worker   if (MaxOutArgsSizeBytes != 0) {
2090*03ce13f7SAndroid Build Coastguard Worker     T = makeReg(getPointerType());
2091*03ce13f7SAndroid Build Coastguard Worker     Operand *OutArgsSizeRF = legalize(
2092*03ce13f7SAndroid Build Coastguard Worker         Ctx->getConstantInt32(MaxOutArgsSizeBytes), Legal_Reg | Legal_Flex);
2093*03ce13f7SAndroid Build Coastguard Worker     _add(T, SP, OutArgsSizeRF);
2094*03ce13f7SAndroid Build Coastguard Worker   }
2095*03ce13f7SAndroid Build Coastguard Worker 
2096*03ce13f7SAndroid Build Coastguard Worker   _mov(Dest, T);
2097*03ce13f7SAndroid Build Coastguard Worker }
2098*03ce13f7SAndroid Build Coastguard Worker 
div0Check(Type Ty,Operand * SrcLo,Operand * SrcHi)2099*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::div0Check(Type Ty, Operand *SrcLo, Operand *SrcHi) {
2100*03ce13f7SAndroid Build Coastguard Worker   if (isGuaranteedNonzeroInt(SrcLo) || isGuaranteedNonzeroInt(SrcHi))
2101*03ce13f7SAndroid Build Coastguard Worker     return;
2102*03ce13f7SAndroid Build Coastguard Worker   Variable *SrcLoReg = legalizeToReg(SrcLo);
2103*03ce13f7SAndroid Build Coastguard Worker   switch (Ty) {
2104*03ce13f7SAndroid Build Coastguard Worker   default:
2105*03ce13f7SAndroid Build Coastguard Worker     llvm_unreachable(
2106*03ce13f7SAndroid Build Coastguard Worker         ("Unexpected type in div0Check: " + typeStdString(Ty)).c_str());
2107*03ce13f7SAndroid Build Coastguard Worker   case IceType_i8:
2108*03ce13f7SAndroid Build Coastguard Worker   case IceType_i16: {
2109*03ce13f7SAndroid Build Coastguard Worker     Operand *ShAmtImm = shAmtImm(32 - getScalarIntBitWidth(Ty));
2110*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(IceType_i32);
2111*03ce13f7SAndroid Build Coastguard Worker     _lsls(T, SrcLoReg, ShAmtImm);
2112*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(T);
2113*03ce13f7SAndroid Build Coastguard Worker   } break;
2114*03ce13f7SAndroid Build Coastguard Worker   case IceType_i32: {
2115*03ce13f7SAndroid Build Coastguard Worker     _tst(SrcLoReg, SrcLoReg);
2116*03ce13f7SAndroid Build Coastguard Worker     break;
2117*03ce13f7SAndroid Build Coastguard Worker   }
2118*03ce13f7SAndroid Build Coastguard Worker   case IceType_i64: {
2119*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(IceType_i32);
2120*03ce13f7SAndroid Build Coastguard Worker     _orrs(T, SrcLoReg, legalize(SrcHi, Legal_Reg | Legal_Flex));
2121*03ce13f7SAndroid Build Coastguard Worker     // T isn't going to be used, but we need the side-effect of setting flags
2122*03ce13f7SAndroid Build Coastguard Worker     // from this operation.
2123*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(T);
2124*03ce13f7SAndroid Build Coastguard Worker   }
2125*03ce13f7SAndroid Build Coastguard Worker   }
2126*03ce13f7SAndroid Build Coastguard Worker   auto *Label = InstARM32Label::create(Func, this);
2127*03ce13f7SAndroid Build Coastguard Worker   _br(Label, CondARM32::NE);
2128*03ce13f7SAndroid Build Coastguard Worker   _trap();
2129*03ce13f7SAndroid Build Coastguard Worker   Context.insert(Label);
2130*03ce13f7SAndroid Build Coastguard Worker }
2131*03ce13f7SAndroid Build Coastguard Worker 
lowerIDivRem(Variable * Dest,Variable * T,Variable * Src0R,Operand * Src1,ExtInstr ExtFunc,DivInstr DivFunc,bool IsRemainder)2132*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerIDivRem(Variable *Dest, Variable *T, Variable *Src0R,
2133*03ce13f7SAndroid Build Coastguard Worker                                Operand *Src1, ExtInstr ExtFunc,
2134*03ce13f7SAndroid Build Coastguard Worker                                DivInstr DivFunc, bool IsRemainder) {
2135*03ce13f7SAndroid Build Coastguard Worker   div0Check(Dest->getType(), Src1, nullptr);
2136*03ce13f7SAndroid Build Coastguard Worker   Variable *Src1R = legalizeToReg(Src1);
2137*03ce13f7SAndroid Build Coastguard Worker   Variable *T0R = Src0R;
2138*03ce13f7SAndroid Build Coastguard Worker   Variable *T1R = Src1R;
2139*03ce13f7SAndroid Build Coastguard Worker   if (Dest->getType() != IceType_i32) {
2140*03ce13f7SAndroid Build Coastguard Worker     T0R = makeReg(IceType_i32);
2141*03ce13f7SAndroid Build Coastguard Worker     (this->*ExtFunc)(T0R, Src0R, CondARM32::AL);
2142*03ce13f7SAndroid Build Coastguard Worker     T1R = makeReg(IceType_i32);
2143*03ce13f7SAndroid Build Coastguard Worker     (this->*ExtFunc)(T1R, Src1R, CondARM32::AL);
2144*03ce13f7SAndroid Build Coastguard Worker   }
2145*03ce13f7SAndroid Build Coastguard Worker   if (hasCPUFeature(TargetARM32Features::HWDivArm)) {
2146*03ce13f7SAndroid Build Coastguard Worker     (this->*DivFunc)(T, T0R, T1R, CondARM32::AL);
2147*03ce13f7SAndroid Build Coastguard Worker     if (IsRemainder) {
2148*03ce13f7SAndroid Build Coastguard Worker       Variable *T2 = makeReg(IceType_i32);
2149*03ce13f7SAndroid Build Coastguard Worker       _mls(T2, T, T1R, T0R);
2150*03ce13f7SAndroid Build Coastguard Worker       T = T2;
2151*03ce13f7SAndroid Build Coastguard Worker     }
2152*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
2153*03ce13f7SAndroid Build Coastguard Worker   } else {
2154*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("div should have already been turned into a call");
2155*03ce13f7SAndroid Build Coastguard Worker   }
2156*03ce13f7SAndroid Build Coastguard Worker }
2157*03ce13f7SAndroid Build Coastguard Worker 
2158*03ce13f7SAndroid Build Coastguard Worker TargetARM32::SafeBoolChain
lowerInt1Arithmetic(const InstArithmetic * Instr)2159*03ce13f7SAndroid Build Coastguard Worker TargetARM32::lowerInt1Arithmetic(const InstArithmetic *Instr) {
2160*03ce13f7SAndroid Build Coastguard Worker   Variable *Dest = Instr->getDest();
2161*03ce13f7SAndroid Build Coastguard Worker   assert(Dest->getType() == IceType_i1);
2162*03ce13f7SAndroid Build Coastguard Worker 
2163*03ce13f7SAndroid Build Coastguard Worker   // So folding didn't work for Instr. Not a problem: We just need to
2164*03ce13f7SAndroid Build Coastguard Worker   // materialize the Sources, and perform the operation. We create regular
2165*03ce13f7SAndroid Build Coastguard Worker   // Variables (and not infinite-weight ones) because this call might recurse a
2166*03ce13f7SAndroid Build Coastguard Worker   // lot, and we might end up with tons of infinite weight temporaries.
2167*03ce13f7SAndroid Build Coastguard Worker   assert(Instr->getSrcSize() == 2);
2168*03ce13f7SAndroid Build Coastguard Worker   Variable *Src0 = Func->makeVariable(IceType_i1);
2169*03ce13f7SAndroid Build Coastguard Worker   SafeBoolChain Src0Safe = lowerInt1(Src0, Instr->getSrc(0));
2170*03ce13f7SAndroid Build Coastguard Worker 
2171*03ce13f7SAndroid Build Coastguard Worker   Operand *Src1 = Instr->getSrc(1);
2172*03ce13f7SAndroid Build Coastguard Worker   SafeBoolChain Src1Safe = SBC_Yes;
2173*03ce13f7SAndroid Build Coastguard Worker 
2174*03ce13f7SAndroid Build Coastguard Worker   if (!llvm::isa<Constant>(Src1)) {
2175*03ce13f7SAndroid Build Coastguard Worker     Variable *Src1V = Func->makeVariable(IceType_i1);
2176*03ce13f7SAndroid Build Coastguard Worker     Src1Safe = lowerInt1(Src1V, Src1);
2177*03ce13f7SAndroid Build Coastguard Worker     Src1 = Src1V;
2178*03ce13f7SAndroid Build Coastguard Worker   }
2179*03ce13f7SAndroid Build Coastguard Worker 
2180*03ce13f7SAndroid Build Coastguard Worker   Variable *T = makeReg(IceType_i1);
2181*03ce13f7SAndroid Build Coastguard Worker   Src0 = legalizeToReg(Src0);
2182*03ce13f7SAndroid Build Coastguard Worker   Operand *Src1RF = legalize(Src1, Legal_Reg | Legal_Flex);
2183*03ce13f7SAndroid Build Coastguard Worker   switch (Instr->getOp()) {
2184*03ce13f7SAndroid Build Coastguard Worker   default:
2185*03ce13f7SAndroid Build Coastguard Worker     // If this Unreachable is ever executed, add the offending operation to
2186*03ce13f7SAndroid Build Coastguard Worker     // the list of valid consumers.
2187*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Unhandled i1 Op");
2188*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::And:
2189*03ce13f7SAndroid Build Coastguard Worker     _and(T, Src0, Src1RF);
2190*03ce13f7SAndroid Build Coastguard Worker     break;
2191*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Or:
2192*03ce13f7SAndroid Build Coastguard Worker     _orr(T, Src0, Src1RF);
2193*03ce13f7SAndroid Build Coastguard Worker     break;
2194*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Xor:
2195*03ce13f7SAndroid Build Coastguard Worker     _eor(T, Src0, Src1RF);
2196*03ce13f7SAndroid Build Coastguard Worker     break;
2197*03ce13f7SAndroid Build Coastguard Worker   }
2198*03ce13f7SAndroid Build Coastguard Worker   _mov(Dest, T);
2199*03ce13f7SAndroid Build Coastguard Worker   return Src0Safe == SBC_Yes && Src1Safe == SBC_Yes ? SBC_Yes : SBC_No;
2200*03ce13f7SAndroid Build Coastguard Worker }
2201*03ce13f7SAndroid Build Coastguard Worker 
2202*03ce13f7SAndroid Build Coastguard Worker namespace {
2203*03ce13f7SAndroid Build Coastguard Worker // NumericOperands is used during arithmetic/icmp lowering for constant folding.
2204*03ce13f7SAndroid Build Coastguard Worker // It holds the two sources operands, and maintains some state as to whether one
2205*03ce13f7SAndroid Build Coastguard Worker // of them is a constant. If one of the operands is a constant, then it will be
2206*03ce13f7SAndroid Build Coastguard Worker // be stored as the operation's second source, with a bit indicating whether the
2207*03ce13f7SAndroid Build Coastguard Worker // operands were swapped.
2208*03ce13f7SAndroid Build Coastguard Worker //
2209*03ce13f7SAndroid Build Coastguard Worker // The class is split into a base class with operand type-independent methods,
2210*03ce13f7SAndroid Build Coastguard Worker // and a derived, templated class, for each type of operand we want to fold
2211*03ce13f7SAndroid Build Coastguard Worker // constants for:
2212*03ce13f7SAndroid Build Coastguard Worker //
2213*03ce13f7SAndroid Build Coastguard Worker // NumericOperandsBase --> NumericOperands<ConstantFloat>
2214*03ce13f7SAndroid Build Coastguard Worker //                     --> NumericOperands<ConstantDouble>
2215*03ce13f7SAndroid Build Coastguard Worker //                     --> NumericOperands<ConstantInt32>
2216*03ce13f7SAndroid Build Coastguard Worker //
2217*03ce13f7SAndroid Build Coastguard Worker // NumericOperands<ConstantInt32> also exposes helper methods for emitting
2218*03ce13f7SAndroid Build Coastguard Worker // inverted/negated immediates.
2219*03ce13f7SAndroid Build Coastguard Worker class NumericOperandsBase {
2220*03ce13f7SAndroid Build Coastguard Worker   NumericOperandsBase() = delete;
2221*03ce13f7SAndroid Build Coastguard Worker   NumericOperandsBase(const NumericOperandsBase &) = delete;
2222*03ce13f7SAndroid Build Coastguard Worker   NumericOperandsBase &operator=(const NumericOperandsBase &) = delete;
2223*03ce13f7SAndroid Build Coastguard Worker 
2224*03ce13f7SAndroid Build Coastguard Worker public:
NumericOperandsBase(Operand * S0,Operand * S1)2225*03ce13f7SAndroid Build Coastguard Worker   NumericOperandsBase(Operand *S0, Operand *S1)
2226*03ce13f7SAndroid Build Coastguard Worker       : Src0(NonConstOperand(S0, S1)), Src1(ConstOperand(S0, S1)),
2227*03ce13f7SAndroid Build Coastguard Worker         Swapped(Src0 == S1 && S0 != S1) {
2228*03ce13f7SAndroid Build Coastguard Worker     assert(Src0 != nullptr);
2229*03ce13f7SAndroid Build Coastguard Worker     assert(Src1 != nullptr);
2230*03ce13f7SAndroid Build Coastguard Worker     assert(Src0 != Src1 || S0 == S1);
2231*03ce13f7SAndroid Build Coastguard Worker   }
2232*03ce13f7SAndroid Build Coastguard Worker 
hasConstOperand() const2233*03ce13f7SAndroid Build Coastguard Worker   bool hasConstOperand() const {
2234*03ce13f7SAndroid Build Coastguard Worker     return llvm::isa<Constant>(Src1) && !llvm::isa<ConstantRelocatable>(Src1);
2235*03ce13f7SAndroid Build Coastguard Worker   }
2236*03ce13f7SAndroid Build Coastguard Worker 
swappedOperands() const2237*03ce13f7SAndroid Build Coastguard Worker   bool swappedOperands() const { return Swapped; }
2238*03ce13f7SAndroid Build Coastguard Worker 
src0R(TargetARM32 * Target) const2239*03ce13f7SAndroid Build Coastguard Worker   Variable *src0R(TargetARM32 *Target) const {
2240*03ce13f7SAndroid Build Coastguard Worker     return legalizeToReg(Target, Src0);
2241*03ce13f7SAndroid Build Coastguard Worker   }
2242*03ce13f7SAndroid Build Coastguard Worker 
unswappedSrc0R(TargetARM32 * Target) const2243*03ce13f7SAndroid Build Coastguard Worker   Variable *unswappedSrc0R(TargetARM32 *Target) const {
2244*03ce13f7SAndroid Build Coastguard Worker     return legalizeToReg(Target, Swapped ? Src1 : Src0);
2245*03ce13f7SAndroid Build Coastguard Worker   }
2246*03ce13f7SAndroid Build Coastguard Worker 
src1RF(TargetARM32 * Target) const2247*03ce13f7SAndroid Build Coastguard Worker   Operand *src1RF(TargetARM32 *Target) const {
2248*03ce13f7SAndroid Build Coastguard Worker     return legalizeToRegOrFlex(Target, Src1);
2249*03ce13f7SAndroid Build Coastguard Worker   }
2250*03ce13f7SAndroid Build Coastguard Worker 
unswappedSrc1R(TargetARM32 * Target) const2251*03ce13f7SAndroid Build Coastguard Worker   Variable *unswappedSrc1R(TargetARM32 *Target) const {
2252*03ce13f7SAndroid Build Coastguard Worker     return legalizeToReg(Target, Swapped ? Src0 : Src1);
2253*03ce13f7SAndroid Build Coastguard Worker   }
2254*03ce13f7SAndroid Build Coastguard Worker 
src1() const2255*03ce13f7SAndroid Build Coastguard Worker   Operand *src1() const { return Src1; }
2256*03ce13f7SAndroid Build Coastguard Worker 
2257*03ce13f7SAndroid Build Coastguard Worker protected:
2258*03ce13f7SAndroid Build Coastguard Worker   Operand *const Src0;
2259*03ce13f7SAndroid Build Coastguard Worker   Operand *const Src1;
2260*03ce13f7SAndroid Build Coastguard Worker   const bool Swapped;
2261*03ce13f7SAndroid Build Coastguard Worker 
legalizeToReg(TargetARM32 * Target,Operand * Src)2262*03ce13f7SAndroid Build Coastguard Worker   static Variable *legalizeToReg(TargetARM32 *Target, Operand *Src) {
2263*03ce13f7SAndroid Build Coastguard Worker     return Target->legalizeToReg(Src);
2264*03ce13f7SAndroid Build Coastguard Worker   }
2265*03ce13f7SAndroid Build Coastguard Worker 
legalizeToRegOrFlex(TargetARM32 * Target,Operand * Src)2266*03ce13f7SAndroid Build Coastguard Worker   static Operand *legalizeToRegOrFlex(TargetARM32 *Target, Operand *Src) {
2267*03ce13f7SAndroid Build Coastguard Worker     return Target->legalize(Src,
2268*03ce13f7SAndroid Build Coastguard Worker                             TargetARM32::Legal_Reg | TargetARM32::Legal_Flex);
2269*03ce13f7SAndroid Build Coastguard Worker   }
2270*03ce13f7SAndroid Build Coastguard Worker 
2271*03ce13f7SAndroid Build Coastguard Worker private:
NonConstOperand(Operand * S0,Operand * S1)2272*03ce13f7SAndroid Build Coastguard Worker   static Operand *NonConstOperand(Operand *S0, Operand *S1) {
2273*03ce13f7SAndroid Build Coastguard Worker     if (!llvm::isa<Constant>(S0))
2274*03ce13f7SAndroid Build Coastguard Worker       return S0;
2275*03ce13f7SAndroid Build Coastguard Worker     if (!llvm::isa<Constant>(S1))
2276*03ce13f7SAndroid Build Coastguard Worker       return S1;
2277*03ce13f7SAndroid Build Coastguard Worker     if (llvm::isa<ConstantRelocatable>(S1) &&
2278*03ce13f7SAndroid Build Coastguard Worker         !llvm::isa<ConstantRelocatable>(S0))
2279*03ce13f7SAndroid Build Coastguard Worker       return S1;
2280*03ce13f7SAndroid Build Coastguard Worker     return S0;
2281*03ce13f7SAndroid Build Coastguard Worker   }
2282*03ce13f7SAndroid Build Coastguard Worker 
ConstOperand(Operand * S0,Operand * S1)2283*03ce13f7SAndroid Build Coastguard Worker   static Operand *ConstOperand(Operand *S0, Operand *S1) {
2284*03ce13f7SAndroid Build Coastguard Worker     if (!llvm::isa<Constant>(S0))
2285*03ce13f7SAndroid Build Coastguard Worker       return S1;
2286*03ce13f7SAndroid Build Coastguard Worker     if (!llvm::isa<Constant>(S1))
2287*03ce13f7SAndroid Build Coastguard Worker       return S0;
2288*03ce13f7SAndroid Build Coastguard Worker     if (llvm::isa<ConstantRelocatable>(S1) &&
2289*03ce13f7SAndroid Build Coastguard Worker         !llvm::isa<ConstantRelocatable>(S0))
2290*03ce13f7SAndroid Build Coastguard Worker       return S0;
2291*03ce13f7SAndroid Build Coastguard Worker     return S1;
2292*03ce13f7SAndroid Build Coastguard Worker   }
2293*03ce13f7SAndroid Build Coastguard Worker };
2294*03ce13f7SAndroid Build Coastguard Worker 
2295*03ce13f7SAndroid Build Coastguard Worker template <typename C> class NumericOperands : public NumericOperandsBase {
2296*03ce13f7SAndroid Build Coastguard Worker   NumericOperands() = delete;
2297*03ce13f7SAndroid Build Coastguard Worker   NumericOperands(const NumericOperands &) = delete;
2298*03ce13f7SAndroid Build Coastguard Worker   NumericOperands &operator=(const NumericOperands &) = delete;
2299*03ce13f7SAndroid Build Coastguard Worker 
2300*03ce13f7SAndroid Build Coastguard Worker public:
NumericOperands(Operand * S0,Operand * S1)2301*03ce13f7SAndroid Build Coastguard Worker   NumericOperands(Operand *S0, Operand *S1) : NumericOperandsBase(S0, S1) {
2302*03ce13f7SAndroid Build Coastguard Worker     assert(!hasConstOperand() || llvm::isa<C>(this->Src1));
2303*03ce13f7SAndroid Build Coastguard Worker   }
2304*03ce13f7SAndroid Build Coastguard Worker 
getConstantValue() const2305*03ce13f7SAndroid Build Coastguard Worker   typename C::PrimType getConstantValue() const {
2306*03ce13f7SAndroid Build Coastguard Worker     return llvm::cast<C>(Src1)->getValue();
2307*03ce13f7SAndroid Build Coastguard Worker   }
2308*03ce13f7SAndroid Build Coastguard Worker };
2309*03ce13f7SAndroid Build Coastguard Worker 
2310*03ce13f7SAndroid Build Coastguard Worker using FloatOperands = NumericOperands<ConstantFloat>;
2311*03ce13f7SAndroid Build Coastguard Worker using DoubleOperands = NumericOperands<ConstantDouble>;
2312*03ce13f7SAndroid Build Coastguard Worker 
2313*03ce13f7SAndroid Build Coastguard Worker class Int32Operands : public NumericOperands<ConstantInteger32> {
2314*03ce13f7SAndroid Build Coastguard Worker   Int32Operands() = delete;
2315*03ce13f7SAndroid Build Coastguard Worker   Int32Operands(const Int32Operands &) = delete;
2316*03ce13f7SAndroid Build Coastguard Worker   Int32Operands &operator=(const Int32Operands &) = delete;
2317*03ce13f7SAndroid Build Coastguard Worker 
2318*03ce13f7SAndroid Build Coastguard Worker public:
Int32Operands(Operand * S0,Operand * S1)2319*03ce13f7SAndroid Build Coastguard Worker   Int32Operands(Operand *S0, Operand *S1) : NumericOperands(S0, S1) {}
2320*03ce13f7SAndroid Build Coastguard Worker 
unswappedSrc1RShAmtImm(TargetARM32 * Target) const2321*03ce13f7SAndroid Build Coastguard Worker   Operand *unswappedSrc1RShAmtImm(TargetARM32 *Target) const {
2322*03ce13f7SAndroid Build Coastguard Worker     if (!swappedOperands() && hasConstOperand()) {
2323*03ce13f7SAndroid Build Coastguard Worker       return Target->shAmtImm(getConstantValue() & 0x1F);
2324*03ce13f7SAndroid Build Coastguard Worker     }
2325*03ce13f7SAndroid Build Coastguard Worker     return legalizeToReg(Target, Swapped ? Src0 : Src1);
2326*03ce13f7SAndroid Build Coastguard Worker   }
2327*03ce13f7SAndroid Build Coastguard Worker 
isSrc1ImmediateZero() const2328*03ce13f7SAndroid Build Coastguard Worker   bool isSrc1ImmediateZero() const {
2329*03ce13f7SAndroid Build Coastguard Worker     if (!swappedOperands() && hasConstOperand()) {
2330*03ce13f7SAndroid Build Coastguard Worker       return getConstantValue() == 0;
2331*03ce13f7SAndroid Build Coastguard Worker     }
2332*03ce13f7SAndroid Build Coastguard Worker     return false;
2333*03ce13f7SAndroid Build Coastguard Worker   }
2334*03ce13f7SAndroid Build Coastguard Worker 
immediateIsFlexEncodable() const2335*03ce13f7SAndroid Build Coastguard Worker   bool immediateIsFlexEncodable() const {
2336*03ce13f7SAndroid Build Coastguard Worker     uint32_t Rotate, Imm8;
2337*03ce13f7SAndroid Build Coastguard Worker     return OperandARM32FlexImm::canHoldImm(getConstantValue(), &Rotate, &Imm8);
2338*03ce13f7SAndroid Build Coastguard Worker   }
2339*03ce13f7SAndroid Build Coastguard Worker 
negatedImmediateIsFlexEncodable() const2340*03ce13f7SAndroid Build Coastguard Worker   bool negatedImmediateIsFlexEncodable() const {
2341*03ce13f7SAndroid Build Coastguard Worker     uint32_t Rotate, Imm8;
2342*03ce13f7SAndroid Build Coastguard Worker     return OperandARM32FlexImm::canHoldImm(
2343*03ce13f7SAndroid Build Coastguard Worker         -static_cast<int32_t>(getConstantValue()), &Rotate, &Imm8);
2344*03ce13f7SAndroid Build Coastguard Worker   }
2345*03ce13f7SAndroid Build Coastguard Worker 
negatedSrc1F(TargetARM32 * Target) const2346*03ce13f7SAndroid Build Coastguard Worker   Operand *negatedSrc1F(TargetARM32 *Target) const {
2347*03ce13f7SAndroid Build Coastguard Worker     return legalizeToRegOrFlex(Target,
2348*03ce13f7SAndroid Build Coastguard Worker                                Target->getCtx()->getConstantInt32(
2349*03ce13f7SAndroid Build Coastguard Worker                                    -static_cast<int32_t>(getConstantValue())));
2350*03ce13f7SAndroid Build Coastguard Worker   }
2351*03ce13f7SAndroid Build Coastguard Worker 
invertedImmediateIsFlexEncodable() const2352*03ce13f7SAndroid Build Coastguard Worker   bool invertedImmediateIsFlexEncodable() const {
2353*03ce13f7SAndroid Build Coastguard Worker     uint32_t Rotate, Imm8;
2354*03ce13f7SAndroid Build Coastguard Worker     return OperandARM32FlexImm::canHoldImm(
2355*03ce13f7SAndroid Build Coastguard Worker         ~static_cast<uint32_t>(getConstantValue()), &Rotate, &Imm8);
2356*03ce13f7SAndroid Build Coastguard Worker   }
2357*03ce13f7SAndroid Build Coastguard Worker 
invertedSrc1F(TargetARM32 * Target) const2358*03ce13f7SAndroid Build Coastguard Worker   Operand *invertedSrc1F(TargetARM32 *Target) const {
2359*03ce13f7SAndroid Build Coastguard Worker     return legalizeToRegOrFlex(Target,
2360*03ce13f7SAndroid Build Coastguard Worker                                Target->getCtx()->getConstantInt32(
2361*03ce13f7SAndroid Build Coastguard Worker                                    ~static_cast<uint32_t>(getConstantValue())));
2362*03ce13f7SAndroid Build Coastguard Worker   }
2363*03ce13f7SAndroid Build Coastguard Worker };
2364*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
2365*03ce13f7SAndroid Build Coastguard Worker 
preambleDivRem(const InstCall * Instr)2366*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::preambleDivRem(const InstCall *Instr) {
2367*03ce13f7SAndroid Build Coastguard Worker   Operand *Src1 = Instr->getArg(1);
2368*03ce13f7SAndroid Build Coastguard Worker 
2369*03ce13f7SAndroid Build Coastguard Worker   switch (Src1->getType()) {
2370*03ce13f7SAndroid Build Coastguard Worker   default:
2371*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Invalid type for idiv.");
2372*03ce13f7SAndroid Build Coastguard Worker   case IceType_i64: {
2373*03ce13f7SAndroid Build Coastguard Worker     if (auto *C = llvm::dyn_cast<ConstantInteger64>(Src1)) {
2374*03ce13f7SAndroid Build Coastguard Worker       if (C->getValue() == 0) {
2375*03ce13f7SAndroid Build Coastguard Worker         _trap();
2376*03ce13f7SAndroid Build Coastguard Worker         return;
2377*03ce13f7SAndroid Build Coastguard Worker       }
2378*03ce13f7SAndroid Build Coastguard Worker     }
2379*03ce13f7SAndroid Build Coastguard Worker     div0Check(IceType_i64, loOperand(Src1), hiOperand(Src1));
2380*03ce13f7SAndroid Build Coastguard Worker     return;
2381*03ce13f7SAndroid Build Coastguard Worker   }
2382*03ce13f7SAndroid Build Coastguard Worker   case IceType_i32: {
2383*03ce13f7SAndroid Build Coastguard Worker     // Src0 and Src1 have already been appropriately extended to an i32, so we
2384*03ce13f7SAndroid Build Coastguard Worker     // don't check for i8 and i16.
2385*03ce13f7SAndroid Build Coastguard Worker     if (auto *C = llvm::dyn_cast<ConstantInteger32>(Src1)) {
2386*03ce13f7SAndroid Build Coastguard Worker       if (C->getValue() == 0) {
2387*03ce13f7SAndroid Build Coastguard Worker         _trap();
2388*03ce13f7SAndroid Build Coastguard Worker         return;
2389*03ce13f7SAndroid Build Coastguard Worker       }
2390*03ce13f7SAndroid Build Coastguard Worker     }
2391*03ce13f7SAndroid Build Coastguard Worker     div0Check(IceType_i32, Src1, nullptr);
2392*03ce13f7SAndroid Build Coastguard Worker     return;
2393*03ce13f7SAndroid Build Coastguard Worker   }
2394*03ce13f7SAndroid Build Coastguard Worker   }
2395*03ce13f7SAndroid Build Coastguard Worker }
2396*03ce13f7SAndroid Build Coastguard Worker 
lowerInt64Arithmetic(InstArithmetic::OpKind Op,Variable * Dest,Operand * Src0,Operand * Src1)2397*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerInt64Arithmetic(InstArithmetic::OpKind Op,
2398*03ce13f7SAndroid Build Coastguard Worker                                        Variable *Dest, Operand *Src0,
2399*03ce13f7SAndroid Build Coastguard Worker                                        Operand *Src1) {
2400*03ce13f7SAndroid Build Coastguard Worker   Int32Operands SrcsLo(loOperand(Src0), loOperand(Src1));
2401*03ce13f7SAndroid Build Coastguard Worker   Int32Operands SrcsHi(hiOperand(Src0), hiOperand(Src1));
2402*03ce13f7SAndroid Build Coastguard Worker   assert(SrcsLo.swappedOperands() == SrcsHi.swappedOperands());
2403*03ce13f7SAndroid Build Coastguard Worker   assert(SrcsLo.hasConstOperand() == SrcsHi.hasConstOperand());
2404*03ce13f7SAndroid Build Coastguard Worker 
2405*03ce13f7SAndroid Build Coastguard Worker   auto *DestLo = llvm::cast<Variable>(loOperand(Dest));
2406*03ce13f7SAndroid Build Coastguard Worker   auto *DestHi = llvm::cast<Variable>(hiOperand(Dest));
2407*03ce13f7SAndroid Build Coastguard Worker   Variable *T_Lo = makeReg(DestLo->getType());
2408*03ce13f7SAndroid Build Coastguard Worker   Variable *T_Hi = makeReg(DestHi->getType());
2409*03ce13f7SAndroid Build Coastguard Worker 
2410*03ce13f7SAndroid Build Coastguard Worker   switch (Op) {
2411*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::_num:
2412*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Unknown arithmetic operator");
2413*03ce13f7SAndroid Build Coastguard Worker     return;
2414*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Add: {
2415*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0LoR = SrcsLo.src0R(this);
2416*03ce13f7SAndroid Build Coastguard Worker     Operand *Src1LoRF = SrcsLo.src1RF(this);
2417*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0HiR = SrcsHi.src0R(this);
2418*03ce13f7SAndroid Build Coastguard Worker     Operand *Src1HiRF = SrcsHi.src1RF(this);
2419*03ce13f7SAndroid Build Coastguard Worker     _adds(T_Lo, Src0LoR, Src1LoRF);
2420*03ce13f7SAndroid Build Coastguard Worker     _mov(DestLo, T_Lo);
2421*03ce13f7SAndroid Build Coastguard Worker     _adc(T_Hi, Src0HiR, Src1HiRF);
2422*03ce13f7SAndroid Build Coastguard Worker     _mov(DestHi, T_Hi);
2423*03ce13f7SAndroid Build Coastguard Worker     return;
2424*03ce13f7SAndroid Build Coastguard Worker   }
2425*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::And: {
2426*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0LoR = SrcsLo.src0R(this);
2427*03ce13f7SAndroid Build Coastguard Worker     Operand *Src1LoRF = SrcsLo.src1RF(this);
2428*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0HiR = SrcsHi.src0R(this);
2429*03ce13f7SAndroid Build Coastguard Worker     Operand *Src1HiRF = SrcsHi.src1RF(this);
2430*03ce13f7SAndroid Build Coastguard Worker     _and(T_Lo, Src0LoR, Src1LoRF);
2431*03ce13f7SAndroid Build Coastguard Worker     _mov(DestLo, T_Lo);
2432*03ce13f7SAndroid Build Coastguard Worker     _and(T_Hi, Src0HiR, Src1HiRF);
2433*03ce13f7SAndroid Build Coastguard Worker     _mov(DestHi, T_Hi);
2434*03ce13f7SAndroid Build Coastguard Worker     return;
2435*03ce13f7SAndroid Build Coastguard Worker   }
2436*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Or: {
2437*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0LoR = SrcsLo.src0R(this);
2438*03ce13f7SAndroid Build Coastguard Worker     Operand *Src1LoRF = SrcsLo.src1RF(this);
2439*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0HiR = SrcsHi.src0R(this);
2440*03ce13f7SAndroid Build Coastguard Worker     Operand *Src1HiRF = SrcsHi.src1RF(this);
2441*03ce13f7SAndroid Build Coastguard Worker     _orr(T_Lo, Src0LoR, Src1LoRF);
2442*03ce13f7SAndroid Build Coastguard Worker     _mov(DestLo, T_Lo);
2443*03ce13f7SAndroid Build Coastguard Worker     _orr(T_Hi, Src0HiR, Src1HiRF);
2444*03ce13f7SAndroid Build Coastguard Worker     _mov(DestHi, T_Hi);
2445*03ce13f7SAndroid Build Coastguard Worker     return;
2446*03ce13f7SAndroid Build Coastguard Worker   }
2447*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Xor: {
2448*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0LoR = SrcsLo.src0R(this);
2449*03ce13f7SAndroid Build Coastguard Worker     Operand *Src1LoRF = SrcsLo.src1RF(this);
2450*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0HiR = SrcsHi.src0R(this);
2451*03ce13f7SAndroid Build Coastguard Worker     Operand *Src1HiRF = SrcsHi.src1RF(this);
2452*03ce13f7SAndroid Build Coastguard Worker     _eor(T_Lo, Src0LoR, Src1LoRF);
2453*03ce13f7SAndroid Build Coastguard Worker     _mov(DestLo, T_Lo);
2454*03ce13f7SAndroid Build Coastguard Worker     _eor(T_Hi, Src0HiR, Src1HiRF);
2455*03ce13f7SAndroid Build Coastguard Worker     _mov(DestHi, T_Hi);
2456*03ce13f7SAndroid Build Coastguard Worker     return;
2457*03ce13f7SAndroid Build Coastguard Worker   }
2458*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Sub: {
2459*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0LoR = SrcsLo.src0R(this);
2460*03ce13f7SAndroid Build Coastguard Worker     Operand *Src1LoRF = SrcsLo.src1RF(this);
2461*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0HiR = SrcsHi.src0R(this);
2462*03ce13f7SAndroid Build Coastguard Worker     Operand *Src1HiRF = SrcsHi.src1RF(this);
2463*03ce13f7SAndroid Build Coastguard Worker     if (SrcsLo.swappedOperands()) {
2464*03ce13f7SAndroid Build Coastguard Worker       _rsbs(T_Lo, Src0LoR, Src1LoRF);
2465*03ce13f7SAndroid Build Coastguard Worker       _mov(DestLo, T_Lo);
2466*03ce13f7SAndroid Build Coastguard Worker       _rsc(T_Hi, Src0HiR, Src1HiRF);
2467*03ce13f7SAndroid Build Coastguard Worker       _mov(DestHi, T_Hi);
2468*03ce13f7SAndroid Build Coastguard Worker     } else {
2469*03ce13f7SAndroid Build Coastguard Worker       _subs(T_Lo, Src0LoR, Src1LoRF);
2470*03ce13f7SAndroid Build Coastguard Worker       _mov(DestLo, T_Lo);
2471*03ce13f7SAndroid Build Coastguard Worker       _sbc(T_Hi, Src0HiR, Src1HiRF);
2472*03ce13f7SAndroid Build Coastguard Worker       _mov(DestHi, T_Hi);
2473*03ce13f7SAndroid Build Coastguard Worker     }
2474*03ce13f7SAndroid Build Coastguard Worker     return;
2475*03ce13f7SAndroid Build Coastguard Worker   }
2476*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Mul: {
2477*03ce13f7SAndroid Build Coastguard Worker     // GCC 4.8 does:
2478*03ce13f7SAndroid Build Coastguard Worker     // a=b*c ==>
2479*03ce13f7SAndroid Build Coastguard Worker     //   t_acc =(mul) (b.lo * c.hi)
2480*03ce13f7SAndroid Build Coastguard Worker     //   t_acc =(mla) (c.lo * b.hi) + t_acc
2481*03ce13f7SAndroid Build Coastguard Worker     //   t.hi,t.lo =(umull) b.lo * c.lo
2482*03ce13f7SAndroid Build Coastguard Worker     //   t.hi += t_acc
2483*03ce13f7SAndroid Build Coastguard Worker     //   a.lo = t.lo
2484*03ce13f7SAndroid Build Coastguard Worker     //   a.hi = t.hi
2485*03ce13f7SAndroid Build Coastguard Worker     //
2486*03ce13f7SAndroid Build Coastguard Worker     // LLVM does:
2487*03ce13f7SAndroid Build Coastguard Worker     //   t.hi,t.lo =(umull) b.lo * c.lo
2488*03ce13f7SAndroid Build Coastguard Worker     //   t.hi =(mla) (b.lo * c.hi) + t.hi
2489*03ce13f7SAndroid Build Coastguard Worker     //   t.hi =(mla) (b.hi * c.lo) + t.hi
2490*03ce13f7SAndroid Build Coastguard Worker     //   a.lo = t.lo
2491*03ce13f7SAndroid Build Coastguard Worker     //   a.hi = t.hi
2492*03ce13f7SAndroid Build Coastguard Worker     //
2493*03ce13f7SAndroid Build Coastguard Worker     // LLVM's lowering has fewer instructions, but more register pressure:
2494*03ce13f7SAndroid Build Coastguard Worker     // t.lo is live from beginning to end, while GCC delays the two-dest
2495*03ce13f7SAndroid Build Coastguard Worker     // instruction till the end, and kills c.hi immediately.
2496*03ce13f7SAndroid Build Coastguard Worker     Variable *T_Acc = makeReg(IceType_i32);
2497*03ce13f7SAndroid Build Coastguard Worker     Variable *T_Acc1 = makeReg(IceType_i32);
2498*03ce13f7SAndroid Build Coastguard Worker     Variable *T_Hi1 = makeReg(IceType_i32);
2499*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0RLo = SrcsLo.unswappedSrc0R(this);
2500*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0RHi = SrcsHi.unswappedSrc0R(this);
2501*03ce13f7SAndroid Build Coastguard Worker     Variable *Src1RLo = SrcsLo.unswappedSrc1R(this);
2502*03ce13f7SAndroid Build Coastguard Worker     Variable *Src1RHi = SrcsHi.unswappedSrc1R(this);
2503*03ce13f7SAndroid Build Coastguard Worker     _mul(T_Acc, Src0RLo, Src1RHi);
2504*03ce13f7SAndroid Build Coastguard Worker     _mla(T_Acc1, Src1RLo, Src0RHi, T_Acc);
2505*03ce13f7SAndroid Build Coastguard Worker     _umull(T_Lo, T_Hi1, Src0RLo, Src1RLo);
2506*03ce13f7SAndroid Build Coastguard Worker     _add(T_Hi, T_Hi1, T_Acc1);
2507*03ce13f7SAndroid Build Coastguard Worker     _mov(DestLo, T_Lo);
2508*03ce13f7SAndroid Build Coastguard Worker     _mov(DestHi, T_Hi);
2509*03ce13f7SAndroid Build Coastguard Worker     return;
2510*03ce13f7SAndroid Build Coastguard Worker   }
2511*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Shl: {
2512*03ce13f7SAndroid Build Coastguard Worker     if (!SrcsLo.swappedOperands() && SrcsLo.hasConstOperand()) {
2513*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0RLo = SrcsLo.src0R(this);
2514*03ce13f7SAndroid Build Coastguard Worker       // Truncating the ShAmt to [0, 63] because that's what ARM does anyway.
2515*03ce13f7SAndroid Build Coastguard Worker       const int32_t ShAmtImm = SrcsLo.getConstantValue() & 0x3F;
2516*03ce13f7SAndroid Build Coastguard Worker       if (ShAmtImm == 0) {
2517*03ce13f7SAndroid Build Coastguard Worker         _mov(DestLo, Src0RLo);
2518*03ce13f7SAndroid Build Coastguard Worker         _mov(DestHi, SrcsHi.src0R(this));
2519*03ce13f7SAndroid Build Coastguard Worker         return;
2520*03ce13f7SAndroid Build Coastguard Worker       }
2521*03ce13f7SAndroid Build Coastguard Worker 
2522*03ce13f7SAndroid Build Coastguard Worker       if (ShAmtImm >= 32) {
2523*03ce13f7SAndroid Build Coastguard Worker         if (ShAmtImm == 32) {
2524*03ce13f7SAndroid Build Coastguard Worker           _mov(DestHi, Src0RLo);
2525*03ce13f7SAndroid Build Coastguard Worker         } else {
2526*03ce13f7SAndroid Build Coastguard Worker           Operand *ShAmtOp = shAmtImm(ShAmtImm - 32);
2527*03ce13f7SAndroid Build Coastguard Worker           _lsl(T_Hi, Src0RLo, ShAmtOp);
2528*03ce13f7SAndroid Build Coastguard Worker           _mov(DestHi, T_Hi);
2529*03ce13f7SAndroid Build Coastguard Worker         }
2530*03ce13f7SAndroid Build Coastguard Worker 
2531*03ce13f7SAndroid Build Coastguard Worker         Operand *_0 =
2532*03ce13f7SAndroid Build Coastguard Worker             legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex);
2533*03ce13f7SAndroid Build Coastguard Worker         _mov(T_Lo, _0);
2534*03ce13f7SAndroid Build Coastguard Worker         _mov(DestLo, T_Lo);
2535*03ce13f7SAndroid Build Coastguard Worker         return;
2536*03ce13f7SAndroid Build Coastguard Worker       }
2537*03ce13f7SAndroid Build Coastguard Worker 
2538*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0RHi = SrcsHi.src0R(this);
2539*03ce13f7SAndroid Build Coastguard Worker       Operand *ShAmtOp = shAmtImm(ShAmtImm);
2540*03ce13f7SAndroid Build Coastguard Worker       Operand *ComplShAmtOp = shAmtImm(32 - ShAmtImm);
2541*03ce13f7SAndroid Build Coastguard Worker       _lsl(T_Hi, Src0RHi, ShAmtOp);
2542*03ce13f7SAndroid Build Coastguard Worker       _orr(T_Hi, T_Hi,
2543*03ce13f7SAndroid Build Coastguard Worker            OperandARM32FlexReg::create(Func, IceType_i32, Src0RLo,
2544*03ce13f7SAndroid Build Coastguard Worker                                        OperandARM32::LSR, ComplShAmtOp));
2545*03ce13f7SAndroid Build Coastguard Worker       _mov(DestHi, T_Hi);
2546*03ce13f7SAndroid Build Coastguard Worker 
2547*03ce13f7SAndroid Build Coastguard Worker       _lsl(T_Lo, Src0RLo, ShAmtOp);
2548*03ce13f7SAndroid Build Coastguard Worker       _mov(DestLo, T_Lo);
2549*03ce13f7SAndroid Build Coastguard Worker       return;
2550*03ce13f7SAndroid Build Coastguard Worker     }
2551*03ce13f7SAndroid Build Coastguard Worker 
2552*03ce13f7SAndroid Build Coastguard Worker     // a=b<<c ==>
2553*03ce13f7SAndroid Build Coastguard Worker     // pnacl-llc does:
2554*03ce13f7SAndroid Build Coastguard Worker     // mov     t_b.lo, b.lo
2555*03ce13f7SAndroid Build Coastguard Worker     // mov     t_b.hi, b.hi
2556*03ce13f7SAndroid Build Coastguard Worker     // mov     t_c.lo, c.lo
2557*03ce13f7SAndroid Build Coastguard Worker     // rsb     T0, t_c.lo, #32
2558*03ce13f7SAndroid Build Coastguard Worker     // lsr     T1, t_b.lo, T0
2559*03ce13f7SAndroid Build Coastguard Worker     // orr     t_a.hi, T1, t_b.hi, lsl t_c.lo
2560*03ce13f7SAndroid Build Coastguard Worker     // sub     T2, t_c.lo, #32
2561*03ce13f7SAndroid Build Coastguard Worker     // cmp     T2, #0
2562*03ce13f7SAndroid Build Coastguard Worker     // lslge   t_a.hi, t_b.lo, T2
2563*03ce13f7SAndroid Build Coastguard Worker     // lsl     t_a.lo, t_b.lo, t_c.lo
2564*03ce13f7SAndroid Build Coastguard Worker     // mov     a.lo, t_a.lo
2565*03ce13f7SAndroid Build Coastguard Worker     // mov     a.hi, t_a.hi
2566*03ce13f7SAndroid Build Coastguard Worker     //
2567*03ce13f7SAndroid Build Coastguard Worker     // GCC 4.8 does:
2568*03ce13f7SAndroid Build Coastguard Worker     // sub t_c1, c.lo, #32
2569*03ce13f7SAndroid Build Coastguard Worker     // lsl t_hi, b.hi, c.lo
2570*03ce13f7SAndroid Build Coastguard Worker     // orr t_hi, t_hi, b.lo, lsl t_c1
2571*03ce13f7SAndroid Build Coastguard Worker     // rsb t_c2, c.lo, #32
2572*03ce13f7SAndroid Build Coastguard Worker     // orr t_hi, t_hi, b.lo, lsr t_c2
2573*03ce13f7SAndroid Build Coastguard Worker     // lsl t_lo, b.lo, c.lo
2574*03ce13f7SAndroid Build Coastguard Worker     // a.lo = t_lo
2575*03ce13f7SAndroid Build Coastguard Worker     // a.hi = t_hi
2576*03ce13f7SAndroid Build Coastguard Worker     //
2577*03ce13f7SAndroid Build Coastguard Worker     // These are incompatible, therefore we mimic pnacl-llc.
2578*03ce13f7SAndroid Build Coastguard Worker     // Can be strength-reduced for constant-shifts, but we don't do that for
2579*03ce13f7SAndroid Build Coastguard Worker     // now.
2580*03ce13f7SAndroid Build Coastguard Worker     // Given the sub/rsb T_C, C.lo, #32, one of the T_C will be negative. On
2581*03ce13f7SAndroid Build Coastguard Worker     // ARM, shifts only take the lower 8 bits of the shift register, and
2582*03ce13f7SAndroid Build Coastguard Worker     // saturate to the range 0-32, so the negative value will saturate to 32.
2583*03ce13f7SAndroid Build Coastguard Worker     Operand *_32 = legalize(Ctx->getConstantInt32(32), Legal_Reg | Legal_Flex);
2584*03ce13f7SAndroid Build Coastguard Worker     Operand *_0 =
2585*03ce13f7SAndroid Build Coastguard Worker         legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex);
2586*03ce13f7SAndroid Build Coastguard Worker     Variable *T0 = makeReg(IceType_i32);
2587*03ce13f7SAndroid Build Coastguard Worker     Variable *T1 = makeReg(IceType_i32);
2588*03ce13f7SAndroid Build Coastguard Worker     Variable *T2 = makeReg(IceType_i32);
2589*03ce13f7SAndroid Build Coastguard Worker     Variable *TA_Hi = makeReg(IceType_i32);
2590*03ce13f7SAndroid Build Coastguard Worker     Variable *TA_Lo = makeReg(IceType_i32);
2591*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0RLo = SrcsLo.unswappedSrc0R(this);
2592*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0RHi = SrcsHi.unswappedSrc0R(this);
2593*03ce13f7SAndroid Build Coastguard Worker     Variable *Src1RLo = SrcsLo.unswappedSrc1R(this);
2594*03ce13f7SAndroid Build Coastguard Worker     _rsb(T0, Src1RLo, _32);
2595*03ce13f7SAndroid Build Coastguard Worker     _lsr(T1, Src0RLo, T0);
2596*03ce13f7SAndroid Build Coastguard Worker     _orr(TA_Hi, T1,
2597*03ce13f7SAndroid Build Coastguard Worker          OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi,
2598*03ce13f7SAndroid Build Coastguard Worker                                      OperandARM32::LSL, Src1RLo));
2599*03ce13f7SAndroid Build Coastguard Worker     _sub(T2, Src1RLo, _32);
2600*03ce13f7SAndroid Build Coastguard Worker     _cmp(T2, _0);
2601*03ce13f7SAndroid Build Coastguard Worker     _lsl(TA_Hi, Src0RLo, T2, CondARM32::GE);
2602*03ce13f7SAndroid Build Coastguard Worker     _set_dest_redefined();
2603*03ce13f7SAndroid Build Coastguard Worker     _lsl(TA_Lo, Src0RLo, Src1RLo);
2604*03ce13f7SAndroid Build Coastguard Worker     _mov(DestLo, TA_Lo);
2605*03ce13f7SAndroid Build Coastguard Worker     _mov(DestHi, TA_Hi);
2606*03ce13f7SAndroid Build Coastguard Worker     return;
2607*03ce13f7SAndroid Build Coastguard Worker   }
2608*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Lshr:
2609*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Ashr: {
2610*03ce13f7SAndroid Build Coastguard Worker     const bool ASR = Op == InstArithmetic::Ashr;
2611*03ce13f7SAndroid Build Coastguard Worker     if (!SrcsLo.swappedOperands() && SrcsLo.hasConstOperand()) {
2612*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0RHi = SrcsHi.src0R(this);
2613*03ce13f7SAndroid Build Coastguard Worker       // Truncating the ShAmt to [0, 63] because that's what ARM does anyway.
2614*03ce13f7SAndroid Build Coastguard Worker       const int32_t ShAmt = SrcsLo.getConstantValue() & 0x3F;
2615*03ce13f7SAndroid Build Coastguard Worker       if (ShAmt == 0) {
2616*03ce13f7SAndroid Build Coastguard Worker         _mov(DestHi, Src0RHi);
2617*03ce13f7SAndroid Build Coastguard Worker         _mov(DestLo, SrcsLo.src0R(this));
2618*03ce13f7SAndroid Build Coastguard Worker         return;
2619*03ce13f7SAndroid Build Coastguard Worker       }
2620*03ce13f7SAndroid Build Coastguard Worker 
2621*03ce13f7SAndroid Build Coastguard Worker       if (ShAmt >= 32) {
2622*03ce13f7SAndroid Build Coastguard Worker         if (ShAmt == 32) {
2623*03ce13f7SAndroid Build Coastguard Worker           _mov(DestLo, Src0RHi);
2624*03ce13f7SAndroid Build Coastguard Worker         } else {
2625*03ce13f7SAndroid Build Coastguard Worker           Operand *ShAmtImm = shAmtImm(ShAmt - 32);
2626*03ce13f7SAndroid Build Coastguard Worker           if (ASR) {
2627*03ce13f7SAndroid Build Coastguard Worker             _asr(T_Lo, Src0RHi, ShAmtImm);
2628*03ce13f7SAndroid Build Coastguard Worker           } else {
2629*03ce13f7SAndroid Build Coastguard Worker             _lsr(T_Lo, Src0RHi, ShAmtImm);
2630*03ce13f7SAndroid Build Coastguard Worker           }
2631*03ce13f7SAndroid Build Coastguard Worker           _mov(DestLo, T_Lo);
2632*03ce13f7SAndroid Build Coastguard Worker         }
2633*03ce13f7SAndroid Build Coastguard Worker 
2634*03ce13f7SAndroid Build Coastguard Worker         if (ASR) {
2635*03ce13f7SAndroid Build Coastguard Worker           Operand *_31 = shAmtImm(31);
2636*03ce13f7SAndroid Build Coastguard Worker           _asr(T_Hi, Src0RHi, _31);
2637*03ce13f7SAndroid Build Coastguard Worker         } else {
2638*03ce13f7SAndroid Build Coastguard Worker           Operand *_0 = legalize(Ctx->getConstantZero(IceType_i32),
2639*03ce13f7SAndroid Build Coastguard Worker                                  Legal_Reg | Legal_Flex);
2640*03ce13f7SAndroid Build Coastguard Worker           _mov(T_Hi, _0);
2641*03ce13f7SAndroid Build Coastguard Worker         }
2642*03ce13f7SAndroid Build Coastguard Worker         _mov(DestHi, T_Hi);
2643*03ce13f7SAndroid Build Coastguard Worker         return;
2644*03ce13f7SAndroid Build Coastguard Worker       }
2645*03ce13f7SAndroid Build Coastguard Worker 
2646*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0RLo = SrcsLo.src0R(this);
2647*03ce13f7SAndroid Build Coastguard Worker       Operand *ShAmtImm = shAmtImm(ShAmt);
2648*03ce13f7SAndroid Build Coastguard Worker       Operand *ComplShAmtImm = shAmtImm(32 - ShAmt);
2649*03ce13f7SAndroid Build Coastguard Worker       _lsr(T_Lo, Src0RLo, ShAmtImm);
2650*03ce13f7SAndroid Build Coastguard Worker       _orr(T_Lo, T_Lo,
2651*03ce13f7SAndroid Build Coastguard Worker            OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi,
2652*03ce13f7SAndroid Build Coastguard Worker                                        OperandARM32::LSL, ComplShAmtImm));
2653*03ce13f7SAndroid Build Coastguard Worker       _mov(DestLo, T_Lo);
2654*03ce13f7SAndroid Build Coastguard Worker 
2655*03ce13f7SAndroid Build Coastguard Worker       if (ASR) {
2656*03ce13f7SAndroid Build Coastguard Worker         _asr(T_Hi, Src0RHi, ShAmtImm);
2657*03ce13f7SAndroid Build Coastguard Worker       } else {
2658*03ce13f7SAndroid Build Coastguard Worker         _lsr(T_Hi, Src0RHi, ShAmtImm);
2659*03ce13f7SAndroid Build Coastguard Worker       }
2660*03ce13f7SAndroid Build Coastguard Worker       _mov(DestHi, T_Hi);
2661*03ce13f7SAndroid Build Coastguard Worker       return;
2662*03ce13f7SAndroid Build Coastguard Worker     }
2663*03ce13f7SAndroid Build Coastguard Worker 
2664*03ce13f7SAndroid Build Coastguard Worker     // a=b>>c
2665*03ce13f7SAndroid Build Coastguard Worker     // pnacl-llc does:
2666*03ce13f7SAndroid Build Coastguard Worker     // mov        t_b.lo, b.lo
2667*03ce13f7SAndroid Build Coastguard Worker     // mov        t_b.hi, b.hi
2668*03ce13f7SAndroid Build Coastguard Worker     // mov        t_c.lo, c.lo
2669*03ce13f7SAndroid Build Coastguard Worker     // lsr        T0, t_b.lo, t_c.lo
2670*03ce13f7SAndroid Build Coastguard Worker     // rsb        T1, t_c.lo, #32
2671*03ce13f7SAndroid Build Coastguard Worker     // orr        t_a.lo, T0, t_b.hi, lsl T1
2672*03ce13f7SAndroid Build Coastguard Worker     // sub        T2, t_c.lo, #32
2673*03ce13f7SAndroid Build Coastguard Worker     // cmp        T2, #0
2674*03ce13f7SAndroid Build Coastguard Worker     // [al]srge   t_a.lo, t_b.hi, T2
2675*03ce13f7SAndroid Build Coastguard Worker     // [al]sr     t_a.hi, t_b.hi, t_c.lo
2676*03ce13f7SAndroid Build Coastguard Worker     // mov        a.lo, t_a.lo
2677*03ce13f7SAndroid Build Coastguard Worker     // mov        a.hi, t_a.hi
2678*03ce13f7SAndroid Build Coastguard Worker     //
2679*03ce13f7SAndroid Build Coastguard Worker     // GCC 4.8 does (lsr):
2680*03ce13f7SAndroid Build Coastguard Worker     // rsb        t_c1, c.lo, #32
2681*03ce13f7SAndroid Build Coastguard Worker     // lsr        t_lo, b.lo, c.lo
2682*03ce13f7SAndroid Build Coastguard Worker     // orr        t_lo, t_lo, b.hi, lsl t_c1
2683*03ce13f7SAndroid Build Coastguard Worker     // sub        t_c2, c.lo, #32
2684*03ce13f7SAndroid Build Coastguard Worker     // orr        t_lo, t_lo, b.hi, lsr t_c2
2685*03ce13f7SAndroid Build Coastguard Worker     // lsr        t_hi, b.hi, c.lo
2686*03ce13f7SAndroid Build Coastguard Worker     // mov        a.lo, t_lo
2687*03ce13f7SAndroid Build Coastguard Worker     // mov        a.hi, t_hi
2688*03ce13f7SAndroid Build Coastguard Worker     //
2689*03ce13f7SAndroid Build Coastguard Worker     // These are incompatible, therefore we mimic pnacl-llc.
2690*03ce13f7SAndroid Build Coastguard Worker     Operand *_32 = legalize(Ctx->getConstantInt32(32), Legal_Reg | Legal_Flex);
2691*03ce13f7SAndroid Build Coastguard Worker     Operand *_0 =
2692*03ce13f7SAndroid Build Coastguard Worker         legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex);
2693*03ce13f7SAndroid Build Coastguard Worker     Variable *T0 = makeReg(IceType_i32);
2694*03ce13f7SAndroid Build Coastguard Worker     Variable *T1 = makeReg(IceType_i32);
2695*03ce13f7SAndroid Build Coastguard Worker     Variable *T2 = makeReg(IceType_i32);
2696*03ce13f7SAndroid Build Coastguard Worker     Variable *TA_Lo = makeReg(IceType_i32);
2697*03ce13f7SAndroid Build Coastguard Worker     Variable *TA_Hi = makeReg(IceType_i32);
2698*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0RLo = SrcsLo.unswappedSrc0R(this);
2699*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0RHi = SrcsHi.unswappedSrc0R(this);
2700*03ce13f7SAndroid Build Coastguard Worker     Variable *Src1RLo = SrcsLo.unswappedSrc1R(this);
2701*03ce13f7SAndroid Build Coastguard Worker     _lsr(T0, Src0RLo, Src1RLo);
2702*03ce13f7SAndroid Build Coastguard Worker     _rsb(T1, Src1RLo, _32);
2703*03ce13f7SAndroid Build Coastguard Worker     _orr(TA_Lo, T0,
2704*03ce13f7SAndroid Build Coastguard Worker          OperandARM32FlexReg::create(Func, IceType_i32, Src0RHi,
2705*03ce13f7SAndroid Build Coastguard Worker                                      OperandARM32::LSL, T1));
2706*03ce13f7SAndroid Build Coastguard Worker     _sub(T2, Src1RLo, _32);
2707*03ce13f7SAndroid Build Coastguard Worker     _cmp(T2, _0);
2708*03ce13f7SAndroid Build Coastguard Worker     if (ASR) {
2709*03ce13f7SAndroid Build Coastguard Worker       _asr(TA_Lo, Src0RHi, T2, CondARM32::GE);
2710*03ce13f7SAndroid Build Coastguard Worker       _set_dest_redefined();
2711*03ce13f7SAndroid Build Coastguard Worker       _asr(TA_Hi, Src0RHi, Src1RLo);
2712*03ce13f7SAndroid Build Coastguard Worker     } else {
2713*03ce13f7SAndroid Build Coastguard Worker       _lsr(TA_Lo, Src0RHi, T2, CondARM32::GE);
2714*03ce13f7SAndroid Build Coastguard Worker       _set_dest_redefined();
2715*03ce13f7SAndroid Build Coastguard Worker       _lsr(TA_Hi, Src0RHi, Src1RLo);
2716*03ce13f7SAndroid Build Coastguard Worker     }
2717*03ce13f7SAndroid Build Coastguard Worker     _mov(DestLo, TA_Lo);
2718*03ce13f7SAndroid Build Coastguard Worker     _mov(DestHi, TA_Hi);
2719*03ce13f7SAndroid Build Coastguard Worker     return;
2720*03ce13f7SAndroid Build Coastguard Worker   }
2721*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Fadd:
2722*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Fsub:
2723*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Fmul:
2724*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Fdiv:
2725*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Frem:
2726*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("FP instruction with i64 type");
2727*03ce13f7SAndroid Build Coastguard Worker     return;
2728*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Udiv:
2729*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Sdiv:
2730*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Urem:
2731*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Srem:
2732*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Call-helper-involved instruction for i64 type "
2733*03ce13f7SAndroid Build Coastguard Worker                              "should have already been handled before");
2734*03ce13f7SAndroid Build Coastguard Worker     return;
2735*03ce13f7SAndroid Build Coastguard Worker   }
2736*03ce13f7SAndroid Build Coastguard Worker }
2737*03ce13f7SAndroid Build Coastguard Worker 
2738*03ce13f7SAndroid Build Coastguard Worker namespace {
2739*03ce13f7SAndroid Build Coastguard Worker // StrengthReduction is a namespace with the strength reduction machinery. The
2740*03ce13f7SAndroid Build Coastguard Worker // entry point is the StrengthReduction::tryToOptimize method. It returns true
2741*03ce13f7SAndroid Build Coastguard Worker // if the optimization can be performed, and false otherwise.
2742*03ce13f7SAndroid Build Coastguard Worker //
2743*03ce13f7SAndroid Build Coastguard Worker // If the optimization can be performed, tryToOptimize sets its NumOperations
2744*03ce13f7SAndroid Build Coastguard Worker // parameter to the number of shifts that are needed to perform the
2745*03ce13f7SAndroid Build Coastguard Worker // multiplication; and it sets the Operations parameter with <ShAmt, AddOrSub>
2746*03ce13f7SAndroid Build Coastguard Worker // tuples that describe how to materialize the multiplication.
2747*03ce13f7SAndroid Build Coastguard Worker //
2748*03ce13f7SAndroid Build Coastguard Worker // The algorithm finds contiguous 1s in the Multiplication source, and uses one
2749*03ce13f7SAndroid Build Coastguard Worker // or two shifts to materialize it. A sequence of 1s, e.g.,
2750*03ce13f7SAndroid Build Coastguard Worker //
2751*03ce13f7SAndroid Build Coastguard Worker //                  M           N
2752*03ce13f7SAndroid Build Coastguard Worker //   ...00000000000011111...111110000000...
2753*03ce13f7SAndroid Build Coastguard Worker //
2754*03ce13f7SAndroid Build Coastguard Worker // is materializable with (1 << (M + 1)) - (1 << N):
2755*03ce13f7SAndroid Build Coastguard Worker //
2756*03ce13f7SAndroid Build Coastguard Worker //   ...00000000000100000...000000000000...      [1 << (M + 1)]
2757*03ce13f7SAndroid Build Coastguard Worker //   ...00000000000000000...000010000000... (-)  [1 << N]
2758*03ce13f7SAndroid Build Coastguard Worker //   --------------------------------------
2759*03ce13f7SAndroid Build Coastguard Worker //   ...00000000000011111...111110000000...
2760*03ce13f7SAndroid Build Coastguard Worker //
2761*03ce13f7SAndroid Build Coastguard Worker // And a single bit set, which is just a left shift.
2762*03ce13f7SAndroid Build Coastguard Worker namespace StrengthReduction {
2763*03ce13f7SAndroid Build Coastguard Worker enum AggregationOperation {
2764*03ce13f7SAndroid Build Coastguard Worker   AO_Invalid,
2765*03ce13f7SAndroid Build Coastguard Worker   AO_Add,
2766*03ce13f7SAndroid Build Coastguard Worker   AO_Sub,
2767*03ce13f7SAndroid Build Coastguard Worker };
2768*03ce13f7SAndroid Build Coastguard Worker 
2769*03ce13f7SAndroid Build Coastguard Worker // AggregateElement is a glorified <ShAmt, AddOrSub> tuple.
2770*03ce13f7SAndroid Build Coastguard Worker class AggregationElement {
2771*03ce13f7SAndroid Build Coastguard Worker   AggregationElement(const AggregationElement &) = delete;
2772*03ce13f7SAndroid Build Coastguard Worker 
2773*03ce13f7SAndroid Build Coastguard Worker public:
2774*03ce13f7SAndroid Build Coastguard Worker   AggregationElement() = default;
2775*03ce13f7SAndroid Build Coastguard Worker   AggregationElement &operator=(const AggregationElement &) = default;
AggregationElement(AggregationOperation Op,uint32_t ShAmt)2776*03ce13f7SAndroid Build Coastguard Worker   AggregationElement(AggregationOperation Op, uint32_t ShAmt)
2777*03ce13f7SAndroid Build Coastguard Worker       : Op(Op), ShAmt(ShAmt) {}
2778*03ce13f7SAndroid Build Coastguard Worker 
createShiftedOperand(Cfg * Func,Variable * OpR) const2779*03ce13f7SAndroid Build Coastguard Worker   Operand *createShiftedOperand(Cfg *Func, Variable *OpR) const {
2780*03ce13f7SAndroid Build Coastguard Worker     assert(OpR->mustHaveReg());
2781*03ce13f7SAndroid Build Coastguard Worker     if (ShAmt == 0) {
2782*03ce13f7SAndroid Build Coastguard Worker       return OpR;
2783*03ce13f7SAndroid Build Coastguard Worker     }
2784*03ce13f7SAndroid Build Coastguard Worker     return OperandARM32FlexReg::create(
2785*03ce13f7SAndroid Build Coastguard Worker         Func, IceType_i32, OpR, OperandARM32::LSL,
2786*03ce13f7SAndroid Build Coastguard Worker         OperandARM32ShAmtImm::create(
2787*03ce13f7SAndroid Build Coastguard Worker             Func, llvm::cast<ConstantInteger32>(
2788*03ce13f7SAndroid Build Coastguard Worker                       Func->getContext()->getConstantInt32(ShAmt))));
2789*03ce13f7SAndroid Build Coastguard Worker   }
2790*03ce13f7SAndroid Build Coastguard Worker 
aggregateWithAdd() const2791*03ce13f7SAndroid Build Coastguard Worker   bool aggregateWithAdd() const {
2792*03ce13f7SAndroid Build Coastguard Worker     switch (Op) {
2793*03ce13f7SAndroid Build Coastguard Worker     case AO_Invalid:
2794*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error("Invalid Strength Reduction Operations.");
2795*03ce13f7SAndroid Build Coastguard Worker     case AO_Add:
2796*03ce13f7SAndroid Build Coastguard Worker       return true;
2797*03ce13f7SAndroid Build Coastguard Worker     case AO_Sub:
2798*03ce13f7SAndroid Build Coastguard Worker       return false;
2799*03ce13f7SAndroid Build Coastguard Worker     }
2800*03ce13f7SAndroid Build Coastguard Worker     llvm_unreachable("(silence g++ warning)");
2801*03ce13f7SAndroid Build Coastguard Worker   }
2802*03ce13f7SAndroid Build Coastguard Worker 
shAmt() const2803*03ce13f7SAndroid Build Coastguard Worker   uint32_t shAmt() const { return ShAmt; }
2804*03ce13f7SAndroid Build Coastguard Worker 
2805*03ce13f7SAndroid Build Coastguard Worker private:
2806*03ce13f7SAndroid Build Coastguard Worker   AggregationOperation Op = AO_Invalid;
2807*03ce13f7SAndroid Build Coastguard Worker   uint32_t ShAmt;
2808*03ce13f7SAndroid Build Coastguard Worker };
2809*03ce13f7SAndroid Build Coastguard Worker 
2810*03ce13f7SAndroid Build Coastguard Worker // [RangeStart, RangeEnd] is a range of 1s in Src.
2811*03ce13f7SAndroid Build Coastguard Worker template <std::size_t N>
addOperations(uint32_t RangeStart,uint32_t RangeEnd,SizeT * NumOperations,std::array<AggregationElement,N> * Operations)2812*03ce13f7SAndroid Build Coastguard Worker bool addOperations(uint32_t RangeStart, uint32_t RangeEnd, SizeT *NumOperations,
2813*03ce13f7SAndroid Build Coastguard Worker                    std::array<AggregationElement, N> *Operations) {
2814*03ce13f7SAndroid Build Coastguard Worker   assert(*NumOperations < N);
2815*03ce13f7SAndroid Build Coastguard Worker   if (RangeStart == RangeEnd) {
2816*03ce13f7SAndroid Build Coastguard Worker     // Single bit set:
2817*03ce13f7SAndroid Build Coastguard Worker     // Src           : 0...00010...
2818*03ce13f7SAndroid Build Coastguard Worker     // RangeStart    :        ^
2819*03ce13f7SAndroid Build Coastguard Worker     // RangeEnd      :        ^
2820*03ce13f7SAndroid Build Coastguard Worker     // NegSrc        : 0...00001...
2821*03ce13f7SAndroid Build Coastguard Worker     (*Operations)[*NumOperations] = AggregationElement(AO_Add, RangeStart);
2822*03ce13f7SAndroid Build Coastguard Worker     ++(*NumOperations);
2823*03ce13f7SAndroid Build Coastguard Worker     return true;
2824*03ce13f7SAndroid Build Coastguard Worker   }
2825*03ce13f7SAndroid Build Coastguard Worker 
2826*03ce13f7SAndroid Build Coastguard Worker   // Sequence of 1s: (two operations required.)
2827*03ce13f7SAndroid Build Coastguard Worker   // Src           : 0...00011...110...
2828*03ce13f7SAndroid Build Coastguard Worker   // RangeStart    :        ^
2829*03ce13f7SAndroid Build Coastguard Worker   // RangeEnd      :              ^
2830*03ce13f7SAndroid Build Coastguard Worker   // NegSrc        : 0...00000...001...
2831*03ce13f7SAndroid Build Coastguard Worker   if (*NumOperations + 1 >= N) {
2832*03ce13f7SAndroid Build Coastguard Worker     return false;
2833*03ce13f7SAndroid Build Coastguard Worker   }
2834*03ce13f7SAndroid Build Coastguard Worker   (*Operations)[*NumOperations] = AggregationElement(AO_Add, RangeStart + 1);
2835*03ce13f7SAndroid Build Coastguard Worker   ++(*NumOperations);
2836*03ce13f7SAndroid Build Coastguard Worker   (*Operations)[*NumOperations] = AggregationElement(AO_Sub, RangeEnd);
2837*03ce13f7SAndroid Build Coastguard Worker   ++(*NumOperations);
2838*03ce13f7SAndroid Build Coastguard Worker   return true;
2839*03ce13f7SAndroid Build Coastguard Worker }
2840*03ce13f7SAndroid Build Coastguard Worker 
2841*03ce13f7SAndroid Build Coastguard Worker // tryToOptmize scans Src looking for sequences of 1s (including the unitary bit
2842*03ce13f7SAndroid Build Coastguard Worker // 1 surrounded by zeroes.
2843*03ce13f7SAndroid Build Coastguard Worker template <std::size_t N>
tryToOptimize(uint32_t Src,SizeT * NumOperations,std::array<AggregationElement,N> * Operations)2844*03ce13f7SAndroid Build Coastguard Worker bool tryToOptimize(uint32_t Src, SizeT *NumOperations,
2845*03ce13f7SAndroid Build Coastguard Worker                    std::array<AggregationElement, N> *Operations) {
2846*03ce13f7SAndroid Build Coastguard Worker   constexpr uint32_t SrcSizeBits = sizeof(Src) * CHAR_BIT;
2847*03ce13f7SAndroid Build Coastguard Worker   uint32_t NegSrc = ~Src;
2848*03ce13f7SAndroid Build Coastguard Worker 
2849*03ce13f7SAndroid Build Coastguard Worker   *NumOperations = 0;
2850*03ce13f7SAndroid Build Coastguard Worker   while (Src != 0 && *NumOperations < N) {
2851*03ce13f7SAndroid Build Coastguard Worker     // Each step of the algorithm:
2852*03ce13f7SAndroid Build Coastguard Worker     //   * finds L, the last bit set in Src;
2853*03ce13f7SAndroid Build Coastguard Worker     //   * clears all the upper bits in NegSrc up to bit L;
2854*03ce13f7SAndroid Build Coastguard Worker     //   * finds nL, the last bit set in NegSrc;
2855*03ce13f7SAndroid Build Coastguard Worker     //   * clears all the upper bits in Src up to bit nL;
2856*03ce13f7SAndroid Build Coastguard Worker     //
2857*03ce13f7SAndroid Build Coastguard Worker     // if L == nL + 1, then a unitary 1 was found in Src. Otherwise, a sequence
2858*03ce13f7SAndroid Build Coastguard Worker     // of 1s starting at L, and ending at nL + 1, was found.
2859*03ce13f7SAndroid Build Coastguard Worker     const uint32_t SrcLastBitSet = llvm::findLastSet(Src);
2860*03ce13f7SAndroid Build Coastguard Worker     const uint32_t NegSrcClearMask =
2861*03ce13f7SAndroid Build Coastguard Worker         (SrcLastBitSet == 0) ? 0
2862*03ce13f7SAndroid Build Coastguard Worker                              : (0xFFFFFFFFu) >> (SrcSizeBits - SrcLastBitSet);
2863*03ce13f7SAndroid Build Coastguard Worker     NegSrc &= NegSrcClearMask;
2864*03ce13f7SAndroid Build Coastguard Worker     if (NegSrc == 0) {
2865*03ce13f7SAndroid Build Coastguard Worker       if (addOperations(SrcLastBitSet, 0, NumOperations, Operations)) {
2866*03ce13f7SAndroid Build Coastguard Worker         return true;
2867*03ce13f7SAndroid Build Coastguard Worker       }
2868*03ce13f7SAndroid Build Coastguard Worker       return false;
2869*03ce13f7SAndroid Build Coastguard Worker     }
2870*03ce13f7SAndroid Build Coastguard Worker     const uint32_t NegSrcLastBitSet = llvm::findLastSet(NegSrc);
2871*03ce13f7SAndroid Build Coastguard Worker     assert(NegSrcLastBitSet < SrcLastBitSet);
2872*03ce13f7SAndroid Build Coastguard Worker     const uint32_t SrcClearMask =
2873*03ce13f7SAndroid Build Coastguard Worker         (NegSrcLastBitSet == 0)
2874*03ce13f7SAndroid Build Coastguard Worker             ? 0
2875*03ce13f7SAndroid Build Coastguard Worker             : (0xFFFFFFFFu) >> (SrcSizeBits - NegSrcLastBitSet);
2876*03ce13f7SAndroid Build Coastguard Worker     Src &= SrcClearMask;
2877*03ce13f7SAndroid Build Coastguard Worker     if (!addOperations(SrcLastBitSet, NegSrcLastBitSet + 1, NumOperations,
2878*03ce13f7SAndroid Build Coastguard Worker                        Operations)) {
2879*03ce13f7SAndroid Build Coastguard Worker       return false;
2880*03ce13f7SAndroid Build Coastguard Worker     }
2881*03ce13f7SAndroid Build Coastguard Worker   }
2882*03ce13f7SAndroid Build Coastguard Worker 
2883*03ce13f7SAndroid Build Coastguard Worker   return Src == 0;
2884*03ce13f7SAndroid Build Coastguard Worker }
2885*03ce13f7SAndroid Build Coastguard Worker } // end of namespace StrengthReduction
2886*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
2887*03ce13f7SAndroid Build Coastguard Worker 
lowerArithmetic(const InstArithmetic * Instr)2888*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerArithmetic(const InstArithmetic *Instr) {
2889*03ce13f7SAndroid Build Coastguard Worker   Variable *Dest = Instr->getDest();
2890*03ce13f7SAndroid Build Coastguard Worker 
2891*03ce13f7SAndroid Build Coastguard Worker   if (Dest->isRematerializable()) {
2892*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeDef>(Dest);
2893*03ce13f7SAndroid Build Coastguard Worker     return;
2894*03ce13f7SAndroid Build Coastguard Worker   }
2895*03ce13f7SAndroid Build Coastguard Worker 
2896*03ce13f7SAndroid Build Coastguard Worker   Type DestTy = Dest->getType();
2897*03ce13f7SAndroid Build Coastguard Worker   if (DestTy == IceType_i1) {
2898*03ce13f7SAndroid Build Coastguard Worker     lowerInt1Arithmetic(Instr);
2899*03ce13f7SAndroid Build Coastguard Worker     return;
2900*03ce13f7SAndroid Build Coastguard Worker   }
2901*03ce13f7SAndroid Build Coastguard Worker 
2902*03ce13f7SAndroid Build Coastguard Worker   Operand *Src0 = legalizeUndef(Instr->getSrc(0));
2903*03ce13f7SAndroid Build Coastguard Worker   Operand *Src1 = legalizeUndef(Instr->getSrc(1));
2904*03ce13f7SAndroid Build Coastguard Worker   if (DestTy == IceType_i64) {
2905*03ce13f7SAndroid Build Coastguard Worker     lowerInt64Arithmetic(Instr->getOp(), Instr->getDest(), Src0, Src1);
2906*03ce13f7SAndroid Build Coastguard Worker     return;
2907*03ce13f7SAndroid Build Coastguard Worker   }
2908*03ce13f7SAndroid Build Coastguard Worker 
2909*03ce13f7SAndroid Build Coastguard Worker   if (isVectorType(DestTy)) {
2910*03ce13f7SAndroid Build Coastguard Worker     switch (Instr->getOp()) {
2911*03ce13f7SAndroid Build Coastguard Worker     default:
2912*03ce13f7SAndroid Build Coastguard Worker       UnimplementedLoweringError(this, Instr);
2913*03ce13f7SAndroid Build Coastguard Worker       return;
2914*03ce13f7SAndroid Build Coastguard Worker     // Explicitly allow vector instructions we have implemented/enabled.
2915*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Add:
2916*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::And:
2917*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Ashr:
2918*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Fadd:
2919*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Fmul:
2920*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Fsub:
2921*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Lshr:
2922*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Mul:
2923*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Or:
2924*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Shl:
2925*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Sub:
2926*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Xor:
2927*03ce13f7SAndroid Build Coastguard Worker       break;
2928*03ce13f7SAndroid Build Coastguard Worker     }
2929*03ce13f7SAndroid Build Coastguard Worker   }
2930*03ce13f7SAndroid Build Coastguard Worker 
2931*03ce13f7SAndroid Build Coastguard Worker   Variable *T = makeReg(DestTy);
2932*03ce13f7SAndroid Build Coastguard Worker 
2933*03ce13f7SAndroid Build Coastguard Worker   // * Handle div/rem separately. They require a non-legalized Src1 to inspect
2934*03ce13f7SAndroid Build Coastguard Worker   // whether or not Src1 is a non-zero constant. Once legalized it is more
2935*03ce13f7SAndroid Build Coastguard Worker   // difficult to determine (constant may be moved to a register).
2936*03ce13f7SAndroid Build Coastguard Worker   // * Handle floating point arithmetic separately: they require Src1 to be
2937*03ce13f7SAndroid Build Coastguard Worker   // legalized to a register.
2938*03ce13f7SAndroid Build Coastguard Worker   switch (Instr->getOp()) {
2939*03ce13f7SAndroid Build Coastguard Worker   default:
2940*03ce13f7SAndroid Build Coastguard Worker     break;
2941*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Udiv: {
2942*03ce13f7SAndroid Build Coastguard Worker     constexpr bool NotRemainder = false;
2943*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = legalizeToReg(Src0);
2944*03ce13f7SAndroid Build Coastguard Worker     lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv,
2945*03ce13f7SAndroid Build Coastguard Worker                  NotRemainder);
2946*03ce13f7SAndroid Build Coastguard Worker     return;
2947*03ce13f7SAndroid Build Coastguard Worker   }
2948*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Sdiv: {
2949*03ce13f7SAndroid Build Coastguard Worker     constexpr bool NotRemainder = false;
2950*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = legalizeToReg(Src0);
2951*03ce13f7SAndroid Build Coastguard Worker     lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, &TargetARM32::_sdiv,
2952*03ce13f7SAndroid Build Coastguard Worker                  NotRemainder);
2953*03ce13f7SAndroid Build Coastguard Worker     return;
2954*03ce13f7SAndroid Build Coastguard Worker   }
2955*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Urem: {
2956*03ce13f7SAndroid Build Coastguard Worker     constexpr bool IsRemainder = true;
2957*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = legalizeToReg(Src0);
2958*03ce13f7SAndroid Build Coastguard Worker     lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_uxt, &TargetARM32::_udiv,
2959*03ce13f7SAndroid Build Coastguard Worker                  IsRemainder);
2960*03ce13f7SAndroid Build Coastguard Worker     return;
2961*03ce13f7SAndroid Build Coastguard Worker   }
2962*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Srem: {
2963*03ce13f7SAndroid Build Coastguard Worker     constexpr bool IsRemainder = true;
2964*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = legalizeToReg(Src0);
2965*03ce13f7SAndroid Build Coastguard Worker     lowerIDivRem(Dest, T, Src0R, Src1, &TargetARM32::_sxt, &TargetARM32::_sdiv,
2966*03ce13f7SAndroid Build Coastguard Worker                  IsRemainder);
2967*03ce13f7SAndroid Build Coastguard Worker     return;
2968*03ce13f7SAndroid Build Coastguard Worker   }
2969*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Frem: {
2970*03ce13f7SAndroid Build Coastguard Worker     if (!isScalarFloatingType(DestTy)) {
2971*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error("Unexpected type when lowering frem.");
2972*03ce13f7SAndroid Build Coastguard Worker     }
2973*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Frem should have already been lowered.");
2974*03ce13f7SAndroid Build Coastguard Worker   }
2975*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Fadd: {
2976*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = legalizeToReg(Src0);
2977*03ce13f7SAndroid Build Coastguard Worker     if (const Inst *Src1Producer = Computations.getProducerOf(Src1)) {
2978*03ce13f7SAndroid Build Coastguard Worker       Variable *Src1R = legalizeToReg(Src1Producer->getSrc(0));
2979*03ce13f7SAndroid Build Coastguard Worker       Variable *Src2R = legalizeToReg(Src1Producer->getSrc(1));
2980*03ce13f7SAndroid Build Coastguard Worker       _vmla(Src0R, Src1R, Src2R);
2981*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, Src0R);
2982*03ce13f7SAndroid Build Coastguard Worker       return;
2983*03ce13f7SAndroid Build Coastguard Worker     }
2984*03ce13f7SAndroid Build Coastguard Worker 
2985*03ce13f7SAndroid Build Coastguard Worker     Variable *Src1R = legalizeToReg(Src1);
2986*03ce13f7SAndroid Build Coastguard Worker     _vadd(T, Src0R, Src1R);
2987*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
2988*03ce13f7SAndroid Build Coastguard Worker     return;
2989*03ce13f7SAndroid Build Coastguard Worker   }
2990*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Fsub: {
2991*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = legalizeToReg(Src0);
2992*03ce13f7SAndroid Build Coastguard Worker     if (const Inst *Src1Producer = Computations.getProducerOf(Src1)) {
2993*03ce13f7SAndroid Build Coastguard Worker       Variable *Src1R = legalizeToReg(Src1Producer->getSrc(0));
2994*03ce13f7SAndroid Build Coastguard Worker       Variable *Src2R = legalizeToReg(Src1Producer->getSrc(1));
2995*03ce13f7SAndroid Build Coastguard Worker       _vmls(Src0R, Src1R, Src2R);
2996*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, Src0R);
2997*03ce13f7SAndroid Build Coastguard Worker       return;
2998*03ce13f7SAndroid Build Coastguard Worker     }
2999*03ce13f7SAndroid Build Coastguard Worker     Variable *Src1R = legalizeToReg(Src1);
3000*03ce13f7SAndroid Build Coastguard Worker     _vsub(T, Src0R, Src1R);
3001*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
3002*03ce13f7SAndroid Build Coastguard Worker     return;
3003*03ce13f7SAndroid Build Coastguard Worker   }
3004*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Fmul: {
3005*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = legalizeToReg(Src0);
3006*03ce13f7SAndroid Build Coastguard Worker     Variable *Src1R = legalizeToReg(Src1);
3007*03ce13f7SAndroid Build Coastguard Worker     _vmul(T, Src0R, Src1R);
3008*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
3009*03ce13f7SAndroid Build Coastguard Worker     return;
3010*03ce13f7SAndroid Build Coastguard Worker   }
3011*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Fdiv: {
3012*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = legalizeToReg(Src0);
3013*03ce13f7SAndroid Build Coastguard Worker     Variable *Src1R = legalizeToReg(Src1);
3014*03ce13f7SAndroid Build Coastguard Worker     _vdiv(T, Src0R, Src1R);
3015*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
3016*03ce13f7SAndroid Build Coastguard Worker     return;
3017*03ce13f7SAndroid Build Coastguard Worker   }
3018*03ce13f7SAndroid Build Coastguard Worker   }
3019*03ce13f7SAndroid Build Coastguard Worker 
3020*03ce13f7SAndroid Build Coastguard Worker   // Handle everything else here.
3021*03ce13f7SAndroid Build Coastguard Worker   Int32Operands Srcs(Src0, Src1);
3022*03ce13f7SAndroid Build Coastguard Worker   switch (Instr->getOp()) {
3023*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::_num:
3024*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Unknown arithmetic operator");
3025*03ce13f7SAndroid Build Coastguard Worker     return;
3026*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Add: {
3027*03ce13f7SAndroid Build Coastguard Worker     if (const Inst *Src1Producer = Computations.getProducerOf(Src1)) {
3028*03ce13f7SAndroid Build Coastguard Worker       assert(!isVectorType(DestTy));
3029*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R = legalizeToReg(Src0);
3030*03ce13f7SAndroid Build Coastguard Worker       Variable *Src1R = legalizeToReg(Src1Producer->getSrc(0));
3031*03ce13f7SAndroid Build Coastguard Worker       Variable *Src2R = legalizeToReg(Src1Producer->getSrc(1));
3032*03ce13f7SAndroid Build Coastguard Worker       _mla(T, Src1R, Src2R, Src0R);
3033*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
3034*03ce13f7SAndroid Build Coastguard Worker       return;
3035*03ce13f7SAndroid Build Coastguard Worker     }
3036*03ce13f7SAndroid Build Coastguard Worker 
3037*03ce13f7SAndroid Build Coastguard Worker     if (Srcs.hasConstOperand()) {
3038*03ce13f7SAndroid Build Coastguard Worker       if (!Srcs.immediateIsFlexEncodable() &&
3039*03ce13f7SAndroid Build Coastguard Worker           Srcs.negatedImmediateIsFlexEncodable()) {
3040*03ce13f7SAndroid Build Coastguard Worker         assert(!isVectorType(DestTy));
3041*03ce13f7SAndroid Build Coastguard Worker         Variable *Src0R = Srcs.src0R(this);
3042*03ce13f7SAndroid Build Coastguard Worker         Operand *Src1F = Srcs.negatedSrc1F(this);
3043*03ce13f7SAndroid Build Coastguard Worker         if (!Srcs.swappedOperands()) {
3044*03ce13f7SAndroid Build Coastguard Worker           _sub(T, Src0R, Src1F);
3045*03ce13f7SAndroid Build Coastguard Worker         } else {
3046*03ce13f7SAndroid Build Coastguard Worker           _rsb(T, Src0R, Src1F);
3047*03ce13f7SAndroid Build Coastguard Worker         }
3048*03ce13f7SAndroid Build Coastguard Worker         _mov(Dest, T);
3049*03ce13f7SAndroid Build Coastguard Worker         return;
3050*03ce13f7SAndroid Build Coastguard Worker       }
3051*03ce13f7SAndroid Build Coastguard Worker     }
3052*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = Srcs.src0R(this);
3053*03ce13f7SAndroid Build Coastguard Worker     if (isVectorType(DestTy)) {
3054*03ce13f7SAndroid Build Coastguard Worker       Variable *Src1R = legalizeToReg(Src1);
3055*03ce13f7SAndroid Build Coastguard Worker       _vadd(T, Src0R, Src1R);
3056*03ce13f7SAndroid Build Coastguard Worker     } else {
3057*03ce13f7SAndroid Build Coastguard Worker       Operand *Src1RF = Srcs.src1RF(this);
3058*03ce13f7SAndroid Build Coastguard Worker       _add(T, Src0R, Src1RF);
3059*03ce13f7SAndroid Build Coastguard Worker     }
3060*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
3061*03ce13f7SAndroid Build Coastguard Worker     return;
3062*03ce13f7SAndroid Build Coastguard Worker   }
3063*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::And: {
3064*03ce13f7SAndroid Build Coastguard Worker     if (Srcs.hasConstOperand()) {
3065*03ce13f7SAndroid Build Coastguard Worker       if (!Srcs.immediateIsFlexEncodable() &&
3066*03ce13f7SAndroid Build Coastguard Worker           Srcs.invertedImmediateIsFlexEncodable()) {
3067*03ce13f7SAndroid Build Coastguard Worker         Variable *Src0R = Srcs.src0R(this);
3068*03ce13f7SAndroid Build Coastguard Worker         Operand *Src1F = Srcs.invertedSrc1F(this);
3069*03ce13f7SAndroid Build Coastguard Worker         _bic(T, Src0R, Src1F);
3070*03ce13f7SAndroid Build Coastguard Worker         _mov(Dest, T);
3071*03ce13f7SAndroid Build Coastguard Worker         return;
3072*03ce13f7SAndroid Build Coastguard Worker       }
3073*03ce13f7SAndroid Build Coastguard Worker     }
3074*03ce13f7SAndroid Build Coastguard Worker     assert(isIntegerType(DestTy));
3075*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = Srcs.src0R(this);
3076*03ce13f7SAndroid Build Coastguard Worker     if (isVectorType(DestTy)) {
3077*03ce13f7SAndroid Build Coastguard Worker       Variable *Src1R = legalizeToReg(Src1);
3078*03ce13f7SAndroid Build Coastguard Worker       _vand(T, Src0R, Src1R);
3079*03ce13f7SAndroid Build Coastguard Worker     } else {
3080*03ce13f7SAndroid Build Coastguard Worker       Operand *Src1RF = Srcs.src1RF(this);
3081*03ce13f7SAndroid Build Coastguard Worker       _and(T, Src0R, Src1RF);
3082*03ce13f7SAndroid Build Coastguard Worker     }
3083*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
3084*03ce13f7SAndroid Build Coastguard Worker     return;
3085*03ce13f7SAndroid Build Coastguard Worker   }
3086*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Or: {
3087*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = Srcs.src0R(this);
3088*03ce13f7SAndroid Build Coastguard Worker     assert(isIntegerType(DestTy));
3089*03ce13f7SAndroid Build Coastguard Worker     if (isVectorType(DestTy)) {
3090*03ce13f7SAndroid Build Coastguard Worker       Variable *Src1R = legalizeToReg(Src1);
3091*03ce13f7SAndroid Build Coastguard Worker       _vorr(T, Src0R, Src1R);
3092*03ce13f7SAndroid Build Coastguard Worker     } else {
3093*03ce13f7SAndroid Build Coastguard Worker       Operand *Src1RF = Srcs.src1RF(this);
3094*03ce13f7SAndroid Build Coastguard Worker       _orr(T, Src0R, Src1RF);
3095*03ce13f7SAndroid Build Coastguard Worker     }
3096*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
3097*03ce13f7SAndroid Build Coastguard Worker     return;
3098*03ce13f7SAndroid Build Coastguard Worker   }
3099*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Xor: {
3100*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = Srcs.src0R(this);
3101*03ce13f7SAndroid Build Coastguard Worker     assert(isIntegerType(DestTy));
3102*03ce13f7SAndroid Build Coastguard Worker     if (isVectorType(DestTy)) {
3103*03ce13f7SAndroid Build Coastguard Worker       Variable *Src1R = legalizeToReg(Src1);
3104*03ce13f7SAndroid Build Coastguard Worker       _veor(T, Src0R, Src1R);
3105*03ce13f7SAndroid Build Coastguard Worker     } else {
3106*03ce13f7SAndroid Build Coastguard Worker       Operand *Src1RF = Srcs.src1RF(this);
3107*03ce13f7SAndroid Build Coastguard Worker       _eor(T, Src0R, Src1RF);
3108*03ce13f7SAndroid Build Coastguard Worker     }
3109*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
3110*03ce13f7SAndroid Build Coastguard Worker     return;
3111*03ce13f7SAndroid Build Coastguard Worker   }
3112*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Sub: {
3113*03ce13f7SAndroid Build Coastguard Worker     if (const Inst *Src1Producer = Computations.getProducerOf(Src1)) {
3114*03ce13f7SAndroid Build Coastguard Worker       assert(!isVectorType(DestTy));
3115*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R = legalizeToReg(Src0);
3116*03ce13f7SAndroid Build Coastguard Worker       Variable *Src1R = legalizeToReg(Src1Producer->getSrc(0));
3117*03ce13f7SAndroid Build Coastguard Worker       Variable *Src2R = legalizeToReg(Src1Producer->getSrc(1));
3118*03ce13f7SAndroid Build Coastguard Worker       _mls(T, Src1R, Src2R, Src0R);
3119*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
3120*03ce13f7SAndroid Build Coastguard Worker       return;
3121*03ce13f7SAndroid Build Coastguard Worker     }
3122*03ce13f7SAndroid Build Coastguard Worker 
3123*03ce13f7SAndroid Build Coastguard Worker     if (Srcs.hasConstOperand()) {
3124*03ce13f7SAndroid Build Coastguard Worker       assert(!isVectorType(DestTy));
3125*03ce13f7SAndroid Build Coastguard Worker       if (Srcs.immediateIsFlexEncodable()) {
3126*03ce13f7SAndroid Build Coastguard Worker         Variable *Src0R = Srcs.src0R(this);
3127*03ce13f7SAndroid Build Coastguard Worker         Operand *Src1RF = Srcs.src1RF(this);
3128*03ce13f7SAndroid Build Coastguard Worker         if (Srcs.swappedOperands()) {
3129*03ce13f7SAndroid Build Coastguard Worker           _rsb(T, Src0R, Src1RF);
3130*03ce13f7SAndroid Build Coastguard Worker         } else {
3131*03ce13f7SAndroid Build Coastguard Worker           _sub(T, Src0R, Src1RF);
3132*03ce13f7SAndroid Build Coastguard Worker         }
3133*03ce13f7SAndroid Build Coastguard Worker         _mov(Dest, T);
3134*03ce13f7SAndroid Build Coastguard Worker         return;
3135*03ce13f7SAndroid Build Coastguard Worker       }
3136*03ce13f7SAndroid Build Coastguard Worker       if (!Srcs.swappedOperands() && Srcs.negatedImmediateIsFlexEncodable()) {
3137*03ce13f7SAndroid Build Coastguard Worker         Variable *Src0R = Srcs.src0R(this);
3138*03ce13f7SAndroid Build Coastguard Worker         Operand *Src1F = Srcs.negatedSrc1F(this);
3139*03ce13f7SAndroid Build Coastguard Worker         _add(T, Src0R, Src1F);
3140*03ce13f7SAndroid Build Coastguard Worker         _mov(Dest, T);
3141*03ce13f7SAndroid Build Coastguard Worker         return;
3142*03ce13f7SAndroid Build Coastguard Worker       }
3143*03ce13f7SAndroid Build Coastguard Worker     }
3144*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = Srcs.unswappedSrc0R(this);
3145*03ce13f7SAndroid Build Coastguard Worker     Variable *Src1R = Srcs.unswappedSrc1R(this);
3146*03ce13f7SAndroid Build Coastguard Worker     if (isVectorType(DestTy)) {
3147*03ce13f7SAndroid Build Coastguard Worker       _vsub(T, Src0R, Src1R);
3148*03ce13f7SAndroid Build Coastguard Worker     } else {
3149*03ce13f7SAndroid Build Coastguard Worker       _sub(T, Src0R, Src1R);
3150*03ce13f7SAndroid Build Coastguard Worker     }
3151*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
3152*03ce13f7SAndroid Build Coastguard Worker     return;
3153*03ce13f7SAndroid Build Coastguard Worker   }
3154*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Mul: {
3155*03ce13f7SAndroid Build Coastguard Worker     const bool OptM1 = Func->getOptLevel() == Opt_m1;
3156*03ce13f7SAndroid Build Coastguard Worker     if (!OptM1 && Srcs.hasConstOperand()) {
3157*03ce13f7SAndroid Build Coastguard Worker       constexpr std::size_t MaxShifts = 4;
3158*03ce13f7SAndroid Build Coastguard Worker       std::array<StrengthReduction::AggregationElement, MaxShifts> Shifts;
3159*03ce13f7SAndroid Build Coastguard Worker       SizeT NumOperations;
3160*03ce13f7SAndroid Build Coastguard Worker       int32_t Const = Srcs.getConstantValue();
3161*03ce13f7SAndroid Build Coastguard Worker       const bool Invert = Const < 0;
3162*03ce13f7SAndroid Build Coastguard Worker       const bool MultiplyByZero = Const == 0;
3163*03ce13f7SAndroid Build Coastguard Worker       Operand *_0 =
3164*03ce13f7SAndroid Build Coastguard Worker           legalize(Ctx->getConstantZero(DestTy), Legal_Reg | Legal_Flex);
3165*03ce13f7SAndroid Build Coastguard Worker 
3166*03ce13f7SAndroid Build Coastguard Worker       if (MultiplyByZero) {
3167*03ce13f7SAndroid Build Coastguard Worker         _mov(T, _0);
3168*03ce13f7SAndroid Build Coastguard Worker         _mov(Dest, T);
3169*03ce13f7SAndroid Build Coastguard Worker         return;
3170*03ce13f7SAndroid Build Coastguard Worker       }
3171*03ce13f7SAndroid Build Coastguard Worker 
3172*03ce13f7SAndroid Build Coastguard Worker       if (Invert) {
3173*03ce13f7SAndroid Build Coastguard Worker         Const = -Const;
3174*03ce13f7SAndroid Build Coastguard Worker       }
3175*03ce13f7SAndroid Build Coastguard Worker 
3176*03ce13f7SAndroid Build Coastguard Worker       if (StrengthReduction::tryToOptimize(Const, &NumOperations, &Shifts)) {
3177*03ce13f7SAndroid Build Coastguard Worker         assert(NumOperations >= 1);
3178*03ce13f7SAndroid Build Coastguard Worker         Variable *Src0R = Srcs.src0R(this);
3179*03ce13f7SAndroid Build Coastguard Worker         int32_t Start;
3180*03ce13f7SAndroid Build Coastguard Worker         int32_t End;
3181*03ce13f7SAndroid Build Coastguard Worker         if (NumOperations == 1 || Shifts[NumOperations - 1].shAmt() != 0) {
3182*03ce13f7SAndroid Build Coastguard Worker           // Multiplication by a power of 2 (NumOperations == 1); or
3183*03ce13f7SAndroid Build Coastguard Worker           // Multiplication by a even number not a power of 2.
3184*03ce13f7SAndroid Build Coastguard Worker           Start = 1;
3185*03ce13f7SAndroid Build Coastguard Worker           End = NumOperations;
3186*03ce13f7SAndroid Build Coastguard Worker           assert(Shifts[0].aggregateWithAdd());
3187*03ce13f7SAndroid Build Coastguard Worker           _lsl(T, Src0R, shAmtImm(Shifts[0].shAmt()));
3188*03ce13f7SAndroid Build Coastguard Worker         } else {
3189*03ce13f7SAndroid Build Coastguard Worker           // Multiplication by an odd number. Put the free barrel shifter to a
3190*03ce13f7SAndroid Build Coastguard Worker           // good use.
3191*03ce13f7SAndroid Build Coastguard Worker           Start = 0;
3192*03ce13f7SAndroid Build Coastguard Worker           End = NumOperations - 2;
3193*03ce13f7SAndroid Build Coastguard Worker           const StrengthReduction::AggregationElement &Last =
3194*03ce13f7SAndroid Build Coastguard Worker               Shifts[NumOperations - 1];
3195*03ce13f7SAndroid Build Coastguard Worker           const StrengthReduction::AggregationElement &SecondToLast =
3196*03ce13f7SAndroid Build Coastguard Worker               Shifts[NumOperations - 2];
3197*03ce13f7SAndroid Build Coastguard Worker           if (!Last.aggregateWithAdd()) {
3198*03ce13f7SAndroid Build Coastguard Worker             assert(SecondToLast.aggregateWithAdd());
3199*03ce13f7SAndroid Build Coastguard Worker             _rsb(T, Src0R, SecondToLast.createShiftedOperand(Func, Src0R));
3200*03ce13f7SAndroid Build Coastguard Worker           } else if (!SecondToLast.aggregateWithAdd()) {
3201*03ce13f7SAndroid Build Coastguard Worker             assert(Last.aggregateWithAdd());
3202*03ce13f7SAndroid Build Coastguard Worker             _sub(T, Src0R, SecondToLast.createShiftedOperand(Func, Src0R));
3203*03ce13f7SAndroid Build Coastguard Worker           } else {
3204*03ce13f7SAndroid Build Coastguard Worker             _add(T, Src0R, SecondToLast.createShiftedOperand(Func, Src0R));
3205*03ce13f7SAndroid Build Coastguard Worker           }
3206*03ce13f7SAndroid Build Coastguard Worker         }
3207*03ce13f7SAndroid Build Coastguard Worker 
3208*03ce13f7SAndroid Build Coastguard Worker         // Odd numbers :   S                                 E   I   I
3209*03ce13f7SAndroid Build Coastguard Worker         //               +---+---+---+---+---+---+ ... +---+---+---+---+
3210*03ce13f7SAndroid Build Coastguard Worker         //     Shifts  = |   |   |   |   |   |   | ... |   |   |   |   |
3211*03ce13f7SAndroid Build Coastguard Worker         //               +---+---+---+---+---+---+ ... +---+---+---+---+
3212*03ce13f7SAndroid Build Coastguard Worker         // Even numbers:   I   S                                     E
3213*03ce13f7SAndroid Build Coastguard Worker         //
3214*03ce13f7SAndroid Build Coastguard Worker         // S: Start; E: End; I: Init
3215*03ce13f7SAndroid Build Coastguard Worker         for (int32_t I = Start; I < End; ++I) {
3216*03ce13f7SAndroid Build Coastguard Worker           const StrengthReduction::AggregationElement &Current = Shifts[I];
3217*03ce13f7SAndroid Build Coastguard Worker           Operand *SrcF = Current.createShiftedOperand(Func, Src0R);
3218*03ce13f7SAndroid Build Coastguard Worker           if (Current.aggregateWithAdd()) {
3219*03ce13f7SAndroid Build Coastguard Worker             _add(T, T, SrcF);
3220*03ce13f7SAndroid Build Coastguard Worker           } else {
3221*03ce13f7SAndroid Build Coastguard Worker             _sub(T, T, SrcF);
3222*03ce13f7SAndroid Build Coastguard Worker           }
3223*03ce13f7SAndroid Build Coastguard Worker         }
3224*03ce13f7SAndroid Build Coastguard Worker 
3225*03ce13f7SAndroid Build Coastguard Worker         if (Invert) {
3226*03ce13f7SAndroid Build Coastguard Worker           // T = 0 - T.
3227*03ce13f7SAndroid Build Coastguard Worker           _rsb(T, T, _0);
3228*03ce13f7SAndroid Build Coastguard Worker         }
3229*03ce13f7SAndroid Build Coastguard Worker 
3230*03ce13f7SAndroid Build Coastguard Worker         _mov(Dest, T);
3231*03ce13f7SAndroid Build Coastguard Worker         return;
3232*03ce13f7SAndroid Build Coastguard Worker       }
3233*03ce13f7SAndroid Build Coastguard Worker     }
3234*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = Srcs.unswappedSrc0R(this);
3235*03ce13f7SAndroid Build Coastguard Worker     Variable *Src1R = Srcs.unswappedSrc1R(this);
3236*03ce13f7SAndroid Build Coastguard Worker     if (isVectorType(DestTy)) {
3237*03ce13f7SAndroid Build Coastguard Worker       _vmul(T, Src0R, Src1R);
3238*03ce13f7SAndroid Build Coastguard Worker     } else {
3239*03ce13f7SAndroid Build Coastguard Worker       _mul(T, Src0R, Src1R);
3240*03ce13f7SAndroid Build Coastguard Worker     }
3241*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
3242*03ce13f7SAndroid Build Coastguard Worker     return;
3243*03ce13f7SAndroid Build Coastguard Worker   }
3244*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Shl: {
3245*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = Srcs.unswappedSrc0R(this);
3246*03ce13f7SAndroid Build Coastguard Worker     if (!isVectorType(T->getType())) {
3247*03ce13f7SAndroid Build Coastguard Worker       if (Srcs.isSrc1ImmediateZero()) {
3248*03ce13f7SAndroid Build Coastguard Worker         _mov(T, Src0R);
3249*03ce13f7SAndroid Build Coastguard Worker       } else {
3250*03ce13f7SAndroid Build Coastguard Worker         Operand *Src1R = Srcs.unswappedSrc1RShAmtImm(this);
3251*03ce13f7SAndroid Build Coastguard Worker         _lsl(T, Src0R, Src1R);
3252*03ce13f7SAndroid Build Coastguard Worker       }
3253*03ce13f7SAndroid Build Coastguard Worker     } else {
3254*03ce13f7SAndroid Build Coastguard Worker       if (Srcs.hasConstOperand()) {
3255*03ce13f7SAndroid Build Coastguard Worker         ConstantInteger32 *ShAmt = llvm::cast<ConstantInteger32>(Srcs.src1());
3256*03ce13f7SAndroid Build Coastguard Worker         _vshl(T, Src0R, ShAmt);
3257*03ce13f7SAndroid Build Coastguard Worker       } else {
3258*03ce13f7SAndroid Build Coastguard Worker         auto *Src1R = Srcs.unswappedSrc1R(this);
3259*03ce13f7SAndroid Build Coastguard Worker         _vshl(T, Src0R, Src1R)->setSignType(InstARM32::FS_Unsigned);
3260*03ce13f7SAndroid Build Coastguard Worker       }
3261*03ce13f7SAndroid Build Coastguard Worker     }
3262*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
3263*03ce13f7SAndroid Build Coastguard Worker     return;
3264*03ce13f7SAndroid Build Coastguard Worker   }
3265*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Lshr: {
3266*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = Srcs.unswappedSrc0R(this);
3267*03ce13f7SAndroid Build Coastguard Worker     if (!isVectorType(T->getType())) {
3268*03ce13f7SAndroid Build Coastguard Worker       if (DestTy != IceType_i32) {
3269*03ce13f7SAndroid Build Coastguard Worker         _uxt(Src0R, Src0R);
3270*03ce13f7SAndroid Build Coastguard Worker       }
3271*03ce13f7SAndroid Build Coastguard Worker       if (Srcs.isSrc1ImmediateZero()) {
3272*03ce13f7SAndroid Build Coastguard Worker         _mov(T, Src0R);
3273*03ce13f7SAndroid Build Coastguard Worker       } else {
3274*03ce13f7SAndroid Build Coastguard Worker         Operand *Src1R = Srcs.unswappedSrc1RShAmtImm(this);
3275*03ce13f7SAndroid Build Coastguard Worker         _lsr(T, Src0R, Src1R);
3276*03ce13f7SAndroid Build Coastguard Worker       }
3277*03ce13f7SAndroid Build Coastguard Worker     } else {
3278*03ce13f7SAndroid Build Coastguard Worker       if (Srcs.hasConstOperand()) {
3279*03ce13f7SAndroid Build Coastguard Worker         ConstantInteger32 *ShAmt = llvm::cast<ConstantInteger32>(Srcs.src1());
3280*03ce13f7SAndroid Build Coastguard Worker         _vshr(T, Src0R, ShAmt)->setSignType(InstARM32::FS_Unsigned);
3281*03ce13f7SAndroid Build Coastguard Worker       } else {
3282*03ce13f7SAndroid Build Coastguard Worker         auto *Src1R = Srcs.unswappedSrc1R(this);
3283*03ce13f7SAndroid Build Coastguard Worker         auto *Src1RNeg = makeReg(Src1R->getType());
3284*03ce13f7SAndroid Build Coastguard Worker         _vneg(Src1RNeg, Src1R);
3285*03ce13f7SAndroid Build Coastguard Worker         _vshl(T, Src0R, Src1RNeg)->setSignType(InstARM32::FS_Unsigned);
3286*03ce13f7SAndroid Build Coastguard Worker       }
3287*03ce13f7SAndroid Build Coastguard Worker     }
3288*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
3289*03ce13f7SAndroid Build Coastguard Worker     return;
3290*03ce13f7SAndroid Build Coastguard Worker   }
3291*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Ashr: {
3292*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = Srcs.unswappedSrc0R(this);
3293*03ce13f7SAndroid Build Coastguard Worker     if (!isVectorType(T->getType())) {
3294*03ce13f7SAndroid Build Coastguard Worker       if (DestTy != IceType_i32) {
3295*03ce13f7SAndroid Build Coastguard Worker         _sxt(Src0R, Src0R);
3296*03ce13f7SAndroid Build Coastguard Worker       }
3297*03ce13f7SAndroid Build Coastguard Worker       if (Srcs.isSrc1ImmediateZero()) {
3298*03ce13f7SAndroid Build Coastguard Worker         _mov(T, Src0R);
3299*03ce13f7SAndroid Build Coastguard Worker       } else {
3300*03ce13f7SAndroid Build Coastguard Worker         _asr(T, Src0R, Srcs.unswappedSrc1RShAmtImm(this));
3301*03ce13f7SAndroid Build Coastguard Worker       }
3302*03ce13f7SAndroid Build Coastguard Worker     } else {
3303*03ce13f7SAndroid Build Coastguard Worker       if (Srcs.hasConstOperand()) {
3304*03ce13f7SAndroid Build Coastguard Worker         ConstantInteger32 *ShAmt = llvm::cast<ConstantInteger32>(Srcs.src1());
3305*03ce13f7SAndroid Build Coastguard Worker         _vshr(T, Src0R, ShAmt)->setSignType(InstARM32::FS_Signed);
3306*03ce13f7SAndroid Build Coastguard Worker       } else {
3307*03ce13f7SAndroid Build Coastguard Worker         auto *Src1R = Srcs.unswappedSrc1R(this);
3308*03ce13f7SAndroid Build Coastguard Worker         auto *Src1RNeg = makeReg(Src1R->getType());
3309*03ce13f7SAndroid Build Coastguard Worker         _vneg(Src1RNeg, Src1R);
3310*03ce13f7SAndroid Build Coastguard Worker         _vshl(T, Src0R, Src1RNeg)->setSignType(InstARM32::FS_Signed);
3311*03ce13f7SAndroid Build Coastguard Worker       }
3312*03ce13f7SAndroid Build Coastguard Worker     }
3313*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
3314*03ce13f7SAndroid Build Coastguard Worker     return;
3315*03ce13f7SAndroid Build Coastguard Worker   }
3316*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Udiv:
3317*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Sdiv:
3318*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Urem:
3319*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Srem:
3320*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error(
3321*03ce13f7SAndroid Build Coastguard Worker         "Integer div/rem should have been handled earlier.");
3322*03ce13f7SAndroid Build Coastguard Worker     return;
3323*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Fadd:
3324*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Fsub:
3325*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Fmul:
3326*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Fdiv:
3327*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Frem:
3328*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error(
3329*03ce13f7SAndroid Build Coastguard Worker         "Floating point arith should have been handled earlier.");
3330*03ce13f7SAndroid Build Coastguard Worker     return;
3331*03ce13f7SAndroid Build Coastguard Worker   }
3332*03ce13f7SAndroid Build Coastguard Worker }
3333*03ce13f7SAndroid Build Coastguard Worker 
lowerAssign(const InstAssign * Instr)3334*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerAssign(const InstAssign *Instr) {
3335*03ce13f7SAndroid Build Coastguard Worker   Variable *Dest = Instr->getDest();
3336*03ce13f7SAndroid Build Coastguard Worker 
3337*03ce13f7SAndroid Build Coastguard Worker   if (Dest->isRematerializable()) {
3338*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeDef>(Dest);
3339*03ce13f7SAndroid Build Coastguard Worker     return;
3340*03ce13f7SAndroid Build Coastguard Worker   }
3341*03ce13f7SAndroid Build Coastguard Worker 
3342*03ce13f7SAndroid Build Coastguard Worker   Operand *Src0 = Instr->getSrc(0);
3343*03ce13f7SAndroid Build Coastguard Worker   assert(Dest->getType() == Src0->getType());
3344*03ce13f7SAndroid Build Coastguard Worker   if (Dest->getType() == IceType_i64) {
3345*03ce13f7SAndroid Build Coastguard Worker     Src0 = legalizeUndef(Src0);
3346*03ce13f7SAndroid Build Coastguard Worker 
3347*03ce13f7SAndroid Build Coastguard Worker     Variable *T_Lo = makeReg(IceType_i32);
3348*03ce13f7SAndroid Build Coastguard Worker     auto *DestLo = llvm::cast<Variable>(loOperand(Dest));
3349*03ce13f7SAndroid Build Coastguard Worker     Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg | Legal_Flex);
3350*03ce13f7SAndroid Build Coastguard Worker     _mov(T_Lo, Src0Lo);
3351*03ce13f7SAndroid Build Coastguard Worker     _mov(DestLo, T_Lo);
3352*03ce13f7SAndroid Build Coastguard Worker 
3353*03ce13f7SAndroid Build Coastguard Worker     Variable *T_Hi = makeReg(IceType_i32);
3354*03ce13f7SAndroid Build Coastguard Worker     auto *DestHi = llvm::cast<Variable>(hiOperand(Dest));
3355*03ce13f7SAndroid Build Coastguard Worker     Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg | Legal_Flex);
3356*03ce13f7SAndroid Build Coastguard Worker     _mov(T_Hi, Src0Hi);
3357*03ce13f7SAndroid Build Coastguard Worker     _mov(DestHi, T_Hi);
3358*03ce13f7SAndroid Build Coastguard Worker 
3359*03ce13f7SAndroid Build Coastguard Worker     return;
3360*03ce13f7SAndroid Build Coastguard Worker   }
3361*03ce13f7SAndroid Build Coastguard Worker 
3362*03ce13f7SAndroid Build Coastguard Worker   Operand *NewSrc;
3363*03ce13f7SAndroid Build Coastguard Worker   if (Dest->hasReg()) {
3364*03ce13f7SAndroid Build Coastguard Worker     // If Dest already has a physical register, then legalize the Src operand
3365*03ce13f7SAndroid Build Coastguard Worker     // into a Variable with the same register assignment. This especially
3366*03ce13f7SAndroid Build Coastguard Worker     // helps allow the use of Flex operands.
3367*03ce13f7SAndroid Build Coastguard Worker     NewSrc = legalize(Src0, Legal_Reg | Legal_Flex, Dest->getRegNum());
3368*03ce13f7SAndroid Build Coastguard Worker   } else {
3369*03ce13f7SAndroid Build Coastguard Worker     // Dest could be a stack operand. Since we could potentially need to do a
3370*03ce13f7SAndroid Build Coastguard Worker     // Store (and store can only have Register operands), legalize this to a
3371*03ce13f7SAndroid Build Coastguard Worker     // register.
3372*03ce13f7SAndroid Build Coastguard Worker     NewSrc = legalize(Src0, Legal_Reg);
3373*03ce13f7SAndroid Build Coastguard Worker   }
3374*03ce13f7SAndroid Build Coastguard Worker 
3375*03ce13f7SAndroid Build Coastguard Worker   if (isVectorType(Dest->getType()) || isScalarFloatingType(Dest->getType())) {
3376*03ce13f7SAndroid Build Coastguard Worker     NewSrc = legalize(NewSrc, Legal_Reg | Legal_Mem);
3377*03ce13f7SAndroid Build Coastguard Worker   }
3378*03ce13f7SAndroid Build Coastguard Worker   _mov(Dest, NewSrc);
3379*03ce13f7SAndroid Build Coastguard Worker }
3380*03ce13f7SAndroid Build Coastguard Worker 
lowerInt1ForBranch(Operand * Boolean,const LowerInt1BranchTarget & TargetTrue,const LowerInt1BranchTarget & TargetFalse,uint32_t ShortCircuitable)3381*03ce13f7SAndroid Build Coastguard Worker TargetARM32::ShortCircuitCondAndLabel TargetARM32::lowerInt1ForBranch(
3382*03ce13f7SAndroid Build Coastguard Worker     Operand *Boolean, const LowerInt1BranchTarget &TargetTrue,
3383*03ce13f7SAndroid Build Coastguard Worker     const LowerInt1BranchTarget &TargetFalse, uint32_t ShortCircuitable) {
3384*03ce13f7SAndroid Build Coastguard Worker   InstARM32Label *NewShortCircuitLabel = nullptr;
3385*03ce13f7SAndroid Build Coastguard Worker   Operand *_1 = legalize(Ctx->getConstantInt1(1), Legal_Reg | Legal_Flex);
3386*03ce13f7SAndroid Build Coastguard Worker 
3387*03ce13f7SAndroid Build Coastguard Worker   const Inst *Producer = Computations.getProducerOf(Boolean);
3388*03ce13f7SAndroid Build Coastguard Worker 
3389*03ce13f7SAndroid Build Coastguard Worker   if (Producer == nullptr) {
3390*03ce13f7SAndroid Build Coastguard Worker     // No producer, no problem: just do emit code to perform (Boolean & 1) and
3391*03ce13f7SAndroid Build Coastguard Worker     // set the flags register. The branch should be taken if the resulting flags
3392*03ce13f7SAndroid Build Coastguard Worker     // indicate a non-zero result.
3393*03ce13f7SAndroid Build Coastguard Worker     _tst(legalizeToReg(Boolean), _1);
3394*03ce13f7SAndroid Build Coastguard Worker     return ShortCircuitCondAndLabel(CondWhenTrue(CondARM32::NE));
3395*03ce13f7SAndroid Build Coastguard Worker   }
3396*03ce13f7SAndroid Build Coastguard Worker 
3397*03ce13f7SAndroid Build Coastguard Worker   switch (Producer->getKind()) {
3398*03ce13f7SAndroid Build Coastguard Worker   default:
3399*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Unexpected producer.");
3400*03ce13f7SAndroid Build Coastguard Worker   case Inst::Icmp: {
3401*03ce13f7SAndroid Build Coastguard Worker     return ShortCircuitCondAndLabel(
3402*03ce13f7SAndroid Build Coastguard Worker         lowerIcmpCond(llvm::cast<InstIcmp>(Producer)));
3403*03ce13f7SAndroid Build Coastguard Worker   } break;
3404*03ce13f7SAndroid Build Coastguard Worker   case Inst::Fcmp: {
3405*03ce13f7SAndroid Build Coastguard Worker     return ShortCircuitCondAndLabel(
3406*03ce13f7SAndroid Build Coastguard Worker         lowerFcmpCond(llvm::cast<InstFcmp>(Producer)));
3407*03ce13f7SAndroid Build Coastguard Worker   } break;
3408*03ce13f7SAndroid Build Coastguard Worker   case Inst::Cast: {
3409*03ce13f7SAndroid Build Coastguard Worker     const auto *CastProducer = llvm::cast<InstCast>(Producer);
3410*03ce13f7SAndroid Build Coastguard Worker     assert(CastProducer->getCastKind() == InstCast::Trunc);
3411*03ce13f7SAndroid Build Coastguard Worker     Operand *Src = CastProducer->getSrc(0);
3412*03ce13f7SAndroid Build Coastguard Worker     if (Src->getType() == IceType_i64)
3413*03ce13f7SAndroid Build Coastguard Worker       Src = loOperand(Src);
3414*03ce13f7SAndroid Build Coastguard Worker     _tst(legalizeToReg(Src), _1);
3415*03ce13f7SAndroid Build Coastguard Worker     return ShortCircuitCondAndLabel(CondWhenTrue(CondARM32::NE));
3416*03ce13f7SAndroid Build Coastguard Worker   } break;
3417*03ce13f7SAndroid Build Coastguard Worker   case Inst::Arithmetic: {
3418*03ce13f7SAndroid Build Coastguard Worker     const auto *ArithProducer = llvm::cast<InstArithmetic>(Producer);
3419*03ce13f7SAndroid Build Coastguard Worker     switch (ArithProducer->getOp()) {
3420*03ce13f7SAndroid Build Coastguard Worker     default:
3421*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error("Unhandled Arithmetic Producer.");
3422*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::And: {
3423*03ce13f7SAndroid Build Coastguard Worker       if (!(ShortCircuitable & SC_And)) {
3424*03ce13f7SAndroid Build Coastguard Worker         NewShortCircuitLabel = InstARM32Label::create(Func, this);
3425*03ce13f7SAndroid Build Coastguard Worker       }
3426*03ce13f7SAndroid Build Coastguard Worker 
3427*03ce13f7SAndroid Build Coastguard Worker       LowerInt1BranchTarget NewTarget =
3428*03ce13f7SAndroid Build Coastguard Worker           TargetFalse.createForLabelOrDuplicate(NewShortCircuitLabel);
3429*03ce13f7SAndroid Build Coastguard Worker 
3430*03ce13f7SAndroid Build Coastguard Worker       ShortCircuitCondAndLabel CondAndLabel = lowerInt1ForBranch(
3431*03ce13f7SAndroid Build Coastguard Worker           Producer->getSrc(0), TargetTrue, NewTarget, SC_And);
3432*03ce13f7SAndroid Build Coastguard Worker       const CondWhenTrue &Cond = CondAndLabel.Cond;
3433*03ce13f7SAndroid Build Coastguard Worker 
3434*03ce13f7SAndroid Build Coastguard Worker       _br_short_circuit(NewTarget, Cond.invert());
3435*03ce13f7SAndroid Build Coastguard Worker 
3436*03ce13f7SAndroid Build Coastguard Worker       InstARM32Label *const ShortCircuitLabel = CondAndLabel.ShortCircuitTarget;
3437*03ce13f7SAndroid Build Coastguard Worker       if (ShortCircuitLabel != nullptr)
3438*03ce13f7SAndroid Build Coastguard Worker         Context.insert(ShortCircuitLabel);
3439*03ce13f7SAndroid Build Coastguard Worker 
3440*03ce13f7SAndroid Build Coastguard Worker       return ShortCircuitCondAndLabel(
3441*03ce13f7SAndroid Build Coastguard Worker           lowerInt1ForBranch(Producer->getSrc(1), TargetTrue, NewTarget, SC_All)
3442*03ce13f7SAndroid Build Coastguard Worker               .assertNoLabelAndReturnCond(),
3443*03ce13f7SAndroid Build Coastguard Worker           NewShortCircuitLabel);
3444*03ce13f7SAndroid Build Coastguard Worker     } break;
3445*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Or: {
3446*03ce13f7SAndroid Build Coastguard Worker       if (!(ShortCircuitable & SC_Or)) {
3447*03ce13f7SAndroid Build Coastguard Worker         NewShortCircuitLabel = InstARM32Label::create(Func, this);
3448*03ce13f7SAndroid Build Coastguard Worker       }
3449*03ce13f7SAndroid Build Coastguard Worker 
3450*03ce13f7SAndroid Build Coastguard Worker       LowerInt1BranchTarget NewTarget =
3451*03ce13f7SAndroid Build Coastguard Worker           TargetTrue.createForLabelOrDuplicate(NewShortCircuitLabel);
3452*03ce13f7SAndroid Build Coastguard Worker 
3453*03ce13f7SAndroid Build Coastguard Worker       ShortCircuitCondAndLabel CondAndLabel = lowerInt1ForBranch(
3454*03ce13f7SAndroid Build Coastguard Worker           Producer->getSrc(0), NewTarget, TargetFalse, SC_Or);
3455*03ce13f7SAndroid Build Coastguard Worker       const CondWhenTrue &Cond = CondAndLabel.Cond;
3456*03ce13f7SAndroid Build Coastguard Worker 
3457*03ce13f7SAndroid Build Coastguard Worker       _br_short_circuit(NewTarget, Cond);
3458*03ce13f7SAndroid Build Coastguard Worker 
3459*03ce13f7SAndroid Build Coastguard Worker       InstARM32Label *const ShortCircuitLabel = CondAndLabel.ShortCircuitTarget;
3460*03ce13f7SAndroid Build Coastguard Worker       if (ShortCircuitLabel != nullptr)
3461*03ce13f7SAndroid Build Coastguard Worker         Context.insert(ShortCircuitLabel);
3462*03ce13f7SAndroid Build Coastguard Worker 
3463*03ce13f7SAndroid Build Coastguard Worker       return ShortCircuitCondAndLabel(lowerInt1ForBranch(Producer->getSrc(1),
3464*03ce13f7SAndroid Build Coastguard Worker                                                          NewTarget, TargetFalse,
3465*03ce13f7SAndroid Build Coastguard Worker                                                          SC_All)
3466*03ce13f7SAndroid Build Coastguard Worker                                           .assertNoLabelAndReturnCond(),
3467*03ce13f7SAndroid Build Coastguard Worker                                       NewShortCircuitLabel);
3468*03ce13f7SAndroid Build Coastguard Worker     } break;
3469*03ce13f7SAndroid Build Coastguard Worker     }
3470*03ce13f7SAndroid Build Coastguard Worker   }
3471*03ce13f7SAndroid Build Coastguard Worker   }
3472*03ce13f7SAndroid Build Coastguard Worker }
3473*03ce13f7SAndroid Build Coastguard Worker 
lowerBr(const InstBr * Instr)3474*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerBr(const InstBr *Instr) {
3475*03ce13f7SAndroid Build Coastguard Worker   if (Instr->isUnconditional()) {
3476*03ce13f7SAndroid Build Coastguard Worker     _br(Instr->getTargetUnconditional());
3477*03ce13f7SAndroid Build Coastguard Worker     return;
3478*03ce13f7SAndroid Build Coastguard Worker   }
3479*03ce13f7SAndroid Build Coastguard Worker 
3480*03ce13f7SAndroid Build Coastguard Worker   CfgNode *TargetTrue = Instr->getTargetTrue();
3481*03ce13f7SAndroid Build Coastguard Worker   CfgNode *TargetFalse = Instr->getTargetFalse();
3482*03ce13f7SAndroid Build Coastguard Worker   ShortCircuitCondAndLabel CondAndLabel = lowerInt1ForBranch(
3483*03ce13f7SAndroid Build Coastguard Worker       Instr->getCondition(), LowerInt1BranchTarget(TargetTrue),
3484*03ce13f7SAndroid Build Coastguard Worker       LowerInt1BranchTarget(TargetFalse), SC_All);
3485*03ce13f7SAndroid Build Coastguard Worker   assert(CondAndLabel.ShortCircuitTarget == nullptr);
3486*03ce13f7SAndroid Build Coastguard Worker 
3487*03ce13f7SAndroid Build Coastguard Worker   const CondWhenTrue &Cond = CondAndLabel.Cond;
3488*03ce13f7SAndroid Build Coastguard Worker   if (Cond.WhenTrue1 != CondARM32::kNone) {
3489*03ce13f7SAndroid Build Coastguard Worker     assert(Cond.WhenTrue0 != CondARM32::AL);
3490*03ce13f7SAndroid Build Coastguard Worker     _br(TargetTrue, Cond.WhenTrue1);
3491*03ce13f7SAndroid Build Coastguard Worker   }
3492*03ce13f7SAndroid Build Coastguard Worker 
3493*03ce13f7SAndroid Build Coastguard Worker   switch (Cond.WhenTrue0) {
3494*03ce13f7SAndroid Build Coastguard Worker   default:
3495*03ce13f7SAndroid Build Coastguard Worker     _br(TargetTrue, TargetFalse, Cond.WhenTrue0);
3496*03ce13f7SAndroid Build Coastguard Worker     break;
3497*03ce13f7SAndroid Build Coastguard Worker   case CondARM32::kNone:
3498*03ce13f7SAndroid Build Coastguard Worker     _br(TargetFalse);
3499*03ce13f7SAndroid Build Coastguard Worker     break;
3500*03ce13f7SAndroid Build Coastguard Worker   case CondARM32::AL:
3501*03ce13f7SAndroid Build Coastguard Worker     _br(TargetTrue);
3502*03ce13f7SAndroid Build Coastguard Worker     break;
3503*03ce13f7SAndroid Build Coastguard Worker   }
3504*03ce13f7SAndroid Build Coastguard Worker }
3505*03ce13f7SAndroid Build Coastguard Worker 
lowerCall(const InstCall * Instr)3506*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerCall(const InstCall *Instr) {
3507*03ce13f7SAndroid Build Coastguard Worker   Operand *CallTarget = Instr->getCallTarget();
3508*03ce13f7SAndroid Build Coastguard Worker   if (Instr->isTargetHelperCall()) {
3509*03ce13f7SAndroid Build Coastguard Worker     auto TargetHelperPreamble = ARM32HelpersPreamble.find(CallTarget);
3510*03ce13f7SAndroid Build Coastguard Worker     if (TargetHelperPreamble != ARM32HelpersPreamble.end()) {
3511*03ce13f7SAndroid Build Coastguard Worker       (this->*TargetHelperPreamble->second)(Instr);
3512*03ce13f7SAndroid Build Coastguard Worker     }
3513*03ce13f7SAndroid Build Coastguard Worker   }
3514*03ce13f7SAndroid Build Coastguard Worker   MaybeLeafFunc = false;
3515*03ce13f7SAndroid Build Coastguard Worker   NeedsStackAlignment = true;
3516*03ce13f7SAndroid Build Coastguard Worker 
3517*03ce13f7SAndroid Build Coastguard Worker   // Assign arguments to registers and stack. Also reserve stack.
3518*03ce13f7SAndroid Build Coastguard Worker   TargetARM32::CallingConv CC;
3519*03ce13f7SAndroid Build Coastguard Worker   // Pair of Arg Operand -> GPR number assignments.
3520*03ce13f7SAndroid Build Coastguard Worker   llvm::SmallVector<std::pair<Operand *, RegNumT>, NumGPRArgs> GPRArgs;
3521*03ce13f7SAndroid Build Coastguard Worker   llvm::SmallVector<std::pair<Operand *, RegNumT>, NumFP32Args> FPArgs;
3522*03ce13f7SAndroid Build Coastguard Worker   // Pair of Arg Operand -> stack offset.
3523*03ce13f7SAndroid Build Coastguard Worker   llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs;
3524*03ce13f7SAndroid Build Coastguard Worker   size_t ParameterAreaSizeBytes = 0;
3525*03ce13f7SAndroid Build Coastguard Worker 
3526*03ce13f7SAndroid Build Coastguard Worker   // Classify each argument operand according to the location where the
3527*03ce13f7SAndroid Build Coastguard Worker   // argument is passed.
3528*03ce13f7SAndroid Build Coastguard Worker   for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) {
3529*03ce13f7SAndroid Build Coastguard Worker     Operand *Arg = legalizeUndef(Instr->getArg(i));
3530*03ce13f7SAndroid Build Coastguard Worker     const Type Ty = Arg->getType();
3531*03ce13f7SAndroid Build Coastguard Worker     bool InReg = false;
3532*03ce13f7SAndroid Build Coastguard Worker     RegNumT Reg;
3533*03ce13f7SAndroid Build Coastguard Worker     if (isScalarIntegerType(Ty)) {
3534*03ce13f7SAndroid Build Coastguard Worker       InReg = CC.argInGPR(Ty, &Reg);
3535*03ce13f7SAndroid Build Coastguard Worker     } else {
3536*03ce13f7SAndroid Build Coastguard Worker       InReg = CC.argInVFP(Ty, &Reg);
3537*03ce13f7SAndroid Build Coastguard Worker     }
3538*03ce13f7SAndroid Build Coastguard Worker 
3539*03ce13f7SAndroid Build Coastguard Worker     if (!InReg) {
3540*03ce13f7SAndroid Build Coastguard Worker       ParameterAreaSizeBytes =
3541*03ce13f7SAndroid Build Coastguard Worker           applyStackAlignmentTy(ParameterAreaSizeBytes, Ty);
3542*03ce13f7SAndroid Build Coastguard Worker       StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes));
3543*03ce13f7SAndroid Build Coastguard Worker       ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty);
3544*03ce13f7SAndroid Build Coastguard Worker       continue;
3545*03ce13f7SAndroid Build Coastguard Worker     }
3546*03ce13f7SAndroid Build Coastguard Worker 
3547*03ce13f7SAndroid Build Coastguard Worker     if (Ty == IceType_i64) {
3548*03ce13f7SAndroid Build Coastguard Worker       Operand *Lo = loOperand(Arg);
3549*03ce13f7SAndroid Build Coastguard Worker       Operand *Hi = hiOperand(Arg);
3550*03ce13f7SAndroid Build Coastguard Worker       GPRArgs.push_back(std::make_pair(
3551*03ce13f7SAndroid Build Coastguard Worker           Lo, RegNumT::fixme(RegARM32::getI64PairFirstGPRNum(Reg))));
3552*03ce13f7SAndroid Build Coastguard Worker       GPRArgs.push_back(std::make_pair(
3553*03ce13f7SAndroid Build Coastguard Worker           Hi, RegNumT::fixme(RegARM32::getI64PairSecondGPRNum(Reg))));
3554*03ce13f7SAndroid Build Coastguard Worker     } else if (isScalarIntegerType(Ty)) {
3555*03ce13f7SAndroid Build Coastguard Worker       GPRArgs.push_back(std::make_pair(Arg, Reg));
3556*03ce13f7SAndroid Build Coastguard Worker     } else {
3557*03ce13f7SAndroid Build Coastguard Worker       FPArgs.push_back(std::make_pair(Arg, Reg));
3558*03ce13f7SAndroid Build Coastguard Worker     }
3559*03ce13f7SAndroid Build Coastguard Worker   }
3560*03ce13f7SAndroid Build Coastguard Worker 
3561*03ce13f7SAndroid Build Coastguard Worker   // Adjust the parameter area so that the stack is aligned. It is assumed that
3562*03ce13f7SAndroid Build Coastguard Worker   // the stack is already aligned at the start of the calling sequence.
3563*03ce13f7SAndroid Build Coastguard Worker   ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes);
3564*03ce13f7SAndroid Build Coastguard Worker 
3565*03ce13f7SAndroid Build Coastguard Worker   if (ParameterAreaSizeBytes > MaxOutArgsSizeBytes) {
3566*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("MaxOutArgsSizeBytes is not really a max.");
3567*03ce13f7SAndroid Build Coastguard Worker   }
3568*03ce13f7SAndroid Build Coastguard Worker 
3569*03ce13f7SAndroid Build Coastguard Worker   // Copy arguments that are passed on the stack to the appropriate stack
3570*03ce13f7SAndroid Build Coastguard Worker   // locations.
3571*03ce13f7SAndroid Build Coastguard Worker   Variable *SP = getPhysicalRegister(RegARM32::Reg_sp);
3572*03ce13f7SAndroid Build Coastguard Worker   for (auto &StackArg : StackArgs) {
3573*03ce13f7SAndroid Build Coastguard Worker     ConstantInteger32 *Loc =
3574*03ce13f7SAndroid Build Coastguard Worker         llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(StackArg.second));
3575*03ce13f7SAndroid Build Coastguard Worker     Type Ty = StackArg.first->getType();
3576*03ce13f7SAndroid Build Coastguard Worker     OperandARM32Mem *Addr;
3577*03ce13f7SAndroid Build Coastguard Worker     constexpr bool SignExt = false;
3578*03ce13f7SAndroid Build Coastguard Worker     if (OperandARM32Mem::canHoldOffset(Ty, SignExt, StackArg.second)) {
3579*03ce13f7SAndroid Build Coastguard Worker       Addr = OperandARM32Mem::create(Func, Ty, SP, Loc);
3580*03ce13f7SAndroid Build Coastguard Worker     } else {
3581*03ce13f7SAndroid Build Coastguard Worker       Variable *NewBase = Func->makeVariable(SP->getType());
3582*03ce13f7SAndroid Build Coastguard Worker       lowerArithmetic(
3583*03ce13f7SAndroid Build Coastguard Worker           InstArithmetic::create(Func, InstArithmetic::Add, NewBase, SP, Loc));
3584*03ce13f7SAndroid Build Coastguard Worker       Addr = formMemoryOperand(NewBase, Ty);
3585*03ce13f7SAndroid Build Coastguard Worker     }
3586*03ce13f7SAndroid Build Coastguard Worker     lowerStore(InstStore::create(Func, StackArg.first, Addr));
3587*03ce13f7SAndroid Build Coastguard Worker   }
3588*03ce13f7SAndroid Build Coastguard Worker 
3589*03ce13f7SAndroid Build Coastguard Worker   // Generate the call instruction. Assign its result to a temporary with high
3590*03ce13f7SAndroid Build Coastguard Worker   // register allocation weight.
3591*03ce13f7SAndroid Build Coastguard Worker   Variable *Dest = Instr->getDest();
3592*03ce13f7SAndroid Build Coastguard Worker   // ReturnReg doubles as ReturnRegLo as necessary.
3593*03ce13f7SAndroid Build Coastguard Worker   Variable *ReturnReg = nullptr;
3594*03ce13f7SAndroid Build Coastguard Worker   Variable *ReturnRegHi = nullptr;
3595*03ce13f7SAndroid Build Coastguard Worker   if (Dest) {
3596*03ce13f7SAndroid Build Coastguard Worker     switch (Dest->getType()) {
3597*03ce13f7SAndroid Build Coastguard Worker     case IceType_NUM:
3598*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error("Invalid Call dest type");
3599*03ce13f7SAndroid Build Coastguard Worker       break;
3600*03ce13f7SAndroid Build Coastguard Worker     case IceType_void:
3601*03ce13f7SAndroid Build Coastguard Worker       break;
3602*03ce13f7SAndroid Build Coastguard Worker     case IceType_i1:
3603*03ce13f7SAndroid Build Coastguard Worker       assert(Computations.getProducerOf(Dest) == nullptr);
3604*03ce13f7SAndroid Build Coastguard Worker     // Fall-through intended.
3605*03ce13f7SAndroid Build Coastguard Worker     case IceType_i8:
3606*03ce13f7SAndroid Build Coastguard Worker     case IceType_i16:
3607*03ce13f7SAndroid Build Coastguard Worker     case IceType_i32:
3608*03ce13f7SAndroid Build Coastguard Worker       ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_r0);
3609*03ce13f7SAndroid Build Coastguard Worker       break;
3610*03ce13f7SAndroid Build Coastguard Worker     case IceType_i64:
3611*03ce13f7SAndroid Build Coastguard Worker       ReturnReg = makeReg(IceType_i32, RegARM32::Reg_r0);
3612*03ce13f7SAndroid Build Coastguard Worker       ReturnRegHi = makeReg(IceType_i32, RegARM32::Reg_r1);
3613*03ce13f7SAndroid Build Coastguard Worker       break;
3614*03ce13f7SAndroid Build Coastguard Worker     case IceType_f32:
3615*03ce13f7SAndroid Build Coastguard Worker       ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_s0);
3616*03ce13f7SAndroid Build Coastguard Worker       break;
3617*03ce13f7SAndroid Build Coastguard Worker     case IceType_f64:
3618*03ce13f7SAndroid Build Coastguard Worker       ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_d0);
3619*03ce13f7SAndroid Build Coastguard Worker       break;
3620*03ce13f7SAndroid Build Coastguard Worker     case IceType_v4i1:
3621*03ce13f7SAndroid Build Coastguard Worker     case IceType_v8i1:
3622*03ce13f7SAndroid Build Coastguard Worker     case IceType_v16i1:
3623*03ce13f7SAndroid Build Coastguard Worker     case IceType_v16i8:
3624*03ce13f7SAndroid Build Coastguard Worker     case IceType_v8i16:
3625*03ce13f7SAndroid Build Coastguard Worker     case IceType_v4i32:
3626*03ce13f7SAndroid Build Coastguard Worker     case IceType_v4f32:
3627*03ce13f7SAndroid Build Coastguard Worker       ReturnReg = makeReg(Dest->getType(), RegARM32::Reg_q0);
3628*03ce13f7SAndroid Build Coastguard Worker       break;
3629*03ce13f7SAndroid Build Coastguard Worker     }
3630*03ce13f7SAndroid Build Coastguard Worker   }
3631*03ce13f7SAndroid Build Coastguard Worker 
3632*03ce13f7SAndroid Build Coastguard Worker   // Allow ConstantRelocatable to be left alone as a direct call, but force
3633*03ce13f7SAndroid Build Coastguard Worker   // other constants like ConstantInteger32 to be in a register and make it an
3634*03ce13f7SAndroid Build Coastguard Worker   // indirect call.
3635*03ce13f7SAndroid Build Coastguard Worker   if (!llvm::isa<ConstantRelocatable>(CallTarget)) {
3636*03ce13f7SAndroid Build Coastguard Worker     CallTarget = legalize(CallTarget, Legal_Reg);
3637*03ce13f7SAndroid Build Coastguard Worker   }
3638*03ce13f7SAndroid Build Coastguard Worker 
3639*03ce13f7SAndroid Build Coastguard Worker   // Copy arguments to be passed in registers to the appropriate registers.
3640*03ce13f7SAndroid Build Coastguard Worker   CfgVector<Variable *> RegArgs;
3641*03ce13f7SAndroid Build Coastguard Worker   for (auto &FPArg : FPArgs) {
3642*03ce13f7SAndroid Build Coastguard Worker     RegArgs.emplace_back(legalizeToReg(FPArg.first, FPArg.second));
3643*03ce13f7SAndroid Build Coastguard Worker   }
3644*03ce13f7SAndroid Build Coastguard Worker   for (auto &GPRArg : GPRArgs) {
3645*03ce13f7SAndroid Build Coastguard Worker     RegArgs.emplace_back(legalizeToReg(GPRArg.first, GPRArg.second));
3646*03ce13f7SAndroid Build Coastguard Worker   }
3647*03ce13f7SAndroid Build Coastguard Worker 
3648*03ce13f7SAndroid Build Coastguard Worker   // Generate a FakeUse of register arguments so that they do not get dead code
3649*03ce13f7SAndroid Build Coastguard Worker   // eliminated as a result of the FakeKill of scratch registers after the call.
3650*03ce13f7SAndroid Build Coastguard Worker   // These fake-uses need to be placed here to avoid argument registers from
3651*03ce13f7SAndroid Build Coastguard Worker   // being used during the legalizeToReg() calls above.
3652*03ce13f7SAndroid Build Coastguard Worker   for (auto *RegArg : RegArgs) {
3653*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(RegArg);
3654*03ce13f7SAndroid Build Coastguard Worker   }
3655*03ce13f7SAndroid Build Coastguard Worker 
3656*03ce13f7SAndroid Build Coastguard Worker   InstARM32Call *NewCall = Context.insert<InstARM32Call>(ReturnReg, CallTarget);
3657*03ce13f7SAndroid Build Coastguard Worker 
3658*03ce13f7SAndroid Build Coastguard Worker   if (ReturnRegHi)
3659*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeDef>(ReturnRegHi);
3660*03ce13f7SAndroid Build Coastguard Worker 
3661*03ce13f7SAndroid Build Coastguard Worker   // Insert a register-kill pseudo instruction.
3662*03ce13f7SAndroid Build Coastguard Worker   Context.insert<InstFakeKill>(NewCall);
3663*03ce13f7SAndroid Build Coastguard Worker 
3664*03ce13f7SAndroid Build Coastguard Worker   // Generate a FakeUse to keep the call live if necessary.
3665*03ce13f7SAndroid Build Coastguard Worker   if (Instr->hasSideEffects() && ReturnReg) {
3666*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(ReturnReg);
3667*03ce13f7SAndroid Build Coastguard Worker   }
3668*03ce13f7SAndroid Build Coastguard Worker 
3669*03ce13f7SAndroid Build Coastguard Worker   if (Dest != nullptr) {
3670*03ce13f7SAndroid Build Coastguard Worker     // Assign the result of the call to Dest.
3671*03ce13f7SAndroid Build Coastguard Worker     if (ReturnReg != nullptr) {
3672*03ce13f7SAndroid Build Coastguard Worker       if (ReturnRegHi) {
3673*03ce13f7SAndroid Build Coastguard Worker         auto *Dest64On32 = llvm::cast<Variable64On32>(Dest);
3674*03ce13f7SAndroid Build Coastguard Worker         Variable *DestLo = Dest64On32->getLo();
3675*03ce13f7SAndroid Build Coastguard Worker         Variable *DestHi = Dest64On32->getHi();
3676*03ce13f7SAndroid Build Coastguard Worker         _mov(DestLo, ReturnReg);
3677*03ce13f7SAndroid Build Coastguard Worker         _mov(DestHi, ReturnRegHi);
3678*03ce13f7SAndroid Build Coastguard Worker       } else {
3679*03ce13f7SAndroid Build Coastguard Worker         if (isFloatingType(Dest->getType()) || isVectorType(Dest->getType())) {
3680*03ce13f7SAndroid Build Coastguard Worker           _mov(Dest, ReturnReg);
3681*03ce13f7SAndroid Build Coastguard Worker         } else {
3682*03ce13f7SAndroid Build Coastguard Worker           assert(isIntegerType(Dest->getType()) &&
3683*03ce13f7SAndroid Build Coastguard Worker                  typeWidthInBytes(Dest->getType()) <= 4);
3684*03ce13f7SAndroid Build Coastguard Worker           _mov(Dest, ReturnReg);
3685*03ce13f7SAndroid Build Coastguard Worker         }
3686*03ce13f7SAndroid Build Coastguard Worker       }
3687*03ce13f7SAndroid Build Coastguard Worker     }
3688*03ce13f7SAndroid Build Coastguard Worker   }
3689*03ce13f7SAndroid Build Coastguard Worker 
3690*03ce13f7SAndroid Build Coastguard Worker   if (Instr->isTargetHelperCall()) {
3691*03ce13f7SAndroid Build Coastguard Worker     auto TargetHelpersPostamble = ARM32HelpersPostamble.find(CallTarget);
3692*03ce13f7SAndroid Build Coastguard Worker     if (TargetHelpersPostamble != ARM32HelpersPostamble.end()) {
3693*03ce13f7SAndroid Build Coastguard Worker       (this->*TargetHelpersPostamble->second)(Instr);
3694*03ce13f7SAndroid Build Coastguard Worker     }
3695*03ce13f7SAndroid Build Coastguard Worker   }
3696*03ce13f7SAndroid Build Coastguard Worker }
3697*03ce13f7SAndroid Build Coastguard Worker 
3698*03ce13f7SAndroid Build Coastguard Worker namespace {
configureBitcastTemporary(Variable64On32 * Var)3699*03ce13f7SAndroid Build Coastguard Worker void configureBitcastTemporary(Variable64On32 *Var) {
3700*03ce13f7SAndroid Build Coastguard Worker   Var->setMustNotHaveReg();
3701*03ce13f7SAndroid Build Coastguard Worker   Var->getHi()->setMustHaveReg();
3702*03ce13f7SAndroid Build Coastguard Worker   Var->getLo()->setMustHaveReg();
3703*03ce13f7SAndroid Build Coastguard Worker }
3704*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
3705*03ce13f7SAndroid Build Coastguard Worker 
lowerCast(const InstCast * Instr)3706*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerCast(const InstCast *Instr) {
3707*03ce13f7SAndroid Build Coastguard Worker   InstCast::OpKind CastKind = Instr->getCastKind();
3708*03ce13f7SAndroid Build Coastguard Worker   Variable *Dest = Instr->getDest();
3709*03ce13f7SAndroid Build Coastguard Worker   const Type DestTy = Dest->getType();
3710*03ce13f7SAndroid Build Coastguard Worker   Operand *Src0 = legalizeUndef(Instr->getSrc(0));
3711*03ce13f7SAndroid Build Coastguard Worker   switch (CastKind) {
3712*03ce13f7SAndroid Build Coastguard Worker   default:
3713*03ce13f7SAndroid Build Coastguard Worker     Func->setError("Cast type not supported");
3714*03ce13f7SAndroid Build Coastguard Worker     return;
3715*03ce13f7SAndroid Build Coastguard Worker   case InstCast::Sext: {
3716*03ce13f7SAndroid Build Coastguard Worker     if (isVectorType(DestTy)) {
3717*03ce13f7SAndroid Build Coastguard Worker       Variable *T0 = makeReg(DestTy);
3718*03ce13f7SAndroid Build Coastguard Worker       Variable *T1 = makeReg(DestTy);
3719*03ce13f7SAndroid Build Coastguard Worker       ConstantInteger32 *ShAmt = nullptr;
3720*03ce13f7SAndroid Build Coastguard Worker       switch (DestTy) {
3721*03ce13f7SAndroid Build Coastguard Worker       default:
3722*03ce13f7SAndroid Build Coastguard Worker         llvm::report_fatal_error("Unexpected type in vector sext.");
3723*03ce13f7SAndroid Build Coastguard Worker       case IceType_v16i8:
3724*03ce13f7SAndroid Build Coastguard Worker         ShAmt = llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(7));
3725*03ce13f7SAndroid Build Coastguard Worker         break;
3726*03ce13f7SAndroid Build Coastguard Worker       case IceType_v8i16:
3727*03ce13f7SAndroid Build Coastguard Worker         ShAmt = llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(15));
3728*03ce13f7SAndroid Build Coastguard Worker         break;
3729*03ce13f7SAndroid Build Coastguard Worker       case IceType_v4i32:
3730*03ce13f7SAndroid Build Coastguard Worker         ShAmt = llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(31));
3731*03ce13f7SAndroid Build Coastguard Worker         break;
3732*03ce13f7SAndroid Build Coastguard Worker       }
3733*03ce13f7SAndroid Build Coastguard Worker       auto *Src0R = legalizeToReg(Src0);
3734*03ce13f7SAndroid Build Coastguard Worker       _vshl(T0, Src0R, ShAmt);
3735*03ce13f7SAndroid Build Coastguard Worker       _vshr(T1, T0, ShAmt)->setSignType(InstARM32::FS_Signed);
3736*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T1);
3737*03ce13f7SAndroid Build Coastguard Worker     } else if (DestTy == IceType_i64) {
3738*03ce13f7SAndroid Build Coastguard Worker       // t1=sxtb src; t2= mov t1 asr #31; dst.lo=t1; dst.hi=t2
3739*03ce13f7SAndroid Build Coastguard Worker       Constant *ShiftAmt = Ctx->getConstantInt32(31);
3740*03ce13f7SAndroid Build Coastguard Worker       auto *DestLo = llvm::cast<Variable>(loOperand(Dest));
3741*03ce13f7SAndroid Build Coastguard Worker       auto *DestHi = llvm::cast<Variable>(hiOperand(Dest));
3742*03ce13f7SAndroid Build Coastguard Worker       Variable *T_Lo = makeReg(DestLo->getType());
3743*03ce13f7SAndroid Build Coastguard Worker       if (Src0->getType() == IceType_i32) {
3744*03ce13f7SAndroid Build Coastguard Worker         Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex);
3745*03ce13f7SAndroid Build Coastguard Worker         _mov(T_Lo, Src0RF);
3746*03ce13f7SAndroid Build Coastguard Worker       } else if (Src0->getType() != IceType_i1) {
3747*03ce13f7SAndroid Build Coastguard Worker         Variable *Src0R = legalizeToReg(Src0);
3748*03ce13f7SAndroid Build Coastguard Worker         _sxt(T_Lo, Src0R);
3749*03ce13f7SAndroid Build Coastguard Worker       } else {
3750*03ce13f7SAndroid Build Coastguard Worker         Operand *_0 = Ctx->getConstantZero(IceType_i32);
3751*03ce13f7SAndroid Build Coastguard Worker         Operand *_m1 = Ctx->getConstantInt32(-1);
3752*03ce13f7SAndroid Build Coastguard Worker         lowerInt1ForSelect(T_Lo, Src0, _m1, _0);
3753*03ce13f7SAndroid Build Coastguard Worker       }
3754*03ce13f7SAndroid Build Coastguard Worker       _mov(DestLo, T_Lo);
3755*03ce13f7SAndroid Build Coastguard Worker       Variable *T_Hi = makeReg(DestHi->getType());
3756*03ce13f7SAndroid Build Coastguard Worker       if (Src0->getType() != IceType_i1) {
3757*03ce13f7SAndroid Build Coastguard Worker         _mov(T_Hi, OperandARM32FlexReg::create(Func, IceType_i32, T_Lo,
3758*03ce13f7SAndroid Build Coastguard Worker                                                OperandARM32::ASR, ShiftAmt));
3759*03ce13f7SAndroid Build Coastguard Worker       } else {
3760*03ce13f7SAndroid Build Coastguard Worker         // For i1, the asr instruction is already done above.
3761*03ce13f7SAndroid Build Coastguard Worker         _mov(T_Hi, T_Lo);
3762*03ce13f7SAndroid Build Coastguard Worker       }
3763*03ce13f7SAndroid Build Coastguard Worker       _mov(DestHi, T_Hi);
3764*03ce13f7SAndroid Build Coastguard Worker     } else if (Src0->getType() != IceType_i1) {
3765*03ce13f7SAndroid Build Coastguard Worker       // t1 = sxt src; dst = t1
3766*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R = legalizeToReg(Src0);
3767*03ce13f7SAndroid Build Coastguard Worker       Variable *T = makeReg(DestTy);
3768*03ce13f7SAndroid Build Coastguard Worker       _sxt(T, Src0R);
3769*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
3770*03ce13f7SAndroid Build Coastguard Worker     } else {
3771*03ce13f7SAndroid Build Coastguard Worker       Constant *_0 = Ctx->getConstantZero(IceType_i32);
3772*03ce13f7SAndroid Build Coastguard Worker       Operand *_m1 = Ctx->getConstantInt(DestTy, -1);
3773*03ce13f7SAndroid Build Coastguard Worker       Variable *T = makeReg(DestTy);
3774*03ce13f7SAndroid Build Coastguard Worker       lowerInt1ForSelect(T, Src0, _m1, _0);
3775*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
3776*03ce13f7SAndroid Build Coastguard Worker     }
3777*03ce13f7SAndroid Build Coastguard Worker     break;
3778*03ce13f7SAndroid Build Coastguard Worker   }
3779*03ce13f7SAndroid Build Coastguard Worker   case InstCast::Zext: {
3780*03ce13f7SAndroid Build Coastguard Worker     if (isVectorType(DestTy)) {
3781*03ce13f7SAndroid Build Coastguard Worker       auto *Mask = makeReg(DestTy);
3782*03ce13f7SAndroid Build Coastguard Worker       auto *_1 = Ctx->getConstantInt32(1);
3783*03ce13f7SAndroid Build Coastguard Worker       auto *T = makeReg(DestTy);
3784*03ce13f7SAndroid Build Coastguard Worker       auto *Src0R = legalizeToReg(Src0);
3785*03ce13f7SAndroid Build Coastguard Worker       _mov(Mask, _1);
3786*03ce13f7SAndroid Build Coastguard Worker       _vand(T, Src0R, Mask);
3787*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
3788*03ce13f7SAndroid Build Coastguard Worker     } else if (DestTy == IceType_i64) {
3789*03ce13f7SAndroid Build Coastguard Worker       // t1=uxtb src; dst.lo=t1; dst.hi=0
3790*03ce13f7SAndroid Build Coastguard Worker       Operand *_0 =
3791*03ce13f7SAndroid Build Coastguard Worker           legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex);
3792*03ce13f7SAndroid Build Coastguard Worker       auto *DestLo = llvm::cast<Variable>(loOperand(Dest));
3793*03ce13f7SAndroid Build Coastguard Worker       auto *DestHi = llvm::cast<Variable>(hiOperand(Dest));
3794*03ce13f7SAndroid Build Coastguard Worker       Variable *T_Lo = makeReg(DestLo->getType());
3795*03ce13f7SAndroid Build Coastguard Worker 
3796*03ce13f7SAndroid Build Coastguard Worker       switch (Src0->getType()) {
3797*03ce13f7SAndroid Build Coastguard Worker       default: {
3798*03ce13f7SAndroid Build Coastguard Worker         assert(Src0->getType() != IceType_i64);
3799*03ce13f7SAndroid Build Coastguard Worker         _uxt(T_Lo, legalizeToReg(Src0));
3800*03ce13f7SAndroid Build Coastguard Worker       } break;
3801*03ce13f7SAndroid Build Coastguard Worker       case IceType_i32: {
3802*03ce13f7SAndroid Build Coastguard Worker         _mov(T_Lo, legalize(Src0, Legal_Reg | Legal_Flex));
3803*03ce13f7SAndroid Build Coastguard Worker       } break;
3804*03ce13f7SAndroid Build Coastguard Worker       case IceType_i1: {
3805*03ce13f7SAndroid Build Coastguard Worker         SafeBoolChain Safe = lowerInt1(T_Lo, Src0);
3806*03ce13f7SAndroid Build Coastguard Worker         if (Safe == SBC_No) {
3807*03ce13f7SAndroid Build Coastguard Worker           Operand *_1 =
3808*03ce13f7SAndroid Build Coastguard Worker               legalize(Ctx->getConstantInt1(1), Legal_Reg | Legal_Flex);
3809*03ce13f7SAndroid Build Coastguard Worker           _and(T_Lo, T_Lo, _1);
3810*03ce13f7SAndroid Build Coastguard Worker         }
3811*03ce13f7SAndroid Build Coastguard Worker       } break;
3812*03ce13f7SAndroid Build Coastguard Worker       }
3813*03ce13f7SAndroid Build Coastguard Worker 
3814*03ce13f7SAndroid Build Coastguard Worker       _mov(DestLo, T_Lo);
3815*03ce13f7SAndroid Build Coastguard Worker 
3816*03ce13f7SAndroid Build Coastguard Worker       Variable *T_Hi = makeReg(DestLo->getType());
3817*03ce13f7SAndroid Build Coastguard Worker       _mov(T_Hi, _0);
3818*03ce13f7SAndroid Build Coastguard Worker       _mov(DestHi, T_Hi);
3819*03ce13f7SAndroid Build Coastguard Worker     } else if (Src0->getType() == IceType_i1) {
3820*03ce13f7SAndroid Build Coastguard Worker       Variable *T = makeReg(DestTy);
3821*03ce13f7SAndroid Build Coastguard Worker 
3822*03ce13f7SAndroid Build Coastguard Worker       SafeBoolChain Safe = lowerInt1(T, Src0);
3823*03ce13f7SAndroid Build Coastguard Worker       if (Safe == SBC_No) {
3824*03ce13f7SAndroid Build Coastguard Worker         Operand *_1 = legalize(Ctx->getConstantInt1(1), Legal_Reg | Legal_Flex);
3825*03ce13f7SAndroid Build Coastguard Worker         _and(T, T, _1);
3826*03ce13f7SAndroid Build Coastguard Worker       }
3827*03ce13f7SAndroid Build Coastguard Worker 
3828*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
3829*03ce13f7SAndroid Build Coastguard Worker     } else {
3830*03ce13f7SAndroid Build Coastguard Worker       // t1 = uxt src; dst = t1
3831*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R = legalizeToReg(Src0);
3832*03ce13f7SAndroid Build Coastguard Worker       Variable *T = makeReg(DestTy);
3833*03ce13f7SAndroid Build Coastguard Worker       _uxt(T, Src0R);
3834*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
3835*03ce13f7SAndroid Build Coastguard Worker     }
3836*03ce13f7SAndroid Build Coastguard Worker     break;
3837*03ce13f7SAndroid Build Coastguard Worker   }
3838*03ce13f7SAndroid Build Coastguard Worker   case InstCast::Trunc: {
3839*03ce13f7SAndroid Build Coastguard Worker     if (isVectorType(DestTy)) {
3840*03ce13f7SAndroid Build Coastguard Worker       auto *T = makeReg(DestTy);
3841*03ce13f7SAndroid Build Coastguard Worker       auto *Src0R = legalizeToReg(Src0);
3842*03ce13f7SAndroid Build Coastguard Worker       _mov(T, Src0R);
3843*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
3844*03ce13f7SAndroid Build Coastguard Worker     } else {
3845*03ce13f7SAndroid Build Coastguard Worker       if (Src0->getType() == IceType_i64)
3846*03ce13f7SAndroid Build Coastguard Worker         Src0 = loOperand(Src0);
3847*03ce13f7SAndroid Build Coastguard Worker       Operand *Src0RF = legalize(Src0, Legal_Reg | Legal_Flex);
3848*03ce13f7SAndroid Build Coastguard Worker       // t1 = trunc Src0RF; Dest = t1
3849*03ce13f7SAndroid Build Coastguard Worker       Variable *T = makeReg(DestTy);
3850*03ce13f7SAndroid Build Coastguard Worker       _mov(T, Src0RF);
3851*03ce13f7SAndroid Build Coastguard Worker       if (DestTy == IceType_i1)
3852*03ce13f7SAndroid Build Coastguard Worker         _and(T, T, Ctx->getConstantInt1(1));
3853*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
3854*03ce13f7SAndroid Build Coastguard Worker     }
3855*03ce13f7SAndroid Build Coastguard Worker     break;
3856*03ce13f7SAndroid Build Coastguard Worker   }
3857*03ce13f7SAndroid Build Coastguard Worker   case InstCast::Fptrunc:
3858*03ce13f7SAndroid Build Coastguard Worker   case InstCast::Fpext: {
3859*03ce13f7SAndroid Build Coastguard Worker     // fptrunc: dest.f32 = fptrunc src0.fp64
3860*03ce13f7SAndroid Build Coastguard Worker     // fpext: dest.f64 = fptrunc src0.fp32
3861*03ce13f7SAndroid Build Coastguard Worker     const bool IsTrunc = CastKind == InstCast::Fptrunc;
3862*03ce13f7SAndroid Build Coastguard Worker     assert(!isVectorType(DestTy));
3863*03ce13f7SAndroid Build Coastguard Worker     assert(DestTy == (IsTrunc ? IceType_f32 : IceType_f64));
3864*03ce13f7SAndroid Build Coastguard Worker     assert(Src0->getType() == (IsTrunc ? IceType_f64 : IceType_f32));
3865*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = legalizeToReg(Src0);
3866*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(DestTy);
3867*03ce13f7SAndroid Build Coastguard Worker     _vcvt(T, Src0R, IsTrunc ? InstARM32Vcvt::D2s : InstARM32Vcvt::S2d);
3868*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
3869*03ce13f7SAndroid Build Coastguard Worker     break;
3870*03ce13f7SAndroid Build Coastguard Worker   }
3871*03ce13f7SAndroid Build Coastguard Worker   case InstCast::Fptosi:
3872*03ce13f7SAndroid Build Coastguard Worker   case InstCast::Fptoui: {
3873*03ce13f7SAndroid Build Coastguard Worker     const bool DestIsSigned = CastKind == InstCast::Fptosi;
3874*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = legalizeToReg(Src0);
3875*03ce13f7SAndroid Build Coastguard Worker 
3876*03ce13f7SAndroid Build Coastguard Worker     if (isVectorType(DestTy)) {
3877*03ce13f7SAndroid Build Coastguard Worker       assert(typeElementType(Src0->getType()) == IceType_f32);
3878*03ce13f7SAndroid Build Coastguard Worker       auto *T = makeReg(DestTy);
3879*03ce13f7SAndroid Build Coastguard Worker       _vcvt(T, Src0R,
3880*03ce13f7SAndroid Build Coastguard Worker             DestIsSigned ? InstARM32Vcvt::Vs2si : InstARM32Vcvt::Vs2ui);
3881*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
3882*03ce13f7SAndroid Build Coastguard Worker       break;
3883*03ce13f7SAndroid Build Coastguard Worker     }
3884*03ce13f7SAndroid Build Coastguard Worker 
3885*03ce13f7SAndroid Build Coastguard Worker     const bool Src0IsF32 = isFloat32Asserting32Or64(Src0->getType());
3886*03ce13f7SAndroid Build Coastguard Worker     if (llvm::isa<Variable64On32>(Dest)) {
3887*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error("fp-to-i64 should have been pre-lowered.");
3888*03ce13f7SAndroid Build Coastguard Worker     }
3889*03ce13f7SAndroid Build Coastguard Worker     // fptosi:
3890*03ce13f7SAndroid Build Coastguard Worker     //     t1.fp = vcvt src0.fp
3891*03ce13f7SAndroid Build Coastguard Worker     //     t2.i32 = vmov t1.fp
3892*03ce13f7SAndroid Build Coastguard Worker     //     dest.int = conv t2.i32     @ Truncates the result if needed.
3893*03ce13f7SAndroid Build Coastguard Worker     // fptoui:
3894*03ce13f7SAndroid Build Coastguard Worker     //     t1.fp = vcvt src0.fp
3895*03ce13f7SAndroid Build Coastguard Worker     //     t2.u32 = vmov t1.fp
3896*03ce13f7SAndroid Build Coastguard Worker     //     dest.uint = conv t2.u32    @ Truncates the result if needed.
3897*03ce13f7SAndroid Build Coastguard Worker     Variable *T_fp = makeReg(IceType_f32);
3898*03ce13f7SAndroid Build Coastguard Worker     const InstARM32Vcvt::VcvtVariant Conversion =
3899*03ce13f7SAndroid Build Coastguard Worker         Src0IsF32 ? (DestIsSigned ? InstARM32Vcvt::S2si : InstARM32Vcvt::S2ui)
3900*03ce13f7SAndroid Build Coastguard Worker                   : (DestIsSigned ? InstARM32Vcvt::D2si : InstARM32Vcvt::D2ui);
3901*03ce13f7SAndroid Build Coastguard Worker     _vcvt(T_fp, Src0R, Conversion);
3902*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(IceType_i32);
3903*03ce13f7SAndroid Build Coastguard Worker     _mov(T, T_fp);
3904*03ce13f7SAndroid Build Coastguard Worker     if (DestTy != IceType_i32) {
3905*03ce13f7SAndroid Build Coastguard Worker       Variable *T_1 = makeReg(DestTy);
3906*03ce13f7SAndroid Build Coastguard Worker       lowerCast(InstCast::create(Func, InstCast::Trunc, T_1, T));
3907*03ce13f7SAndroid Build Coastguard Worker       T = T_1;
3908*03ce13f7SAndroid Build Coastguard Worker     }
3909*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
3910*03ce13f7SAndroid Build Coastguard Worker     break;
3911*03ce13f7SAndroid Build Coastguard Worker   }
3912*03ce13f7SAndroid Build Coastguard Worker   case InstCast::Sitofp:
3913*03ce13f7SAndroid Build Coastguard Worker   case InstCast::Uitofp: {
3914*03ce13f7SAndroid Build Coastguard Worker     const bool SourceIsSigned = CastKind == InstCast::Sitofp;
3915*03ce13f7SAndroid Build Coastguard Worker 
3916*03ce13f7SAndroid Build Coastguard Worker     if (isVectorType(DestTy)) {
3917*03ce13f7SAndroid Build Coastguard Worker       assert(typeElementType(DestTy) == IceType_f32);
3918*03ce13f7SAndroid Build Coastguard Worker       auto *T = makeReg(DestTy);
3919*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R = legalizeToReg(Src0);
3920*03ce13f7SAndroid Build Coastguard Worker       _vcvt(T, Src0R,
3921*03ce13f7SAndroid Build Coastguard Worker             SourceIsSigned ? InstARM32Vcvt::Vsi2s : InstARM32Vcvt::Vui2s);
3922*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
3923*03ce13f7SAndroid Build Coastguard Worker       break;
3924*03ce13f7SAndroid Build Coastguard Worker     }
3925*03ce13f7SAndroid Build Coastguard Worker 
3926*03ce13f7SAndroid Build Coastguard Worker     const bool DestIsF32 = isFloat32Asserting32Or64(DestTy);
3927*03ce13f7SAndroid Build Coastguard Worker     if (Src0->getType() == IceType_i64) {
3928*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error("i64-to-fp should have been pre-lowered.");
3929*03ce13f7SAndroid Build Coastguard Worker     }
3930*03ce13f7SAndroid Build Coastguard Worker     // sitofp:
3931*03ce13f7SAndroid Build Coastguard Worker     //     t1.i32 = sext src.int    @ sign-extends src0 if needed.
3932*03ce13f7SAndroid Build Coastguard Worker     //     t2.fp32 = vmov t1.i32
3933*03ce13f7SAndroid Build Coastguard Worker     //     t3.fp = vcvt.{fp}.s32    @ fp is either f32 or f64
3934*03ce13f7SAndroid Build Coastguard Worker     // uitofp:
3935*03ce13f7SAndroid Build Coastguard Worker     //     t1.i32 = zext src.int    @ zero-extends src0 if needed.
3936*03ce13f7SAndroid Build Coastguard Worker     //     t2.fp32 = vmov t1.i32
3937*03ce13f7SAndroid Build Coastguard Worker     //     t3.fp = vcvt.{fp}.s32    @ fp is either f32 or f64
3938*03ce13f7SAndroid Build Coastguard Worker     if (Src0->getType() != IceType_i32) {
3939*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R_32 = makeReg(IceType_i32);
3940*03ce13f7SAndroid Build Coastguard Worker       lowerCast(InstCast::create(
3941*03ce13f7SAndroid Build Coastguard Worker           Func, SourceIsSigned ? InstCast::Sext : InstCast::Zext, Src0R_32,
3942*03ce13f7SAndroid Build Coastguard Worker           Src0));
3943*03ce13f7SAndroid Build Coastguard Worker       Src0 = Src0R_32;
3944*03ce13f7SAndroid Build Coastguard Worker     }
3945*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = legalizeToReg(Src0);
3946*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R_f32 = makeReg(IceType_f32);
3947*03ce13f7SAndroid Build Coastguard Worker     _mov(Src0R_f32, Src0R);
3948*03ce13f7SAndroid Build Coastguard Worker     Src0R = Src0R_f32;
3949*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(DestTy);
3950*03ce13f7SAndroid Build Coastguard Worker     const InstARM32Vcvt::VcvtVariant Conversion =
3951*03ce13f7SAndroid Build Coastguard Worker         DestIsF32
3952*03ce13f7SAndroid Build Coastguard Worker             ? (SourceIsSigned ? InstARM32Vcvt::Si2s : InstARM32Vcvt::Ui2s)
3953*03ce13f7SAndroid Build Coastguard Worker             : (SourceIsSigned ? InstARM32Vcvt::Si2d : InstARM32Vcvt::Ui2d);
3954*03ce13f7SAndroid Build Coastguard Worker     _vcvt(T, Src0R, Conversion);
3955*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
3956*03ce13f7SAndroid Build Coastguard Worker     break;
3957*03ce13f7SAndroid Build Coastguard Worker   }
3958*03ce13f7SAndroid Build Coastguard Worker   case InstCast::Bitcast: {
3959*03ce13f7SAndroid Build Coastguard Worker     Operand *Src0 = Instr->getSrc(0);
3960*03ce13f7SAndroid Build Coastguard Worker     if (DestTy == Src0->getType()) {
3961*03ce13f7SAndroid Build Coastguard Worker       auto *Assign = InstAssign::create(Func, Dest, Src0);
3962*03ce13f7SAndroid Build Coastguard Worker       lowerAssign(Assign);
3963*03ce13f7SAndroid Build Coastguard Worker       return;
3964*03ce13f7SAndroid Build Coastguard Worker     }
3965*03ce13f7SAndroid Build Coastguard Worker     switch (DestTy) {
3966*03ce13f7SAndroid Build Coastguard Worker     case IceType_NUM:
3967*03ce13f7SAndroid Build Coastguard Worker     case IceType_void:
3968*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error("Unexpected bitcast.");
3969*03ce13f7SAndroid Build Coastguard Worker     case IceType_i1:
3970*03ce13f7SAndroid Build Coastguard Worker       UnimplementedLoweringError(this, Instr);
3971*03ce13f7SAndroid Build Coastguard Worker       break;
3972*03ce13f7SAndroid Build Coastguard Worker     case IceType_i8:
3973*03ce13f7SAndroid Build Coastguard Worker       assert(Src0->getType() == IceType_v8i1);
3974*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error(
3975*03ce13f7SAndroid Build Coastguard Worker           "i8 to v8i1 conversion should have been prelowered.");
3976*03ce13f7SAndroid Build Coastguard Worker       break;
3977*03ce13f7SAndroid Build Coastguard Worker     case IceType_i16:
3978*03ce13f7SAndroid Build Coastguard Worker       assert(Src0->getType() == IceType_v16i1);
3979*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error(
3980*03ce13f7SAndroid Build Coastguard Worker           "i16 to v16i1 conversion should have been prelowered.");
3981*03ce13f7SAndroid Build Coastguard Worker       break;
3982*03ce13f7SAndroid Build Coastguard Worker     case IceType_i32:
3983*03ce13f7SAndroid Build Coastguard Worker     case IceType_f32: {
3984*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R = legalizeToReg(Src0);
3985*03ce13f7SAndroid Build Coastguard Worker       Variable *T = makeReg(DestTy);
3986*03ce13f7SAndroid Build Coastguard Worker       _mov(T, Src0R);
3987*03ce13f7SAndroid Build Coastguard Worker       lowerAssign(InstAssign::create(Func, Dest, T));
3988*03ce13f7SAndroid Build Coastguard Worker       break;
3989*03ce13f7SAndroid Build Coastguard Worker     }
3990*03ce13f7SAndroid Build Coastguard Worker     case IceType_i64: {
3991*03ce13f7SAndroid Build Coastguard Worker       // t0, t1 <- src0
3992*03ce13f7SAndroid Build Coastguard Worker       // dest[31..0]  = t0
3993*03ce13f7SAndroid Build Coastguard Worker       // dest[63..32] = t1
3994*03ce13f7SAndroid Build Coastguard Worker       assert(Src0->getType() == IceType_f64);
3995*03ce13f7SAndroid Build Coastguard Worker       auto *T = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64));
3996*03ce13f7SAndroid Build Coastguard Worker       T->initHiLo(Func);
3997*03ce13f7SAndroid Build Coastguard Worker       configureBitcastTemporary(T);
3998*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R = legalizeToReg(Src0);
3999*03ce13f7SAndroid Build Coastguard Worker       _mov(T, Src0R);
4000*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeUse>(T->getHi());
4001*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeUse>(T->getLo());
4002*03ce13f7SAndroid Build Coastguard Worker       lowerAssign(InstAssign::create(Func, Dest, T));
4003*03ce13f7SAndroid Build Coastguard Worker       break;
4004*03ce13f7SAndroid Build Coastguard Worker     }
4005*03ce13f7SAndroid Build Coastguard Worker     case IceType_f64: {
4006*03ce13f7SAndroid Build Coastguard Worker       // T0 <- lo(src)
4007*03ce13f7SAndroid Build Coastguard Worker       // T1 <- hi(src)
4008*03ce13f7SAndroid Build Coastguard Worker       // vmov T2, T0, T1
4009*03ce13f7SAndroid Build Coastguard Worker       // Dest <- T2
4010*03ce13f7SAndroid Build Coastguard Worker       assert(Src0->getType() == IceType_i64);
4011*03ce13f7SAndroid Build Coastguard Worker       Variable *T = makeReg(DestTy);
4012*03ce13f7SAndroid Build Coastguard Worker       auto *Src64 = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64));
4013*03ce13f7SAndroid Build Coastguard Worker       Src64->initHiLo(Func);
4014*03ce13f7SAndroid Build Coastguard Worker       configureBitcastTemporary(Src64);
4015*03ce13f7SAndroid Build Coastguard Worker       lowerAssign(InstAssign::create(Func, Src64, Src0));
4016*03ce13f7SAndroid Build Coastguard Worker       _mov(T, Src64);
4017*03ce13f7SAndroid Build Coastguard Worker       lowerAssign(InstAssign::create(Func, Dest, T));
4018*03ce13f7SAndroid Build Coastguard Worker       break;
4019*03ce13f7SAndroid Build Coastguard Worker     }
4020*03ce13f7SAndroid Build Coastguard Worker     case IceType_v8i1:
4021*03ce13f7SAndroid Build Coastguard Worker       assert(Src0->getType() == IceType_i8);
4022*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error(
4023*03ce13f7SAndroid Build Coastguard Worker           "v8i1 to i8 conversion should have been prelowered.");
4024*03ce13f7SAndroid Build Coastguard Worker       break;
4025*03ce13f7SAndroid Build Coastguard Worker     case IceType_v16i1:
4026*03ce13f7SAndroid Build Coastguard Worker       assert(Src0->getType() == IceType_i16);
4027*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error(
4028*03ce13f7SAndroid Build Coastguard Worker           "v16i1 to i16 conversion should have been prelowered.");
4029*03ce13f7SAndroid Build Coastguard Worker       break;
4030*03ce13f7SAndroid Build Coastguard Worker     case IceType_v4i1:
4031*03ce13f7SAndroid Build Coastguard Worker     case IceType_v8i16:
4032*03ce13f7SAndroid Build Coastguard Worker     case IceType_v16i8:
4033*03ce13f7SAndroid Build Coastguard Worker     case IceType_v4f32:
4034*03ce13f7SAndroid Build Coastguard Worker     case IceType_v4i32: {
4035*03ce13f7SAndroid Build Coastguard Worker       assert(typeWidthInBytes(DestTy) == typeWidthInBytes(Src0->getType()));
4036*03ce13f7SAndroid Build Coastguard Worker       assert(isVectorType(DestTy) == isVectorType(Src0->getType()));
4037*03ce13f7SAndroid Build Coastguard Worker       Variable *T = makeReg(DestTy);
4038*03ce13f7SAndroid Build Coastguard Worker       _mov(T, Src0);
4039*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
4040*03ce13f7SAndroid Build Coastguard Worker       break;
4041*03ce13f7SAndroid Build Coastguard Worker     }
4042*03ce13f7SAndroid Build Coastguard Worker     }
4043*03ce13f7SAndroid Build Coastguard Worker     break;
4044*03ce13f7SAndroid Build Coastguard Worker   }
4045*03ce13f7SAndroid Build Coastguard Worker   }
4046*03ce13f7SAndroid Build Coastguard Worker }
4047*03ce13f7SAndroid Build Coastguard Worker 
lowerExtractElement(const InstExtractElement * Instr)4048*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerExtractElement(const InstExtractElement *Instr) {
4049*03ce13f7SAndroid Build Coastguard Worker   Variable *Dest = Instr->getDest();
4050*03ce13f7SAndroid Build Coastguard Worker   Type DestTy = Dest->getType();
4051*03ce13f7SAndroid Build Coastguard Worker 
4052*03ce13f7SAndroid Build Coastguard Worker   Variable *Src0 = legalizeToReg(Instr->getSrc(0));
4053*03ce13f7SAndroid Build Coastguard Worker   Operand *Src1 = Instr->getSrc(1);
4054*03ce13f7SAndroid Build Coastguard Worker 
4055*03ce13f7SAndroid Build Coastguard Worker   if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src1)) {
4056*03ce13f7SAndroid Build Coastguard Worker     const uint32_t Index = Imm->getValue();
4057*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(DestTy);
4058*03ce13f7SAndroid Build Coastguard Worker     Variable *TSrc0 = makeReg(Src0->getType());
4059*03ce13f7SAndroid Build Coastguard Worker 
4060*03ce13f7SAndroid Build Coastguard Worker     if (isFloatingType(DestTy)) {
4061*03ce13f7SAndroid Build Coastguard Worker       // We need to make sure the source is in a suitable register.
4062*03ce13f7SAndroid Build Coastguard Worker       TSrc0->setRegClass(RegARM32::RCARM32_QtoS);
4063*03ce13f7SAndroid Build Coastguard Worker     }
4064*03ce13f7SAndroid Build Coastguard Worker 
4065*03ce13f7SAndroid Build Coastguard Worker     _mov(TSrc0, Src0);
4066*03ce13f7SAndroid Build Coastguard Worker     _extractelement(T, TSrc0, Index);
4067*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
4068*03ce13f7SAndroid Build Coastguard Worker     return;
4069*03ce13f7SAndroid Build Coastguard Worker   }
4070*03ce13f7SAndroid Build Coastguard Worker   assert(false && "extractelement requires a constant index");
4071*03ce13f7SAndroid Build Coastguard Worker }
4072*03ce13f7SAndroid Build Coastguard Worker 
4073*03ce13f7SAndroid Build Coastguard Worker namespace {
4074*03ce13f7SAndroid Build Coastguard Worker // Validates FCMPARM32_TABLE's declaration w.r.t. InstFcmp::FCondition ordering
4075*03ce13f7SAndroid Build Coastguard Worker // (and naming).
4076*03ce13f7SAndroid Build Coastguard Worker enum {
4077*03ce13f7SAndroid Build Coastguard Worker #define X(val, CC0, CC1, CC0_V, CC1_V, INV_V, NEG_V) _fcmp_ll_##val,
4078*03ce13f7SAndroid Build Coastguard Worker   FCMPARM32_TABLE
4079*03ce13f7SAndroid Build Coastguard Worker #undef X
4080*03ce13f7SAndroid Build Coastguard Worker       _fcmp_ll_NUM
4081*03ce13f7SAndroid Build Coastguard Worker };
4082*03ce13f7SAndroid Build Coastguard Worker 
4083*03ce13f7SAndroid Build Coastguard Worker enum {
4084*03ce13f7SAndroid Build Coastguard Worker #define X(tag, str) _fcmp_hl_##tag = InstFcmp::tag,
4085*03ce13f7SAndroid Build Coastguard Worker   ICEINSTFCMP_TABLE
4086*03ce13f7SAndroid Build Coastguard Worker #undef X
4087*03ce13f7SAndroid Build Coastguard Worker       _fcmp_hl_NUM
4088*03ce13f7SAndroid Build Coastguard Worker };
4089*03ce13f7SAndroid Build Coastguard Worker 
4090*03ce13f7SAndroid Build Coastguard Worker static_assert((uint32_t)_fcmp_hl_NUM == (uint32_t)_fcmp_ll_NUM,
4091*03ce13f7SAndroid Build Coastguard Worker               "Inconsistency between high-level and low-level fcmp tags.");
4092*03ce13f7SAndroid Build Coastguard Worker #define X(tag, str)                                                            \
4093*03ce13f7SAndroid Build Coastguard Worker   static_assert(                                                               \
4094*03ce13f7SAndroid Build Coastguard Worker       (uint32_t)_fcmp_hl_##tag == (uint32_t)_fcmp_ll_##tag,                    \
4095*03ce13f7SAndroid Build Coastguard Worker       "Inconsistency between high-level and low-level fcmp tag " #tag);
4096*03ce13f7SAndroid Build Coastguard Worker ICEINSTFCMP_TABLE
4097*03ce13f7SAndroid Build Coastguard Worker #undef X
4098*03ce13f7SAndroid Build Coastguard Worker 
4099*03ce13f7SAndroid Build Coastguard Worker struct {
4100*03ce13f7SAndroid Build Coastguard Worker   CondARM32::Cond CC0;
4101*03ce13f7SAndroid Build Coastguard Worker   CondARM32::Cond CC1;
4102*03ce13f7SAndroid Build Coastguard Worker } TableFcmp[] = {
4103*03ce13f7SAndroid Build Coastguard Worker #define X(val, CC0, CC1, CC0_V, CC1_V, INV_V, NEG_V)                           \
4104*03ce13f7SAndroid Build Coastguard Worker   {CondARM32::CC0, CondARM32::CC1},
4105*03ce13f7SAndroid Build Coastguard Worker     FCMPARM32_TABLE
4106*03ce13f7SAndroid Build Coastguard Worker #undef X
4107*03ce13f7SAndroid Build Coastguard Worker };
4108*03ce13f7SAndroid Build Coastguard Worker 
isFloatingPointZero(const Operand * Src)4109*03ce13f7SAndroid Build Coastguard Worker bool isFloatingPointZero(const Operand *Src) {
4110*03ce13f7SAndroid Build Coastguard Worker   if (const auto *F32 = llvm::dyn_cast<const ConstantFloat>(Src)) {
4111*03ce13f7SAndroid Build Coastguard Worker     return Utils::isPositiveZero(F32->getValue());
4112*03ce13f7SAndroid Build Coastguard Worker   }
4113*03ce13f7SAndroid Build Coastguard Worker 
4114*03ce13f7SAndroid Build Coastguard Worker   if (const auto *F64 = llvm::dyn_cast<const ConstantDouble>(Src)) {
4115*03ce13f7SAndroid Build Coastguard Worker     return Utils::isPositiveZero(F64->getValue());
4116*03ce13f7SAndroid Build Coastguard Worker   }
4117*03ce13f7SAndroid Build Coastguard Worker 
4118*03ce13f7SAndroid Build Coastguard Worker   return false;
4119*03ce13f7SAndroid Build Coastguard Worker }
4120*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
4121*03ce13f7SAndroid Build Coastguard Worker 
lowerFcmpCond(const InstFcmp * Instr)4122*03ce13f7SAndroid Build Coastguard Worker TargetARM32::CondWhenTrue TargetARM32::lowerFcmpCond(const InstFcmp *Instr) {
4123*03ce13f7SAndroid Build Coastguard Worker   InstFcmp::FCond Condition = Instr->getCondition();
4124*03ce13f7SAndroid Build Coastguard Worker   switch (Condition) {
4125*03ce13f7SAndroid Build Coastguard Worker   case InstFcmp::False:
4126*03ce13f7SAndroid Build Coastguard Worker     return CondWhenTrue(CondARM32::kNone);
4127*03ce13f7SAndroid Build Coastguard Worker   case InstFcmp::True:
4128*03ce13f7SAndroid Build Coastguard Worker     return CondWhenTrue(CondARM32::AL);
4129*03ce13f7SAndroid Build Coastguard Worker     break;
4130*03ce13f7SAndroid Build Coastguard Worker   default: {
4131*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = legalizeToReg(Instr->getSrc(0));
4132*03ce13f7SAndroid Build Coastguard Worker     Operand *Src1 = Instr->getSrc(1);
4133*03ce13f7SAndroid Build Coastguard Worker     if (isFloatingPointZero(Src1)) {
4134*03ce13f7SAndroid Build Coastguard Worker       _vcmp(Src0R, OperandARM32FlexFpZero::create(Func, Src0R->getType()));
4135*03ce13f7SAndroid Build Coastguard Worker     } else {
4136*03ce13f7SAndroid Build Coastguard Worker       _vcmp(Src0R, legalizeToReg(Src1));
4137*03ce13f7SAndroid Build Coastguard Worker     }
4138*03ce13f7SAndroid Build Coastguard Worker     _vmrs();
4139*03ce13f7SAndroid Build Coastguard Worker     assert(Condition < llvm::array_lengthof(TableFcmp));
4140*03ce13f7SAndroid Build Coastguard Worker     return CondWhenTrue(TableFcmp[Condition].CC0, TableFcmp[Condition].CC1);
4141*03ce13f7SAndroid Build Coastguard Worker   }
4142*03ce13f7SAndroid Build Coastguard Worker   }
4143*03ce13f7SAndroid Build Coastguard Worker }
4144*03ce13f7SAndroid Build Coastguard Worker 
lowerFcmp(const InstFcmp * Instr)4145*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerFcmp(const InstFcmp *Instr) {
4146*03ce13f7SAndroid Build Coastguard Worker   Variable *Dest = Instr->getDest();
4147*03ce13f7SAndroid Build Coastguard Worker   const Type DestTy = Dest->getType();
4148*03ce13f7SAndroid Build Coastguard Worker 
4149*03ce13f7SAndroid Build Coastguard Worker   if (isVectorType(DestTy)) {
4150*03ce13f7SAndroid Build Coastguard Worker     if (Instr->getCondition() == InstFcmp::False) {
4151*03ce13f7SAndroid Build Coastguard Worker       constexpr Type SafeTypeForMovingConstant = IceType_v4i32;
4152*03ce13f7SAndroid Build Coastguard Worker       auto *T = makeReg(SafeTypeForMovingConstant);
4153*03ce13f7SAndroid Build Coastguard Worker       _mov(T, llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(0)));
4154*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
4155*03ce13f7SAndroid Build Coastguard Worker       return;
4156*03ce13f7SAndroid Build Coastguard Worker     }
4157*03ce13f7SAndroid Build Coastguard Worker 
4158*03ce13f7SAndroid Build Coastguard Worker     if (Instr->getCondition() == InstFcmp::True) {
4159*03ce13f7SAndroid Build Coastguard Worker       constexpr Type SafeTypeForMovingConstant = IceType_v4i32;
4160*03ce13f7SAndroid Build Coastguard Worker       auto *T = makeReg(SafeTypeForMovingConstant);
4161*03ce13f7SAndroid Build Coastguard Worker       _mov(T, llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(1)));
4162*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
4163*03ce13f7SAndroid Build Coastguard Worker       return;
4164*03ce13f7SAndroid Build Coastguard Worker     }
4165*03ce13f7SAndroid Build Coastguard Worker 
4166*03ce13f7SAndroid Build Coastguard Worker     Variable *T0;
4167*03ce13f7SAndroid Build Coastguard Worker     Variable *T1;
4168*03ce13f7SAndroid Build Coastguard Worker     bool Negate = false;
4169*03ce13f7SAndroid Build Coastguard Worker     auto *Src0 = legalizeToReg(Instr->getSrc(0));
4170*03ce13f7SAndroid Build Coastguard Worker     auto *Src1 = legalizeToReg(Instr->getSrc(1));
4171*03ce13f7SAndroid Build Coastguard Worker 
4172*03ce13f7SAndroid Build Coastguard Worker     switch (Instr->getCondition()) {
4173*03ce13f7SAndroid Build Coastguard Worker     default:
4174*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error("Unhandled fp comparison.");
4175*03ce13f7SAndroid Build Coastguard Worker #define _Vcnone(Tptr, S0, S1)                                                  \
4176*03ce13f7SAndroid Build Coastguard Worker   do {                                                                         \
4177*03ce13f7SAndroid Build Coastguard Worker     *(Tptr) = nullptr;                                                         \
4178*03ce13f7SAndroid Build Coastguard Worker   } while (0)
4179*03ce13f7SAndroid Build Coastguard Worker #define _Vceq(Tptr, S0, S1)                                                    \
4180*03ce13f7SAndroid Build Coastguard Worker   do {                                                                         \
4181*03ce13f7SAndroid Build Coastguard Worker     *(Tptr) = makeReg(DestTy);                                                 \
4182*03ce13f7SAndroid Build Coastguard Worker     _vceq(*(Tptr), S0, S1);                                                    \
4183*03ce13f7SAndroid Build Coastguard Worker   } while (0)
4184*03ce13f7SAndroid Build Coastguard Worker #define _Vcge(Tptr, S0, S1)                                                    \
4185*03ce13f7SAndroid Build Coastguard Worker   do {                                                                         \
4186*03ce13f7SAndroid Build Coastguard Worker     *(Tptr) = makeReg(DestTy);                                                 \
4187*03ce13f7SAndroid Build Coastguard Worker     _vcge(*(Tptr), S0, S1)->setSignType(InstARM32::FS_Signed);                 \
4188*03ce13f7SAndroid Build Coastguard Worker   } while (0)
4189*03ce13f7SAndroid Build Coastguard Worker #define _Vcgt(Tptr, S0, S1)                                                    \
4190*03ce13f7SAndroid Build Coastguard Worker   do {                                                                         \
4191*03ce13f7SAndroid Build Coastguard Worker     *(Tptr) = makeReg(DestTy);                                                 \
4192*03ce13f7SAndroid Build Coastguard Worker     _vcgt(*(Tptr), S0, S1)->setSignType(InstARM32::FS_Signed);                 \
4193*03ce13f7SAndroid Build Coastguard Worker   } while (0)
4194*03ce13f7SAndroid Build Coastguard Worker #define X(val, CC0, CC1, CC0_V, CC1_V, INV_V, NEG_V)                           \
4195*03ce13f7SAndroid Build Coastguard Worker   case InstFcmp::val: {                                                        \
4196*03ce13f7SAndroid Build Coastguard Worker     _Vc##CC0_V(&T0, (INV_V) ? Src1 : Src0, (INV_V) ? Src0 : Src1);             \
4197*03ce13f7SAndroid Build Coastguard Worker     _Vc##CC1_V(&T1, (INV_V) ? Src0 : Src1, (INV_V) ? Src1 : Src0);             \
4198*03ce13f7SAndroid Build Coastguard Worker     Negate = NEG_V;                                                            \
4199*03ce13f7SAndroid Build Coastguard Worker   } break;
4200*03ce13f7SAndroid Build Coastguard Worker       FCMPARM32_TABLE
4201*03ce13f7SAndroid Build Coastguard Worker #undef X
4202*03ce13f7SAndroid Build Coastguard Worker #undef _Vcgt
4203*03ce13f7SAndroid Build Coastguard Worker #undef _Vcge
4204*03ce13f7SAndroid Build Coastguard Worker #undef _Vceq
4205*03ce13f7SAndroid Build Coastguard Worker #undef _Vcnone
4206*03ce13f7SAndroid Build Coastguard Worker     }
4207*03ce13f7SAndroid Build Coastguard Worker     assert(T0 != nullptr);
4208*03ce13f7SAndroid Build Coastguard Worker     Variable *T = T0;
4209*03ce13f7SAndroid Build Coastguard Worker     if (T1 != nullptr) {
4210*03ce13f7SAndroid Build Coastguard Worker       T = makeReg(DestTy);
4211*03ce13f7SAndroid Build Coastguard Worker       _vorr(T, T0, T1);
4212*03ce13f7SAndroid Build Coastguard Worker     }
4213*03ce13f7SAndroid Build Coastguard Worker 
4214*03ce13f7SAndroid Build Coastguard Worker     if (Negate) {
4215*03ce13f7SAndroid Build Coastguard Worker       auto *TNeg = makeReg(DestTy);
4216*03ce13f7SAndroid Build Coastguard Worker       _vmvn(TNeg, T);
4217*03ce13f7SAndroid Build Coastguard Worker       T = TNeg;
4218*03ce13f7SAndroid Build Coastguard Worker     }
4219*03ce13f7SAndroid Build Coastguard Worker 
4220*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
4221*03ce13f7SAndroid Build Coastguard Worker     return;
4222*03ce13f7SAndroid Build Coastguard Worker   }
4223*03ce13f7SAndroid Build Coastguard Worker 
4224*03ce13f7SAndroid Build Coastguard Worker   Variable *T = makeReg(IceType_i1);
4225*03ce13f7SAndroid Build Coastguard Worker   Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex);
4226*03ce13f7SAndroid Build Coastguard Worker   Operand *_0 =
4227*03ce13f7SAndroid Build Coastguard Worker       legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex);
4228*03ce13f7SAndroid Build Coastguard Worker 
4229*03ce13f7SAndroid Build Coastguard Worker   CondWhenTrue Cond = lowerFcmpCond(Instr);
4230*03ce13f7SAndroid Build Coastguard Worker 
4231*03ce13f7SAndroid Build Coastguard Worker   bool RedefineT = false;
4232*03ce13f7SAndroid Build Coastguard Worker   if (Cond.WhenTrue0 != CondARM32::AL) {
4233*03ce13f7SAndroid Build Coastguard Worker     _mov(T, _0);
4234*03ce13f7SAndroid Build Coastguard Worker     RedefineT = true;
4235*03ce13f7SAndroid Build Coastguard Worker   }
4236*03ce13f7SAndroid Build Coastguard Worker 
4237*03ce13f7SAndroid Build Coastguard Worker   if (Cond.WhenTrue0 == CondARM32::kNone) {
4238*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
4239*03ce13f7SAndroid Build Coastguard Worker     return;
4240*03ce13f7SAndroid Build Coastguard Worker   }
4241*03ce13f7SAndroid Build Coastguard Worker 
4242*03ce13f7SAndroid Build Coastguard Worker   if (RedefineT) {
4243*03ce13f7SAndroid Build Coastguard Worker     _mov_redefined(T, _1, Cond.WhenTrue0);
4244*03ce13f7SAndroid Build Coastguard Worker   } else {
4245*03ce13f7SAndroid Build Coastguard Worker     _mov(T, _1, Cond.WhenTrue0);
4246*03ce13f7SAndroid Build Coastguard Worker   }
4247*03ce13f7SAndroid Build Coastguard Worker 
4248*03ce13f7SAndroid Build Coastguard Worker   if (Cond.WhenTrue1 != CondARM32::kNone) {
4249*03ce13f7SAndroid Build Coastguard Worker     _mov_redefined(T, _1, Cond.WhenTrue1);
4250*03ce13f7SAndroid Build Coastguard Worker   }
4251*03ce13f7SAndroid Build Coastguard Worker 
4252*03ce13f7SAndroid Build Coastguard Worker   _mov(Dest, T);
4253*03ce13f7SAndroid Build Coastguard Worker }
4254*03ce13f7SAndroid Build Coastguard Worker 
4255*03ce13f7SAndroid Build Coastguard Worker TargetARM32::CondWhenTrue
lowerInt64IcmpCond(InstIcmp::ICond Condition,Operand * Src0,Operand * Src1)4256*03ce13f7SAndroid Build Coastguard Worker TargetARM32::lowerInt64IcmpCond(InstIcmp::ICond Condition, Operand *Src0,
4257*03ce13f7SAndroid Build Coastguard Worker                                 Operand *Src1) {
4258*03ce13f7SAndroid Build Coastguard Worker   assert(Condition < llvm::array_lengthof(TableIcmp64));
4259*03ce13f7SAndroid Build Coastguard Worker 
4260*03ce13f7SAndroid Build Coastguard Worker   Int32Operands SrcsLo(loOperand(Src0), loOperand(Src1));
4261*03ce13f7SAndroid Build Coastguard Worker   Int32Operands SrcsHi(hiOperand(Src0), hiOperand(Src1));
4262*03ce13f7SAndroid Build Coastguard Worker   assert(SrcsLo.hasConstOperand() == SrcsHi.hasConstOperand());
4263*03ce13f7SAndroid Build Coastguard Worker   assert(SrcsLo.swappedOperands() == SrcsHi.swappedOperands());
4264*03ce13f7SAndroid Build Coastguard Worker 
4265*03ce13f7SAndroid Build Coastguard Worker   if (SrcsLo.hasConstOperand()) {
4266*03ce13f7SAndroid Build Coastguard Worker     const uint32_t ValueLo = SrcsLo.getConstantValue();
4267*03ce13f7SAndroid Build Coastguard Worker     const uint32_t ValueHi = SrcsHi.getConstantValue();
4268*03ce13f7SAndroid Build Coastguard Worker     const uint64_t Value = (static_cast<uint64_t>(ValueHi) << 32) | ValueLo;
4269*03ce13f7SAndroid Build Coastguard Worker     if ((Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) &&
4270*03ce13f7SAndroid Build Coastguard Worker         Value == 0) {
4271*03ce13f7SAndroid Build Coastguard Worker       Variable *T = makeReg(IceType_i32);
4272*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0LoR = SrcsLo.src0R(this);
4273*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0HiR = SrcsHi.src0R(this);
4274*03ce13f7SAndroid Build Coastguard Worker       _orrs(T, Src0LoR, Src0HiR);
4275*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeUse>(T);
4276*03ce13f7SAndroid Build Coastguard Worker       return CondWhenTrue(TableIcmp64[Condition].C1);
4277*03ce13f7SAndroid Build Coastguard Worker     }
4278*03ce13f7SAndroid Build Coastguard Worker 
4279*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0RLo = SrcsLo.src0R(this);
4280*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0RHi = SrcsHi.src0R(this);
4281*03ce13f7SAndroid Build Coastguard Worker     Operand *Src1RFLo = SrcsLo.src1RF(this);
4282*03ce13f7SAndroid Build Coastguard Worker     Operand *Src1RFHi = ValueLo == ValueHi ? Src1RFLo : SrcsHi.src1RF(this);
4283*03ce13f7SAndroid Build Coastguard Worker 
4284*03ce13f7SAndroid Build Coastguard Worker     const bool UseRsb =
4285*03ce13f7SAndroid Build Coastguard Worker         TableIcmp64[Condition].Swapped != SrcsLo.swappedOperands();
4286*03ce13f7SAndroid Build Coastguard Worker 
4287*03ce13f7SAndroid Build Coastguard Worker     if (UseRsb) {
4288*03ce13f7SAndroid Build Coastguard Worker       if (TableIcmp64[Condition].IsSigned) {
4289*03ce13f7SAndroid Build Coastguard Worker         Variable *T = makeReg(IceType_i32);
4290*03ce13f7SAndroid Build Coastguard Worker         _rsbs(T, Src0RLo, Src1RFLo);
4291*03ce13f7SAndroid Build Coastguard Worker         Context.insert<InstFakeUse>(T);
4292*03ce13f7SAndroid Build Coastguard Worker 
4293*03ce13f7SAndroid Build Coastguard Worker         T = makeReg(IceType_i32);
4294*03ce13f7SAndroid Build Coastguard Worker         _rscs(T, Src0RHi, Src1RFHi);
4295*03ce13f7SAndroid Build Coastguard Worker         // We need to add a FakeUse here because liveness gets mad at us (Def
4296*03ce13f7SAndroid Build Coastguard Worker         // without Use.) Note that flag-setting instructions are considered to
4297*03ce13f7SAndroid Build Coastguard Worker         // have side effects and, therefore, are not DCE'ed.
4298*03ce13f7SAndroid Build Coastguard Worker         Context.insert<InstFakeUse>(T);
4299*03ce13f7SAndroid Build Coastguard Worker       } else {
4300*03ce13f7SAndroid Build Coastguard Worker         Variable *T = makeReg(IceType_i32);
4301*03ce13f7SAndroid Build Coastguard Worker         _rsbs(T, Src0RHi, Src1RFHi);
4302*03ce13f7SAndroid Build Coastguard Worker         Context.insert<InstFakeUse>(T);
4303*03ce13f7SAndroid Build Coastguard Worker 
4304*03ce13f7SAndroid Build Coastguard Worker         T = makeReg(IceType_i32);
4305*03ce13f7SAndroid Build Coastguard Worker         _rsbs(T, Src0RLo, Src1RFLo, CondARM32::EQ);
4306*03ce13f7SAndroid Build Coastguard Worker         Context.insert<InstFakeUse>(T);
4307*03ce13f7SAndroid Build Coastguard Worker       }
4308*03ce13f7SAndroid Build Coastguard Worker     } else {
4309*03ce13f7SAndroid Build Coastguard Worker       if (TableIcmp64[Condition].IsSigned) {
4310*03ce13f7SAndroid Build Coastguard Worker         _cmp(Src0RLo, Src1RFLo);
4311*03ce13f7SAndroid Build Coastguard Worker         Variable *T = makeReg(IceType_i32);
4312*03ce13f7SAndroid Build Coastguard Worker         _sbcs(T, Src0RHi, Src1RFHi);
4313*03ce13f7SAndroid Build Coastguard Worker         Context.insert<InstFakeUse>(T);
4314*03ce13f7SAndroid Build Coastguard Worker       } else {
4315*03ce13f7SAndroid Build Coastguard Worker         _cmp(Src0RHi, Src1RFHi);
4316*03ce13f7SAndroid Build Coastguard Worker         _cmp(Src0RLo, Src1RFLo, CondARM32::EQ);
4317*03ce13f7SAndroid Build Coastguard Worker       }
4318*03ce13f7SAndroid Build Coastguard Worker     }
4319*03ce13f7SAndroid Build Coastguard Worker 
4320*03ce13f7SAndroid Build Coastguard Worker     return CondWhenTrue(TableIcmp64[Condition].C1);
4321*03ce13f7SAndroid Build Coastguard Worker   }
4322*03ce13f7SAndroid Build Coastguard Worker 
4323*03ce13f7SAndroid Build Coastguard Worker   Variable *Src0RLo, *Src0RHi;
4324*03ce13f7SAndroid Build Coastguard Worker   Operand *Src1RFLo, *Src1RFHi;
4325*03ce13f7SAndroid Build Coastguard Worker   if (TableIcmp64[Condition].Swapped) {
4326*03ce13f7SAndroid Build Coastguard Worker     Src0RLo = legalizeToReg(loOperand(Src1));
4327*03ce13f7SAndroid Build Coastguard Worker     Src0RHi = legalizeToReg(hiOperand(Src1));
4328*03ce13f7SAndroid Build Coastguard Worker     Src1RFLo = legalizeToReg(loOperand(Src0));
4329*03ce13f7SAndroid Build Coastguard Worker     Src1RFHi = legalizeToReg(hiOperand(Src0));
4330*03ce13f7SAndroid Build Coastguard Worker   } else {
4331*03ce13f7SAndroid Build Coastguard Worker     Src0RLo = legalizeToReg(loOperand(Src0));
4332*03ce13f7SAndroid Build Coastguard Worker     Src0RHi = legalizeToReg(hiOperand(Src0));
4333*03ce13f7SAndroid Build Coastguard Worker     Src1RFLo = legalizeToReg(loOperand(Src1));
4334*03ce13f7SAndroid Build Coastguard Worker     Src1RFHi = legalizeToReg(hiOperand(Src1));
4335*03ce13f7SAndroid Build Coastguard Worker   }
4336*03ce13f7SAndroid Build Coastguard Worker 
4337*03ce13f7SAndroid Build Coastguard Worker   // a=icmp cond, b, c ==>
4338*03ce13f7SAndroid Build Coastguard Worker   // GCC does:
4339*03ce13f7SAndroid Build Coastguard Worker   //   cmp      b.hi, c.hi     or  cmp      b.lo, c.lo
4340*03ce13f7SAndroid Build Coastguard Worker   //   cmp.eq   b.lo, c.lo         sbcs t1, b.hi, c.hi
4341*03ce13f7SAndroid Build Coastguard Worker   //   mov.<C1> t, #1              mov.<C1> t, #1
4342*03ce13f7SAndroid Build Coastguard Worker   //   mov.<C2> t, #0              mov.<C2> t, #0
4343*03ce13f7SAndroid Build Coastguard Worker   //   mov      a, t               mov      a, t
4344*03ce13f7SAndroid Build Coastguard Worker   // where the "cmp.eq b.lo, c.lo" is used for unsigned and "sbcs t1, hi, hi"
4345*03ce13f7SAndroid Build Coastguard Worker   // is used for signed compares. In some cases, b and c need to be swapped as
4346*03ce13f7SAndroid Build Coastguard Worker   // well.
4347*03ce13f7SAndroid Build Coastguard Worker   //
4348*03ce13f7SAndroid Build Coastguard Worker   // LLVM does:
4349*03ce13f7SAndroid Build Coastguard Worker   // for EQ and NE:
4350*03ce13f7SAndroid Build Coastguard Worker   //   eor  t1, b.hi, c.hi
4351*03ce13f7SAndroid Build Coastguard Worker   //   eor  t2, b.lo, c.hi
4352*03ce13f7SAndroid Build Coastguard Worker   //   orrs t, t1, t2
4353*03ce13f7SAndroid Build Coastguard Worker   //   mov.<C> t, #1
4354*03ce13f7SAndroid Build Coastguard Worker   //   mov  a, t
4355*03ce13f7SAndroid Build Coastguard Worker   //
4356*03ce13f7SAndroid Build Coastguard Worker   // that's nice in that it's just as short but has fewer dependencies for
4357*03ce13f7SAndroid Build Coastguard Worker   // better ILP at the cost of more registers.
4358*03ce13f7SAndroid Build Coastguard Worker   //
4359*03ce13f7SAndroid Build Coastguard Worker   // Otherwise for signed/unsigned <, <=, etc. LLVM uses a sequence with two
4360*03ce13f7SAndroid Build Coastguard Worker   // unconditional mov #0, two cmps, two conditional mov #1, and one
4361*03ce13f7SAndroid Build Coastguard Worker   // conditional reg mov. That has few dependencies for good ILP, but is a
4362*03ce13f7SAndroid Build Coastguard Worker   // longer sequence.
4363*03ce13f7SAndroid Build Coastguard Worker   //
4364*03ce13f7SAndroid Build Coastguard Worker   // So, we are going with the GCC version since it's usually better (except
4365*03ce13f7SAndroid Build Coastguard Worker   // perhaps for eq/ne). We could revisit special-casing eq/ne later.
4366*03ce13f7SAndroid Build Coastguard Worker   if (TableIcmp64[Condition].IsSigned) {
4367*03ce13f7SAndroid Build Coastguard Worker     Variable *ScratchReg = makeReg(IceType_i32);
4368*03ce13f7SAndroid Build Coastguard Worker     _cmp(Src0RLo, Src1RFLo);
4369*03ce13f7SAndroid Build Coastguard Worker     _sbcs(ScratchReg, Src0RHi, Src1RFHi);
4370*03ce13f7SAndroid Build Coastguard Worker     // ScratchReg isn't going to be used, but we need the side-effect of
4371*03ce13f7SAndroid Build Coastguard Worker     // setting flags from this operation.
4372*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(ScratchReg);
4373*03ce13f7SAndroid Build Coastguard Worker   } else {
4374*03ce13f7SAndroid Build Coastguard Worker     _cmp(Src0RHi, Src1RFHi);
4375*03ce13f7SAndroid Build Coastguard Worker     _cmp(Src0RLo, Src1RFLo, CondARM32::EQ);
4376*03ce13f7SAndroid Build Coastguard Worker   }
4377*03ce13f7SAndroid Build Coastguard Worker   return CondWhenTrue(TableIcmp64[Condition].C1);
4378*03ce13f7SAndroid Build Coastguard Worker }
4379*03ce13f7SAndroid Build Coastguard Worker 
4380*03ce13f7SAndroid Build Coastguard Worker TargetARM32::CondWhenTrue
lowerInt32IcmpCond(InstIcmp::ICond Condition,Operand * Src0,Operand * Src1)4381*03ce13f7SAndroid Build Coastguard Worker TargetARM32::lowerInt32IcmpCond(InstIcmp::ICond Condition, Operand *Src0,
4382*03ce13f7SAndroid Build Coastguard Worker                                 Operand *Src1) {
4383*03ce13f7SAndroid Build Coastguard Worker   Int32Operands Srcs(Src0, Src1);
4384*03ce13f7SAndroid Build Coastguard Worker   if (!Srcs.hasConstOperand()) {
4385*03ce13f7SAndroid Build Coastguard Worker 
4386*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = Srcs.src0R(this);
4387*03ce13f7SAndroid Build Coastguard Worker     Operand *Src1RF = Srcs.src1RF(this);
4388*03ce13f7SAndroid Build Coastguard Worker     _cmp(Src0R, Src1RF);
4389*03ce13f7SAndroid Build Coastguard Worker     return CondWhenTrue(getIcmp32Mapping(Condition));
4390*03ce13f7SAndroid Build Coastguard Worker   }
4391*03ce13f7SAndroid Build Coastguard Worker 
4392*03ce13f7SAndroid Build Coastguard Worker   Variable *Src0R = Srcs.src0R(this);
4393*03ce13f7SAndroid Build Coastguard Worker   const int32_t Value = Srcs.getConstantValue();
4394*03ce13f7SAndroid Build Coastguard Worker   if ((Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) && Value == 0) {
4395*03ce13f7SAndroid Build Coastguard Worker     _tst(Src0R, Src0R);
4396*03ce13f7SAndroid Build Coastguard Worker     return CondWhenTrue(getIcmp32Mapping(Condition));
4397*03ce13f7SAndroid Build Coastguard Worker   }
4398*03ce13f7SAndroid Build Coastguard Worker 
4399*03ce13f7SAndroid Build Coastguard Worker   if (!Srcs.swappedOperands() && !Srcs.immediateIsFlexEncodable() &&
4400*03ce13f7SAndroid Build Coastguard Worker       Srcs.negatedImmediateIsFlexEncodable()) {
4401*03ce13f7SAndroid Build Coastguard Worker     Operand *Src1F = Srcs.negatedSrc1F(this);
4402*03ce13f7SAndroid Build Coastguard Worker     _cmn(Src0R, Src1F);
4403*03ce13f7SAndroid Build Coastguard Worker     return CondWhenTrue(getIcmp32Mapping(Condition));
4404*03ce13f7SAndroid Build Coastguard Worker   }
4405*03ce13f7SAndroid Build Coastguard Worker 
4406*03ce13f7SAndroid Build Coastguard Worker   Operand *Src1RF = Srcs.src1RF(this);
4407*03ce13f7SAndroid Build Coastguard Worker   if (!Srcs.swappedOperands()) {
4408*03ce13f7SAndroid Build Coastguard Worker     _cmp(Src0R, Src1RF);
4409*03ce13f7SAndroid Build Coastguard Worker   } else {
4410*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(IceType_i32);
4411*03ce13f7SAndroid Build Coastguard Worker     _rsbs(T, Src0R, Src1RF);
4412*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(T);
4413*03ce13f7SAndroid Build Coastguard Worker   }
4414*03ce13f7SAndroid Build Coastguard Worker   return CondWhenTrue(getIcmp32Mapping(Condition));
4415*03ce13f7SAndroid Build Coastguard Worker }
4416*03ce13f7SAndroid Build Coastguard Worker 
4417*03ce13f7SAndroid Build Coastguard Worker TargetARM32::CondWhenTrue
lowerInt8AndInt16IcmpCond(InstIcmp::ICond Condition,Operand * Src0,Operand * Src1)4418*03ce13f7SAndroid Build Coastguard Worker TargetARM32::lowerInt8AndInt16IcmpCond(InstIcmp::ICond Condition, Operand *Src0,
4419*03ce13f7SAndroid Build Coastguard Worker                                        Operand *Src1) {
4420*03ce13f7SAndroid Build Coastguard Worker   Int32Operands Srcs(Src0, Src1);
4421*03ce13f7SAndroid Build Coastguard Worker   const int32_t ShAmt = 32 - getScalarIntBitWidth(Src0->getType());
4422*03ce13f7SAndroid Build Coastguard Worker   assert(ShAmt >= 0);
4423*03ce13f7SAndroid Build Coastguard Worker 
4424*03ce13f7SAndroid Build Coastguard Worker   if (!Srcs.hasConstOperand()) {
4425*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0R = makeReg(IceType_i32);
4426*03ce13f7SAndroid Build Coastguard Worker     Operand *ShAmtImm = shAmtImm(ShAmt);
4427*03ce13f7SAndroid Build Coastguard Worker     _lsl(Src0R, legalizeToReg(Src0), ShAmtImm);
4428*03ce13f7SAndroid Build Coastguard Worker 
4429*03ce13f7SAndroid Build Coastguard Worker     Variable *Src1R = legalizeToReg(Src1);
4430*03ce13f7SAndroid Build Coastguard Worker     auto *Src1F = OperandARM32FlexReg::create(Func, IceType_i32, Src1R,
4431*03ce13f7SAndroid Build Coastguard Worker                                               OperandARM32::LSL, ShAmtImm);
4432*03ce13f7SAndroid Build Coastguard Worker     _cmp(Src0R, Src1F);
4433*03ce13f7SAndroid Build Coastguard Worker     return CondWhenTrue(getIcmp32Mapping(Condition));
4434*03ce13f7SAndroid Build Coastguard Worker   }
4435*03ce13f7SAndroid Build Coastguard Worker 
4436*03ce13f7SAndroid Build Coastguard Worker   const int32_t Value = Srcs.getConstantValue();
4437*03ce13f7SAndroid Build Coastguard Worker   if ((Condition == InstIcmp::Eq || Condition == InstIcmp::Ne) && Value == 0) {
4438*03ce13f7SAndroid Build Coastguard Worker     Operand *ShAmtImm = shAmtImm(ShAmt);
4439*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(IceType_i32);
4440*03ce13f7SAndroid Build Coastguard Worker     _lsls(T, Srcs.src0R(this), ShAmtImm);
4441*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(T);
4442*03ce13f7SAndroid Build Coastguard Worker     return CondWhenTrue(getIcmp32Mapping(Condition));
4443*03ce13f7SAndroid Build Coastguard Worker   }
4444*03ce13f7SAndroid Build Coastguard Worker 
4445*03ce13f7SAndroid Build Coastguard Worker   Variable *ConstR = makeReg(IceType_i32);
4446*03ce13f7SAndroid Build Coastguard Worker   _mov(ConstR,
4447*03ce13f7SAndroid Build Coastguard Worker        legalize(Ctx->getConstantInt32(Value << ShAmt), Legal_Reg | Legal_Flex));
4448*03ce13f7SAndroid Build Coastguard Worker   Operand *NonConstF = OperandARM32FlexReg::create(
4449*03ce13f7SAndroid Build Coastguard Worker       Func, IceType_i32, Srcs.src0R(this), OperandARM32::LSL,
4450*03ce13f7SAndroid Build Coastguard Worker       Ctx->getConstantInt32(ShAmt));
4451*03ce13f7SAndroid Build Coastguard Worker 
4452*03ce13f7SAndroid Build Coastguard Worker   if (Srcs.swappedOperands()) {
4453*03ce13f7SAndroid Build Coastguard Worker     _cmp(ConstR, NonConstF);
4454*03ce13f7SAndroid Build Coastguard Worker   } else {
4455*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(IceType_i32);
4456*03ce13f7SAndroid Build Coastguard Worker     _rsbs(T, ConstR, NonConstF);
4457*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(T);
4458*03ce13f7SAndroid Build Coastguard Worker   }
4459*03ce13f7SAndroid Build Coastguard Worker   return CondWhenTrue(getIcmp32Mapping(Condition));
4460*03ce13f7SAndroid Build Coastguard Worker }
4461*03ce13f7SAndroid Build Coastguard Worker 
lowerIcmpCond(const InstIcmp * Instr)4462*03ce13f7SAndroid Build Coastguard Worker TargetARM32::CondWhenTrue TargetARM32::lowerIcmpCond(const InstIcmp *Instr) {
4463*03ce13f7SAndroid Build Coastguard Worker   return lowerIcmpCond(Instr->getCondition(), Instr->getSrc(0),
4464*03ce13f7SAndroid Build Coastguard Worker                        Instr->getSrc(1));
4465*03ce13f7SAndroid Build Coastguard Worker }
4466*03ce13f7SAndroid Build Coastguard Worker 
lowerIcmpCond(InstIcmp::ICond Condition,Operand * Src0,Operand * Src1)4467*03ce13f7SAndroid Build Coastguard Worker TargetARM32::CondWhenTrue TargetARM32::lowerIcmpCond(InstIcmp::ICond Condition,
4468*03ce13f7SAndroid Build Coastguard Worker                                                      Operand *Src0,
4469*03ce13f7SAndroid Build Coastguard Worker                                                      Operand *Src1) {
4470*03ce13f7SAndroid Build Coastguard Worker   Src0 = legalizeUndef(Src0);
4471*03ce13f7SAndroid Build Coastguard Worker   Src1 = legalizeUndef(Src1);
4472*03ce13f7SAndroid Build Coastguard Worker 
4473*03ce13f7SAndroid Build Coastguard Worker   // a=icmp cond b, c ==>
4474*03ce13f7SAndroid Build Coastguard Worker   // GCC does:
4475*03ce13f7SAndroid Build Coastguard Worker   //   <u/s>xtb tb, b
4476*03ce13f7SAndroid Build Coastguard Worker   //   <u/s>xtb tc, c
4477*03ce13f7SAndroid Build Coastguard Worker   //   cmp      tb, tc
4478*03ce13f7SAndroid Build Coastguard Worker   //   mov.C1   t, #0
4479*03ce13f7SAndroid Build Coastguard Worker   //   mov.C2   t, #1
4480*03ce13f7SAndroid Build Coastguard Worker   //   mov      a, t
4481*03ce13f7SAndroid Build Coastguard Worker   // where the unsigned/sign extension is not needed for 32-bit. They also have
4482*03ce13f7SAndroid Build Coastguard Worker   // special cases for EQ and NE. E.g., for NE:
4483*03ce13f7SAndroid Build Coastguard Worker   //   <extend to tb, tc>
4484*03ce13f7SAndroid Build Coastguard Worker   //   subs     t, tb, tc
4485*03ce13f7SAndroid Build Coastguard Worker   //   movne    t, #1
4486*03ce13f7SAndroid Build Coastguard Worker   //   mov      a, t
4487*03ce13f7SAndroid Build Coastguard Worker   //
4488*03ce13f7SAndroid Build Coastguard Worker   // LLVM does:
4489*03ce13f7SAndroid Build Coastguard Worker   //   lsl     tb, b, #<N>
4490*03ce13f7SAndroid Build Coastguard Worker   //   mov     t, #0
4491*03ce13f7SAndroid Build Coastguard Worker   //   cmp     tb, c, lsl #<N>
4492*03ce13f7SAndroid Build Coastguard Worker   //   mov.<C> t, #1
4493*03ce13f7SAndroid Build Coastguard Worker   //   mov     a, t
4494*03ce13f7SAndroid Build Coastguard Worker   //
4495*03ce13f7SAndroid Build Coastguard Worker   // the left shift is by 0, 16, or 24, which allows the comparison to focus on
4496*03ce13f7SAndroid Build Coastguard Worker   // the digits that actually matter (for 16-bit or 8-bit signed/unsigned). For
4497*03ce13f7SAndroid Build Coastguard Worker   // the unsigned case, for some reason it does similar to GCC and does a uxtb
4498*03ce13f7SAndroid Build Coastguard Worker   // first. It's not clear to me why that special-casing is needed.
4499*03ce13f7SAndroid Build Coastguard Worker   //
4500*03ce13f7SAndroid Build Coastguard Worker   // We'll go with the LLVM way for now, since it's shorter and has just as few
4501*03ce13f7SAndroid Build Coastguard Worker   // dependencies.
4502*03ce13f7SAndroid Build Coastguard Worker   switch (Src0->getType()) {
4503*03ce13f7SAndroid Build Coastguard Worker   default:
4504*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Unhandled type in lowerIcmpCond");
4505*03ce13f7SAndroid Build Coastguard Worker   case IceType_i1:
4506*03ce13f7SAndroid Build Coastguard Worker   case IceType_i8:
4507*03ce13f7SAndroid Build Coastguard Worker   case IceType_i16:
4508*03ce13f7SAndroid Build Coastguard Worker     return lowerInt8AndInt16IcmpCond(Condition, Src0, Src1);
4509*03ce13f7SAndroid Build Coastguard Worker   case IceType_i32:
4510*03ce13f7SAndroid Build Coastguard Worker     return lowerInt32IcmpCond(Condition, Src0, Src1);
4511*03ce13f7SAndroid Build Coastguard Worker   case IceType_i64:
4512*03ce13f7SAndroid Build Coastguard Worker     return lowerInt64IcmpCond(Condition, Src0, Src1);
4513*03ce13f7SAndroid Build Coastguard Worker   }
4514*03ce13f7SAndroid Build Coastguard Worker }
4515*03ce13f7SAndroid Build Coastguard Worker 
lowerIcmp(const InstIcmp * Instr)4516*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerIcmp(const InstIcmp *Instr) {
4517*03ce13f7SAndroid Build Coastguard Worker   Variable *Dest = Instr->getDest();
4518*03ce13f7SAndroid Build Coastguard Worker   const Type DestTy = Dest->getType();
4519*03ce13f7SAndroid Build Coastguard Worker 
4520*03ce13f7SAndroid Build Coastguard Worker   if (isVectorType(DestTy)) {
4521*03ce13f7SAndroid Build Coastguard Worker     auto *T = makeReg(DestTy);
4522*03ce13f7SAndroid Build Coastguard Worker     auto *Src0 = legalizeToReg(Instr->getSrc(0));
4523*03ce13f7SAndroid Build Coastguard Worker     auto *Src1 = legalizeToReg(Instr->getSrc(1));
4524*03ce13f7SAndroid Build Coastguard Worker     const Type SrcTy = Src0->getType();
4525*03ce13f7SAndroid Build Coastguard Worker 
4526*03ce13f7SAndroid Build Coastguard Worker     bool NeedsShl = false;
4527*03ce13f7SAndroid Build Coastguard Worker     Type NewTypeAfterShl;
4528*03ce13f7SAndroid Build Coastguard Worker     SizeT ShAmt;
4529*03ce13f7SAndroid Build Coastguard Worker     switch (SrcTy) {
4530*03ce13f7SAndroid Build Coastguard Worker     default:
4531*03ce13f7SAndroid Build Coastguard Worker       break;
4532*03ce13f7SAndroid Build Coastguard Worker     case IceType_v16i1:
4533*03ce13f7SAndroid Build Coastguard Worker       NeedsShl = true;
4534*03ce13f7SAndroid Build Coastguard Worker       NewTypeAfterShl = IceType_v16i8;
4535*03ce13f7SAndroid Build Coastguard Worker       ShAmt = 7;
4536*03ce13f7SAndroid Build Coastguard Worker       break;
4537*03ce13f7SAndroid Build Coastguard Worker     case IceType_v8i1:
4538*03ce13f7SAndroid Build Coastguard Worker       NeedsShl = true;
4539*03ce13f7SAndroid Build Coastguard Worker       NewTypeAfterShl = IceType_v8i16;
4540*03ce13f7SAndroid Build Coastguard Worker       ShAmt = 15;
4541*03ce13f7SAndroid Build Coastguard Worker       break;
4542*03ce13f7SAndroid Build Coastguard Worker     case IceType_v4i1:
4543*03ce13f7SAndroid Build Coastguard Worker       NeedsShl = true;
4544*03ce13f7SAndroid Build Coastguard Worker       NewTypeAfterShl = IceType_v4i32;
4545*03ce13f7SAndroid Build Coastguard Worker       ShAmt = 31;
4546*03ce13f7SAndroid Build Coastguard Worker       break;
4547*03ce13f7SAndroid Build Coastguard Worker     }
4548*03ce13f7SAndroid Build Coastguard Worker 
4549*03ce13f7SAndroid Build Coastguard Worker     if (NeedsShl) {
4550*03ce13f7SAndroid Build Coastguard Worker       auto *Imm = llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(ShAmt));
4551*03ce13f7SAndroid Build Coastguard Worker       auto *Src0T = makeReg(NewTypeAfterShl);
4552*03ce13f7SAndroid Build Coastguard Worker       auto *Src0Shl = makeReg(NewTypeAfterShl);
4553*03ce13f7SAndroid Build Coastguard Worker       _mov(Src0T, Src0);
4554*03ce13f7SAndroid Build Coastguard Worker       _vshl(Src0Shl, Src0T, Imm);
4555*03ce13f7SAndroid Build Coastguard Worker       Src0 = Src0Shl;
4556*03ce13f7SAndroid Build Coastguard Worker 
4557*03ce13f7SAndroid Build Coastguard Worker       auto *Src1T = makeReg(NewTypeAfterShl);
4558*03ce13f7SAndroid Build Coastguard Worker       auto *Src1Shl = makeReg(NewTypeAfterShl);
4559*03ce13f7SAndroid Build Coastguard Worker       _mov(Src1T, Src1);
4560*03ce13f7SAndroid Build Coastguard Worker       _vshl(Src1Shl, Src1T, Imm);
4561*03ce13f7SAndroid Build Coastguard Worker       Src1 = Src1Shl;
4562*03ce13f7SAndroid Build Coastguard Worker     }
4563*03ce13f7SAndroid Build Coastguard Worker 
4564*03ce13f7SAndroid Build Coastguard Worker     switch (Instr->getCondition()) {
4565*03ce13f7SAndroid Build Coastguard Worker     default:
4566*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error("Unhandled integer comparison.");
4567*03ce13f7SAndroid Build Coastguard Worker #define _Vceq(T, S0, S1, Signed) _vceq(T, S0, S1)
4568*03ce13f7SAndroid Build Coastguard Worker #define _Vcge(T, S0, S1, Signed)                                               \
4569*03ce13f7SAndroid Build Coastguard Worker   _vcge(T, S0, S1)->setSignType(Signed ? InstARM32::FS_Signed                  \
4570*03ce13f7SAndroid Build Coastguard Worker                                        : InstARM32::FS_Unsigned)
4571*03ce13f7SAndroid Build Coastguard Worker #define _Vcgt(T, S0, S1, Signed)                                               \
4572*03ce13f7SAndroid Build Coastguard Worker   _vcgt(T, S0, S1)->setSignType(Signed ? InstARM32::FS_Signed                  \
4573*03ce13f7SAndroid Build Coastguard Worker                                        : InstARM32::FS_Unsigned)
4574*03ce13f7SAndroid Build Coastguard Worker #define X(val, is_signed, swapped64, C_32, C1_64, C2_64, C_V, INV_V, NEG_V)    \
4575*03ce13f7SAndroid Build Coastguard Worker   case InstIcmp::val: {                                                        \
4576*03ce13f7SAndroid Build Coastguard Worker     _Vc##C_V(T, (INV_V) ? Src1 : Src0, (INV_V) ? Src0 : Src1, is_signed);      \
4577*03ce13f7SAndroid Build Coastguard Worker     if (NEG_V) {                                                               \
4578*03ce13f7SAndroid Build Coastguard Worker       auto *TInv = makeReg(DestTy);                                            \
4579*03ce13f7SAndroid Build Coastguard Worker       _vmvn(TInv, T);                                                          \
4580*03ce13f7SAndroid Build Coastguard Worker       T = TInv;                                                                \
4581*03ce13f7SAndroid Build Coastguard Worker     }                                                                          \
4582*03ce13f7SAndroid Build Coastguard Worker   } break;
4583*03ce13f7SAndroid Build Coastguard Worker       ICMPARM32_TABLE
4584*03ce13f7SAndroid Build Coastguard Worker #undef X
4585*03ce13f7SAndroid Build Coastguard Worker #undef _Vcgt
4586*03ce13f7SAndroid Build Coastguard Worker #undef _Vcge
4587*03ce13f7SAndroid Build Coastguard Worker #undef _Vceq
4588*03ce13f7SAndroid Build Coastguard Worker     }
4589*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
4590*03ce13f7SAndroid Build Coastguard Worker     return;
4591*03ce13f7SAndroid Build Coastguard Worker   }
4592*03ce13f7SAndroid Build Coastguard Worker 
4593*03ce13f7SAndroid Build Coastguard Worker   Operand *_0 =
4594*03ce13f7SAndroid Build Coastguard Worker       legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex);
4595*03ce13f7SAndroid Build Coastguard Worker   Operand *_1 = legalize(Ctx->getConstantInt32(1), Legal_Reg | Legal_Flex);
4596*03ce13f7SAndroid Build Coastguard Worker   Variable *T = makeReg(IceType_i1);
4597*03ce13f7SAndroid Build Coastguard Worker 
4598*03ce13f7SAndroid Build Coastguard Worker   _mov(T, _0);
4599*03ce13f7SAndroid Build Coastguard Worker   CondWhenTrue Cond = lowerIcmpCond(Instr);
4600*03ce13f7SAndroid Build Coastguard Worker   _mov_redefined(T, _1, Cond.WhenTrue0);
4601*03ce13f7SAndroid Build Coastguard Worker   _mov(Dest, T);
4602*03ce13f7SAndroid Build Coastguard Worker 
4603*03ce13f7SAndroid Build Coastguard Worker   assert(Cond.WhenTrue1 == CondARM32::kNone);
4604*03ce13f7SAndroid Build Coastguard Worker 
4605*03ce13f7SAndroid Build Coastguard Worker   return;
4606*03ce13f7SAndroid Build Coastguard Worker }
4607*03ce13f7SAndroid Build Coastguard Worker 
lowerInsertElement(const InstInsertElement * Instr)4608*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerInsertElement(const InstInsertElement *Instr) {
4609*03ce13f7SAndroid Build Coastguard Worker   Variable *Dest = Instr->getDest();
4610*03ce13f7SAndroid Build Coastguard Worker   Type DestTy = Dest->getType();
4611*03ce13f7SAndroid Build Coastguard Worker 
4612*03ce13f7SAndroid Build Coastguard Worker   Variable *Src0 = legalizeToReg(Instr->getSrc(0));
4613*03ce13f7SAndroid Build Coastguard Worker   Variable *Src1 = legalizeToReg(Instr->getSrc(1));
4614*03ce13f7SAndroid Build Coastguard Worker   Operand *Src2 = Instr->getSrc(2);
4615*03ce13f7SAndroid Build Coastguard Worker 
4616*03ce13f7SAndroid Build Coastguard Worker   if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src2)) {
4617*03ce13f7SAndroid Build Coastguard Worker     const uint32_t Index = Imm->getValue();
4618*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(DestTy);
4619*03ce13f7SAndroid Build Coastguard Worker 
4620*03ce13f7SAndroid Build Coastguard Worker     if (isFloatingType(DestTy)) {
4621*03ce13f7SAndroid Build Coastguard Worker       T->setRegClass(RegARM32::RCARM32_QtoS);
4622*03ce13f7SAndroid Build Coastguard Worker     }
4623*03ce13f7SAndroid Build Coastguard Worker 
4624*03ce13f7SAndroid Build Coastguard Worker     _mov(T, Src0);
4625*03ce13f7SAndroid Build Coastguard Worker     _insertelement(T, Src1, Index);
4626*03ce13f7SAndroid Build Coastguard Worker     _set_dest_redefined();
4627*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
4628*03ce13f7SAndroid Build Coastguard Worker     return;
4629*03ce13f7SAndroid Build Coastguard Worker   }
4630*03ce13f7SAndroid Build Coastguard Worker   assert(false && "insertelement requires a constant index");
4631*03ce13f7SAndroid Build Coastguard Worker }
4632*03ce13f7SAndroid Build Coastguard Worker 
4633*03ce13f7SAndroid Build Coastguard Worker namespace {
getConstantMemoryOrder(Operand * Opnd)4634*03ce13f7SAndroid Build Coastguard Worker inline uint64_t getConstantMemoryOrder(Operand *Opnd) {
4635*03ce13f7SAndroid Build Coastguard Worker   if (auto *Integer = llvm::dyn_cast<ConstantInteger32>(Opnd))
4636*03ce13f7SAndroid Build Coastguard Worker     return Integer->getValue();
4637*03ce13f7SAndroid Build Coastguard Worker   return Intrinsics::MemoryOrderInvalid;
4638*03ce13f7SAndroid Build Coastguard Worker }
4639*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
4640*03ce13f7SAndroid Build Coastguard Worker 
lowerLoadLinkedStoreExclusive(Type Ty,Operand * Addr,std::function<Variable * (Variable *)> Operation,CondARM32::Cond Cond)4641*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerLoadLinkedStoreExclusive(
4642*03ce13f7SAndroid Build Coastguard Worker     Type Ty, Operand *Addr, std::function<Variable *(Variable *)> Operation,
4643*03ce13f7SAndroid Build Coastguard Worker     CondARM32::Cond Cond) {
4644*03ce13f7SAndroid Build Coastguard Worker 
4645*03ce13f7SAndroid Build Coastguard Worker   auto *Retry = Context.insert<InstARM32Label>(this);
4646*03ce13f7SAndroid Build Coastguard Worker 
4647*03ce13f7SAndroid Build Coastguard Worker   { // scoping for loop highlighting.
4648*03ce13f7SAndroid Build Coastguard Worker     Variable *Success = makeReg(IceType_i32);
4649*03ce13f7SAndroid Build Coastguard Worker     Variable *Tmp = (Ty == IceType_i64) ? makeI64RegPair() : makeReg(Ty);
4650*03ce13f7SAndroid Build Coastguard Worker     auto *_0 = Ctx->getConstantZero(IceType_i32);
4651*03ce13f7SAndroid Build Coastguard Worker 
4652*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeDef>(Tmp);
4653*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(Tmp);
4654*03ce13f7SAndroid Build Coastguard Worker     Variable *AddrR = legalizeToReg(Addr);
4655*03ce13f7SAndroid Build Coastguard Worker     _ldrex(Tmp, formMemoryOperand(AddrR, Ty))->setDestRedefined();
4656*03ce13f7SAndroid Build Coastguard Worker     auto *StoreValue = Operation(Tmp);
4657*03ce13f7SAndroid Build Coastguard Worker     assert(StoreValue->mustHaveReg());
4658*03ce13f7SAndroid Build Coastguard Worker     // strex requires Dest to be a register other than Value or Addr. This
4659*03ce13f7SAndroid Build Coastguard Worker     // restriction is cleanly represented by adding an "early" definition of
4660*03ce13f7SAndroid Build Coastguard Worker     // Dest (or a latter use of all the sources.)
4661*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeDef>(Success);
4662*03ce13f7SAndroid Build Coastguard Worker     if (Cond != CondARM32::AL) {
4663*03ce13f7SAndroid Build Coastguard Worker       _mov_redefined(Success, legalize(_0, Legal_Reg | Legal_Flex),
4664*03ce13f7SAndroid Build Coastguard Worker                      InstARM32::getOppositeCondition(Cond));
4665*03ce13f7SAndroid Build Coastguard Worker     }
4666*03ce13f7SAndroid Build Coastguard Worker     _strex(Success, StoreValue, formMemoryOperand(AddrR, Ty), Cond)
4667*03ce13f7SAndroid Build Coastguard Worker         ->setDestRedefined();
4668*03ce13f7SAndroid Build Coastguard Worker     _cmp(Success, _0);
4669*03ce13f7SAndroid Build Coastguard Worker   }
4670*03ce13f7SAndroid Build Coastguard Worker 
4671*03ce13f7SAndroid Build Coastguard Worker   _br(Retry, CondARM32::NE);
4672*03ce13f7SAndroid Build Coastguard Worker }
4673*03ce13f7SAndroid Build Coastguard Worker 
4674*03ce13f7SAndroid Build Coastguard Worker namespace {
createArithInst(Cfg * Func,uint32_t Operation,Variable * Dest,Variable * Src0,Operand * Src1)4675*03ce13f7SAndroid Build Coastguard Worker InstArithmetic *createArithInst(Cfg *Func, uint32_t Operation, Variable *Dest,
4676*03ce13f7SAndroid Build Coastguard Worker                                 Variable *Src0, Operand *Src1) {
4677*03ce13f7SAndroid Build Coastguard Worker   InstArithmetic::OpKind Oper;
4678*03ce13f7SAndroid Build Coastguard Worker   switch (Operation) {
4679*03ce13f7SAndroid Build Coastguard Worker   default:
4680*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Unknown AtomicRMW operation");
4681*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::AtomicExchange:
4682*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Can't handle Atomic xchg operation");
4683*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::AtomicAdd:
4684*03ce13f7SAndroid Build Coastguard Worker     Oper = InstArithmetic::Add;
4685*03ce13f7SAndroid Build Coastguard Worker     break;
4686*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::AtomicAnd:
4687*03ce13f7SAndroid Build Coastguard Worker     Oper = InstArithmetic::And;
4688*03ce13f7SAndroid Build Coastguard Worker     break;
4689*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::AtomicSub:
4690*03ce13f7SAndroid Build Coastguard Worker     Oper = InstArithmetic::Sub;
4691*03ce13f7SAndroid Build Coastguard Worker     break;
4692*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::AtomicOr:
4693*03ce13f7SAndroid Build Coastguard Worker     Oper = InstArithmetic::Or;
4694*03ce13f7SAndroid Build Coastguard Worker     break;
4695*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::AtomicXor:
4696*03ce13f7SAndroid Build Coastguard Worker     Oper = InstArithmetic::Xor;
4697*03ce13f7SAndroid Build Coastguard Worker     break;
4698*03ce13f7SAndroid Build Coastguard Worker   }
4699*03ce13f7SAndroid Build Coastguard Worker   return InstArithmetic::create(Func, Oper, Dest, Src0, Src1);
4700*03ce13f7SAndroid Build Coastguard Worker }
4701*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
4702*03ce13f7SAndroid Build Coastguard Worker 
lowerAtomicRMW(Variable * Dest,uint32_t Operation,Operand * Addr,Operand * Val)4703*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerAtomicRMW(Variable *Dest, uint32_t Operation,
4704*03ce13f7SAndroid Build Coastguard Worker                                  Operand *Addr, Operand *Val) {
4705*03ce13f7SAndroid Build Coastguard Worker   // retry:
4706*03ce13f7SAndroid Build Coastguard Worker   //     ldrex tmp, [addr]
4707*03ce13f7SAndroid Build Coastguard Worker   //     mov contents, tmp
4708*03ce13f7SAndroid Build Coastguard Worker   //     op result, contents, Val
4709*03ce13f7SAndroid Build Coastguard Worker   //     strex success, result, [addr]
4710*03ce13f7SAndroid Build Coastguard Worker   //     cmp success, 0
4711*03ce13f7SAndroid Build Coastguard Worker   //     jne retry
4712*03ce13f7SAndroid Build Coastguard Worker   //     fake-use(addr, operand)  @ prevents undesirable clobbering.
4713*03ce13f7SAndroid Build Coastguard Worker   //     mov dest, contents
4714*03ce13f7SAndroid Build Coastguard Worker   auto DestTy = Dest->getType();
4715*03ce13f7SAndroid Build Coastguard Worker 
4716*03ce13f7SAndroid Build Coastguard Worker   if (DestTy == IceType_i64) {
4717*03ce13f7SAndroid Build Coastguard Worker     lowerInt64AtomicRMW(Dest, Operation, Addr, Val);
4718*03ce13f7SAndroid Build Coastguard Worker     return;
4719*03ce13f7SAndroid Build Coastguard Worker   }
4720*03ce13f7SAndroid Build Coastguard Worker 
4721*03ce13f7SAndroid Build Coastguard Worker   Operand *ValRF = nullptr;
4722*03ce13f7SAndroid Build Coastguard Worker   if (llvm::isa<ConstantInteger32>(Val)) {
4723*03ce13f7SAndroid Build Coastguard Worker     ValRF = Val;
4724*03ce13f7SAndroid Build Coastguard Worker   } else {
4725*03ce13f7SAndroid Build Coastguard Worker     ValRF = legalizeToReg(Val);
4726*03ce13f7SAndroid Build Coastguard Worker   }
4727*03ce13f7SAndroid Build Coastguard Worker   auto *ContentsR = makeReg(DestTy);
4728*03ce13f7SAndroid Build Coastguard Worker   auto *ResultR = makeReg(DestTy);
4729*03ce13f7SAndroid Build Coastguard Worker 
4730*03ce13f7SAndroid Build Coastguard Worker   _dmb();
4731*03ce13f7SAndroid Build Coastguard Worker   lowerLoadLinkedStoreExclusive(
4732*03ce13f7SAndroid Build Coastguard Worker       DestTy, Addr,
4733*03ce13f7SAndroid Build Coastguard Worker       [this, Operation, ResultR, ContentsR, ValRF](Variable *Tmp) {
4734*03ce13f7SAndroid Build Coastguard Worker         lowerAssign(InstAssign::create(Func, ContentsR, Tmp));
4735*03ce13f7SAndroid Build Coastguard Worker         if (Operation == Intrinsics::AtomicExchange) {
4736*03ce13f7SAndroid Build Coastguard Worker           lowerAssign(InstAssign::create(Func, ResultR, ValRF));
4737*03ce13f7SAndroid Build Coastguard Worker         } else {
4738*03ce13f7SAndroid Build Coastguard Worker           lowerArithmetic(
4739*03ce13f7SAndroid Build Coastguard Worker               createArithInst(Func, Operation, ResultR, ContentsR, ValRF));
4740*03ce13f7SAndroid Build Coastguard Worker         }
4741*03ce13f7SAndroid Build Coastguard Worker         return ResultR;
4742*03ce13f7SAndroid Build Coastguard Worker       });
4743*03ce13f7SAndroid Build Coastguard Worker   _dmb();
4744*03ce13f7SAndroid Build Coastguard Worker   if (auto *ValR = llvm::dyn_cast<Variable>(ValRF)) {
4745*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(ValR);
4746*03ce13f7SAndroid Build Coastguard Worker   }
4747*03ce13f7SAndroid Build Coastguard Worker   // Can't dce ContentsR.
4748*03ce13f7SAndroid Build Coastguard Worker   Context.insert<InstFakeUse>(ContentsR);
4749*03ce13f7SAndroid Build Coastguard Worker   lowerAssign(InstAssign::create(Func, Dest, ContentsR));
4750*03ce13f7SAndroid Build Coastguard Worker }
4751*03ce13f7SAndroid Build Coastguard Worker 
lowerInt64AtomicRMW(Variable * Dest,uint32_t Operation,Operand * Addr,Operand * Val)4752*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerInt64AtomicRMW(Variable *Dest, uint32_t Operation,
4753*03ce13f7SAndroid Build Coastguard Worker                                       Operand *Addr, Operand *Val) {
4754*03ce13f7SAndroid Build Coastguard Worker   assert(Dest->getType() == IceType_i64);
4755*03ce13f7SAndroid Build Coastguard Worker 
4756*03ce13f7SAndroid Build Coastguard Worker   auto *ResultR = makeI64RegPair();
4757*03ce13f7SAndroid Build Coastguard Worker 
4758*03ce13f7SAndroid Build Coastguard Worker   Context.insert<InstFakeDef>(ResultR);
4759*03ce13f7SAndroid Build Coastguard Worker 
4760*03ce13f7SAndroid Build Coastguard Worker   Operand *ValRF = nullptr;
4761*03ce13f7SAndroid Build Coastguard Worker   if (llvm::dyn_cast<ConstantInteger64>(Val)) {
4762*03ce13f7SAndroid Build Coastguard Worker     ValRF = Val;
4763*03ce13f7SAndroid Build Coastguard Worker   } else {
4764*03ce13f7SAndroid Build Coastguard Worker     auto *ValR64 = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64));
4765*03ce13f7SAndroid Build Coastguard Worker     ValR64->initHiLo(Func);
4766*03ce13f7SAndroid Build Coastguard Worker     ValR64->setMustNotHaveReg();
4767*03ce13f7SAndroid Build Coastguard Worker     ValR64->getLo()->setMustHaveReg();
4768*03ce13f7SAndroid Build Coastguard Worker     ValR64->getHi()->setMustHaveReg();
4769*03ce13f7SAndroid Build Coastguard Worker     lowerAssign(InstAssign::create(Func, ValR64, Val));
4770*03ce13f7SAndroid Build Coastguard Worker     ValRF = ValR64;
4771*03ce13f7SAndroid Build Coastguard Worker   }
4772*03ce13f7SAndroid Build Coastguard Worker 
4773*03ce13f7SAndroid Build Coastguard Worker   auto *ContentsR = llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64));
4774*03ce13f7SAndroid Build Coastguard Worker   ContentsR->initHiLo(Func);
4775*03ce13f7SAndroid Build Coastguard Worker   ContentsR->setMustNotHaveReg();
4776*03ce13f7SAndroid Build Coastguard Worker   ContentsR->getLo()->setMustHaveReg();
4777*03ce13f7SAndroid Build Coastguard Worker   ContentsR->getHi()->setMustHaveReg();
4778*03ce13f7SAndroid Build Coastguard Worker 
4779*03ce13f7SAndroid Build Coastguard Worker   _dmb();
4780*03ce13f7SAndroid Build Coastguard Worker   lowerLoadLinkedStoreExclusive(
4781*03ce13f7SAndroid Build Coastguard Worker       IceType_i64, Addr,
4782*03ce13f7SAndroid Build Coastguard Worker       [this, Operation, ResultR, ContentsR, ValRF](Variable *Tmp) {
4783*03ce13f7SAndroid Build Coastguard Worker         lowerAssign(InstAssign::create(Func, ContentsR, Tmp));
4784*03ce13f7SAndroid Build Coastguard Worker         Context.insert<InstFakeUse>(Tmp);
4785*03ce13f7SAndroid Build Coastguard Worker         if (Operation == Intrinsics::AtomicExchange) {
4786*03ce13f7SAndroid Build Coastguard Worker           lowerAssign(InstAssign::create(Func, ResultR, ValRF));
4787*03ce13f7SAndroid Build Coastguard Worker         } else {
4788*03ce13f7SAndroid Build Coastguard Worker           lowerArithmetic(
4789*03ce13f7SAndroid Build Coastguard Worker               createArithInst(Func, Operation, ResultR, ContentsR, ValRF));
4790*03ce13f7SAndroid Build Coastguard Worker         }
4791*03ce13f7SAndroid Build Coastguard Worker         Context.insert<InstFakeUse>(ResultR->getHi());
4792*03ce13f7SAndroid Build Coastguard Worker         Context.insert<InstFakeDef>(ResultR, ResultR->getLo())
4793*03ce13f7SAndroid Build Coastguard Worker             ->setDestRedefined();
4794*03ce13f7SAndroid Build Coastguard Worker         return ResultR;
4795*03ce13f7SAndroid Build Coastguard Worker       });
4796*03ce13f7SAndroid Build Coastguard Worker   _dmb();
4797*03ce13f7SAndroid Build Coastguard Worker   if (auto *ValR64 = llvm::dyn_cast<Variable64On32>(ValRF)) {
4798*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(ValR64->getLo());
4799*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(ValR64->getHi());
4800*03ce13f7SAndroid Build Coastguard Worker   }
4801*03ce13f7SAndroid Build Coastguard Worker   lowerAssign(InstAssign::create(Func, Dest, ContentsR));
4802*03ce13f7SAndroid Build Coastguard Worker }
4803*03ce13f7SAndroid Build Coastguard Worker 
postambleCtpop64(const InstCall * Instr)4804*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::postambleCtpop64(const InstCall *Instr) {
4805*03ce13f7SAndroid Build Coastguard Worker   Operand *Arg0 = Instr->getArg(0);
4806*03ce13f7SAndroid Build Coastguard Worker   if (isInt32Asserting32Or64(Arg0->getType())) {
4807*03ce13f7SAndroid Build Coastguard Worker     return;
4808*03ce13f7SAndroid Build Coastguard Worker   }
4809*03ce13f7SAndroid Build Coastguard Worker   // The popcount helpers always return 32-bit values, while the intrinsic's
4810*03ce13f7SAndroid Build Coastguard Worker   // signature matches some 64-bit platform's native instructions and expect to
4811*03ce13f7SAndroid Build Coastguard Worker   // fill a 64-bit reg. Thus, clear the upper bits of the dest just in case the
4812*03ce13f7SAndroid Build Coastguard Worker   // user doesn't do that in the IR or doesn't toss the bits via truncate.
4813*03ce13f7SAndroid Build Coastguard Worker   auto *DestHi = llvm::cast<Variable>(hiOperand(Instr->getDest()));
4814*03ce13f7SAndroid Build Coastguard Worker   Variable *T = makeReg(IceType_i32);
4815*03ce13f7SAndroid Build Coastguard Worker   Operand *_0 =
4816*03ce13f7SAndroid Build Coastguard Worker       legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex);
4817*03ce13f7SAndroid Build Coastguard Worker   _mov(T, _0);
4818*03ce13f7SAndroid Build Coastguard Worker   _mov(DestHi, T);
4819*03ce13f7SAndroid Build Coastguard Worker }
4820*03ce13f7SAndroid Build Coastguard Worker 
lowerIntrinsic(const InstIntrinsic * Instr)4821*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerIntrinsic(const InstIntrinsic *Instr) {
4822*03ce13f7SAndroid Build Coastguard Worker   Variable *Dest = Instr->getDest();
4823*03ce13f7SAndroid Build Coastguard Worker   Type DestTy = (Dest != nullptr) ? Dest->getType() : IceType_void;
4824*03ce13f7SAndroid Build Coastguard Worker   Intrinsics::IntrinsicID ID = Instr->getIntrinsicID();
4825*03ce13f7SAndroid Build Coastguard Worker   switch (ID) {
4826*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::AtomicFence:
4827*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::AtomicFenceAll:
4828*03ce13f7SAndroid Build Coastguard Worker     assert(Dest == nullptr);
4829*03ce13f7SAndroid Build Coastguard Worker     _dmb();
4830*03ce13f7SAndroid Build Coastguard Worker     return;
4831*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::AtomicIsLockFree: {
4832*03ce13f7SAndroid Build Coastguard Worker     Operand *ByteSize = Instr->getArg(0);
4833*03ce13f7SAndroid Build Coastguard Worker     auto *CI = llvm::dyn_cast<ConstantInteger32>(ByteSize);
4834*03ce13f7SAndroid Build Coastguard Worker     if (CI == nullptr) {
4835*03ce13f7SAndroid Build Coastguard Worker       // The PNaCl ABI requires the byte size to be a compile-time constant.
4836*03ce13f7SAndroid Build Coastguard Worker       Func->setError("AtomicIsLockFree byte size should be compile-time const");
4837*03ce13f7SAndroid Build Coastguard Worker       return;
4838*03ce13f7SAndroid Build Coastguard Worker     }
4839*03ce13f7SAndroid Build Coastguard Worker     static constexpr int32_t NotLockFree = 0;
4840*03ce13f7SAndroid Build Coastguard Worker     static constexpr int32_t LockFree = 1;
4841*03ce13f7SAndroid Build Coastguard Worker     int32_t Result = NotLockFree;
4842*03ce13f7SAndroid Build Coastguard Worker     switch (CI->getValue()) {
4843*03ce13f7SAndroid Build Coastguard Worker     case 1:
4844*03ce13f7SAndroid Build Coastguard Worker     case 2:
4845*03ce13f7SAndroid Build Coastguard Worker     case 4:
4846*03ce13f7SAndroid Build Coastguard Worker     case 8:
4847*03ce13f7SAndroid Build Coastguard Worker       Result = LockFree;
4848*03ce13f7SAndroid Build Coastguard Worker       break;
4849*03ce13f7SAndroid Build Coastguard Worker     }
4850*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, legalizeToReg(Ctx->getConstantInt32(Result)));
4851*03ce13f7SAndroid Build Coastguard Worker     return;
4852*03ce13f7SAndroid Build Coastguard Worker   }
4853*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::AtomicLoad: {
4854*03ce13f7SAndroid Build Coastguard Worker     assert(isScalarIntegerType(DestTy));
4855*03ce13f7SAndroid Build Coastguard Worker     // We require the memory address to be naturally aligned. Given that is the
4856*03ce13f7SAndroid Build Coastguard Worker     // case, then normal loads are atomic.
4857*03ce13f7SAndroid Build Coastguard Worker     if (!Intrinsics::isMemoryOrderValid(
4858*03ce13f7SAndroid Build Coastguard Worker             ID, getConstantMemoryOrder(Instr->getArg(1)))) {
4859*03ce13f7SAndroid Build Coastguard Worker       Func->setError("Unexpected memory ordering for AtomicLoad");
4860*03ce13f7SAndroid Build Coastguard Worker       return;
4861*03ce13f7SAndroid Build Coastguard Worker     }
4862*03ce13f7SAndroid Build Coastguard Worker     Variable *T;
4863*03ce13f7SAndroid Build Coastguard Worker 
4864*03ce13f7SAndroid Build Coastguard Worker     if (DestTy == IceType_i64) {
4865*03ce13f7SAndroid Build Coastguard Worker       // ldrex is the only arm instruction that is guaranteed to load a 64-bit
4866*03ce13f7SAndroid Build Coastguard Worker       // integer atomically. Everything else works with a regular ldr.
4867*03ce13f7SAndroid Build Coastguard Worker       T = makeI64RegPair();
4868*03ce13f7SAndroid Build Coastguard Worker       _ldrex(T, formMemoryOperand(Instr->getArg(0), IceType_i64));
4869*03ce13f7SAndroid Build Coastguard Worker     } else {
4870*03ce13f7SAndroid Build Coastguard Worker       T = makeReg(DestTy);
4871*03ce13f7SAndroid Build Coastguard Worker       _ldr(T, formMemoryOperand(Instr->getArg(0), DestTy));
4872*03ce13f7SAndroid Build Coastguard Worker     }
4873*03ce13f7SAndroid Build Coastguard Worker     _dmb();
4874*03ce13f7SAndroid Build Coastguard Worker     lowerAssign(InstAssign::create(Func, Dest, T));
4875*03ce13f7SAndroid Build Coastguard Worker     // Adding a fake-use T to ensure the atomic load is not removed if Dest is
4876*03ce13f7SAndroid Build Coastguard Worker     // unused.
4877*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(T);
4878*03ce13f7SAndroid Build Coastguard Worker     return;
4879*03ce13f7SAndroid Build Coastguard Worker   }
4880*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::AtomicStore: {
4881*03ce13f7SAndroid Build Coastguard Worker     // We require the memory address to be naturally aligned. Given that is the
4882*03ce13f7SAndroid Build Coastguard Worker     // case, then normal loads are atomic.
4883*03ce13f7SAndroid Build Coastguard Worker     if (!Intrinsics::isMemoryOrderValid(
4884*03ce13f7SAndroid Build Coastguard Worker             ID, getConstantMemoryOrder(Instr->getArg(2)))) {
4885*03ce13f7SAndroid Build Coastguard Worker       Func->setError("Unexpected memory ordering for AtomicStore");
4886*03ce13f7SAndroid Build Coastguard Worker       return;
4887*03ce13f7SAndroid Build Coastguard Worker     }
4888*03ce13f7SAndroid Build Coastguard Worker 
4889*03ce13f7SAndroid Build Coastguard Worker     auto *Value = Instr->getArg(0);
4890*03ce13f7SAndroid Build Coastguard Worker     if (Value->getType() == IceType_i64) {
4891*03ce13f7SAndroid Build Coastguard Worker       auto *ValueR = makeI64RegPair();
4892*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeDef>(ValueR);
4893*03ce13f7SAndroid Build Coastguard Worker       lowerAssign(InstAssign::create(Func, ValueR, Value));
4894*03ce13f7SAndroid Build Coastguard Worker       _dmb();
4895*03ce13f7SAndroid Build Coastguard Worker       lowerLoadLinkedStoreExclusive(
4896*03ce13f7SAndroid Build Coastguard Worker           IceType_i64, Instr->getArg(1), [this, ValueR](Variable *Tmp) {
4897*03ce13f7SAndroid Build Coastguard Worker             // The following fake-use prevents the ldrex instruction from being
4898*03ce13f7SAndroid Build Coastguard Worker             // dead code eliminated.
4899*03ce13f7SAndroid Build Coastguard Worker             Context.insert<InstFakeUse>(llvm::cast<Variable>(loOperand(Tmp)));
4900*03ce13f7SAndroid Build Coastguard Worker             Context.insert<InstFakeUse>(llvm::cast<Variable>(hiOperand(Tmp)));
4901*03ce13f7SAndroid Build Coastguard Worker             Context.insert<InstFakeUse>(Tmp);
4902*03ce13f7SAndroid Build Coastguard Worker             return ValueR;
4903*03ce13f7SAndroid Build Coastguard Worker           });
4904*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeUse>(ValueR);
4905*03ce13f7SAndroid Build Coastguard Worker       _dmb();
4906*03ce13f7SAndroid Build Coastguard Worker       return;
4907*03ce13f7SAndroid Build Coastguard Worker     }
4908*03ce13f7SAndroid Build Coastguard Worker 
4909*03ce13f7SAndroid Build Coastguard Worker     auto *ValueR = legalizeToReg(Instr->getArg(0));
4910*03ce13f7SAndroid Build Coastguard Worker     const auto ValueTy = ValueR->getType();
4911*03ce13f7SAndroid Build Coastguard Worker     assert(isScalarIntegerType(ValueTy));
4912*03ce13f7SAndroid Build Coastguard Worker     auto *Addr = legalizeToReg(Instr->getArg(1));
4913*03ce13f7SAndroid Build Coastguard Worker 
4914*03ce13f7SAndroid Build Coastguard Worker     // non-64-bit stores are atomically as long as the address is aligned. This
4915*03ce13f7SAndroid Build Coastguard Worker     // is PNaCl, so addresses are aligned.
4916*03ce13f7SAndroid Build Coastguard Worker     _dmb();
4917*03ce13f7SAndroid Build Coastguard Worker     _str(ValueR, formMemoryOperand(Addr, ValueTy));
4918*03ce13f7SAndroid Build Coastguard Worker     _dmb();
4919*03ce13f7SAndroid Build Coastguard Worker     return;
4920*03ce13f7SAndroid Build Coastguard Worker   }
4921*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::AtomicCmpxchg: {
4922*03ce13f7SAndroid Build Coastguard Worker     // retry:
4923*03ce13f7SAndroid Build Coastguard Worker     //     ldrex tmp, [addr]
4924*03ce13f7SAndroid Build Coastguard Worker     //     cmp tmp, expected
4925*03ce13f7SAndroid Build Coastguard Worker     //     mov expected, tmp
4926*03ce13f7SAndroid Build Coastguard Worker     //     strexeq success, new, [addr]
4927*03ce13f7SAndroid Build Coastguard Worker     //     cmpeq success, #0
4928*03ce13f7SAndroid Build Coastguard Worker     //     bne retry
4929*03ce13f7SAndroid Build Coastguard Worker     //     mov dest, expected
4930*03ce13f7SAndroid Build Coastguard Worker     assert(isScalarIntegerType(DestTy));
4931*03ce13f7SAndroid Build Coastguard Worker     // We require the memory address to be naturally aligned. Given that is the
4932*03ce13f7SAndroid Build Coastguard Worker     // case, then normal loads are atomic.
4933*03ce13f7SAndroid Build Coastguard Worker     if (!Intrinsics::isMemoryOrderValid(
4934*03ce13f7SAndroid Build Coastguard Worker             ID, getConstantMemoryOrder(Instr->getArg(3)),
4935*03ce13f7SAndroid Build Coastguard Worker             getConstantMemoryOrder(Instr->getArg(4)))) {
4936*03ce13f7SAndroid Build Coastguard Worker       Func->setError("Unexpected memory ordering for AtomicCmpxchg");
4937*03ce13f7SAndroid Build Coastguard Worker       return;
4938*03ce13f7SAndroid Build Coastguard Worker     }
4939*03ce13f7SAndroid Build Coastguard Worker 
4940*03ce13f7SAndroid Build Coastguard Worker     if (DestTy == IceType_i64) {
4941*03ce13f7SAndroid Build Coastguard Worker       Variable *LoadedValue = nullptr;
4942*03ce13f7SAndroid Build Coastguard Worker 
4943*03ce13f7SAndroid Build Coastguard Worker       auto *New = makeI64RegPair();
4944*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeDef>(New);
4945*03ce13f7SAndroid Build Coastguard Worker       lowerAssign(InstAssign::create(Func, New, Instr->getArg(2)));
4946*03ce13f7SAndroid Build Coastguard Worker 
4947*03ce13f7SAndroid Build Coastguard Worker       auto *Expected = makeI64RegPair();
4948*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeDef>(Expected);
4949*03ce13f7SAndroid Build Coastguard Worker       lowerAssign(InstAssign::create(Func, Expected, Instr->getArg(1)));
4950*03ce13f7SAndroid Build Coastguard Worker 
4951*03ce13f7SAndroid Build Coastguard Worker       _dmb();
4952*03ce13f7SAndroid Build Coastguard Worker       lowerLoadLinkedStoreExclusive(
4953*03ce13f7SAndroid Build Coastguard Worker           DestTy, Instr->getArg(0),
4954*03ce13f7SAndroid Build Coastguard Worker           [this, Expected, New, &LoadedValue](Variable *Tmp) {
4955*03ce13f7SAndroid Build Coastguard Worker             auto *ExpectedLoR = llvm::cast<Variable>(loOperand(Expected));
4956*03ce13f7SAndroid Build Coastguard Worker             auto *ExpectedHiR = llvm::cast<Variable>(hiOperand(Expected));
4957*03ce13f7SAndroid Build Coastguard Worker             auto *TmpLoR = llvm::cast<Variable>(loOperand(Tmp));
4958*03ce13f7SAndroid Build Coastguard Worker             auto *TmpHiR = llvm::cast<Variable>(hiOperand(Tmp));
4959*03ce13f7SAndroid Build Coastguard Worker             _cmp(TmpLoR, ExpectedLoR);
4960*03ce13f7SAndroid Build Coastguard Worker             _cmp(TmpHiR, ExpectedHiR, CondARM32::EQ);
4961*03ce13f7SAndroid Build Coastguard Worker             LoadedValue = Tmp;
4962*03ce13f7SAndroid Build Coastguard Worker             return New;
4963*03ce13f7SAndroid Build Coastguard Worker           },
4964*03ce13f7SAndroid Build Coastguard Worker           CondARM32::EQ);
4965*03ce13f7SAndroid Build Coastguard Worker       _dmb();
4966*03ce13f7SAndroid Build Coastguard Worker 
4967*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeUse>(LoadedValue);
4968*03ce13f7SAndroid Build Coastguard Worker       lowerAssign(InstAssign::create(Func, Dest, LoadedValue));
4969*03ce13f7SAndroid Build Coastguard Worker       // The fake-use Expected prevents the assignments to Expected (above)
4970*03ce13f7SAndroid Build Coastguard Worker       // from being removed if Dest is not used.
4971*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeUse>(Expected);
4972*03ce13f7SAndroid Build Coastguard Worker       // New needs to be alive here, or its live range will end in the
4973*03ce13f7SAndroid Build Coastguard Worker       // strex instruction.
4974*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeUse>(New);
4975*03ce13f7SAndroid Build Coastguard Worker       return;
4976*03ce13f7SAndroid Build Coastguard Worker     }
4977*03ce13f7SAndroid Build Coastguard Worker 
4978*03ce13f7SAndroid Build Coastguard Worker     auto *New = legalizeToReg(Instr->getArg(2));
4979*03ce13f7SAndroid Build Coastguard Worker     auto *Expected = legalizeToReg(Instr->getArg(1));
4980*03ce13f7SAndroid Build Coastguard Worker     Variable *LoadedValue = nullptr;
4981*03ce13f7SAndroid Build Coastguard Worker 
4982*03ce13f7SAndroid Build Coastguard Worker     _dmb();
4983*03ce13f7SAndroid Build Coastguard Worker     lowerLoadLinkedStoreExclusive(
4984*03ce13f7SAndroid Build Coastguard Worker         DestTy, Instr->getArg(0),
4985*03ce13f7SAndroid Build Coastguard Worker         [this, Expected, New, &LoadedValue](Variable *Tmp) {
4986*03ce13f7SAndroid Build Coastguard Worker           lowerIcmpCond(InstIcmp::Eq, Tmp, Expected);
4987*03ce13f7SAndroid Build Coastguard Worker           LoadedValue = Tmp;
4988*03ce13f7SAndroid Build Coastguard Worker           return New;
4989*03ce13f7SAndroid Build Coastguard Worker         },
4990*03ce13f7SAndroid Build Coastguard Worker         CondARM32::EQ);
4991*03ce13f7SAndroid Build Coastguard Worker     _dmb();
4992*03ce13f7SAndroid Build Coastguard Worker 
4993*03ce13f7SAndroid Build Coastguard Worker     lowerAssign(InstAssign::create(Func, Dest, LoadedValue));
4994*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(Expected);
4995*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstFakeUse>(New);
4996*03ce13f7SAndroid Build Coastguard Worker     return;
4997*03ce13f7SAndroid Build Coastguard Worker   }
4998*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::AtomicRMW: {
4999*03ce13f7SAndroid Build Coastguard Worker     if (!Intrinsics::isMemoryOrderValid(
5000*03ce13f7SAndroid Build Coastguard Worker             ID, getConstantMemoryOrder(Instr->getArg(3)))) {
5001*03ce13f7SAndroid Build Coastguard Worker       Func->setError("Unexpected memory ordering for AtomicRMW");
5002*03ce13f7SAndroid Build Coastguard Worker       return;
5003*03ce13f7SAndroid Build Coastguard Worker     }
5004*03ce13f7SAndroid Build Coastguard Worker     lowerAtomicRMW(
5005*03ce13f7SAndroid Build Coastguard Worker         Dest,
5006*03ce13f7SAndroid Build Coastguard Worker         static_cast<uint32_t>(
5007*03ce13f7SAndroid Build Coastguard Worker             llvm::cast<ConstantInteger32>(Instr->getArg(0))->getValue()),
5008*03ce13f7SAndroid Build Coastguard Worker         Instr->getArg(1), Instr->getArg(2));
5009*03ce13f7SAndroid Build Coastguard Worker     return;
5010*03ce13f7SAndroid Build Coastguard Worker   }
5011*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::Bswap: {
5012*03ce13f7SAndroid Build Coastguard Worker     Operand *Val = Instr->getArg(0);
5013*03ce13f7SAndroid Build Coastguard Worker     Type Ty = Val->getType();
5014*03ce13f7SAndroid Build Coastguard Worker     if (Ty == IceType_i64) {
5015*03ce13f7SAndroid Build Coastguard Worker       Val = legalizeUndef(Val);
5016*03ce13f7SAndroid Build Coastguard Worker       Variable *Val_Lo = legalizeToReg(loOperand(Val));
5017*03ce13f7SAndroid Build Coastguard Worker       Variable *Val_Hi = legalizeToReg(hiOperand(Val));
5018*03ce13f7SAndroid Build Coastguard Worker       Variable *T_Lo = makeReg(IceType_i32);
5019*03ce13f7SAndroid Build Coastguard Worker       Variable *T_Hi = makeReg(IceType_i32);
5020*03ce13f7SAndroid Build Coastguard Worker       auto *DestLo = llvm::cast<Variable>(loOperand(Dest));
5021*03ce13f7SAndroid Build Coastguard Worker       auto *DestHi = llvm::cast<Variable>(hiOperand(Dest));
5022*03ce13f7SAndroid Build Coastguard Worker       _rev(T_Lo, Val_Lo);
5023*03ce13f7SAndroid Build Coastguard Worker       _rev(T_Hi, Val_Hi);
5024*03ce13f7SAndroid Build Coastguard Worker       _mov(DestLo, T_Hi);
5025*03ce13f7SAndroid Build Coastguard Worker       _mov(DestHi, T_Lo);
5026*03ce13f7SAndroid Build Coastguard Worker     } else {
5027*03ce13f7SAndroid Build Coastguard Worker       assert(Ty == IceType_i32 || Ty == IceType_i16);
5028*03ce13f7SAndroid Build Coastguard Worker       Variable *ValR = legalizeToReg(Val);
5029*03ce13f7SAndroid Build Coastguard Worker       Variable *T = makeReg(Ty);
5030*03ce13f7SAndroid Build Coastguard Worker       _rev(T, ValR);
5031*03ce13f7SAndroid Build Coastguard Worker       if (Val->getType() == IceType_i16) {
5032*03ce13f7SAndroid Build Coastguard Worker         Operand *_16 = shAmtImm(16);
5033*03ce13f7SAndroid Build Coastguard Worker         _lsr(T, T, _16);
5034*03ce13f7SAndroid Build Coastguard Worker       }
5035*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
5036*03ce13f7SAndroid Build Coastguard Worker     }
5037*03ce13f7SAndroid Build Coastguard Worker     return;
5038*03ce13f7SAndroid Build Coastguard Worker   }
5039*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::Ctpop: {
5040*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Ctpop should have been prelowered.");
5041*03ce13f7SAndroid Build Coastguard Worker   }
5042*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::Ctlz: {
5043*03ce13f7SAndroid Build Coastguard Worker     // The "is zero undef" parameter is ignored and we always return a
5044*03ce13f7SAndroid Build Coastguard Worker     // well-defined value.
5045*03ce13f7SAndroid Build Coastguard Worker     Operand *Val = Instr->getArg(0);
5046*03ce13f7SAndroid Build Coastguard Worker     Variable *ValLoR;
5047*03ce13f7SAndroid Build Coastguard Worker     Variable *ValHiR = nullptr;
5048*03ce13f7SAndroid Build Coastguard Worker     if (Val->getType() == IceType_i64) {
5049*03ce13f7SAndroid Build Coastguard Worker       Val = legalizeUndef(Val);
5050*03ce13f7SAndroid Build Coastguard Worker       ValLoR = legalizeToReg(loOperand(Val));
5051*03ce13f7SAndroid Build Coastguard Worker       ValHiR = legalizeToReg(hiOperand(Val));
5052*03ce13f7SAndroid Build Coastguard Worker     } else {
5053*03ce13f7SAndroid Build Coastguard Worker       ValLoR = legalizeToReg(Val);
5054*03ce13f7SAndroid Build Coastguard Worker     }
5055*03ce13f7SAndroid Build Coastguard Worker     lowerCLZ(Dest, ValLoR, ValHiR);
5056*03ce13f7SAndroid Build Coastguard Worker     return;
5057*03ce13f7SAndroid Build Coastguard Worker   }
5058*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::Cttz: {
5059*03ce13f7SAndroid Build Coastguard Worker     // Essentially like Clz, but reverse the bits first.
5060*03ce13f7SAndroid Build Coastguard Worker     Operand *Val = Instr->getArg(0);
5061*03ce13f7SAndroid Build Coastguard Worker     Variable *ValLoR;
5062*03ce13f7SAndroid Build Coastguard Worker     Variable *ValHiR = nullptr;
5063*03ce13f7SAndroid Build Coastguard Worker     if (Val->getType() == IceType_i64) {
5064*03ce13f7SAndroid Build Coastguard Worker       Val = legalizeUndef(Val);
5065*03ce13f7SAndroid Build Coastguard Worker       ValLoR = legalizeToReg(loOperand(Val));
5066*03ce13f7SAndroid Build Coastguard Worker       ValHiR = legalizeToReg(hiOperand(Val));
5067*03ce13f7SAndroid Build Coastguard Worker       Variable *TLo = makeReg(IceType_i32);
5068*03ce13f7SAndroid Build Coastguard Worker       Variable *THi = makeReg(IceType_i32);
5069*03ce13f7SAndroid Build Coastguard Worker       _rbit(TLo, ValLoR);
5070*03ce13f7SAndroid Build Coastguard Worker       _rbit(THi, ValHiR);
5071*03ce13f7SAndroid Build Coastguard Worker       ValLoR = THi;
5072*03ce13f7SAndroid Build Coastguard Worker       ValHiR = TLo;
5073*03ce13f7SAndroid Build Coastguard Worker     } else {
5074*03ce13f7SAndroid Build Coastguard Worker       ValLoR = legalizeToReg(Val);
5075*03ce13f7SAndroid Build Coastguard Worker       Variable *T = makeReg(IceType_i32);
5076*03ce13f7SAndroid Build Coastguard Worker       _rbit(T, ValLoR);
5077*03ce13f7SAndroid Build Coastguard Worker       ValLoR = T;
5078*03ce13f7SAndroid Build Coastguard Worker     }
5079*03ce13f7SAndroid Build Coastguard Worker     lowerCLZ(Dest, ValLoR, ValHiR);
5080*03ce13f7SAndroid Build Coastguard Worker     return;
5081*03ce13f7SAndroid Build Coastguard Worker   }
5082*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::Fabs: {
5083*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(DestTy);
5084*03ce13f7SAndroid Build Coastguard Worker     _vabs(T, legalizeToReg(Instr->getArg(0)));
5085*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
5086*03ce13f7SAndroid Build Coastguard Worker     return;
5087*03ce13f7SAndroid Build Coastguard Worker   }
5088*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::Longjmp: {
5089*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("longjmp should have been prelowered.");
5090*03ce13f7SAndroid Build Coastguard Worker   }
5091*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::Memcpy: {
5092*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("memcpy should have been prelowered.");
5093*03ce13f7SAndroid Build Coastguard Worker   }
5094*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::Memmove: {
5095*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("memmove should have been prelowered.");
5096*03ce13f7SAndroid Build Coastguard Worker   }
5097*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::Memset: {
5098*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("memmove should have been prelowered.");
5099*03ce13f7SAndroid Build Coastguard Worker   }
5100*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::Setjmp: {
5101*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("setjmp should have been prelowered.");
5102*03ce13f7SAndroid Build Coastguard Worker   }
5103*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::Sqrt: {
5104*03ce13f7SAndroid Build Coastguard Worker     Variable *Src = legalizeToReg(Instr->getArg(0));
5105*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(DestTy);
5106*03ce13f7SAndroid Build Coastguard Worker     _vsqrt(T, Src);
5107*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
5108*03ce13f7SAndroid Build Coastguard Worker     return;
5109*03ce13f7SAndroid Build Coastguard Worker   }
5110*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::Stacksave: {
5111*03ce13f7SAndroid Build Coastguard Worker     Variable *SP = getPhysicalRegister(RegARM32::Reg_sp);
5112*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, SP);
5113*03ce13f7SAndroid Build Coastguard Worker     return;
5114*03ce13f7SAndroid Build Coastguard Worker   }
5115*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::Stackrestore: {
5116*03ce13f7SAndroid Build Coastguard Worker     Variable *SP = getPhysicalRegister(RegARM32::Reg_sp);
5117*03ce13f7SAndroid Build Coastguard Worker     Variable *Val = legalizeToReg(Instr->getArg(0));
5118*03ce13f7SAndroid Build Coastguard Worker     _mov_redefined(SP, Val);
5119*03ce13f7SAndroid Build Coastguard Worker     return;
5120*03ce13f7SAndroid Build Coastguard Worker   }
5121*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::Trap:
5122*03ce13f7SAndroid Build Coastguard Worker     _trap();
5123*03ce13f7SAndroid Build Coastguard Worker     return;
5124*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::AddSaturateSigned:
5125*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::AddSaturateUnsigned: {
5126*03ce13f7SAndroid Build Coastguard Worker     bool Unsigned = (ID == Intrinsics::AddSaturateUnsigned);
5127*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0 = legalizeToReg(Instr->getArg(0));
5128*03ce13f7SAndroid Build Coastguard Worker     Variable *Src1 = legalizeToReg(Instr->getArg(1));
5129*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(DestTy);
5130*03ce13f7SAndroid Build Coastguard Worker     _vqadd(T, Src0, Src1, Unsigned);
5131*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
5132*03ce13f7SAndroid Build Coastguard Worker     return;
5133*03ce13f7SAndroid Build Coastguard Worker   }
5134*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::LoadSubVector: {
5135*03ce13f7SAndroid Build Coastguard Worker     assert(llvm::isa<ConstantInteger32>(Instr->getArg(1)) &&
5136*03ce13f7SAndroid Build Coastguard Worker            "LoadSubVector second argument must be a constant");
5137*03ce13f7SAndroid Build Coastguard Worker     Variable *Dest = Instr->getDest();
5138*03ce13f7SAndroid Build Coastguard Worker     Type Ty = Dest->getType();
5139*03ce13f7SAndroid Build Coastguard Worker     auto *SubVectorSize = llvm::cast<ConstantInteger32>(Instr->getArg(1));
5140*03ce13f7SAndroid Build Coastguard Worker     Operand *Addr = Instr->getArg(0);
5141*03ce13f7SAndroid Build Coastguard Worker     OperandARM32Mem *Src = formMemoryOperand(Addr, Ty);
5142*03ce13f7SAndroid Build Coastguard Worker     doMockBoundsCheck(Src);
5143*03ce13f7SAndroid Build Coastguard Worker 
5144*03ce13f7SAndroid Build Coastguard Worker     if (Dest->isRematerializable()) {
5145*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeDef>(Dest);
5146*03ce13f7SAndroid Build Coastguard Worker       return;
5147*03ce13f7SAndroid Build Coastguard Worker     }
5148*03ce13f7SAndroid Build Coastguard Worker 
5149*03ce13f7SAndroid Build Coastguard Worker     auto *T = makeReg(Ty);
5150*03ce13f7SAndroid Build Coastguard Worker     switch (SubVectorSize->getValue()) {
5151*03ce13f7SAndroid Build Coastguard Worker     case 4:
5152*03ce13f7SAndroid Build Coastguard Worker       _vldr1d(T, Src);
5153*03ce13f7SAndroid Build Coastguard Worker       break;
5154*03ce13f7SAndroid Build Coastguard Worker     case 8:
5155*03ce13f7SAndroid Build Coastguard Worker       _vldr1q(T, Src);
5156*03ce13f7SAndroid Build Coastguard Worker       break;
5157*03ce13f7SAndroid Build Coastguard Worker     default:
5158*03ce13f7SAndroid Build Coastguard Worker       Func->setError("Unexpected size for LoadSubVector");
5159*03ce13f7SAndroid Build Coastguard Worker       return;
5160*03ce13f7SAndroid Build Coastguard Worker     }
5161*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
5162*03ce13f7SAndroid Build Coastguard Worker     return;
5163*03ce13f7SAndroid Build Coastguard Worker   }
5164*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::StoreSubVector: {
5165*03ce13f7SAndroid Build Coastguard Worker     assert(llvm::isa<ConstantInteger32>(Instr->getArg(2)) &&
5166*03ce13f7SAndroid Build Coastguard Worker            "StoreSubVector third argument must be a constant");
5167*03ce13f7SAndroid Build Coastguard Worker     auto *SubVectorSize = llvm::cast<ConstantInteger32>(Instr->getArg(2));
5168*03ce13f7SAndroid Build Coastguard Worker     Variable *Value = legalizeToReg(Instr->getArg(0));
5169*03ce13f7SAndroid Build Coastguard Worker     Operand *Addr = Instr->getArg(1);
5170*03ce13f7SAndroid Build Coastguard Worker     OperandARM32Mem *NewAddr = formMemoryOperand(Addr, Value->getType());
5171*03ce13f7SAndroid Build Coastguard Worker     doMockBoundsCheck(NewAddr);
5172*03ce13f7SAndroid Build Coastguard Worker 
5173*03ce13f7SAndroid Build Coastguard Worker     Value = legalizeToReg(Value);
5174*03ce13f7SAndroid Build Coastguard Worker 
5175*03ce13f7SAndroid Build Coastguard Worker     switch (SubVectorSize->getValue()) {
5176*03ce13f7SAndroid Build Coastguard Worker     case 4:
5177*03ce13f7SAndroid Build Coastguard Worker       _vstr1d(Value, NewAddr);
5178*03ce13f7SAndroid Build Coastguard Worker       break;
5179*03ce13f7SAndroid Build Coastguard Worker     case 8:
5180*03ce13f7SAndroid Build Coastguard Worker       _vstr1q(Value, NewAddr);
5181*03ce13f7SAndroid Build Coastguard Worker       break;
5182*03ce13f7SAndroid Build Coastguard Worker     default:
5183*03ce13f7SAndroid Build Coastguard Worker       Func->setError("Unexpected size for StoreSubVector");
5184*03ce13f7SAndroid Build Coastguard Worker       return;
5185*03ce13f7SAndroid Build Coastguard Worker     }
5186*03ce13f7SAndroid Build Coastguard Worker     return;
5187*03ce13f7SAndroid Build Coastguard Worker   }
5188*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::MultiplyAddPairs: {
5189*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0 = legalizeToReg(Instr->getArg(0));
5190*03ce13f7SAndroid Build Coastguard Worker     Variable *Src1 = legalizeToReg(Instr->getArg(1));
5191*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(DestTy);
5192*03ce13f7SAndroid Build Coastguard Worker     _vmlap(T, Src0, Src1);
5193*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
5194*03ce13f7SAndroid Build Coastguard Worker     return;
5195*03ce13f7SAndroid Build Coastguard Worker   }
5196*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::MultiplyHighSigned:
5197*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::MultiplyHighUnsigned: {
5198*03ce13f7SAndroid Build Coastguard Worker     bool Unsigned = (ID == Intrinsics::MultiplyHighUnsigned);
5199*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0 = legalizeToReg(Instr->getArg(0));
5200*03ce13f7SAndroid Build Coastguard Worker     Variable *Src1 = legalizeToReg(Instr->getArg(1));
5201*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(DestTy);
5202*03ce13f7SAndroid Build Coastguard Worker     _vmulh(T, Src0, Src1, Unsigned);
5203*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
5204*03ce13f7SAndroid Build Coastguard Worker     return;
5205*03ce13f7SAndroid Build Coastguard Worker   }
5206*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::Nearbyint: {
5207*03ce13f7SAndroid Build Coastguard Worker     UnimplementedLoweringError(this, Instr);
5208*03ce13f7SAndroid Build Coastguard Worker     return;
5209*03ce13f7SAndroid Build Coastguard Worker   }
5210*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::Round: {
5211*03ce13f7SAndroid Build Coastguard Worker     UnimplementedLoweringError(this, Instr);
5212*03ce13f7SAndroid Build Coastguard Worker     return;
5213*03ce13f7SAndroid Build Coastguard Worker   }
5214*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::SignMask: {
5215*03ce13f7SAndroid Build Coastguard Worker     UnimplementedLoweringError(this, Instr);
5216*03ce13f7SAndroid Build Coastguard Worker     return;
5217*03ce13f7SAndroid Build Coastguard Worker   }
5218*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::SubtractSaturateSigned:
5219*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::SubtractSaturateUnsigned: {
5220*03ce13f7SAndroid Build Coastguard Worker     bool Unsigned = (ID == Intrinsics::SubtractSaturateUnsigned);
5221*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0 = legalizeToReg(Instr->getArg(0));
5222*03ce13f7SAndroid Build Coastguard Worker     Variable *Src1 = legalizeToReg(Instr->getArg(1));
5223*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(DestTy);
5224*03ce13f7SAndroid Build Coastguard Worker     _vqsub(T, Src0, Src1, Unsigned);
5225*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
5226*03ce13f7SAndroid Build Coastguard Worker     return;
5227*03ce13f7SAndroid Build Coastguard Worker   }
5228*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::VectorPackSigned:
5229*03ce13f7SAndroid Build Coastguard Worker   case Intrinsics::VectorPackUnsigned: {
5230*03ce13f7SAndroid Build Coastguard Worker     bool Unsigned = (ID == Intrinsics::VectorPackUnsigned);
5231*03ce13f7SAndroid Build Coastguard Worker     bool Saturating = true;
5232*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0 = legalizeToReg(Instr->getArg(0));
5233*03ce13f7SAndroid Build Coastguard Worker     Variable *Src1 = legalizeToReg(Instr->getArg(1));
5234*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(DestTy);
5235*03ce13f7SAndroid Build Coastguard Worker     _vqmovn2(T, Src0, Src1, Unsigned, Saturating);
5236*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
5237*03ce13f7SAndroid Build Coastguard Worker     return;
5238*03ce13f7SAndroid Build Coastguard Worker   }
5239*03ce13f7SAndroid Build Coastguard Worker   default: // UnknownIntrinsic
5240*03ce13f7SAndroid Build Coastguard Worker     Func->setError("Unexpected intrinsic");
5241*03ce13f7SAndroid Build Coastguard Worker     return;
5242*03ce13f7SAndroid Build Coastguard Worker   }
5243*03ce13f7SAndroid Build Coastguard Worker   return;
5244*03ce13f7SAndroid Build Coastguard Worker }
5245*03ce13f7SAndroid Build Coastguard Worker 
lowerCLZ(Variable * Dest,Variable * ValLoR,Variable * ValHiR)5246*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerCLZ(Variable *Dest, Variable *ValLoR, Variable *ValHiR) {
5247*03ce13f7SAndroid Build Coastguard Worker   Type Ty = Dest->getType();
5248*03ce13f7SAndroid Build Coastguard Worker   assert(Ty == IceType_i32 || Ty == IceType_i64);
5249*03ce13f7SAndroid Build Coastguard Worker   Variable *T = makeReg(IceType_i32);
5250*03ce13f7SAndroid Build Coastguard Worker   _clz(T, ValLoR);
5251*03ce13f7SAndroid Build Coastguard Worker   if (Ty == IceType_i64) {
5252*03ce13f7SAndroid Build Coastguard Worker     auto *DestLo = llvm::cast<Variable>(loOperand(Dest));
5253*03ce13f7SAndroid Build Coastguard Worker     auto *DestHi = llvm::cast<Variable>(hiOperand(Dest));
5254*03ce13f7SAndroid Build Coastguard Worker     Operand *Zero =
5255*03ce13f7SAndroid Build Coastguard Worker         legalize(Ctx->getConstantZero(IceType_i32), Legal_Reg | Legal_Flex);
5256*03ce13f7SAndroid Build Coastguard Worker     Operand *ThirtyTwo =
5257*03ce13f7SAndroid Build Coastguard Worker         legalize(Ctx->getConstantInt32(32), Legal_Reg | Legal_Flex);
5258*03ce13f7SAndroid Build Coastguard Worker     _cmp(ValHiR, Zero);
5259*03ce13f7SAndroid Build Coastguard Worker     Variable *T2 = makeReg(IceType_i32);
5260*03ce13f7SAndroid Build Coastguard Worker     _add(T2, T, ThirtyTwo);
5261*03ce13f7SAndroid Build Coastguard Worker     _clz(T2, ValHiR, CondARM32::NE);
5262*03ce13f7SAndroid Build Coastguard Worker     // T2 is actually a source as well when the predicate is not AL (since it
5263*03ce13f7SAndroid Build Coastguard Worker     // may leave T2 alone). We use _set_dest_redefined to prolong the liveness
5264*03ce13f7SAndroid Build Coastguard Worker     // of T2 as if it was used as a source.
5265*03ce13f7SAndroid Build Coastguard Worker     _set_dest_redefined();
5266*03ce13f7SAndroid Build Coastguard Worker     _mov(DestLo, T2);
5267*03ce13f7SAndroid Build Coastguard Worker     Variable *T3 = makeReg(Zero->getType());
5268*03ce13f7SAndroid Build Coastguard Worker     _mov(T3, Zero);
5269*03ce13f7SAndroid Build Coastguard Worker     _mov(DestHi, T3);
5270*03ce13f7SAndroid Build Coastguard Worker     return;
5271*03ce13f7SAndroid Build Coastguard Worker   }
5272*03ce13f7SAndroid Build Coastguard Worker   _mov(Dest, T);
5273*03ce13f7SAndroid Build Coastguard Worker   return;
5274*03ce13f7SAndroid Build Coastguard Worker }
5275*03ce13f7SAndroid Build Coastguard Worker 
lowerLoad(const InstLoad * Load)5276*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerLoad(const InstLoad *Load) {
5277*03ce13f7SAndroid Build Coastguard Worker   // A Load instruction can be treated the same as an Assign instruction, after
5278*03ce13f7SAndroid Build Coastguard Worker   // the source operand is transformed into an OperandARM32Mem operand.
5279*03ce13f7SAndroid Build Coastguard Worker   Type Ty = Load->getDest()->getType();
5280*03ce13f7SAndroid Build Coastguard Worker   Operand *Src0 = formMemoryOperand(Load->getLoadAddress(), Ty);
5281*03ce13f7SAndroid Build Coastguard Worker   Variable *DestLoad = Load->getDest();
5282*03ce13f7SAndroid Build Coastguard Worker 
5283*03ce13f7SAndroid Build Coastguard Worker   // TODO(jvoung): handled folding opportunities. Sign and zero extension can
5284*03ce13f7SAndroid Build Coastguard Worker   // be folded into a load.
5285*03ce13f7SAndroid Build Coastguard Worker   auto *Assign = InstAssign::create(Func, DestLoad, Src0);
5286*03ce13f7SAndroid Build Coastguard Worker   lowerAssign(Assign);
5287*03ce13f7SAndroid Build Coastguard Worker }
5288*03ce13f7SAndroid Build Coastguard Worker 
5289*03ce13f7SAndroid Build Coastguard Worker namespace {
dumpAddressOpt(const Cfg * Func,const Variable * Base,int32_t Offset,const Variable * OffsetReg,int16_t OffsetRegShAmt,const Inst * Reason)5290*03ce13f7SAndroid Build Coastguard Worker void dumpAddressOpt(const Cfg *Func, const Variable *Base, int32_t Offset,
5291*03ce13f7SAndroid Build Coastguard Worker                     const Variable *OffsetReg, int16_t OffsetRegShAmt,
5292*03ce13f7SAndroid Build Coastguard Worker                     const Inst *Reason) {
5293*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::dump())
5294*03ce13f7SAndroid Build Coastguard Worker     return;
5295*03ce13f7SAndroid Build Coastguard Worker   if (!Func->isVerbose(IceV_AddrOpt))
5296*03ce13f7SAndroid Build Coastguard Worker     return;
5297*03ce13f7SAndroid Build Coastguard Worker   OstreamLocker _(Func->getContext());
5298*03ce13f7SAndroid Build Coastguard Worker   Ostream &Str = Func->getContext()->getStrDump();
5299*03ce13f7SAndroid Build Coastguard Worker   Str << "Instruction: ";
5300*03ce13f7SAndroid Build Coastguard Worker   Reason->dumpDecorated(Func);
5301*03ce13f7SAndroid Build Coastguard Worker   Str << "  results in Base=";
5302*03ce13f7SAndroid Build Coastguard Worker   if (Base)
5303*03ce13f7SAndroid Build Coastguard Worker     Base->dump(Func);
5304*03ce13f7SAndroid Build Coastguard Worker   else
5305*03ce13f7SAndroid Build Coastguard Worker     Str << "<null>";
5306*03ce13f7SAndroid Build Coastguard Worker   Str << ", OffsetReg=";
5307*03ce13f7SAndroid Build Coastguard Worker   if (OffsetReg)
5308*03ce13f7SAndroid Build Coastguard Worker     OffsetReg->dump(Func);
5309*03ce13f7SAndroid Build Coastguard Worker   else
5310*03ce13f7SAndroid Build Coastguard Worker     Str << "<null>";
5311*03ce13f7SAndroid Build Coastguard Worker   Str << ", Shift=" << OffsetRegShAmt << ", Offset=" << Offset << "\n";
5312*03ce13f7SAndroid Build Coastguard Worker }
5313*03ce13f7SAndroid Build Coastguard Worker 
matchAssign(const VariablesMetadata * VMetadata,Variable ** Var,int32_t * Offset,const Inst ** Reason)5314*03ce13f7SAndroid Build Coastguard Worker bool matchAssign(const VariablesMetadata *VMetadata, Variable **Var,
5315*03ce13f7SAndroid Build Coastguard Worker                  int32_t *Offset, const Inst **Reason) {
5316*03ce13f7SAndroid Build Coastguard Worker   // Var originates from Var=SrcVar ==> set Var:=SrcVar
5317*03ce13f7SAndroid Build Coastguard Worker   if (*Var == nullptr)
5318*03ce13f7SAndroid Build Coastguard Worker     return false;
5319*03ce13f7SAndroid Build Coastguard Worker   const Inst *VarAssign = VMetadata->getSingleDefinition(*Var);
5320*03ce13f7SAndroid Build Coastguard Worker   if (!VarAssign)
5321*03ce13f7SAndroid Build Coastguard Worker     return false;
5322*03ce13f7SAndroid Build Coastguard Worker   assert(!VMetadata->isMultiDef(*Var));
5323*03ce13f7SAndroid Build Coastguard Worker   if (!llvm::isa<InstAssign>(VarAssign))
5324*03ce13f7SAndroid Build Coastguard Worker     return false;
5325*03ce13f7SAndroid Build Coastguard Worker 
5326*03ce13f7SAndroid Build Coastguard Worker   Operand *SrcOp = VarAssign->getSrc(0);
5327*03ce13f7SAndroid Build Coastguard Worker   bool Optimized = false;
5328*03ce13f7SAndroid Build Coastguard Worker   if (auto *SrcVar = llvm::dyn_cast<Variable>(SrcOp)) {
5329*03ce13f7SAndroid Build Coastguard Worker     if (!VMetadata->isMultiDef(SrcVar) ||
5330*03ce13f7SAndroid Build Coastguard Worker         // TODO: ensure SrcVar stays single-BB
5331*03ce13f7SAndroid Build Coastguard Worker         false) {
5332*03ce13f7SAndroid Build Coastguard Worker       Optimized = true;
5333*03ce13f7SAndroid Build Coastguard Worker       *Var = SrcVar;
5334*03ce13f7SAndroid Build Coastguard Worker     } else if (auto *Const = llvm::dyn_cast<ConstantInteger32>(SrcOp)) {
5335*03ce13f7SAndroid Build Coastguard Worker       int32_t MoreOffset = Const->getValue();
5336*03ce13f7SAndroid Build Coastguard Worker       int32_t NewOffset = MoreOffset + *Offset;
5337*03ce13f7SAndroid Build Coastguard Worker       if (Utils::WouldOverflowAdd(*Offset, MoreOffset))
5338*03ce13f7SAndroid Build Coastguard Worker         return false;
5339*03ce13f7SAndroid Build Coastguard Worker       *Var = nullptr;
5340*03ce13f7SAndroid Build Coastguard Worker       *Offset += NewOffset;
5341*03ce13f7SAndroid Build Coastguard Worker       Optimized = true;
5342*03ce13f7SAndroid Build Coastguard Worker     }
5343*03ce13f7SAndroid Build Coastguard Worker   }
5344*03ce13f7SAndroid Build Coastguard Worker 
5345*03ce13f7SAndroid Build Coastguard Worker   if (Optimized) {
5346*03ce13f7SAndroid Build Coastguard Worker     *Reason = VarAssign;
5347*03ce13f7SAndroid Build Coastguard Worker   }
5348*03ce13f7SAndroid Build Coastguard Worker 
5349*03ce13f7SAndroid Build Coastguard Worker   return Optimized;
5350*03ce13f7SAndroid Build Coastguard Worker }
5351*03ce13f7SAndroid Build Coastguard Worker 
isAddOrSub(const Inst * Instr,InstArithmetic::OpKind * Kind)5352*03ce13f7SAndroid Build Coastguard Worker bool isAddOrSub(const Inst *Instr, InstArithmetic::OpKind *Kind) {
5353*03ce13f7SAndroid Build Coastguard Worker   if (const auto *Arith = llvm::dyn_cast<InstArithmetic>(Instr)) {
5354*03ce13f7SAndroid Build Coastguard Worker     switch (Arith->getOp()) {
5355*03ce13f7SAndroid Build Coastguard Worker     default:
5356*03ce13f7SAndroid Build Coastguard Worker       return false;
5357*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Add:
5358*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Sub:
5359*03ce13f7SAndroid Build Coastguard Worker       *Kind = Arith->getOp();
5360*03ce13f7SAndroid Build Coastguard Worker       return true;
5361*03ce13f7SAndroid Build Coastguard Worker     }
5362*03ce13f7SAndroid Build Coastguard Worker   }
5363*03ce13f7SAndroid Build Coastguard Worker   return false;
5364*03ce13f7SAndroid Build Coastguard Worker }
5365*03ce13f7SAndroid Build Coastguard Worker 
matchCombinedBaseIndex(const VariablesMetadata * VMetadata,Variable ** Base,Variable ** OffsetReg,int32_t OffsetRegShamt,const Inst ** Reason)5366*03ce13f7SAndroid Build Coastguard Worker bool matchCombinedBaseIndex(const VariablesMetadata *VMetadata, Variable **Base,
5367*03ce13f7SAndroid Build Coastguard Worker                             Variable **OffsetReg, int32_t OffsetRegShamt,
5368*03ce13f7SAndroid Build Coastguard Worker                             const Inst **Reason) {
5369*03ce13f7SAndroid Build Coastguard Worker   // OffsetReg==nullptr && Base is Base=Var1+Var2 ==>
5370*03ce13f7SAndroid Build Coastguard Worker   //   set Base=Var1, OffsetReg=Var2, Shift=0
5371*03ce13f7SAndroid Build Coastguard Worker   if (*Base == nullptr)
5372*03ce13f7SAndroid Build Coastguard Worker     return false;
5373*03ce13f7SAndroid Build Coastguard Worker   if (*OffsetReg != nullptr)
5374*03ce13f7SAndroid Build Coastguard Worker     return false;
5375*03ce13f7SAndroid Build Coastguard Worker   (void)OffsetRegShamt;
5376*03ce13f7SAndroid Build Coastguard Worker   assert(OffsetRegShamt == 0);
5377*03ce13f7SAndroid Build Coastguard Worker   const Inst *BaseInst = VMetadata->getSingleDefinition(*Base);
5378*03ce13f7SAndroid Build Coastguard Worker   if (BaseInst == nullptr)
5379*03ce13f7SAndroid Build Coastguard Worker     return false;
5380*03ce13f7SAndroid Build Coastguard Worker   assert(!VMetadata->isMultiDef(*Base));
5381*03ce13f7SAndroid Build Coastguard Worker   if (BaseInst->getSrcSize() < 2)
5382*03ce13f7SAndroid Build Coastguard Worker     return false;
5383*03ce13f7SAndroid Build Coastguard Worker   auto *Var1 = llvm::dyn_cast<Variable>(BaseInst->getSrc(0));
5384*03ce13f7SAndroid Build Coastguard Worker   if (!Var1)
5385*03ce13f7SAndroid Build Coastguard Worker     return false;
5386*03ce13f7SAndroid Build Coastguard Worker   if (VMetadata->isMultiDef(Var1))
5387*03ce13f7SAndroid Build Coastguard Worker     return false;
5388*03ce13f7SAndroid Build Coastguard Worker   auto *Var2 = llvm::dyn_cast<Variable>(BaseInst->getSrc(1));
5389*03ce13f7SAndroid Build Coastguard Worker   if (!Var2)
5390*03ce13f7SAndroid Build Coastguard Worker     return false;
5391*03ce13f7SAndroid Build Coastguard Worker   if (VMetadata->isMultiDef(Var2))
5392*03ce13f7SAndroid Build Coastguard Worker     return false;
5393*03ce13f7SAndroid Build Coastguard Worker   InstArithmetic::OpKind _;
5394*03ce13f7SAndroid Build Coastguard Worker   if (!isAddOrSub(BaseInst, &_) ||
5395*03ce13f7SAndroid Build Coastguard Worker       // TODO: ensure Var1 and Var2 stay single-BB
5396*03ce13f7SAndroid Build Coastguard Worker       false)
5397*03ce13f7SAndroid Build Coastguard Worker     return false;
5398*03ce13f7SAndroid Build Coastguard Worker   *Base = Var1;
5399*03ce13f7SAndroid Build Coastguard Worker   *OffsetReg = Var2;
5400*03ce13f7SAndroid Build Coastguard Worker   // OffsetRegShamt is already 0.
5401*03ce13f7SAndroid Build Coastguard Worker   *Reason = BaseInst;
5402*03ce13f7SAndroid Build Coastguard Worker   return true;
5403*03ce13f7SAndroid Build Coastguard Worker }
5404*03ce13f7SAndroid Build Coastguard Worker 
matchShiftedOffsetReg(const VariablesMetadata * VMetadata,Variable ** OffsetReg,OperandARM32::ShiftKind * Kind,int32_t * OffsetRegShamt,const Inst ** Reason)5405*03ce13f7SAndroid Build Coastguard Worker bool matchShiftedOffsetReg(const VariablesMetadata *VMetadata,
5406*03ce13f7SAndroid Build Coastguard Worker                            Variable **OffsetReg, OperandARM32::ShiftKind *Kind,
5407*03ce13f7SAndroid Build Coastguard Worker                            int32_t *OffsetRegShamt, const Inst **Reason) {
5408*03ce13f7SAndroid Build Coastguard Worker   // OffsetReg is OffsetReg=Var*Const && log2(Const)+Shift<=32 ==>
5409*03ce13f7SAndroid Build Coastguard Worker   //   OffsetReg=Var, Shift+=log2(Const)
5410*03ce13f7SAndroid Build Coastguard Worker   // OffsetReg is OffsetReg=Var<<Const && Const+Shift<=32 ==>
5411*03ce13f7SAndroid Build Coastguard Worker   //   OffsetReg=Var, Shift+=Const
5412*03ce13f7SAndroid Build Coastguard Worker   // OffsetReg is OffsetReg=Var>>Const && Const-Shift>=-32 ==>
5413*03ce13f7SAndroid Build Coastguard Worker   //   OffsetReg=Var, Shift-=Const
5414*03ce13f7SAndroid Build Coastguard Worker   OperandARM32::ShiftKind NewShiftKind = OperandARM32::kNoShift;
5415*03ce13f7SAndroid Build Coastguard Worker   if (*OffsetReg == nullptr)
5416*03ce13f7SAndroid Build Coastguard Worker     return false;
5417*03ce13f7SAndroid Build Coastguard Worker   auto *IndexInst = VMetadata->getSingleDefinition(*OffsetReg);
5418*03ce13f7SAndroid Build Coastguard Worker   if (IndexInst == nullptr)
5419*03ce13f7SAndroid Build Coastguard Worker     return false;
5420*03ce13f7SAndroid Build Coastguard Worker   assert(!VMetadata->isMultiDef(*OffsetReg));
5421*03ce13f7SAndroid Build Coastguard Worker   if (IndexInst->getSrcSize() < 2)
5422*03ce13f7SAndroid Build Coastguard Worker     return false;
5423*03ce13f7SAndroid Build Coastguard Worker   auto *ArithInst = llvm::dyn_cast<InstArithmetic>(IndexInst);
5424*03ce13f7SAndroid Build Coastguard Worker   if (ArithInst == nullptr)
5425*03ce13f7SAndroid Build Coastguard Worker     return false;
5426*03ce13f7SAndroid Build Coastguard Worker   auto *Var = llvm::dyn_cast<Variable>(ArithInst->getSrc(0));
5427*03ce13f7SAndroid Build Coastguard Worker   if (Var == nullptr)
5428*03ce13f7SAndroid Build Coastguard Worker     return false;
5429*03ce13f7SAndroid Build Coastguard Worker   auto *Const = llvm::dyn_cast<ConstantInteger32>(ArithInst->getSrc(1));
5430*03ce13f7SAndroid Build Coastguard Worker   if (Const == nullptr) {
5431*03ce13f7SAndroid Build Coastguard Worker     assert(!llvm::isa<ConstantInteger32>(ArithInst->getSrc(0)));
5432*03ce13f7SAndroid Build Coastguard Worker     return false;
5433*03ce13f7SAndroid Build Coastguard Worker   }
5434*03ce13f7SAndroid Build Coastguard Worker   if (VMetadata->isMultiDef(Var) || Const->getType() != IceType_i32)
5435*03ce13f7SAndroid Build Coastguard Worker     return false;
5436*03ce13f7SAndroid Build Coastguard Worker 
5437*03ce13f7SAndroid Build Coastguard Worker   uint32_t NewShamt = -1;
5438*03ce13f7SAndroid Build Coastguard Worker   switch (ArithInst->getOp()) {
5439*03ce13f7SAndroid Build Coastguard Worker   default:
5440*03ce13f7SAndroid Build Coastguard Worker     return false;
5441*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Shl: {
5442*03ce13f7SAndroid Build Coastguard Worker     NewShiftKind = OperandARM32::LSL;
5443*03ce13f7SAndroid Build Coastguard Worker     NewShamt = Const->getValue();
5444*03ce13f7SAndroid Build Coastguard Worker     if (NewShamt > 31)
5445*03ce13f7SAndroid Build Coastguard Worker       return false;
5446*03ce13f7SAndroid Build Coastguard Worker   } break;
5447*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Lshr: {
5448*03ce13f7SAndroid Build Coastguard Worker     NewShiftKind = OperandARM32::LSR;
5449*03ce13f7SAndroid Build Coastguard Worker     NewShamt = Const->getValue();
5450*03ce13f7SAndroid Build Coastguard Worker     if (NewShamt > 31)
5451*03ce13f7SAndroid Build Coastguard Worker       return false;
5452*03ce13f7SAndroid Build Coastguard Worker   } break;
5453*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Ashr: {
5454*03ce13f7SAndroid Build Coastguard Worker     NewShiftKind = OperandARM32::ASR;
5455*03ce13f7SAndroid Build Coastguard Worker     NewShamt = Const->getValue();
5456*03ce13f7SAndroid Build Coastguard Worker     if (NewShamt > 31)
5457*03ce13f7SAndroid Build Coastguard Worker       return false;
5458*03ce13f7SAndroid Build Coastguard Worker   } break;
5459*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Udiv:
5460*03ce13f7SAndroid Build Coastguard Worker   case InstArithmetic::Mul: {
5461*03ce13f7SAndroid Build Coastguard Worker     const uint32_t UnsignedConst = Const->getValue();
5462*03ce13f7SAndroid Build Coastguard Worker     NewShamt = llvm::findFirstSet(UnsignedConst);
5463*03ce13f7SAndroid Build Coastguard Worker     if (NewShamt != llvm::findLastSet(UnsignedConst)) {
5464*03ce13f7SAndroid Build Coastguard Worker       // First bit set is not the same as the last bit set, so Const is not
5465*03ce13f7SAndroid Build Coastguard Worker       // a power of 2.
5466*03ce13f7SAndroid Build Coastguard Worker       return false;
5467*03ce13f7SAndroid Build Coastguard Worker     }
5468*03ce13f7SAndroid Build Coastguard Worker     NewShiftKind = ArithInst->getOp() == InstArithmetic::Udiv
5469*03ce13f7SAndroid Build Coastguard Worker                        ? OperandARM32::LSR
5470*03ce13f7SAndroid Build Coastguard Worker                        : OperandARM32::LSL;
5471*03ce13f7SAndroid Build Coastguard Worker   } break;
5472*03ce13f7SAndroid Build Coastguard Worker   }
5473*03ce13f7SAndroid Build Coastguard Worker   // Allowed "transitions":
5474*03ce13f7SAndroid Build Coastguard Worker   //   kNoShift -> * iff NewShamt < 31
5475*03ce13f7SAndroid Build Coastguard Worker   //   LSL -> LSL    iff NewShamt + OffsetRegShamt < 31
5476*03ce13f7SAndroid Build Coastguard Worker   //   LSR -> LSR    iff NewShamt + OffsetRegShamt < 31
5477*03ce13f7SAndroid Build Coastguard Worker   //   ASR -> ASR    iff NewShamt + OffsetRegShamt < 31
5478*03ce13f7SAndroid Build Coastguard Worker   if (*Kind != OperandARM32::kNoShift && *Kind != NewShiftKind) {
5479*03ce13f7SAndroid Build Coastguard Worker     return false;
5480*03ce13f7SAndroid Build Coastguard Worker   }
5481*03ce13f7SAndroid Build Coastguard Worker   const int32_t NewOffsetRegShamt = *OffsetRegShamt + NewShamt;
5482*03ce13f7SAndroid Build Coastguard Worker   if (NewOffsetRegShamt > 31)
5483*03ce13f7SAndroid Build Coastguard Worker     return false;
5484*03ce13f7SAndroid Build Coastguard Worker   *OffsetReg = Var;
5485*03ce13f7SAndroid Build Coastguard Worker   *OffsetRegShamt = NewOffsetRegShamt;
5486*03ce13f7SAndroid Build Coastguard Worker   *Kind = NewShiftKind;
5487*03ce13f7SAndroid Build Coastguard Worker   *Reason = IndexInst;
5488*03ce13f7SAndroid Build Coastguard Worker   return true;
5489*03ce13f7SAndroid Build Coastguard Worker }
5490*03ce13f7SAndroid Build Coastguard Worker 
matchOffsetBase(const VariablesMetadata * VMetadata,Variable ** Base,int32_t * Offset,const Inst ** Reason)5491*03ce13f7SAndroid Build Coastguard Worker bool matchOffsetBase(const VariablesMetadata *VMetadata, Variable **Base,
5492*03ce13f7SAndroid Build Coastguard Worker                      int32_t *Offset, const Inst **Reason) {
5493*03ce13f7SAndroid Build Coastguard Worker   // Base is Base=Var+Const || Base is Base=Const+Var ==>
5494*03ce13f7SAndroid Build Coastguard Worker   //   set Base=Var, Offset+=Const
5495*03ce13f7SAndroid Build Coastguard Worker   // Base is Base=Var-Const ==>
5496*03ce13f7SAndroid Build Coastguard Worker   //   set Base=Var, Offset-=Const
5497*03ce13f7SAndroid Build Coastguard Worker   if (*Base == nullptr)
5498*03ce13f7SAndroid Build Coastguard Worker     return false;
5499*03ce13f7SAndroid Build Coastguard Worker   const Inst *BaseInst = VMetadata->getSingleDefinition(*Base);
5500*03ce13f7SAndroid Build Coastguard Worker   if (BaseInst == nullptr) {
5501*03ce13f7SAndroid Build Coastguard Worker     return false;
5502*03ce13f7SAndroid Build Coastguard Worker   }
5503*03ce13f7SAndroid Build Coastguard Worker   assert(!VMetadata->isMultiDef(*Base));
5504*03ce13f7SAndroid Build Coastguard Worker 
5505*03ce13f7SAndroid Build Coastguard Worker   auto *ArithInst = llvm::dyn_cast<const InstArithmetic>(BaseInst);
5506*03ce13f7SAndroid Build Coastguard Worker   if (ArithInst == nullptr)
5507*03ce13f7SAndroid Build Coastguard Worker     return false;
5508*03ce13f7SAndroid Build Coastguard Worker   InstArithmetic::OpKind Kind;
5509*03ce13f7SAndroid Build Coastguard Worker   if (!isAddOrSub(ArithInst, &Kind))
5510*03ce13f7SAndroid Build Coastguard Worker     return false;
5511*03ce13f7SAndroid Build Coastguard Worker   bool IsAdd = Kind == InstArithmetic::Add;
5512*03ce13f7SAndroid Build Coastguard Worker   Operand *Src0 = ArithInst->getSrc(0);
5513*03ce13f7SAndroid Build Coastguard Worker   Operand *Src1 = ArithInst->getSrc(1);
5514*03ce13f7SAndroid Build Coastguard Worker   auto *Var0 = llvm::dyn_cast<Variable>(Src0);
5515*03ce13f7SAndroid Build Coastguard Worker   auto *Var1 = llvm::dyn_cast<Variable>(Src1);
5516*03ce13f7SAndroid Build Coastguard Worker   auto *Const0 = llvm::dyn_cast<ConstantInteger32>(Src0);
5517*03ce13f7SAndroid Build Coastguard Worker   auto *Const1 = llvm::dyn_cast<ConstantInteger32>(Src1);
5518*03ce13f7SAndroid Build Coastguard Worker   Variable *NewBase = nullptr;
5519*03ce13f7SAndroid Build Coastguard Worker   int32_t NewOffset = *Offset;
5520*03ce13f7SAndroid Build Coastguard Worker 
5521*03ce13f7SAndroid Build Coastguard Worker   if (Var0 == nullptr && Const0 == nullptr) {
5522*03ce13f7SAndroid Build Coastguard Worker     assert(llvm::isa<ConstantRelocatable>(Src0));
5523*03ce13f7SAndroid Build Coastguard Worker     return false;
5524*03ce13f7SAndroid Build Coastguard Worker   }
5525*03ce13f7SAndroid Build Coastguard Worker 
5526*03ce13f7SAndroid Build Coastguard Worker   if (Var1 == nullptr && Const1 == nullptr) {
5527*03ce13f7SAndroid Build Coastguard Worker     assert(llvm::isa<ConstantRelocatable>(Src1));
5528*03ce13f7SAndroid Build Coastguard Worker     return false;
5529*03ce13f7SAndroid Build Coastguard Worker   }
5530*03ce13f7SAndroid Build Coastguard Worker 
5531*03ce13f7SAndroid Build Coastguard Worker   if (Var0 && Var1)
5532*03ce13f7SAndroid Build Coastguard Worker     // TODO(jpp): merge base/index splitting into here.
5533*03ce13f7SAndroid Build Coastguard Worker     return false;
5534*03ce13f7SAndroid Build Coastguard Worker   if (!IsAdd && Var1)
5535*03ce13f7SAndroid Build Coastguard Worker     return false;
5536*03ce13f7SAndroid Build Coastguard Worker   if (Var0)
5537*03ce13f7SAndroid Build Coastguard Worker     NewBase = Var0;
5538*03ce13f7SAndroid Build Coastguard Worker   else if (Var1)
5539*03ce13f7SAndroid Build Coastguard Worker     NewBase = Var1;
5540*03ce13f7SAndroid Build Coastguard Worker   // Compute the updated constant offset.
5541*03ce13f7SAndroid Build Coastguard Worker   if (Const0) {
5542*03ce13f7SAndroid Build Coastguard Worker     int32_t MoreOffset = IsAdd ? Const0->getValue() : -Const0->getValue();
5543*03ce13f7SAndroid Build Coastguard Worker     if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
5544*03ce13f7SAndroid Build Coastguard Worker       return false;
5545*03ce13f7SAndroid Build Coastguard Worker     NewOffset += MoreOffset;
5546*03ce13f7SAndroid Build Coastguard Worker   }
5547*03ce13f7SAndroid Build Coastguard Worker   if (Const1) {
5548*03ce13f7SAndroid Build Coastguard Worker     int32_t MoreOffset = IsAdd ? Const1->getValue() : -Const1->getValue();
5549*03ce13f7SAndroid Build Coastguard Worker     if (Utils::WouldOverflowAdd(NewOffset, MoreOffset))
5550*03ce13f7SAndroid Build Coastguard Worker       return false;
5551*03ce13f7SAndroid Build Coastguard Worker     NewOffset += MoreOffset;
5552*03ce13f7SAndroid Build Coastguard Worker   }
5553*03ce13f7SAndroid Build Coastguard Worker 
5554*03ce13f7SAndroid Build Coastguard Worker   // Update the computed address parameters once we are sure optimization
5555*03ce13f7SAndroid Build Coastguard Worker   // is valid.
5556*03ce13f7SAndroid Build Coastguard Worker   *Base = NewBase;
5557*03ce13f7SAndroid Build Coastguard Worker   *Offset = NewOffset;
5558*03ce13f7SAndroid Build Coastguard Worker   *Reason = BaseInst;
5559*03ce13f7SAndroid Build Coastguard Worker   return true;
5560*03ce13f7SAndroid Build Coastguard Worker }
5561*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
5562*03ce13f7SAndroid Build Coastguard Worker 
formAddressingMode(Type Ty,Cfg * Func,const Inst * LdSt,Operand * Base)5563*03ce13f7SAndroid Build Coastguard Worker OperandARM32Mem *TargetARM32::formAddressingMode(Type Ty, Cfg *Func,
5564*03ce13f7SAndroid Build Coastguard Worker                                                  const Inst *LdSt,
5565*03ce13f7SAndroid Build Coastguard Worker                                                  Operand *Base) {
5566*03ce13f7SAndroid Build Coastguard Worker   assert(Base != nullptr);
5567*03ce13f7SAndroid Build Coastguard Worker   int32_t OffsetImm = 0;
5568*03ce13f7SAndroid Build Coastguard Worker   Variable *OffsetReg = nullptr;
5569*03ce13f7SAndroid Build Coastguard Worker   int32_t OffsetRegShamt = 0;
5570*03ce13f7SAndroid Build Coastguard Worker   OperandARM32::ShiftKind ShiftKind = OperandARM32::kNoShift;
5571*03ce13f7SAndroid Build Coastguard Worker 
5572*03ce13f7SAndroid Build Coastguard Worker   Func->resetCurrentNode();
5573*03ce13f7SAndroid Build Coastguard Worker   if (Func->isVerbose(IceV_AddrOpt)) {
5574*03ce13f7SAndroid Build Coastguard Worker     OstreamLocker _(Func->getContext());
5575*03ce13f7SAndroid Build Coastguard Worker     Ostream &Str = Func->getContext()->getStrDump();
5576*03ce13f7SAndroid Build Coastguard Worker     Str << "\nAddress mode formation:\t";
5577*03ce13f7SAndroid Build Coastguard Worker     LdSt->dumpDecorated(Func);
5578*03ce13f7SAndroid Build Coastguard Worker   }
5579*03ce13f7SAndroid Build Coastguard Worker 
5580*03ce13f7SAndroid Build Coastguard Worker   if (isVectorType(Ty))
5581*03ce13f7SAndroid Build Coastguard Worker     // vector loads and stores do not allow offsets, and only support the
5582*03ce13f7SAndroid Build Coastguard Worker     // "[reg]" addressing mode (the other supported modes are write back.)
5583*03ce13f7SAndroid Build Coastguard Worker     return nullptr;
5584*03ce13f7SAndroid Build Coastguard Worker 
5585*03ce13f7SAndroid Build Coastguard Worker   auto *BaseVar = llvm::dyn_cast<Variable>(Base);
5586*03ce13f7SAndroid Build Coastguard Worker   if (BaseVar == nullptr)
5587*03ce13f7SAndroid Build Coastguard Worker     return nullptr;
5588*03ce13f7SAndroid Build Coastguard Worker 
5589*03ce13f7SAndroid Build Coastguard Worker   (void)MemTraitsSize;
5590*03ce13f7SAndroid Build Coastguard Worker   assert(Ty < MemTraitsSize);
5591*03ce13f7SAndroid Build Coastguard Worker   auto *TypeTraits = &MemTraits[Ty];
5592*03ce13f7SAndroid Build Coastguard Worker   const bool CanHaveIndex = TypeTraits->CanHaveIndex;
5593*03ce13f7SAndroid Build Coastguard Worker   const bool CanHaveShiftedIndex = TypeTraits->CanHaveShiftedIndex;
5594*03ce13f7SAndroid Build Coastguard Worker   const bool CanHaveImm = TypeTraits->CanHaveImm;
5595*03ce13f7SAndroid Build Coastguard Worker   const int32_t ValidImmMask = TypeTraits->ValidImmMask;
5596*03ce13f7SAndroid Build Coastguard Worker   (void)ValidImmMask;
5597*03ce13f7SAndroid Build Coastguard Worker   assert(!CanHaveImm || ValidImmMask >= 0);
5598*03ce13f7SAndroid Build Coastguard Worker 
5599*03ce13f7SAndroid Build Coastguard Worker   const VariablesMetadata *VMetadata = Func->getVMetadata();
5600*03ce13f7SAndroid Build Coastguard Worker   const Inst *Reason = nullptr;
5601*03ce13f7SAndroid Build Coastguard Worker 
5602*03ce13f7SAndroid Build Coastguard Worker   do {
5603*03ce13f7SAndroid Build Coastguard Worker     if (Reason != nullptr) {
5604*03ce13f7SAndroid Build Coastguard Worker       dumpAddressOpt(Func, BaseVar, OffsetImm, OffsetReg, OffsetRegShamt,
5605*03ce13f7SAndroid Build Coastguard Worker                      Reason);
5606*03ce13f7SAndroid Build Coastguard Worker       Reason = nullptr;
5607*03ce13f7SAndroid Build Coastguard Worker     }
5608*03ce13f7SAndroid Build Coastguard Worker 
5609*03ce13f7SAndroid Build Coastguard Worker     if (matchAssign(VMetadata, &BaseVar, &OffsetImm, &Reason)) {
5610*03ce13f7SAndroid Build Coastguard Worker       continue;
5611*03ce13f7SAndroid Build Coastguard Worker     }
5612*03ce13f7SAndroid Build Coastguard Worker 
5613*03ce13f7SAndroid Build Coastguard Worker     if (CanHaveIndex &&
5614*03ce13f7SAndroid Build Coastguard Worker         matchAssign(VMetadata, &OffsetReg, &OffsetImm, &Reason)) {
5615*03ce13f7SAndroid Build Coastguard Worker       continue;
5616*03ce13f7SAndroid Build Coastguard Worker     }
5617*03ce13f7SAndroid Build Coastguard Worker 
5618*03ce13f7SAndroid Build Coastguard Worker     if (CanHaveIndex && matchCombinedBaseIndex(VMetadata, &BaseVar, &OffsetReg,
5619*03ce13f7SAndroid Build Coastguard Worker                                                OffsetRegShamt, &Reason)) {
5620*03ce13f7SAndroid Build Coastguard Worker       continue;
5621*03ce13f7SAndroid Build Coastguard Worker     }
5622*03ce13f7SAndroid Build Coastguard Worker 
5623*03ce13f7SAndroid Build Coastguard Worker     if (CanHaveShiftedIndex) {
5624*03ce13f7SAndroid Build Coastguard Worker       if (matchShiftedOffsetReg(VMetadata, &OffsetReg, &ShiftKind,
5625*03ce13f7SAndroid Build Coastguard Worker                                 &OffsetRegShamt, &Reason)) {
5626*03ce13f7SAndroid Build Coastguard Worker         continue;
5627*03ce13f7SAndroid Build Coastguard Worker       }
5628*03ce13f7SAndroid Build Coastguard Worker 
5629*03ce13f7SAndroid Build Coastguard Worker       if ((OffsetRegShamt == 0) &&
5630*03ce13f7SAndroid Build Coastguard Worker           matchShiftedOffsetReg(VMetadata, &BaseVar, &ShiftKind,
5631*03ce13f7SAndroid Build Coastguard Worker                                 &OffsetRegShamt, &Reason)) {
5632*03ce13f7SAndroid Build Coastguard Worker         std::swap(BaseVar, OffsetReg);
5633*03ce13f7SAndroid Build Coastguard Worker         continue;
5634*03ce13f7SAndroid Build Coastguard Worker       }
5635*03ce13f7SAndroid Build Coastguard Worker     }
5636*03ce13f7SAndroid Build Coastguard Worker 
5637*03ce13f7SAndroid Build Coastguard Worker     if (matchOffsetBase(VMetadata, &BaseVar, &OffsetImm, &Reason)) {
5638*03ce13f7SAndroid Build Coastguard Worker       continue;
5639*03ce13f7SAndroid Build Coastguard Worker     }
5640*03ce13f7SAndroid Build Coastguard Worker   } while (Reason);
5641*03ce13f7SAndroid Build Coastguard Worker 
5642*03ce13f7SAndroid Build Coastguard Worker   if (BaseVar == nullptr) {
5643*03ce13f7SAndroid Build Coastguard Worker     // [OffsetReg{, LSL Shamt}{, #OffsetImm}] is not legal in ARM, so we have to
5644*03ce13f7SAndroid Build Coastguard Worker     // legalize the addressing mode to [BaseReg, OffsetReg{, LSL Shamt}].
5645*03ce13f7SAndroid Build Coastguard Worker     // Instead of a zeroed BaseReg, we initialize it with OffsetImm:
5646*03ce13f7SAndroid Build Coastguard Worker     //
5647*03ce13f7SAndroid Build Coastguard Worker     // [OffsetReg{, LSL Shamt}{, #OffsetImm}] ->
5648*03ce13f7SAndroid Build Coastguard Worker     //     mov BaseReg, #OffsetImm
5649*03ce13f7SAndroid Build Coastguard Worker     //     use of [BaseReg, OffsetReg{, LSL Shamt}]
5650*03ce13f7SAndroid Build Coastguard Worker     //
5651*03ce13f7SAndroid Build Coastguard Worker     const Type PointerType = getPointerType();
5652*03ce13f7SAndroid Build Coastguard Worker     BaseVar = makeReg(PointerType);
5653*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstAssign>(BaseVar, Ctx->getConstantInt32(OffsetImm));
5654*03ce13f7SAndroid Build Coastguard Worker     OffsetImm = 0;
5655*03ce13f7SAndroid Build Coastguard Worker   } else if (OffsetImm != 0) {
5656*03ce13f7SAndroid Build Coastguard Worker     // ARM Ldr/Str instructions have limited range immediates. The formation
5657*03ce13f7SAndroid Build Coastguard Worker     // loop above materialized an Immediate carelessly, so we ensure the
5658*03ce13f7SAndroid Build Coastguard Worker     // generated offset is sane.
5659*03ce13f7SAndroid Build Coastguard Worker     const int32_t PositiveOffset = OffsetImm > 0 ? OffsetImm : -OffsetImm;
5660*03ce13f7SAndroid Build Coastguard Worker     const InstArithmetic::OpKind Op =
5661*03ce13f7SAndroid Build Coastguard Worker         OffsetImm > 0 ? InstArithmetic::Add : InstArithmetic::Sub;
5662*03ce13f7SAndroid Build Coastguard Worker 
5663*03ce13f7SAndroid Build Coastguard Worker     if (!CanHaveImm || !isLegalMemOffset(Ty, OffsetImm) ||
5664*03ce13f7SAndroid Build Coastguard Worker         OffsetReg != nullptr) {
5665*03ce13f7SAndroid Build Coastguard Worker       if (OffsetReg == nullptr) {
5666*03ce13f7SAndroid Build Coastguard Worker         // We formed a [Base, #const] addressing mode which is not encodable in
5667*03ce13f7SAndroid Build Coastguard Worker         // ARM. There is little point in forming an address mode now if we don't
5668*03ce13f7SAndroid Build Coastguard Worker         // have an offset. Effectively, we would end up with something like
5669*03ce13f7SAndroid Build Coastguard Worker         //
5670*03ce13f7SAndroid Build Coastguard Worker         // [Base, #const] -> add T, Base, #const
5671*03ce13f7SAndroid Build Coastguard Worker         //                   use of [T]
5672*03ce13f7SAndroid Build Coastguard Worker         //
5673*03ce13f7SAndroid Build Coastguard Worker         // Which is exactly what we already have. So we just bite the bullet
5674*03ce13f7SAndroid Build Coastguard Worker         // here and don't form any address mode.
5675*03ce13f7SAndroid Build Coastguard Worker         return nullptr;
5676*03ce13f7SAndroid Build Coastguard Worker       }
5677*03ce13f7SAndroid Build Coastguard Worker       // We formed [Base, Offset {, LSL Amnt}, #const]. Oops. Legalize it to
5678*03ce13f7SAndroid Build Coastguard Worker       //
5679*03ce13f7SAndroid Build Coastguard Worker       // [Base, Offset, {LSL amount}, #const] ->
5680*03ce13f7SAndroid Build Coastguard Worker       //      add T, Base, #const
5681*03ce13f7SAndroid Build Coastguard Worker       //      use of [T, Offset {, LSL amount}]
5682*03ce13f7SAndroid Build Coastguard Worker       const Type PointerType = getPointerType();
5683*03ce13f7SAndroid Build Coastguard Worker       Variable *T = makeReg(PointerType);
5684*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstArithmetic>(Op, T, BaseVar,
5685*03ce13f7SAndroid Build Coastguard Worker                                      Ctx->getConstantInt32(PositiveOffset));
5686*03ce13f7SAndroid Build Coastguard Worker       BaseVar = T;
5687*03ce13f7SAndroid Build Coastguard Worker       OffsetImm = 0;
5688*03ce13f7SAndroid Build Coastguard Worker     }
5689*03ce13f7SAndroid Build Coastguard Worker   }
5690*03ce13f7SAndroid Build Coastguard Worker 
5691*03ce13f7SAndroid Build Coastguard Worker   assert(BaseVar != nullptr);
5692*03ce13f7SAndroid Build Coastguard Worker   assert(OffsetImm == 0 || OffsetReg == nullptr);
5693*03ce13f7SAndroid Build Coastguard Worker   assert(OffsetReg == nullptr || CanHaveIndex);
5694*03ce13f7SAndroid Build Coastguard Worker   assert(OffsetImm < 0 ? (ValidImmMask & -OffsetImm) == -OffsetImm
5695*03ce13f7SAndroid Build Coastguard Worker                        : (ValidImmMask & OffsetImm) == OffsetImm);
5696*03ce13f7SAndroid Build Coastguard Worker 
5697*03ce13f7SAndroid Build Coastguard Worker   if (OffsetReg != nullptr) {
5698*03ce13f7SAndroid Build Coastguard Worker     Variable *OffsetR = makeReg(getPointerType());
5699*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstAssign>(OffsetR, OffsetReg);
5700*03ce13f7SAndroid Build Coastguard Worker     return OperandARM32Mem::create(Func, Ty, BaseVar, OffsetR, ShiftKind,
5701*03ce13f7SAndroid Build Coastguard Worker                                    OffsetRegShamt);
5702*03ce13f7SAndroid Build Coastguard Worker   }
5703*03ce13f7SAndroid Build Coastguard Worker 
5704*03ce13f7SAndroid Build Coastguard Worker   return OperandARM32Mem::create(
5705*03ce13f7SAndroid Build Coastguard Worker       Func, Ty, BaseVar,
5706*03ce13f7SAndroid Build Coastguard Worker       llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(OffsetImm)));
5707*03ce13f7SAndroid Build Coastguard Worker }
5708*03ce13f7SAndroid Build Coastguard Worker 
doAddressOptLoad()5709*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::doAddressOptLoad() {
5710*03ce13f7SAndroid Build Coastguard Worker   Inst *Instr = iteratorToInst(Context.getCur());
5711*03ce13f7SAndroid Build Coastguard Worker   assert(llvm::isa<InstLoad>(Instr));
5712*03ce13f7SAndroid Build Coastguard Worker   Variable *Dest = Instr->getDest();
5713*03ce13f7SAndroid Build Coastguard Worker   Operand *Addr = Instr->getSrc(0);
5714*03ce13f7SAndroid Build Coastguard Worker   if (OperandARM32Mem *Mem =
5715*03ce13f7SAndroid Build Coastguard Worker           formAddressingMode(Dest->getType(), Func, Instr, Addr)) {
5716*03ce13f7SAndroid Build Coastguard Worker     Instr->setDeleted();
5717*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstLoad>(Dest, Mem);
5718*03ce13f7SAndroid Build Coastguard Worker   }
5719*03ce13f7SAndroid Build Coastguard Worker }
5720*03ce13f7SAndroid Build Coastguard Worker 
lowerPhi(const InstPhi *)5721*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerPhi(const InstPhi * /*Instr*/) {
5722*03ce13f7SAndroid Build Coastguard Worker   Func->setError("Phi found in regular instruction list");
5723*03ce13f7SAndroid Build Coastguard Worker }
5724*03ce13f7SAndroid Build Coastguard Worker 
lowerRet(const InstRet * Instr)5725*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerRet(const InstRet *Instr) {
5726*03ce13f7SAndroid Build Coastguard Worker   Variable *Reg = nullptr;
5727*03ce13f7SAndroid Build Coastguard Worker   if (Instr->hasRetValue()) {
5728*03ce13f7SAndroid Build Coastguard Worker     Operand *Src0 = Instr->getRetValue();
5729*03ce13f7SAndroid Build Coastguard Worker     Type Ty = Src0->getType();
5730*03ce13f7SAndroid Build Coastguard Worker     if (Ty == IceType_i64) {
5731*03ce13f7SAndroid Build Coastguard Worker       Src0 = legalizeUndef(Src0);
5732*03ce13f7SAndroid Build Coastguard Worker       Variable *R0 = legalizeToReg(loOperand(Src0), RegARM32::Reg_r0);
5733*03ce13f7SAndroid Build Coastguard Worker       Variable *R1 = legalizeToReg(hiOperand(Src0), RegARM32::Reg_r1);
5734*03ce13f7SAndroid Build Coastguard Worker       Reg = R0;
5735*03ce13f7SAndroid Build Coastguard Worker       Context.insert<InstFakeUse>(R1);
5736*03ce13f7SAndroid Build Coastguard Worker     } else if (Ty == IceType_f32) {
5737*03ce13f7SAndroid Build Coastguard Worker       Variable *S0 = legalizeToReg(Src0, RegARM32::Reg_s0);
5738*03ce13f7SAndroid Build Coastguard Worker       Reg = S0;
5739*03ce13f7SAndroid Build Coastguard Worker     } else if (Ty == IceType_f64) {
5740*03ce13f7SAndroid Build Coastguard Worker       Variable *D0 = legalizeToReg(Src0, RegARM32::Reg_d0);
5741*03ce13f7SAndroid Build Coastguard Worker       Reg = D0;
5742*03ce13f7SAndroid Build Coastguard Worker     } else if (isVectorType(Src0->getType())) {
5743*03ce13f7SAndroid Build Coastguard Worker       Variable *Q0 = legalizeToReg(Src0, RegARM32::Reg_q0);
5744*03ce13f7SAndroid Build Coastguard Worker       Reg = Q0;
5745*03ce13f7SAndroid Build Coastguard Worker     } else {
5746*03ce13f7SAndroid Build Coastguard Worker       Operand *Src0F = legalize(Src0, Legal_Reg | Legal_Flex);
5747*03ce13f7SAndroid Build Coastguard Worker       Reg = makeReg(Src0F->getType(), RegARM32::Reg_r0);
5748*03ce13f7SAndroid Build Coastguard Worker       _mov(Reg, Src0F, CondARM32::AL);
5749*03ce13f7SAndroid Build Coastguard Worker     }
5750*03ce13f7SAndroid Build Coastguard Worker   }
5751*03ce13f7SAndroid Build Coastguard Worker   // Add a ret instruction even if sandboxing is enabled, because addEpilog
5752*03ce13f7SAndroid Build Coastguard Worker   // explicitly looks for a ret instruction as a marker for where to insert the
5753*03ce13f7SAndroid Build Coastguard Worker   // frame removal instructions. addEpilog is responsible for restoring the
5754*03ce13f7SAndroid Build Coastguard Worker   // "lr" register as needed prior to this ret instruction.
5755*03ce13f7SAndroid Build Coastguard Worker   _ret(getPhysicalRegister(RegARM32::Reg_lr), Reg);
5756*03ce13f7SAndroid Build Coastguard Worker 
5757*03ce13f7SAndroid Build Coastguard Worker   // Add a fake use of sp to make sure sp stays alive for the entire function.
5758*03ce13f7SAndroid Build Coastguard Worker   // Otherwise post-call sp adjustments get dead-code eliminated.
5759*03ce13f7SAndroid Build Coastguard Worker   // TODO: Are there more places where the fake use should be inserted? E.g.
5760*03ce13f7SAndroid Build Coastguard Worker   // "void f(int n){while(1) g(n);}" may not have a ret instruction.
5761*03ce13f7SAndroid Build Coastguard Worker   Variable *SP = getPhysicalRegister(RegARM32::Reg_sp);
5762*03ce13f7SAndroid Build Coastguard Worker   Context.insert<InstFakeUse>(SP);
5763*03ce13f7SAndroid Build Coastguard Worker }
5764*03ce13f7SAndroid Build Coastguard Worker 
lowerShuffleVector(const InstShuffleVector * Instr)5765*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerShuffleVector(const InstShuffleVector *Instr) {
5766*03ce13f7SAndroid Build Coastguard Worker   auto *Dest = Instr->getDest();
5767*03ce13f7SAndroid Build Coastguard Worker   const Type DestTy = Dest->getType();
5768*03ce13f7SAndroid Build Coastguard Worker 
5769*03ce13f7SAndroid Build Coastguard Worker   auto *T = makeReg(DestTy);
5770*03ce13f7SAndroid Build Coastguard Worker   auto *Src0 = Instr->getSrc(0);
5771*03ce13f7SAndroid Build Coastguard Worker   auto *Src1 = Instr->getSrc(1);
5772*03ce13f7SAndroid Build Coastguard Worker   const SizeT NumElements = typeNumElements(DestTy);
5773*03ce13f7SAndroid Build Coastguard Worker   const Type ElementType = typeElementType(DestTy);
5774*03ce13f7SAndroid Build Coastguard Worker 
5775*03ce13f7SAndroid Build Coastguard Worker   bool Replicate = true;
5776*03ce13f7SAndroid Build Coastguard Worker   for (SizeT I = 1; Replicate && I < Instr->getNumIndexes(); ++I) {
5777*03ce13f7SAndroid Build Coastguard Worker     if (Instr->getIndexValue(I) != Instr->getIndexValue(0)) {
5778*03ce13f7SAndroid Build Coastguard Worker       Replicate = false;
5779*03ce13f7SAndroid Build Coastguard Worker     }
5780*03ce13f7SAndroid Build Coastguard Worker   }
5781*03ce13f7SAndroid Build Coastguard Worker 
5782*03ce13f7SAndroid Build Coastguard Worker   if (Replicate) {
5783*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0Var = legalizeToReg(Src0);
5784*03ce13f7SAndroid Build Coastguard Worker     _vdup(T, Src0Var, Instr->getIndexValue(0));
5785*03ce13f7SAndroid Build Coastguard Worker     _mov(Dest, T);
5786*03ce13f7SAndroid Build Coastguard Worker     return;
5787*03ce13f7SAndroid Build Coastguard Worker   }
5788*03ce13f7SAndroid Build Coastguard Worker 
5789*03ce13f7SAndroid Build Coastguard Worker   switch (DestTy) {
5790*03ce13f7SAndroid Build Coastguard Worker   case IceType_v8i1:
5791*03ce13f7SAndroid Build Coastguard Worker   case IceType_v8i16: {
5792*03ce13f7SAndroid Build Coastguard Worker     static constexpr SizeT ExpectedNumElements = 8;
5793*03ce13f7SAndroid Build Coastguard Worker     assert(ExpectedNumElements == Instr->getNumIndexes());
5794*03ce13f7SAndroid Build Coastguard Worker     (void)ExpectedNumElements;
5795*03ce13f7SAndroid Build Coastguard Worker 
5796*03ce13f7SAndroid Build Coastguard Worker     if (Instr->indexesAre(0, 0, 1, 1, 2, 2, 3, 3)) {
5797*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R = legalizeToReg(Src0);
5798*03ce13f7SAndroid Build Coastguard Worker       _vzip(T, Src0R, Src0R);
5799*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
5800*03ce13f7SAndroid Build Coastguard Worker       return;
5801*03ce13f7SAndroid Build Coastguard Worker     }
5802*03ce13f7SAndroid Build Coastguard Worker 
5803*03ce13f7SAndroid Build Coastguard Worker     if (Instr->indexesAre(0, 8, 1, 9, 2, 10, 3, 11)) {
5804*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R = legalizeToReg(Src0);
5805*03ce13f7SAndroid Build Coastguard Worker       Variable *Src1R = legalizeToReg(Src1);
5806*03ce13f7SAndroid Build Coastguard Worker       _vzip(T, Src0R, Src1R);
5807*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
5808*03ce13f7SAndroid Build Coastguard Worker       return;
5809*03ce13f7SAndroid Build Coastguard Worker     }
5810*03ce13f7SAndroid Build Coastguard Worker 
5811*03ce13f7SAndroid Build Coastguard Worker     if (Instr->indexesAre(0, 2, 4, 6, 0, 2, 4, 6)) {
5812*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R = legalizeToReg(Src0);
5813*03ce13f7SAndroid Build Coastguard Worker       _vqmovn2(T, Src0R, Src0R, false, false);
5814*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
5815*03ce13f7SAndroid Build Coastguard Worker       return;
5816*03ce13f7SAndroid Build Coastguard Worker     }
5817*03ce13f7SAndroid Build Coastguard Worker   } break;
5818*03ce13f7SAndroid Build Coastguard Worker   case IceType_v16i1:
5819*03ce13f7SAndroid Build Coastguard Worker   case IceType_v16i8: {
5820*03ce13f7SAndroid Build Coastguard Worker     static constexpr SizeT ExpectedNumElements = 16;
5821*03ce13f7SAndroid Build Coastguard Worker     assert(ExpectedNumElements == Instr->getNumIndexes());
5822*03ce13f7SAndroid Build Coastguard Worker     (void)ExpectedNumElements;
5823*03ce13f7SAndroid Build Coastguard Worker 
5824*03ce13f7SAndroid Build Coastguard Worker     if (Instr->indexesAre(0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7)) {
5825*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R = legalizeToReg(Src0);
5826*03ce13f7SAndroid Build Coastguard Worker       _vzip(T, Src0R, Src0R);
5827*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
5828*03ce13f7SAndroid Build Coastguard Worker       return;
5829*03ce13f7SAndroid Build Coastguard Worker     }
5830*03ce13f7SAndroid Build Coastguard Worker 
5831*03ce13f7SAndroid Build Coastguard Worker     if (Instr->indexesAre(0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7,
5832*03ce13f7SAndroid Build Coastguard Worker                           23)) {
5833*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R = legalizeToReg(Src0);
5834*03ce13f7SAndroid Build Coastguard Worker       Variable *Src1R = legalizeToReg(Src1);
5835*03ce13f7SAndroid Build Coastguard Worker       _vzip(T, Src0R, Src1R);
5836*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
5837*03ce13f7SAndroid Build Coastguard Worker       return;
5838*03ce13f7SAndroid Build Coastguard Worker     }
5839*03ce13f7SAndroid Build Coastguard Worker   } break;
5840*03ce13f7SAndroid Build Coastguard Worker   case IceType_v4i1:
5841*03ce13f7SAndroid Build Coastguard Worker   case IceType_v4i32:
5842*03ce13f7SAndroid Build Coastguard Worker   case IceType_v4f32: {
5843*03ce13f7SAndroid Build Coastguard Worker     static constexpr SizeT ExpectedNumElements = 4;
5844*03ce13f7SAndroid Build Coastguard Worker     assert(ExpectedNumElements == Instr->getNumIndexes());
5845*03ce13f7SAndroid Build Coastguard Worker     (void)ExpectedNumElements;
5846*03ce13f7SAndroid Build Coastguard Worker 
5847*03ce13f7SAndroid Build Coastguard Worker     if (Instr->indexesAre(0, 0, 1, 1)) {
5848*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R = legalizeToReg(Src0);
5849*03ce13f7SAndroid Build Coastguard Worker       _vzip(T, Src0R, Src0R);
5850*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
5851*03ce13f7SAndroid Build Coastguard Worker       return;
5852*03ce13f7SAndroid Build Coastguard Worker     }
5853*03ce13f7SAndroid Build Coastguard Worker 
5854*03ce13f7SAndroid Build Coastguard Worker     if (Instr->indexesAre(0, 4, 1, 5)) {
5855*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R = legalizeToReg(Src0);
5856*03ce13f7SAndroid Build Coastguard Worker       Variable *Src1R = legalizeToReg(Src1);
5857*03ce13f7SAndroid Build Coastguard Worker       _vzip(T, Src0R, Src1R);
5858*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
5859*03ce13f7SAndroid Build Coastguard Worker       return;
5860*03ce13f7SAndroid Build Coastguard Worker     }
5861*03ce13f7SAndroid Build Coastguard Worker 
5862*03ce13f7SAndroid Build Coastguard Worker     if (Instr->indexesAre(0, 1, 4, 5)) {
5863*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R = legalizeToReg(Src0);
5864*03ce13f7SAndroid Build Coastguard Worker       Variable *Src1R = legalizeToReg(Src1);
5865*03ce13f7SAndroid Build Coastguard Worker       _vmovlh(T, Src0R, Src1R);
5866*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
5867*03ce13f7SAndroid Build Coastguard Worker       return;
5868*03ce13f7SAndroid Build Coastguard Worker     }
5869*03ce13f7SAndroid Build Coastguard Worker 
5870*03ce13f7SAndroid Build Coastguard Worker     if (Instr->indexesAre(2, 3, 2, 3)) {
5871*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R = legalizeToReg(Src0);
5872*03ce13f7SAndroid Build Coastguard Worker       _vmovhl(T, Src0R, Src0R);
5873*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
5874*03ce13f7SAndroid Build Coastguard Worker       return;
5875*03ce13f7SAndroid Build Coastguard Worker     }
5876*03ce13f7SAndroid Build Coastguard Worker 
5877*03ce13f7SAndroid Build Coastguard Worker     if (Instr->indexesAre(2, 3, 6, 7)) {
5878*03ce13f7SAndroid Build Coastguard Worker       Variable *Src0R = legalizeToReg(Src0);
5879*03ce13f7SAndroid Build Coastguard Worker       Variable *Src1R = legalizeToReg(Src1);
5880*03ce13f7SAndroid Build Coastguard Worker       _vmovhl(T, Src1R, Src0R);
5881*03ce13f7SAndroid Build Coastguard Worker       _mov(Dest, T);
5882*03ce13f7SAndroid Build Coastguard Worker       return;
5883*03ce13f7SAndroid Build Coastguard Worker     }
5884*03ce13f7SAndroid Build Coastguard Worker   } break;
5885*03ce13f7SAndroid Build Coastguard Worker   default:
5886*03ce13f7SAndroid Build Coastguard Worker     break;
5887*03ce13f7SAndroid Build Coastguard Worker     // TODO(jpp): figure out how to properly lower this without scalarization.
5888*03ce13f7SAndroid Build Coastguard Worker   }
5889*03ce13f7SAndroid Build Coastguard Worker 
5890*03ce13f7SAndroid Build Coastguard Worker   // Unoptimized shuffle. Perform a series of inserts and extracts.
5891*03ce13f7SAndroid Build Coastguard Worker   Context.insert<InstFakeDef>(T);
5892*03ce13f7SAndroid Build Coastguard Worker   for (SizeT I = 0; I < Instr->getNumIndexes(); ++I) {
5893*03ce13f7SAndroid Build Coastguard Worker     auto *Index = Instr->getIndex(I);
5894*03ce13f7SAndroid Build Coastguard Worker     const SizeT Elem = Index->getValue();
5895*03ce13f7SAndroid Build Coastguard Worker     auto *ExtElmt = makeReg(ElementType);
5896*03ce13f7SAndroid Build Coastguard Worker     if (Elem < NumElements) {
5897*03ce13f7SAndroid Build Coastguard Worker       lowerExtractElement(
5898*03ce13f7SAndroid Build Coastguard Worker           InstExtractElement::create(Func, ExtElmt, Src0, Index));
5899*03ce13f7SAndroid Build Coastguard Worker     } else {
5900*03ce13f7SAndroid Build Coastguard Worker       lowerExtractElement(InstExtractElement::create(
5901*03ce13f7SAndroid Build Coastguard Worker           Func, ExtElmt, Src1,
5902*03ce13f7SAndroid Build Coastguard Worker           Ctx->getConstantInt32(Index->getValue() - NumElements)));
5903*03ce13f7SAndroid Build Coastguard Worker     }
5904*03ce13f7SAndroid Build Coastguard Worker     auto *NewT = makeReg(DestTy);
5905*03ce13f7SAndroid Build Coastguard Worker     lowerInsertElement(InstInsertElement::create(Func, NewT, T, ExtElmt,
5906*03ce13f7SAndroid Build Coastguard Worker                                                  Ctx->getConstantInt32(I)));
5907*03ce13f7SAndroid Build Coastguard Worker     T = NewT;
5908*03ce13f7SAndroid Build Coastguard Worker   }
5909*03ce13f7SAndroid Build Coastguard Worker   _mov(Dest, T);
5910*03ce13f7SAndroid Build Coastguard Worker }
5911*03ce13f7SAndroid Build Coastguard Worker 
lowerSelect(const InstSelect * Instr)5912*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerSelect(const InstSelect *Instr) {
5913*03ce13f7SAndroid Build Coastguard Worker   Variable *Dest = Instr->getDest();
5914*03ce13f7SAndroid Build Coastguard Worker   Type DestTy = Dest->getType();
5915*03ce13f7SAndroid Build Coastguard Worker   Operand *SrcT = Instr->getTrueOperand();
5916*03ce13f7SAndroid Build Coastguard Worker   Operand *SrcF = Instr->getFalseOperand();
5917*03ce13f7SAndroid Build Coastguard Worker   Operand *Condition = Instr->getCondition();
5918*03ce13f7SAndroid Build Coastguard Worker 
5919*03ce13f7SAndroid Build Coastguard Worker   if (!isVectorType(DestTy)) {
5920*03ce13f7SAndroid Build Coastguard Worker     lowerInt1ForSelect(Dest, Condition, legalizeUndef(SrcT),
5921*03ce13f7SAndroid Build Coastguard Worker                        legalizeUndef(SrcF));
5922*03ce13f7SAndroid Build Coastguard Worker     return;
5923*03ce13f7SAndroid Build Coastguard Worker   }
5924*03ce13f7SAndroid Build Coastguard Worker 
5925*03ce13f7SAndroid Build Coastguard Worker   Type TType = DestTy;
5926*03ce13f7SAndroid Build Coastguard Worker   switch (DestTy) {
5927*03ce13f7SAndroid Build Coastguard Worker   default:
5928*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Unexpected type for vector select.");
5929*03ce13f7SAndroid Build Coastguard Worker   case IceType_v4i1:
5930*03ce13f7SAndroid Build Coastguard Worker     TType = IceType_v4i32;
5931*03ce13f7SAndroid Build Coastguard Worker     break;
5932*03ce13f7SAndroid Build Coastguard Worker   case IceType_v8i1:
5933*03ce13f7SAndroid Build Coastguard Worker     TType = IceType_v8i16;
5934*03ce13f7SAndroid Build Coastguard Worker     break;
5935*03ce13f7SAndroid Build Coastguard Worker   case IceType_v16i1:
5936*03ce13f7SAndroid Build Coastguard Worker     TType = IceType_v16i8;
5937*03ce13f7SAndroid Build Coastguard Worker     break;
5938*03ce13f7SAndroid Build Coastguard Worker   case IceType_v4f32:
5939*03ce13f7SAndroid Build Coastguard Worker     TType = IceType_v4i32;
5940*03ce13f7SAndroid Build Coastguard Worker     break;
5941*03ce13f7SAndroid Build Coastguard Worker   case IceType_v4i32:
5942*03ce13f7SAndroid Build Coastguard Worker   case IceType_v8i16:
5943*03ce13f7SAndroid Build Coastguard Worker   case IceType_v16i8:
5944*03ce13f7SAndroid Build Coastguard Worker     break;
5945*03ce13f7SAndroid Build Coastguard Worker   }
5946*03ce13f7SAndroid Build Coastguard Worker   auto *T = makeReg(TType);
5947*03ce13f7SAndroid Build Coastguard Worker   lowerCast(InstCast::create(Func, InstCast::Sext, T, Condition));
5948*03ce13f7SAndroid Build Coastguard Worker   auto *SrcTR = legalizeToReg(SrcT);
5949*03ce13f7SAndroid Build Coastguard Worker   auto *SrcFR = legalizeToReg(SrcF);
5950*03ce13f7SAndroid Build Coastguard Worker   _vbsl(T, SrcTR, SrcFR)->setDestRedefined();
5951*03ce13f7SAndroid Build Coastguard Worker   _mov(Dest, T);
5952*03ce13f7SAndroid Build Coastguard Worker }
5953*03ce13f7SAndroid Build Coastguard Worker 
lowerStore(const InstStore * Instr)5954*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerStore(const InstStore *Instr) {
5955*03ce13f7SAndroid Build Coastguard Worker   Operand *Value = Instr->getData();
5956*03ce13f7SAndroid Build Coastguard Worker   Operand *Addr = Instr->getStoreAddress();
5957*03ce13f7SAndroid Build Coastguard Worker   OperandARM32Mem *NewAddr = formMemoryOperand(Addr, Value->getType());
5958*03ce13f7SAndroid Build Coastguard Worker   Type Ty = NewAddr->getType();
5959*03ce13f7SAndroid Build Coastguard Worker 
5960*03ce13f7SAndroid Build Coastguard Worker   if (Ty == IceType_i64) {
5961*03ce13f7SAndroid Build Coastguard Worker     Value = legalizeUndef(Value);
5962*03ce13f7SAndroid Build Coastguard Worker     Variable *ValueHi = legalizeToReg(hiOperand(Value));
5963*03ce13f7SAndroid Build Coastguard Worker     Variable *ValueLo = legalizeToReg(loOperand(Value));
5964*03ce13f7SAndroid Build Coastguard Worker     _str(ValueHi, llvm::cast<OperandARM32Mem>(hiOperand(NewAddr)));
5965*03ce13f7SAndroid Build Coastguard Worker     _str(ValueLo, llvm::cast<OperandARM32Mem>(loOperand(NewAddr)));
5966*03ce13f7SAndroid Build Coastguard Worker   } else {
5967*03ce13f7SAndroid Build Coastguard Worker     Variable *ValueR = legalizeToReg(Value);
5968*03ce13f7SAndroid Build Coastguard Worker     _str(ValueR, NewAddr);
5969*03ce13f7SAndroid Build Coastguard Worker   }
5970*03ce13f7SAndroid Build Coastguard Worker }
5971*03ce13f7SAndroid Build Coastguard Worker 
doAddressOptStore()5972*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::doAddressOptStore() {
5973*03ce13f7SAndroid Build Coastguard Worker   Inst *Instr = iteratorToInst(Context.getCur());
5974*03ce13f7SAndroid Build Coastguard Worker   assert(llvm::isa<InstStore>(Instr));
5975*03ce13f7SAndroid Build Coastguard Worker   Operand *Src = Instr->getSrc(0);
5976*03ce13f7SAndroid Build Coastguard Worker   Operand *Addr = Instr->getSrc(1);
5977*03ce13f7SAndroid Build Coastguard Worker   if (OperandARM32Mem *Mem =
5978*03ce13f7SAndroid Build Coastguard Worker           formAddressingMode(Src->getType(), Func, Instr, Addr)) {
5979*03ce13f7SAndroid Build Coastguard Worker     Instr->setDeleted();
5980*03ce13f7SAndroid Build Coastguard Worker     Context.insert<InstStore>(Src, Mem);
5981*03ce13f7SAndroid Build Coastguard Worker   }
5982*03ce13f7SAndroid Build Coastguard Worker }
5983*03ce13f7SAndroid Build Coastguard Worker 
lowerSwitch(const InstSwitch * Instr)5984*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerSwitch(const InstSwitch *Instr) {
5985*03ce13f7SAndroid Build Coastguard Worker   // This implements the most naive possible lowering.
5986*03ce13f7SAndroid Build Coastguard Worker   // cmp a,val[0]; jeq label[0]; cmp a,val[1]; jeq label[1]; ... jmp default
5987*03ce13f7SAndroid Build Coastguard Worker   Operand *Src0 = Instr->getComparison();
5988*03ce13f7SAndroid Build Coastguard Worker   SizeT NumCases = Instr->getNumCases();
5989*03ce13f7SAndroid Build Coastguard Worker   if (Src0->getType() == IceType_i64) {
5990*03ce13f7SAndroid Build Coastguard Worker     Src0 = legalizeUndef(Src0);
5991*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0Lo = legalizeToReg(loOperand(Src0));
5992*03ce13f7SAndroid Build Coastguard Worker     Variable *Src0Hi = legalizeToReg(hiOperand(Src0));
5993*03ce13f7SAndroid Build Coastguard Worker     for (SizeT I = 0; I < NumCases; ++I) {
5994*03ce13f7SAndroid Build Coastguard Worker       Operand *ValueLo = Ctx->getConstantInt32(Instr->getValue(I));
5995*03ce13f7SAndroid Build Coastguard Worker       Operand *ValueHi = Ctx->getConstantInt32(Instr->getValue(I) >> 32);
5996*03ce13f7SAndroid Build Coastguard Worker       ValueLo = legalize(ValueLo, Legal_Reg | Legal_Flex);
5997*03ce13f7SAndroid Build Coastguard Worker       ValueHi = legalize(ValueHi, Legal_Reg | Legal_Flex);
5998*03ce13f7SAndroid Build Coastguard Worker       _cmp(Src0Lo, ValueLo);
5999*03ce13f7SAndroid Build Coastguard Worker       _cmp(Src0Hi, ValueHi, CondARM32::EQ);
6000*03ce13f7SAndroid Build Coastguard Worker       _br(Instr->getLabel(I), CondARM32::EQ);
6001*03ce13f7SAndroid Build Coastguard Worker     }
6002*03ce13f7SAndroid Build Coastguard Worker     _br(Instr->getLabelDefault());
6003*03ce13f7SAndroid Build Coastguard Worker     return;
6004*03ce13f7SAndroid Build Coastguard Worker   }
6005*03ce13f7SAndroid Build Coastguard Worker 
6006*03ce13f7SAndroid Build Coastguard Worker   Variable *Src0Var = legalizeToReg(Src0);
6007*03ce13f7SAndroid Build Coastguard Worker   // If Src0 is not an i32, we left shift it -- see the icmp lowering for the
6008*03ce13f7SAndroid Build Coastguard Worker   // reason.
6009*03ce13f7SAndroid Build Coastguard Worker   assert(Src0Var->mustHaveReg());
6010*03ce13f7SAndroid Build Coastguard Worker   const size_t ShiftAmt = 32 - getScalarIntBitWidth(Src0->getType());
6011*03ce13f7SAndroid Build Coastguard Worker   assert(ShiftAmt < 32);
6012*03ce13f7SAndroid Build Coastguard Worker   if (ShiftAmt > 0) {
6013*03ce13f7SAndroid Build Coastguard Worker     Operand *ShAmtImm = shAmtImm(ShiftAmt);
6014*03ce13f7SAndroid Build Coastguard Worker     Variable *T = makeReg(IceType_i32);
6015*03ce13f7SAndroid Build Coastguard Worker     _lsl(T, Src0Var, ShAmtImm);
6016*03ce13f7SAndroid Build Coastguard Worker     Src0Var = T;
6017*03ce13f7SAndroid Build Coastguard Worker   }
6018*03ce13f7SAndroid Build Coastguard Worker 
6019*03ce13f7SAndroid Build Coastguard Worker   for (SizeT I = 0; I < NumCases; ++I) {
6020*03ce13f7SAndroid Build Coastguard Worker     Operand *Value = Ctx->getConstantInt32(Instr->getValue(I) << ShiftAmt);
6021*03ce13f7SAndroid Build Coastguard Worker     Value = legalize(Value, Legal_Reg | Legal_Flex);
6022*03ce13f7SAndroid Build Coastguard Worker     _cmp(Src0Var, Value);
6023*03ce13f7SAndroid Build Coastguard Worker     _br(Instr->getLabel(I), CondARM32::EQ);
6024*03ce13f7SAndroid Build Coastguard Worker   }
6025*03ce13f7SAndroid Build Coastguard Worker   _br(Instr->getLabelDefault());
6026*03ce13f7SAndroid Build Coastguard Worker }
6027*03ce13f7SAndroid Build Coastguard Worker 
lowerBreakpoint(const InstBreakpoint * Instr)6028*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerBreakpoint(const InstBreakpoint *Instr) {
6029*03ce13f7SAndroid Build Coastguard Worker   UnimplementedLoweringError(this, Instr);
6030*03ce13f7SAndroid Build Coastguard Worker }
6031*03ce13f7SAndroid Build Coastguard Worker 
lowerUnreachable(const InstUnreachable *)6032*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerUnreachable(const InstUnreachable * /*Instr*/) {
6033*03ce13f7SAndroid Build Coastguard Worker   _trap();
6034*03ce13f7SAndroid Build Coastguard Worker }
6035*03ce13f7SAndroid Build Coastguard Worker 
prelowerPhis()6036*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::prelowerPhis() {
6037*03ce13f7SAndroid Build Coastguard Worker   CfgNode *Node = Context.getNode();
6038*03ce13f7SAndroid Build Coastguard Worker   PhiLowering::prelowerPhis32Bit(this, Node, Func);
6039*03ce13f7SAndroid Build Coastguard Worker }
6040*03ce13f7SAndroid Build Coastguard Worker 
makeVectorOfZeros(Type Ty,RegNumT RegNum)6041*03ce13f7SAndroid Build Coastguard Worker Variable *TargetARM32::makeVectorOfZeros(Type Ty, RegNumT RegNum) {
6042*03ce13f7SAndroid Build Coastguard Worker   Variable *Reg = makeReg(Ty, RegNum);
6043*03ce13f7SAndroid Build Coastguard Worker   Context.insert<InstFakeDef>(Reg);
6044*03ce13f7SAndroid Build Coastguard Worker   assert(isVectorType(Ty));
6045*03ce13f7SAndroid Build Coastguard Worker   _veor(Reg, Reg, Reg);
6046*03ce13f7SAndroid Build Coastguard Worker   return Reg;
6047*03ce13f7SAndroid Build Coastguard Worker }
6048*03ce13f7SAndroid Build Coastguard Worker 
6049*03ce13f7SAndroid Build Coastguard Worker // Helper for legalize() to emit the right code to lower an operand to a
6050*03ce13f7SAndroid Build Coastguard Worker // register of the appropriate type.
copyToReg(Operand * Src,RegNumT RegNum)6051*03ce13f7SAndroid Build Coastguard Worker Variable *TargetARM32::copyToReg(Operand *Src, RegNumT RegNum) {
6052*03ce13f7SAndroid Build Coastguard Worker   Type Ty = Src->getType();
6053*03ce13f7SAndroid Build Coastguard Worker   Variable *Reg = makeReg(Ty, RegNum);
6054*03ce13f7SAndroid Build Coastguard Worker   if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Src)) {
6055*03ce13f7SAndroid Build Coastguard Worker     _ldr(Reg, Mem);
6056*03ce13f7SAndroid Build Coastguard Worker   } else {
6057*03ce13f7SAndroid Build Coastguard Worker     _mov(Reg, Src);
6058*03ce13f7SAndroid Build Coastguard Worker   }
6059*03ce13f7SAndroid Build Coastguard Worker   return Reg;
6060*03ce13f7SAndroid Build Coastguard Worker }
6061*03ce13f7SAndroid Build Coastguard Worker 
6062*03ce13f7SAndroid Build Coastguard Worker // TODO(jpp): remove unneeded else clauses in legalize.
legalize(Operand * From,LegalMask Allowed,RegNumT RegNum)6063*03ce13f7SAndroid Build Coastguard Worker Operand *TargetARM32::legalize(Operand *From, LegalMask Allowed,
6064*03ce13f7SAndroid Build Coastguard Worker                                RegNumT RegNum) {
6065*03ce13f7SAndroid Build Coastguard Worker   Type Ty = From->getType();
6066*03ce13f7SAndroid Build Coastguard Worker   // Assert that a physical register is allowed. To date, all calls to
6067*03ce13f7SAndroid Build Coastguard Worker   // legalize() allow a physical register. Legal_Flex converts registers to the
6068*03ce13f7SAndroid Build Coastguard Worker   // right type OperandARM32FlexReg as needed.
6069*03ce13f7SAndroid Build Coastguard Worker   assert(Allowed & Legal_Reg);
6070*03ce13f7SAndroid Build Coastguard Worker 
6071*03ce13f7SAndroid Build Coastguard Worker   // Copied ipsis literis from TargetX86Base<Machine>.
6072*03ce13f7SAndroid Build Coastguard Worker   if (RegNum.hasNoValue()) {
6073*03ce13f7SAndroid Build Coastguard Worker     if (Variable *Subst = getContext().availabilityGet(From)) {
6074*03ce13f7SAndroid Build Coastguard Worker       // At this point we know there is a potential substitution available.
6075*03ce13f7SAndroid Build Coastguard Worker       if (!Subst->isRematerializable() && Subst->mustHaveReg() &&
6076*03ce13f7SAndroid Build Coastguard Worker           !Subst->hasReg()) {
6077*03ce13f7SAndroid Build Coastguard Worker         // At this point we know the substitution will have a register.
6078*03ce13f7SAndroid Build Coastguard Worker         if (From->getType() == Subst->getType()) {
6079*03ce13f7SAndroid Build Coastguard Worker           // At this point we know the substitution's register is compatible.
6080*03ce13f7SAndroid Build Coastguard Worker           return Subst;
6081*03ce13f7SAndroid Build Coastguard Worker         }
6082*03ce13f7SAndroid Build Coastguard Worker       }
6083*03ce13f7SAndroid Build Coastguard Worker     }
6084*03ce13f7SAndroid Build Coastguard Worker   }
6085*03ce13f7SAndroid Build Coastguard Worker 
6086*03ce13f7SAndroid Build Coastguard Worker   // Go through the various types of operands: OperandARM32Mem,
6087*03ce13f7SAndroid Build Coastguard Worker   // OperandARM32Flex, Constant, and Variable. Given the above assertion, if
6088*03ce13f7SAndroid Build Coastguard Worker   // type of operand is not legal (e.g., OperandARM32Mem and !Legal_Mem), we
6089*03ce13f7SAndroid Build Coastguard Worker   // can always copy to a register.
6090*03ce13f7SAndroid Build Coastguard Worker   if (auto *Mem = llvm::dyn_cast<OperandARM32Mem>(From)) {
6091*03ce13f7SAndroid Build Coastguard Worker     // Before doing anything with a Mem operand, we need to ensure that the
6092*03ce13f7SAndroid Build Coastguard Worker     // Base and Index components are in physical registers.
6093*03ce13f7SAndroid Build Coastguard Worker     Variable *Base = Mem->getBase();
6094*03ce13f7SAndroid Build Coastguard Worker     Variable *Index = Mem->getIndex();
6095*03ce13f7SAndroid Build Coastguard Worker     ConstantInteger32 *Offset = Mem->getOffset();
6096*03ce13f7SAndroid Build Coastguard Worker     assert(Index == nullptr || Offset == nullptr);
6097*03ce13f7SAndroid Build Coastguard Worker     Variable *RegBase = nullptr;
6098*03ce13f7SAndroid Build Coastguard Worker     Variable *RegIndex = nullptr;
6099*03ce13f7SAndroid Build Coastguard Worker     assert(Base);
6100*03ce13f7SAndroid Build Coastguard Worker     RegBase = llvm::cast<Variable>(
6101*03ce13f7SAndroid Build Coastguard Worker         legalize(Base, Legal_Reg | Legal_Rematerializable));
6102*03ce13f7SAndroid Build Coastguard Worker     assert(Ty < MemTraitsSize);
6103*03ce13f7SAndroid Build Coastguard Worker     if (Index) {
6104*03ce13f7SAndroid Build Coastguard Worker       assert(Offset == nullptr);
6105*03ce13f7SAndroid Build Coastguard Worker       assert(MemTraits[Ty].CanHaveIndex);
6106*03ce13f7SAndroid Build Coastguard Worker       RegIndex = legalizeToReg(Index);
6107*03ce13f7SAndroid Build Coastguard Worker     }
6108*03ce13f7SAndroid Build Coastguard Worker     if (Offset && Offset->getValue() != 0) {
6109*03ce13f7SAndroid Build Coastguard Worker       assert(Index == nullptr);
6110*03ce13f7SAndroid Build Coastguard Worker       static constexpr bool ZeroExt = false;
6111*03ce13f7SAndroid Build Coastguard Worker       assert(MemTraits[Ty].CanHaveImm);
6112*03ce13f7SAndroid Build Coastguard Worker       if (!OperandARM32Mem::canHoldOffset(Ty, ZeroExt, Offset->getValue())) {
6113*03ce13f7SAndroid Build Coastguard Worker         llvm::report_fatal_error("Invalid memory offset.");
6114*03ce13f7SAndroid Build Coastguard Worker       }
6115*03ce13f7SAndroid Build Coastguard Worker     }
6116*03ce13f7SAndroid Build Coastguard Worker 
6117*03ce13f7SAndroid Build Coastguard Worker     // Create a new operand if there was a change.
6118*03ce13f7SAndroid Build Coastguard Worker     if (Base != RegBase || Index != RegIndex) {
6119*03ce13f7SAndroid Build Coastguard Worker       // There is only a reg +/- reg or reg + imm form.
6120*03ce13f7SAndroid Build Coastguard Worker       // Figure out which to re-create.
6121*03ce13f7SAndroid Build Coastguard Worker       if (RegIndex) {
6122*03ce13f7SAndroid Build Coastguard Worker         Mem = OperandARM32Mem::create(Func, Ty, RegBase, RegIndex,
6123*03ce13f7SAndroid Build Coastguard Worker                                       Mem->getShiftOp(), Mem->getShiftAmt(),
6124*03ce13f7SAndroid Build Coastguard Worker                                       Mem->getAddrMode());
6125*03ce13f7SAndroid Build Coastguard Worker       } else {
6126*03ce13f7SAndroid Build Coastguard Worker         Mem = OperandARM32Mem::create(Func, Ty, RegBase, Offset,
6127*03ce13f7SAndroid Build Coastguard Worker                                       Mem->getAddrMode());
6128*03ce13f7SAndroid Build Coastguard Worker       }
6129*03ce13f7SAndroid Build Coastguard Worker     }
6130*03ce13f7SAndroid Build Coastguard Worker     if (Allowed & Legal_Mem) {
6131*03ce13f7SAndroid Build Coastguard Worker       From = Mem;
6132*03ce13f7SAndroid Build Coastguard Worker     } else {
6133*03ce13f7SAndroid Build Coastguard Worker       Variable *Reg = makeReg(Ty, RegNum);
6134*03ce13f7SAndroid Build Coastguard Worker       _ldr(Reg, Mem);
6135*03ce13f7SAndroid Build Coastguard Worker       From = Reg;
6136*03ce13f7SAndroid Build Coastguard Worker     }
6137*03ce13f7SAndroid Build Coastguard Worker     return From;
6138*03ce13f7SAndroid Build Coastguard Worker   }
6139*03ce13f7SAndroid Build Coastguard Worker 
6140*03ce13f7SAndroid Build Coastguard Worker   if (auto *Flex = llvm::dyn_cast<OperandARM32Flex>(From)) {
6141*03ce13f7SAndroid Build Coastguard Worker     if (!(Allowed & Legal_Flex)) {
6142*03ce13f7SAndroid Build Coastguard Worker       if (auto *FlexReg = llvm::dyn_cast<OperandARM32FlexReg>(Flex)) {
6143*03ce13f7SAndroid Build Coastguard Worker         if (FlexReg->getShiftOp() == OperandARM32::kNoShift) {
6144*03ce13f7SAndroid Build Coastguard Worker           From = FlexReg->getReg();
6145*03ce13f7SAndroid Build Coastguard Worker           // Fall through and let From be checked as a Variable below, where it
6146*03ce13f7SAndroid Build Coastguard Worker           // may or may not need a register.
6147*03ce13f7SAndroid Build Coastguard Worker         } else {
6148*03ce13f7SAndroid Build Coastguard Worker           return copyToReg(Flex, RegNum);
6149*03ce13f7SAndroid Build Coastguard Worker         }
6150*03ce13f7SAndroid Build Coastguard Worker       } else {
6151*03ce13f7SAndroid Build Coastguard Worker         return copyToReg(Flex, RegNum);
6152*03ce13f7SAndroid Build Coastguard Worker       }
6153*03ce13f7SAndroid Build Coastguard Worker     } else {
6154*03ce13f7SAndroid Build Coastguard Worker       return From;
6155*03ce13f7SAndroid Build Coastguard Worker     }
6156*03ce13f7SAndroid Build Coastguard Worker   }
6157*03ce13f7SAndroid Build Coastguard Worker 
6158*03ce13f7SAndroid Build Coastguard Worker   if (llvm::isa<Constant>(From)) {
6159*03ce13f7SAndroid Build Coastguard Worker     if (llvm::isa<ConstantUndef>(From)) {
6160*03ce13f7SAndroid Build Coastguard Worker       From = legalizeUndef(From, RegNum);
6161*03ce13f7SAndroid Build Coastguard Worker       if (isVectorType(Ty))
6162*03ce13f7SAndroid Build Coastguard Worker         return From;
6163*03ce13f7SAndroid Build Coastguard Worker     }
6164*03ce13f7SAndroid Build Coastguard Worker     // There should be no constants of vector type (other than undef).
6165*03ce13f7SAndroid Build Coastguard Worker     assert(!isVectorType(Ty));
6166*03ce13f7SAndroid Build Coastguard Worker     if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) {
6167*03ce13f7SAndroid Build Coastguard Worker       uint32_t RotateAmt;
6168*03ce13f7SAndroid Build Coastguard Worker       uint32_t Immed_8;
6169*03ce13f7SAndroid Build Coastguard Worker       uint32_t Value = static_cast<uint32_t>(C32->getValue());
6170*03ce13f7SAndroid Build Coastguard Worker       if (OperandARM32FlexImm::canHoldImm(Value, &RotateAmt, &Immed_8)) {
6171*03ce13f7SAndroid Build Coastguard Worker         // The immediate can be encoded as a Flex immediate. We may return the
6172*03ce13f7SAndroid Build Coastguard Worker         // Flex operand if the caller has Allow'ed it.
6173*03ce13f7SAndroid Build Coastguard Worker         auto *OpF = OperandARM32FlexImm::create(Func, Ty, Immed_8, RotateAmt);
6174*03ce13f7SAndroid Build Coastguard Worker         const bool CanBeFlex = Allowed & Legal_Flex;
6175*03ce13f7SAndroid Build Coastguard Worker         if (CanBeFlex)
6176*03ce13f7SAndroid Build Coastguard Worker           return OpF;
6177*03ce13f7SAndroid Build Coastguard Worker         return copyToReg(OpF, RegNum);
6178*03ce13f7SAndroid Build Coastguard Worker       } else if (OperandARM32FlexImm::canHoldImm(~Value, &RotateAmt,
6179*03ce13f7SAndroid Build Coastguard Worker                                                  &Immed_8)) {
6180*03ce13f7SAndroid Build Coastguard Worker         // Even though the immediate can't be encoded as a Flex operand, its
6181*03ce13f7SAndroid Build Coastguard Worker         // inverted bit pattern can, thus we use ARM's mvn to load the 32-bit
6182*03ce13f7SAndroid Build Coastguard Worker         // constant with a single instruction.
6183*03ce13f7SAndroid Build Coastguard Worker         auto *InvOpF =
6184*03ce13f7SAndroid Build Coastguard Worker             OperandARM32FlexImm::create(Func, Ty, Immed_8, RotateAmt);
6185*03ce13f7SAndroid Build Coastguard Worker         Variable *Reg = makeReg(Ty, RegNum);
6186*03ce13f7SAndroid Build Coastguard Worker         _mvn(Reg, InvOpF);
6187*03ce13f7SAndroid Build Coastguard Worker         return Reg;
6188*03ce13f7SAndroid Build Coastguard Worker       } else {
6189*03ce13f7SAndroid Build Coastguard Worker         // Do a movw/movt to a register.
6190*03ce13f7SAndroid Build Coastguard Worker         Variable *Reg = makeReg(Ty, RegNum);
6191*03ce13f7SAndroid Build Coastguard Worker         uint32_t UpperBits = (Value >> 16) & 0xFFFF;
6192*03ce13f7SAndroid Build Coastguard Worker         _movw(Reg,
6193*03ce13f7SAndroid Build Coastguard Worker               UpperBits != 0 ? Ctx->getConstantInt32(Value & 0xFFFF) : C32);
6194*03ce13f7SAndroid Build Coastguard Worker         if (UpperBits != 0) {
6195*03ce13f7SAndroid Build Coastguard Worker           _movt(Reg, Ctx->getConstantInt32(UpperBits));
6196*03ce13f7SAndroid Build Coastguard Worker         }
6197*03ce13f7SAndroid Build Coastguard Worker         return Reg;
6198*03ce13f7SAndroid Build Coastguard Worker       }
6199*03ce13f7SAndroid Build Coastguard Worker     } else if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) {
6200*03ce13f7SAndroid Build Coastguard Worker       Variable *Reg = makeReg(Ty, RegNum);
6201*03ce13f7SAndroid Build Coastguard Worker       _movw(Reg, C);
6202*03ce13f7SAndroid Build Coastguard Worker       _movt(Reg, C);
6203*03ce13f7SAndroid Build Coastguard Worker       return Reg;
6204*03ce13f7SAndroid Build Coastguard Worker     } else {
6205*03ce13f7SAndroid Build Coastguard Worker       assert(isScalarFloatingType(Ty));
6206*03ce13f7SAndroid Build Coastguard Worker       uint32_t ModifiedImm;
6207*03ce13f7SAndroid Build Coastguard Worker       if (OperandARM32FlexFpImm::canHoldImm(From, &ModifiedImm)) {
6208*03ce13f7SAndroid Build Coastguard Worker         Variable *T = makeReg(Ty, RegNum);
6209*03ce13f7SAndroid Build Coastguard Worker         _mov(T,
6210*03ce13f7SAndroid Build Coastguard Worker              OperandARM32FlexFpImm::create(Func, From->getType(), ModifiedImm));
6211*03ce13f7SAndroid Build Coastguard Worker         return T;
6212*03ce13f7SAndroid Build Coastguard Worker       }
6213*03ce13f7SAndroid Build Coastguard Worker 
6214*03ce13f7SAndroid Build Coastguard Worker       if (Ty == IceType_f64 && isFloatingPointZero(From)) {
6215*03ce13f7SAndroid Build Coastguard Worker         // Use T = T ^ T to load a 64-bit fp zero. This does not work for f32
6216*03ce13f7SAndroid Build Coastguard Worker         // because ARM does not have a veor instruction with S registers.
6217*03ce13f7SAndroid Build Coastguard Worker         Variable *T = makeReg(IceType_f64, RegNum);
6218*03ce13f7SAndroid Build Coastguard Worker         Context.insert<InstFakeDef>(T);
6219*03ce13f7SAndroid Build Coastguard Worker         _veor(T, T, T);
6220*03ce13f7SAndroid Build Coastguard Worker         return T;
6221*03ce13f7SAndroid Build Coastguard Worker       }
6222*03ce13f7SAndroid Build Coastguard Worker 
6223*03ce13f7SAndroid Build Coastguard Worker       // Load floats/doubles from literal pool.
6224*03ce13f7SAndroid Build Coastguard Worker       auto *CFrom = llvm::cast<Constant>(From);
6225*03ce13f7SAndroid Build Coastguard Worker       assert(CFrom->getShouldBePooled());
6226*03ce13f7SAndroid Build Coastguard Worker       Constant *Offset = Ctx->getConstantSym(0, CFrom->getLabelName());
6227*03ce13f7SAndroid Build Coastguard Worker       Variable *BaseReg = makeReg(getPointerType());
6228*03ce13f7SAndroid Build Coastguard Worker       _movw(BaseReg, Offset);
6229*03ce13f7SAndroid Build Coastguard Worker       _movt(BaseReg, Offset);
6230*03ce13f7SAndroid Build Coastguard Worker       From = formMemoryOperand(BaseReg, Ty);
6231*03ce13f7SAndroid Build Coastguard Worker       return copyToReg(From, RegNum);
6232*03ce13f7SAndroid Build Coastguard Worker     }
6233*03ce13f7SAndroid Build Coastguard Worker   }
6234*03ce13f7SAndroid Build Coastguard Worker 
6235*03ce13f7SAndroid Build Coastguard Worker   if (auto *Var = llvm::dyn_cast<Variable>(From)) {
6236*03ce13f7SAndroid Build Coastguard Worker     if (Var->isRematerializable()) {
6237*03ce13f7SAndroid Build Coastguard Worker       if (Allowed & Legal_Rematerializable) {
6238*03ce13f7SAndroid Build Coastguard Worker         return From;
6239*03ce13f7SAndroid Build Coastguard Worker       }
6240*03ce13f7SAndroid Build Coastguard Worker 
6241*03ce13f7SAndroid Build Coastguard Worker       Variable *T = makeReg(Var->getType(), RegNum);
6242*03ce13f7SAndroid Build Coastguard Worker       _mov(T, Var);
6243*03ce13f7SAndroid Build Coastguard Worker       return T;
6244*03ce13f7SAndroid Build Coastguard Worker     }
6245*03ce13f7SAndroid Build Coastguard Worker     // Check if the variable is guaranteed a physical register. This can happen
6246*03ce13f7SAndroid Build Coastguard Worker     // either when the variable is pre-colored or when it is assigned infinite
6247*03ce13f7SAndroid Build Coastguard Worker     // weight.
6248*03ce13f7SAndroid Build Coastguard Worker     bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg());
6249*03ce13f7SAndroid Build Coastguard Worker     // We need a new physical register for the operand if:
6250*03ce13f7SAndroid Build Coastguard Worker     //   Mem is not allowed and Var isn't guaranteed a physical
6251*03ce13f7SAndroid Build Coastguard Worker     //   register, or
6252*03ce13f7SAndroid Build Coastguard Worker     //   RegNum is required and Var->getRegNum() doesn't match.
6253*03ce13f7SAndroid Build Coastguard Worker     if ((!(Allowed & Legal_Mem) && !MustHaveRegister) ||
6254*03ce13f7SAndroid Build Coastguard Worker         (RegNum.hasValue() && (RegNum != Var->getRegNum()))) {
6255*03ce13f7SAndroid Build Coastguard Worker       From = copyToReg(From, RegNum);
6256*03ce13f7SAndroid Build Coastguard Worker     }
6257*03ce13f7SAndroid Build Coastguard Worker     return From;
6258*03ce13f7SAndroid Build Coastguard Worker   }
6259*03ce13f7SAndroid Build Coastguard Worker   llvm::report_fatal_error("Unhandled operand kind in legalize()");
6260*03ce13f7SAndroid Build Coastguard Worker 
6261*03ce13f7SAndroid Build Coastguard Worker   return From;
6262*03ce13f7SAndroid Build Coastguard Worker }
6263*03ce13f7SAndroid Build Coastguard Worker 
6264*03ce13f7SAndroid Build Coastguard Worker /// Provide a trivial wrapper to legalize() for this common usage.
legalizeToReg(Operand * From,RegNumT RegNum)6265*03ce13f7SAndroid Build Coastguard Worker Variable *TargetARM32::legalizeToReg(Operand *From, RegNumT RegNum) {
6266*03ce13f7SAndroid Build Coastguard Worker   return llvm::cast<Variable>(legalize(From, Legal_Reg, RegNum));
6267*03ce13f7SAndroid Build Coastguard Worker }
6268*03ce13f7SAndroid Build Coastguard Worker 
6269*03ce13f7SAndroid Build Coastguard Worker /// Legalize undef values to concrete values.
legalizeUndef(Operand * From,RegNumT RegNum)6270*03ce13f7SAndroid Build Coastguard Worker Operand *TargetARM32::legalizeUndef(Operand *From, RegNumT RegNum) {
6271*03ce13f7SAndroid Build Coastguard Worker   Type Ty = From->getType();
6272*03ce13f7SAndroid Build Coastguard Worker   if (llvm::isa<ConstantUndef>(From)) {
6273*03ce13f7SAndroid Build Coastguard Worker     // Lower undefs to zero. Another option is to lower undefs to an
6274*03ce13f7SAndroid Build Coastguard Worker     // uninitialized register; however, using an uninitialized register results
6275*03ce13f7SAndroid Build Coastguard Worker     // in less predictable code.
6276*03ce13f7SAndroid Build Coastguard Worker     //
6277*03ce13f7SAndroid Build Coastguard Worker     // If in the future the implementation is changed to lower undef values to
6278*03ce13f7SAndroid Build Coastguard Worker     // uninitialized registers, a FakeDef will be needed:
6279*03ce13f7SAndroid Build Coastguard Worker     // Context.insert(InstFakeDef::create(Func, Reg)); This is in order to
6280*03ce13f7SAndroid Build Coastguard Worker     // ensure that the live range of Reg is not overestimated. If the constant
6281*03ce13f7SAndroid Build Coastguard Worker     // being lowered is a 64 bit value, then the result should be split and the
6282*03ce13f7SAndroid Build Coastguard Worker     // lo and hi components will need to go in uninitialized registers.
6283*03ce13f7SAndroid Build Coastguard Worker     if (isVectorType(Ty))
6284*03ce13f7SAndroid Build Coastguard Worker       return makeVectorOfZeros(Ty, RegNum);
6285*03ce13f7SAndroid Build Coastguard Worker     return Ctx->getConstantZero(Ty);
6286*03ce13f7SAndroid Build Coastguard Worker   }
6287*03ce13f7SAndroid Build Coastguard Worker   return From;
6288*03ce13f7SAndroid Build Coastguard Worker }
6289*03ce13f7SAndroid Build Coastguard Worker 
formMemoryOperand(Operand * Operand,Type Ty)6290*03ce13f7SAndroid Build Coastguard Worker OperandARM32Mem *TargetARM32::formMemoryOperand(Operand *Operand, Type Ty) {
6291*03ce13f7SAndroid Build Coastguard Worker   auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Operand);
6292*03ce13f7SAndroid Build Coastguard Worker   // It may be the case that address mode optimization already creates an
6293*03ce13f7SAndroid Build Coastguard Worker   // OperandARM32Mem, so in that case it wouldn't need another level of
6294*03ce13f7SAndroid Build Coastguard Worker   // transformation.
6295*03ce13f7SAndroid Build Coastguard Worker   if (Mem) {
6296*03ce13f7SAndroid Build Coastguard Worker     return llvm::cast<OperandARM32Mem>(legalize(Mem));
6297*03ce13f7SAndroid Build Coastguard Worker   }
6298*03ce13f7SAndroid Build Coastguard Worker   // If we didn't do address mode optimization, then we only have a
6299*03ce13f7SAndroid Build Coastguard Worker   // base/offset to work with. ARM always requires a base register, so
6300*03ce13f7SAndroid Build Coastguard Worker   // just use that to hold the operand.
6301*03ce13f7SAndroid Build Coastguard Worker   auto *Base = llvm::cast<Variable>(
6302*03ce13f7SAndroid Build Coastguard Worker       legalize(Operand, Legal_Reg | Legal_Rematerializable));
6303*03ce13f7SAndroid Build Coastguard Worker   return OperandARM32Mem::create(
6304*03ce13f7SAndroid Build Coastguard Worker       Func, Ty, Base,
6305*03ce13f7SAndroid Build Coastguard Worker       llvm::cast<ConstantInteger32>(Ctx->getConstantZero(IceType_i32)));
6306*03ce13f7SAndroid Build Coastguard Worker }
6307*03ce13f7SAndroid Build Coastguard Worker 
makeI64RegPair()6308*03ce13f7SAndroid Build Coastguard Worker Variable64On32 *TargetARM32::makeI64RegPair() {
6309*03ce13f7SAndroid Build Coastguard Worker   Variable64On32 *Reg =
6310*03ce13f7SAndroid Build Coastguard Worker       llvm::cast<Variable64On32>(Func->makeVariable(IceType_i64));
6311*03ce13f7SAndroid Build Coastguard Worker   Reg->setMustHaveReg();
6312*03ce13f7SAndroid Build Coastguard Worker   Reg->initHiLo(Func);
6313*03ce13f7SAndroid Build Coastguard Worker   Reg->getLo()->setMustNotHaveReg();
6314*03ce13f7SAndroid Build Coastguard Worker   Reg->getHi()->setMustNotHaveReg();
6315*03ce13f7SAndroid Build Coastguard Worker   return Reg;
6316*03ce13f7SAndroid Build Coastguard Worker }
6317*03ce13f7SAndroid Build Coastguard Worker 
makeReg(Type Type,RegNumT RegNum)6318*03ce13f7SAndroid Build Coastguard Worker Variable *TargetARM32::makeReg(Type Type, RegNumT RegNum) {
6319*03ce13f7SAndroid Build Coastguard Worker   // There aren't any 64-bit integer registers for ARM32.
6320*03ce13f7SAndroid Build Coastguard Worker   assert(Type != IceType_i64);
6321*03ce13f7SAndroid Build Coastguard Worker   assert(AllowTemporaryWithNoReg || RegNum.hasValue());
6322*03ce13f7SAndroid Build Coastguard Worker   Variable *Reg = Func->makeVariable(Type);
6323*03ce13f7SAndroid Build Coastguard Worker   if (RegNum.hasValue())
6324*03ce13f7SAndroid Build Coastguard Worker     Reg->setRegNum(RegNum);
6325*03ce13f7SAndroid Build Coastguard Worker   else
6326*03ce13f7SAndroid Build Coastguard Worker     Reg->setMustHaveReg();
6327*03ce13f7SAndroid Build Coastguard Worker   return Reg;
6328*03ce13f7SAndroid Build Coastguard Worker }
6329*03ce13f7SAndroid Build Coastguard Worker 
alignRegisterPow2(Variable * Reg,uint32_t Align,RegNumT TmpRegNum)6330*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::alignRegisterPow2(Variable *Reg, uint32_t Align,
6331*03ce13f7SAndroid Build Coastguard Worker                                     RegNumT TmpRegNum) {
6332*03ce13f7SAndroid Build Coastguard Worker   assert(llvm::isPowerOf2_32(Align));
6333*03ce13f7SAndroid Build Coastguard Worker   uint32_t RotateAmt;
6334*03ce13f7SAndroid Build Coastguard Worker   uint32_t Immed_8;
6335*03ce13f7SAndroid Build Coastguard Worker   Operand *Mask;
6336*03ce13f7SAndroid Build Coastguard Worker   // Use AND or BIC to mask off the bits, depending on which immediate fits (if
6337*03ce13f7SAndroid Build Coastguard Worker   // it fits at all). Assume Align is usually small, in which case BIC works
6338*03ce13f7SAndroid Build Coastguard Worker   // better. Thus, this rounds down to the alignment.
6339*03ce13f7SAndroid Build Coastguard Worker   if (OperandARM32FlexImm::canHoldImm(Align - 1, &RotateAmt, &Immed_8)) {
6340*03ce13f7SAndroid Build Coastguard Worker     Mask = legalize(Ctx->getConstantInt32(Align - 1), Legal_Reg | Legal_Flex,
6341*03ce13f7SAndroid Build Coastguard Worker                     TmpRegNum);
6342*03ce13f7SAndroid Build Coastguard Worker     _bic(Reg, Reg, Mask);
6343*03ce13f7SAndroid Build Coastguard Worker   } else {
6344*03ce13f7SAndroid Build Coastguard Worker     Mask = legalize(Ctx->getConstantInt32(-Align), Legal_Reg | Legal_Flex,
6345*03ce13f7SAndroid Build Coastguard Worker                     TmpRegNum);
6346*03ce13f7SAndroid Build Coastguard Worker     _and(Reg, Reg, Mask);
6347*03ce13f7SAndroid Build Coastguard Worker   }
6348*03ce13f7SAndroid Build Coastguard Worker }
6349*03ce13f7SAndroid Build Coastguard Worker 
postLower()6350*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::postLower() {
6351*03ce13f7SAndroid Build Coastguard Worker   if (Func->getOptLevel() == Opt_m1)
6352*03ce13f7SAndroid Build Coastguard Worker     return;
6353*03ce13f7SAndroid Build Coastguard Worker   markRedefinitions();
6354*03ce13f7SAndroid Build Coastguard Worker   Context.availabilityUpdate();
6355*03ce13f7SAndroid Build Coastguard Worker }
6356*03ce13f7SAndroid Build Coastguard Worker 
emit(const ConstantInteger32 * C) const6357*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::emit(const ConstantInteger32 *C) const {
6358*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::dump())
6359*03ce13f7SAndroid Build Coastguard Worker     return;
6360*03ce13f7SAndroid Build Coastguard Worker   Ostream &Str = Ctx->getStrEmit();
6361*03ce13f7SAndroid Build Coastguard Worker   Str << "#" << C->getValue();
6362*03ce13f7SAndroid Build Coastguard Worker }
6363*03ce13f7SAndroid Build Coastguard Worker 
emit(const ConstantInteger64 *) const6364*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::emit(const ConstantInteger64 *) const {
6365*03ce13f7SAndroid Build Coastguard Worker   llvm::report_fatal_error("Not expecting to emit 64-bit integers");
6366*03ce13f7SAndroid Build Coastguard Worker }
6367*03ce13f7SAndroid Build Coastguard Worker 
emit(const ConstantFloat * C) const6368*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::emit(const ConstantFloat *C) const {
6369*03ce13f7SAndroid Build Coastguard Worker   (void)C;
6370*03ce13f7SAndroid Build Coastguard Worker   UnimplementedError(getFlags());
6371*03ce13f7SAndroid Build Coastguard Worker }
6372*03ce13f7SAndroid Build Coastguard Worker 
emit(const ConstantDouble * C) const6373*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::emit(const ConstantDouble *C) const {
6374*03ce13f7SAndroid Build Coastguard Worker   (void)C;
6375*03ce13f7SAndroid Build Coastguard Worker   UnimplementedError(getFlags());
6376*03ce13f7SAndroid Build Coastguard Worker }
6377*03ce13f7SAndroid Build Coastguard Worker 
emit(const ConstantUndef *) const6378*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::emit(const ConstantUndef *) const {
6379*03ce13f7SAndroid Build Coastguard Worker   llvm::report_fatal_error("undef value encountered by emitter.");
6380*03ce13f7SAndroid Build Coastguard Worker }
6381*03ce13f7SAndroid Build Coastguard Worker 
emit(const ConstantRelocatable * C) const6382*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::emit(const ConstantRelocatable *C) const {
6383*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::dump())
6384*03ce13f7SAndroid Build Coastguard Worker     return;
6385*03ce13f7SAndroid Build Coastguard Worker   Ostream &Str = Ctx->getStrEmit();
6386*03ce13f7SAndroid Build Coastguard Worker   Str << "#";
6387*03ce13f7SAndroid Build Coastguard Worker   emitWithoutPrefix(C);
6388*03ce13f7SAndroid Build Coastguard Worker }
6389*03ce13f7SAndroid Build Coastguard Worker 
lowerInt1ForSelect(Variable * Dest,Operand * Boolean,Operand * TrueValue,Operand * FalseValue)6390*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::lowerInt1ForSelect(Variable *Dest, Operand *Boolean,
6391*03ce13f7SAndroid Build Coastguard Worker                                      Operand *TrueValue, Operand *FalseValue) {
6392*03ce13f7SAndroid Build Coastguard Worker   Operand *_1 = legalize(Ctx->getConstantInt1(1), Legal_Reg | Legal_Flex);
6393*03ce13f7SAndroid Build Coastguard Worker 
6394*03ce13f7SAndroid Build Coastguard Worker   assert(Boolean->getType() == IceType_i1);
6395*03ce13f7SAndroid Build Coastguard Worker 
6396*03ce13f7SAndroid Build Coastguard Worker   bool NeedsAnd1 = false;
6397*03ce13f7SAndroid Build Coastguard Worker   if (TrueValue->getType() == IceType_i1) {
6398*03ce13f7SAndroid Build Coastguard Worker     assert(FalseValue->getType() == IceType_i1);
6399*03ce13f7SAndroid Build Coastguard Worker 
6400*03ce13f7SAndroid Build Coastguard Worker     Variable *TrueValueV = Func->makeVariable(IceType_i1);
6401*03ce13f7SAndroid Build Coastguard Worker     SafeBoolChain Src0Safe = lowerInt1(TrueValueV, TrueValue);
6402*03ce13f7SAndroid Build Coastguard Worker     TrueValue = TrueValueV;
6403*03ce13f7SAndroid Build Coastguard Worker 
6404*03ce13f7SAndroid Build Coastguard Worker     Variable *FalseValueV = Func->makeVariable(IceType_i1);
6405*03ce13f7SAndroid Build Coastguard Worker     SafeBoolChain Src1Safe = lowerInt1(FalseValueV, FalseValue);
6406*03ce13f7SAndroid Build Coastguard Worker     FalseValue = FalseValueV;
6407*03ce13f7SAndroid Build Coastguard Worker 
6408*03ce13f7SAndroid Build Coastguard Worker     NeedsAnd1 = Src0Safe == SBC_No || Src1Safe == SBC_No;
6409*03ce13f7SAndroid Build Coastguard Worker   }
6410*03ce13f7SAndroid Build Coastguard Worker 
6411*03ce13f7SAndroid Build Coastguard Worker   Variable *DestLo = (Dest->getType() == IceType_i64)
6412*03ce13f7SAndroid Build Coastguard Worker                          ? llvm::cast<Variable>(loOperand(Dest))
6413*03ce13f7SAndroid Build Coastguard Worker                          : Dest;
6414*03ce13f7SAndroid Build Coastguard Worker   Variable *DestHi = (Dest->getType() == IceType_i64)
6415*03ce13f7SAndroid Build Coastguard Worker                          ? llvm::cast<Variable>(hiOperand(Dest))
6416*03ce13f7SAndroid Build Coastguard Worker                          : nullptr;
6417*03ce13f7SAndroid Build Coastguard Worker   Operand *FalseValueLo = (FalseValue->getType() == IceType_i64)
6418*03ce13f7SAndroid Build Coastguard Worker                               ? loOperand(FalseValue)
6419*03ce13f7SAndroid Build Coastguard Worker                               : FalseValue;
6420*03ce13f7SAndroid Build Coastguard Worker   Operand *FalseValueHi =
6421*03ce13f7SAndroid Build Coastguard Worker       (FalseValue->getType() == IceType_i64) ? hiOperand(FalseValue) : nullptr;
6422*03ce13f7SAndroid Build Coastguard Worker 
6423*03ce13f7SAndroid Build Coastguard Worker   Operand *TrueValueLo =
6424*03ce13f7SAndroid Build Coastguard Worker       (TrueValue->getType() == IceType_i64) ? loOperand(TrueValue) : TrueValue;
6425*03ce13f7SAndroid Build Coastguard Worker   Operand *TrueValueHi =
6426*03ce13f7SAndroid Build Coastguard Worker       (TrueValue->getType() == IceType_i64) ? hiOperand(TrueValue) : nullptr;
6427*03ce13f7SAndroid Build Coastguard Worker 
6428*03ce13f7SAndroid Build Coastguard Worker   Variable *T_Lo = makeReg(DestLo->getType());
6429*03ce13f7SAndroid Build Coastguard Worker   Variable *T_Hi = (DestHi == nullptr) ? nullptr : makeReg(DestHi->getType());
6430*03ce13f7SAndroid Build Coastguard Worker 
6431*03ce13f7SAndroid Build Coastguard Worker   _mov(T_Lo, legalize(FalseValueLo, Legal_Reg | Legal_Flex));
6432*03ce13f7SAndroid Build Coastguard Worker   if (DestHi) {
6433*03ce13f7SAndroid Build Coastguard Worker     _mov(T_Hi, legalize(FalseValueHi, Legal_Reg | Legal_Flex));
6434*03ce13f7SAndroid Build Coastguard Worker   }
6435*03ce13f7SAndroid Build Coastguard Worker 
6436*03ce13f7SAndroid Build Coastguard Worker   CondWhenTrue Cond(CondARM32::kNone);
6437*03ce13f7SAndroid Build Coastguard Worker   // FlagsWereSet is used to determine wether Boolean was folded or not. If not,
6438*03ce13f7SAndroid Build Coastguard Worker   // add an explicit _tst instruction below.
6439*03ce13f7SAndroid Build Coastguard Worker   bool FlagsWereSet = false;
6440*03ce13f7SAndroid Build Coastguard Worker   if (const Inst *Producer = Computations.getProducerOf(Boolean)) {
6441*03ce13f7SAndroid Build Coastguard Worker     switch (Producer->getKind()) {
6442*03ce13f7SAndroid Build Coastguard Worker     default:
6443*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error("Unexpected producer.");
6444*03ce13f7SAndroid Build Coastguard Worker     case Inst::Icmp: {
6445*03ce13f7SAndroid Build Coastguard Worker       Cond = lowerIcmpCond(llvm::cast<InstIcmp>(Producer));
6446*03ce13f7SAndroid Build Coastguard Worker       FlagsWereSet = true;
6447*03ce13f7SAndroid Build Coastguard Worker     } break;
6448*03ce13f7SAndroid Build Coastguard Worker     case Inst::Fcmp: {
6449*03ce13f7SAndroid Build Coastguard Worker       Cond = lowerFcmpCond(llvm::cast<InstFcmp>(Producer));
6450*03ce13f7SAndroid Build Coastguard Worker       FlagsWereSet = true;
6451*03ce13f7SAndroid Build Coastguard Worker     } break;
6452*03ce13f7SAndroid Build Coastguard Worker     case Inst::Cast: {
6453*03ce13f7SAndroid Build Coastguard Worker       const auto *CastProducer = llvm::cast<InstCast>(Producer);
6454*03ce13f7SAndroid Build Coastguard Worker       assert(CastProducer->getCastKind() == InstCast::Trunc);
6455*03ce13f7SAndroid Build Coastguard Worker       Boolean = CastProducer->getSrc(0);
6456*03ce13f7SAndroid Build Coastguard Worker       // No flags were set, so a _tst(Src, 1) will be emitted below. Don't
6457*03ce13f7SAndroid Build Coastguard Worker       // bother legalizing Src to a Reg because it will be legalized before
6458*03ce13f7SAndroid Build Coastguard Worker       // emitting the tst instruction.
6459*03ce13f7SAndroid Build Coastguard Worker       FlagsWereSet = false;
6460*03ce13f7SAndroid Build Coastguard Worker     } break;
6461*03ce13f7SAndroid Build Coastguard Worker     case Inst::Arithmetic: {
6462*03ce13f7SAndroid Build Coastguard Worker       // This is a special case: we eagerly assumed Producer could be folded,
6463*03ce13f7SAndroid Build Coastguard Worker       // but in reality, it can't. No reason to panic: we just lower it using
6464*03ce13f7SAndroid Build Coastguard Worker       // the regular lowerArithmetic helper.
6465*03ce13f7SAndroid Build Coastguard Worker       const auto *ArithProducer = llvm::cast<InstArithmetic>(Producer);
6466*03ce13f7SAndroid Build Coastguard Worker       lowerArithmetic(ArithProducer);
6467*03ce13f7SAndroid Build Coastguard Worker       Boolean = ArithProducer->getDest();
6468*03ce13f7SAndroid Build Coastguard Worker       // No flags were set, so a _tst(Dest, 1) will be emitted below. Don't
6469*03ce13f7SAndroid Build Coastguard Worker       // bother legalizing Dest to a Reg because it will be legalized before
6470*03ce13f7SAndroid Build Coastguard Worker       // emitting  the tst instruction.
6471*03ce13f7SAndroid Build Coastguard Worker       FlagsWereSet = false;
6472*03ce13f7SAndroid Build Coastguard Worker     } break;
6473*03ce13f7SAndroid Build Coastguard Worker     }
6474*03ce13f7SAndroid Build Coastguard Worker   }
6475*03ce13f7SAndroid Build Coastguard Worker 
6476*03ce13f7SAndroid Build Coastguard Worker   if (!FlagsWereSet) {
6477*03ce13f7SAndroid Build Coastguard Worker     // No flags have been set, so emit a tst Boolean, 1.
6478*03ce13f7SAndroid Build Coastguard Worker     Variable *Src = legalizeToReg(Boolean);
6479*03ce13f7SAndroid Build Coastguard Worker     _tst(Src, _1);
6480*03ce13f7SAndroid Build Coastguard Worker     Cond = CondWhenTrue(CondARM32::NE); // i.e., CondARM32::NotZero.
6481*03ce13f7SAndroid Build Coastguard Worker   }
6482*03ce13f7SAndroid Build Coastguard Worker 
6483*03ce13f7SAndroid Build Coastguard Worker   if (Cond.WhenTrue0 == CondARM32::kNone) {
6484*03ce13f7SAndroid Build Coastguard Worker     assert(Cond.WhenTrue1 == CondARM32::kNone);
6485*03ce13f7SAndroid Build Coastguard Worker   } else {
6486*03ce13f7SAndroid Build Coastguard Worker     _mov_redefined(T_Lo, legalize(TrueValueLo, Legal_Reg | Legal_Flex),
6487*03ce13f7SAndroid Build Coastguard Worker                    Cond.WhenTrue0);
6488*03ce13f7SAndroid Build Coastguard Worker     if (DestHi) {
6489*03ce13f7SAndroid Build Coastguard Worker       _mov_redefined(T_Hi, legalize(TrueValueHi, Legal_Reg | Legal_Flex),
6490*03ce13f7SAndroid Build Coastguard Worker                      Cond.WhenTrue0);
6491*03ce13f7SAndroid Build Coastguard Worker     }
6492*03ce13f7SAndroid Build Coastguard Worker   }
6493*03ce13f7SAndroid Build Coastguard Worker 
6494*03ce13f7SAndroid Build Coastguard Worker   if (Cond.WhenTrue1 != CondARM32::kNone) {
6495*03ce13f7SAndroid Build Coastguard Worker     _mov_redefined(T_Lo, legalize(TrueValueLo, Legal_Reg | Legal_Flex),
6496*03ce13f7SAndroid Build Coastguard Worker                    Cond.WhenTrue1);
6497*03ce13f7SAndroid Build Coastguard Worker     if (DestHi) {
6498*03ce13f7SAndroid Build Coastguard Worker       _mov_redefined(T_Hi, legalize(TrueValueHi, Legal_Reg | Legal_Flex),
6499*03ce13f7SAndroid Build Coastguard Worker                      Cond.WhenTrue1);
6500*03ce13f7SAndroid Build Coastguard Worker     }
6501*03ce13f7SAndroid Build Coastguard Worker   }
6502*03ce13f7SAndroid Build Coastguard Worker 
6503*03ce13f7SAndroid Build Coastguard Worker   if (NeedsAnd1) {
6504*03ce13f7SAndroid Build Coastguard Worker     // We lowered something that is unsafe (i.e., can't provably be zero or
6505*03ce13f7SAndroid Build Coastguard Worker     // one). Truncate the result.
6506*03ce13f7SAndroid Build Coastguard Worker     _and(T_Lo, T_Lo, _1);
6507*03ce13f7SAndroid Build Coastguard Worker   }
6508*03ce13f7SAndroid Build Coastguard Worker 
6509*03ce13f7SAndroid Build Coastguard Worker   _mov(DestLo, T_Lo);
6510*03ce13f7SAndroid Build Coastguard Worker   if (DestHi) {
6511*03ce13f7SAndroid Build Coastguard Worker     _mov(DestHi, T_Hi);
6512*03ce13f7SAndroid Build Coastguard Worker   }
6513*03ce13f7SAndroid Build Coastguard Worker }
6514*03ce13f7SAndroid Build Coastguard Worker 
lowerInt1(Variable * Dest,Operand * Boolean)6515*03ce13f7SAndroid Build Coastguard Worker TargetARM32::SafeBoolChain TargetARM32::lowerInt1(Variable *Dest,
6516*03ce13f7SAndroid Build Coastguard Worker                                                   Operand *Boolean) {
6517*03ce13f7SAndroid Build Coastguard Worker   assert(Boolean->getType() == IceType_i1);
6518*03ce13f7SAndroid Build Coastguard Worker   Variable *T = makeReg(IceType_i1);
6519*03ce13f7SAndroid Build Coastguard Worker   Operand *_0 =
6520*03ce13f7SAndroid Build Coastguard Worker       legalize(Ctx->getConstantZero(IceType_i1), Legal_Reg | Legal_Flex);
6521*03ce13f7SAndroid Build Coastguard Worker   Operand *_1 = legalize(Ctx->getConstantInt1(1), Legal_Reg | Legal_Flex);
6522*03ce13f7SAndroid Build Coastguard Worker 
6523*03ce13f7SAndroid Build Coastguard Worker   SafeBoolChain Safe = SBC_Yes;
6524*03ce13f7SAndroid Build Coastguard Worker   if (const Inst *Producer = Computations.getProducerOf(Boolean)) {
6525*03ce13f7SAndroid Build Coastguard Worker     switch (Producer->getKind()) {
6526*03ce13f7SAndroid Build Coastguard Worker     default:
6527*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error("Unexpected producer.");
6528*03ce13f7SAndroid Build Coastguard Worker     case Inst::Icmp: {
6529*03ce13f7SAndroid Build Coastguard Worker       _mov(T, _0);
6530*03ce13f7SAndroid Build Coastguard Worker       CondWhenTrue Cond = lowerIcmpCond(llvm::cast<InstIcmp>(Producer));
6531*03ce13f7SAndroid Build Coastguard Worker       assert(Cond.WhenTrue0 != CondARM32::AL);
6532*03ce13f7SAndroid Build Coastguard Worker       assert(Cond.WhenTrue0 != CondARM32::kNone);
6533*03ce13f7SAndroid Build Coastguard Worker       assert(Cond.WhenTrue1 == CondARM32::kNone);
6534*03ce13f7SAndroid Build Coastguard Worker       _mov_redefined(T, _1, Cond.WhenTrue0);
6535*03ce13f7SAndroid Build Coastguard Worker     } break;
6536*03ce13f7SAndroid Build Coastguard Worker     case Inst::Fcmp: {
6537*03ce13f7SAndroid Build Coastguard Worker       _mov(T, _0);
6538*03ce13f7SAndroid Build Coastguard Worker       Inst *MovZero = Context.getLastInserted();
6539*03ce13f7SAndroid Build Coastguard Worker       CondWhenTrue Cond = lowerFcmpCond(llvm::cast<InstFcmp>(Producer));
6540*03ce13f7SAndroid Build Coastguard Worker       if (Cond.WhenTrue0 == CondARM32::AL) {
6541*03ce13f7SAndroid Build Coastguard Worker         assert(Cond.WhenTrue1 == CondARM32::kNone);
6542*03ce13f7SAndroid Build Coastguard Worker         MovZero->setDeleted();
6543*03ce13f7SAndroid Build Coastguard Worker         _mov(T, _1);
6544*03ce13f7SAndroid Build Coastguard Worker       } else if (Cond.WhenTrue0 != CondARM32::kNone) {
6545*03ce13f7SAndroid Build Coastguard Worker         _mov_redefined(T, _1, Cond.WhenTrue0);
6546*03ce13f7SAndroid Build Coastguard Worker       }
6547*03ce13f7SAndroid Build Coastguard Worker       if (Cond.WhenTrue1 != CondARM32::kNone) {
6548*03ce13f7SAndroid Build Coastguard Worker         assert(Cond.WhenTrue0 != CondARM32::kNone);
6549*03ce13f7SAndroid Build Coastguard Worker         assert(Cond.WhenTrue0 != CondARM32::AL);
6550*03ce13f7SAndroid Build Coastguard Worker         _mov_redefined(T, _1, Cond.WhenTrue1);
6551*03ce13f7SAndroid Build Coastguard Worker       }
6552*03ce13f7SAndroid Build Coastguard Worker     } break;
6553*03ce13f7SAndroid Build Coastguard Worker     case Inst::Cast: {
6554*03ce13f7SAndroid Build Coastguard Worker       const auto *CastProducer = llvm::cast<InstCast>(Producer);
6555*03ce13f7SAndroid Build Coastguard Worker       assert(CastProducer->getCastKind() == InstCast::Trunc);
6556*03ce13f7SAndroid Build Coastguard Worker       Operand *Src = CastProducer->getSrc(0);
6557*03ce13f7SAndroid Build Coastguard Worker       if (Src->getType() == IceType_i64)
6558*03ce13f7SAndroid Build Coastguard Worker         Src = loOperand(Src);
6559*03ce13f7SAndroid Build Coastguard Worker       _mov(T, legalize(Src, Legal_Reg | Legal_Flex));
6560*03ce13f7SAndroid Build Coastguard Worker       Safe = SBC_No;
6561*03ce13f7SAndroid Build Coastguard Worker     } break;
6562*03ce13f7SAndroid Build Coastguard Worker     case Inst::Arithmetic: {
6563*03ce13f7SAndroid Build Coastguard Worker       const auto *ArithProducer = llvm::cast<InstArithmetic>(Producer);
6564*03ce13f7SAndroid Build Coastguard Worker       Safe = lowerInt1Arithmetic(ArithProducer);
6565*03ce13f7SAndroid Build Coastguard Worker       _mov(T, ArithProducer->getDest());
6566*03ce13f7SAndroid Build Coastguard Worker     } break;
6567*03ce13f7SAndroid Build Coastguard Worker     }
6568*03ce13f7SAndroid Build Coastguard Worker   } else {
6569*03ce13f7SAndroid Build Coastguard Worker     _mov(T, legalize(Boolean, Legal_Reg | Legal_Flex));
6570*03ce13f7SAndroid Build Coastguard Worker   }
6571*03ce13f7SAndroid Build Coastguard Worker 
6572*03ce13f7SAndroid Build Coastguard Worker   _mov(Dest, T);
6573*03ce13f7SAndroid Build Coastguard Worker   return Safe;
6574*03ce13f7SAndroid Build Coastguard Worker }
6575*03ce13f7SAndroid Build Coastguard Worker 
6576*03ce13f7SAndroid Build Coastguard Worker namespace {
6577*03ce13f7SAndroid Build Coastguard Worker namespace BoolFolding {
shouldTrackProducer(const Inst & Instr)6578*03ce13f7SAndroid Build Coastguard Worker bool shouldTrackProducer(const Inst &Instr) {
6579*03ce13f7SAndroid Build Coastguard Worker   switch (Instr.getKind()) {
6580*03ce13f7SAndroid Build Coastguard Worker   default:
6581*03ce13f7SAndroid Build Coastguard Worker     return false;
6582*03ce13f7SAndroid Build Coastguard Worker   case Inst::Icmp:
6583*03ce13f7SAndroid Build Coastguard Worker   case Inst::Fcmp:
6584*03ce13f7SAndroid Build Coastguard Worker     return true;
6585*03ce13f7SAndroid Build Coastguard Worker   case Inst::Cast: {
6586*03ce13f7SAndroid Build Coastguard Worker     switch (llvm::cast<InstCast>(&Instr)->getCastKind()) {
6587*03ce13f7SAndroid Build Coastguard Worker     default:
6588*03ce13f7SAndroid Build Coastguard Worker       return false;
6589*03ce13f7SAndroid Build Coastguard Worker     case InstCast::Trunc:
6590*03ce13f7SAndroid Build Coastguard Worker       return true;
6591*03ce13f7SAndroid Build Coastguard Worker     }
6592*03ce13f7SAndroid Build Coastguard Worker   }
6593*03ce13f7SAndroid Build Coastguard Worker   case Inst::Arithmetic: {
6594*03ce13f7SAndroid Build Coastguard Worker     switch (llvm::cast<InstArithmetic>(&Instr)->getOp()) {
6595*03ce13f7SAndroid Build Coastguard Worker     default:
6596*03ce13f7SAndroid Build Coastguard Worker       return false;
6597*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::And:
6598*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Or:
6599*03ce13f7SAndroid Build Coastguard Worker       return true;
6600*03ce13f7SAndroid Build Coastguard Worker     }
6601*03ce13f7SAndroid Build Coastguard Worker   }
6602*03ce13f7SAndroid Build Coastguard Worker   }
6603*03ce13f7SAndroid Build Coastguard Worker }
6604*03ce13f7SAndroid Build Coastguard Worker 
isValidConsumer(const Inst & Instr)6605*03ce13f7SAndroid Build Coastguard Worker bool isValidConsumer(const Inst &Instr) {
6606*03ce13f7SAndroid Build Coastguard Worker   switch (Instr.getKind()) {
6607*03ce13f7SAndroid Build Coastguard Worker   default:
6608*03ce13f7SAndroid Build Coastguard Worker     return false;
6609*03ce13f7SAndroid Build Coastguard Worker   case Inst::Br:
6610*03ce13f7SAndroid Build Coastguard Worker     return true;
6611*03ce13f7SAndroid Build Coastguard Worker   case Inst::Select:
6612*03ce13f7SAndroid Build Coastguard Worker     return !isVectorType(Instr.getDest()->getType());
6613*03ce13f7SAndroid Build Coastguard Worker   case Inst::Cast: {
6614*03ce13f7SAndroid Build Coastguard Worker     switch (llvm::cast<InstCast>(&Instr)->getCastKind()) {
6615*03ce13f7SAndroid Build Coastguard Worker     default:
6616*03ce13f7SAndroid Build Coastguard Worker       return false;
6617*03ce13f7SAndroid Build Coastguard Worker     case InstCast::Sext:
6618*03ce13f7SAndroid Build Coastguard Worker       return !isVectorType(Instr.getDest()->getType());
6619*03ce13f7SAndroid Build Coastguard Worker     case InstCast::Zext:
6620*03ce13f7SAndroid Build Coastguard Worker       return !isVectorType(Instr.getDest()->getType());
6621*03ce13f7SAndroid Build Coastguard Worker     }
6622*03ce13f7SAndroid Build Coastguard Worker   }
6623*03ce13f7SAndroid Build Coastguard Worker   case Inst::Arithmetic: {
6624*03ce13f7SAndroid Build Coastguard Worker     switch (llvm::cast<InstArithmetic>(&Instr)->getOp()) {
6625*03ce13f7SAndroid Build Coastguard Worker     default:
6626*03ce13f7SAndroid Build Coastguard Worker       return false;
6627*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::And:
6628*03ce13f7SAndroid Build Coastguard Worker       return !isVectorType(Instr.getDest()->getType());
6629*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Or:
6630*03ce13f7SAndroid Build Coastguard Worker       return !isVectorType(Instr.getDest()->getType());
6631*03ce13f7SAndroid Build Coastguard Worker     }
6632*03ce13f7SAndroid Build Coastguard Worker   }
6633*03ce13f7SAndroid Build Coastguard Worker   }
6634*03ce13f7SAndroid Build Coastguard Worker }
6635*03ce13f7SAndroid Build Coastguard Worker } // end of namespace BoolFolding
6636*03ce13f7SAndroid Build Coastguard Worker 
6637*03ce13f7SAndroid Build Coastguard Worker namespace FpFolding {
shouldTrackProducer(const Inst & Instr)6638*03ce13f7SAndroid Build Coastguard Worker bool shouldTrackProducer(const Inst &Instr) {
6639*03ce13f7SAndroid Build Coastguard Worker   switch (Instr.getKind()) {
6640*03ce13f7SAndroid Build Coastguard Worker   default:
6641*03ce13f7SAndroid Build Coastguard Worker     return false;
6642*03ce13f7SAndroid Build Coastguard Worker   case Inst::Arithmetic: {
6643*03ce13f7SAndroid Build Coastguard Worker     switch (llvm::cast<InstArithmetic>(&Instr)->getOp()) {
6644*03ce13f7SAndroid Build Coastguard Worker     default:
6645*03ce13f7SAndroid Build Coastguard Worker       return false;
6646*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Fmul:
6647*03ce13f7SAndroid Build Coastguard Worker       return true;
6648*03ce13f7SAndroid Build Coastguard Worker     }
6649*03ce13f7SAndroid Build Coastguard Worker   }
6650*03ce13f7SAndroid Build Coastguard Worker   }
6651*03ce13f7SAndroid Build Coastguard Worker }
6652*03ce13f7SAndroid Build Coastguard Worker 
isValidConsumer(const Inst & Instr)6653*03ce13f7SAndroid Build Coastguard Worker bool isValidConsumer(const Inst &Instr) {
6654*03ce13f7SAndroid Build Coastguard Worker   switch (Instr.getKind()) {
6655*03ce13f7SAndroid Build Coastguard Worker   default:
6656*03ce13f7SAndroid Build Coastguard Worker     return false;
6657*03ce13f7SAndroid Build Coastguard Worker   case Inst::Arithmetic: {
6658*03ce13f7SAndroid Build Coastguard Worker     switch (llvm::cast<InstArithmetic>(&Instr)->getOp()) {
6659*03ce13f7SAndroid Build Coastguard Worker     default:
6660*03ce13f7SAndroid Build Coastguard Worker       return false;
6661*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Fadd:
6662*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Fsub:
6663*03ce13f7SAndroid Build Coastguard Worker       return true;
6664*03ce13f7SAndroid Build Coastguard Worker     }
6665*03ce13f7SAndroid Build Coastguard Worker   }
6666*03ce13f7SAndroid Build Coastguard Worker   }
6667*03ce13f7SAndroid Build Coastguard Worker }
6668*03ce13f7SAndroid Build Coastguard Worker } // end of namespace FpFolding
6669*03ce13f7SAndroid Build Coastguard Worker 
6670*03ce13f7SAndroid Build Coastguard Worker namespace IntFolding {
shouldTrackProducer(const Inst & Instr)6671*03ce13f7SAndroid Build Coastguard Worker bool shouldTrackProducer(const Inst &Instr) {
6672*03ce13f7SAndroid Build Coastguard Worker   switch (Instr.getKind()) {
6673*03ce13f7SAndroid Build Coastguard Worker   default:
6674*03ce13f7SAndroid Build Coastguard Worker     return false;
6675*03ce13f7SAndroid Build Coastguard Worker   case Inst::Arithmetic: {
6676*03ce13f7SAndroid Build Coastguard Worker     switch (llvm::cast<InstArithmetic>(&Instr)->getOp()) {
6677*03ce13f7SAndroid Build Coastguard Worker     default:
6678*03ce13f7SAndroid Build Coastguard Worker       return false;
6679*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Mul:
6680*03ce13f7SAndroid Build Coastguard Worker       return true;
6681*03ce13f7SAndroid Build Coastguard Worker     }
6682*03ce13f7SAndroid Build Coastguard Worker   }
6683*03ce13f7SAndroid Build Coastguard Worker   }
6684*03ce13f7SAndroid Build Coastguard Worker }
6685*03ce13f7SAndroid Build Coastguard Worker 
isValidConsumer(const Inst & Instr)6686*03ce13f7SAndroid Build Coastguard Worker bool isValidConsumer(const Inst &Instr) {
6687*03ce13f7SAndroid Build Coastguard Worker   switch (Instr.getKind()) {
6688*03ce13f7SAndroid Build Coastguard Worker   default:
6689*03ce13f7SAndroid Build Coastguard Worker     return false;
6690*03ce13f7SAndroid Build Coastguard Worker   case Inst::Arithmetic: {
6691*03ce13f7SAndroid Build Coastguard Worker     switch (llvm::cast<InstArithmetic>(&Instr)->getOp()) {
6692*03ce13f7SAndroid Build Coastguard Worker     default:
6693*03ce13f7SAndroid Build Coastguard Worker       return false;
6694*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Add:
6695*03ce13f7SAndroid Build Coastguard Worker     case InstArithmetic::Sub:
6696*03ce13f7SAndroid Build Coastguard Worker       return true;
6697*03ce13f7SAndroid Build Coastguard Worker     }
6698*03ce13f7SAndroid Build Coastguard Worker   }
6699*03ce13f7SAndroid Build Coastguard Worker   }
6700*03ce13f7SAndroid Build Coastguard Worker }
6701*03ce13f7SAndroid Build Coastguard Worker } // namespace IntFolding
6702*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
6703*03ce13f7SAndroid Build Coastguard Worker 
recordProducers(CfgNode * Node)6704*03ce13f7SAndroid Build Coastguard Worker void TargetARM32::ComputationTracker::recordProducers(CfgNode *Node) {
6705*03ce13f7SAndroid Build Coastguard Worker   for (Inst &Instr : Node->getInsts()) {
6706*03ce13f7SAndroid Build Coastguard Worker     // Check whether Instr is a valid producer.
6707*03ce13f7SAndroid Build Coastguard Worker     Variable *Dest = Instr.getDest();
6708*03ce13f7SAndroid Build Coastguard Worker     if (!Instr.isDeleted() // only consider non-deleted instructions; and
6709*03ce13f7SAndroid Build Coastguard Worker         && Dest            // only instructions with an actual dest var; and
6710*03ce13f7SAndroid Build Coastguard Worker         && Dest->getType() == IceType_i1 // only bool-type dest vars; and
6711*03ce13f7SAndroid Build Coastguard Worker         && BoolFolding::shouldTrackProducer(Instr)) { // white-listed instr.
6712*03ce13f7SAndroid Build Coastguard Worker       KnownComputations.emplace(Dest->getIndex(),
6713*03ce13f7SAndroid Build Coastguard Worker                                 ComputationEntry(&Instr, IceType_i1));
6714*03ce13f7SAndroid Build Coastguard Worker     }
6715*03ce13f7SAndroid Build Coastguard Worker     if (!Instr.isDeleted() // only consider non-deleted instructions; and
6716*03ce13f7SAndroid Build Coastguard Worker         && Dest            // only instructions with an actual dest var; and
6717*03ce13f7SAndroid Build Coastguard Worker         && isScalarFloatingType(Dest->getType()) // fp-type only dest vars; and
6718*03ce13f7SAndroid Build Coastguard Worker         && FpFolding::shouldTrackProducer(Instr)) { // white-listed instr.
6719*03ce13f7SAndroid Build Coastguard Worker       KnownComputations.emplace(Dest->getIndex(),
6720*03ce13f7SAndroid Build Coastguard Worker                                 ComputationEntry(&Instr, Dest->getType()));
6721*03ce13f7SAndroid Build Coastguard Worker     }
6722*03ce13f7SAndroid Build Coastguard Worker     if (!Instr.isDeleted() // only consider non-deleted instructions; and
6723*03ce13f7SAndroid Build Coastguard Worker         && Dest            // only instructions with an actual dest var; and
6724*03ce13f7SAndroid Build Coastguard Worker         && Dest->getType() == IceType_i32            // i32 only dest vars; and
6725*03ce13f7SAndroid Build Coastguard Worker         && IntFolding::shouldTrackProducer(Instr)) { // white-listed instr.
6726*03ce13f7SAndroid Build Coastguard Worker       KnownComputations.emplace(Dest->getIndex(),
6727*03ce13f7SAndroid Build Coastguard Worker                                 ComputationEntry(&Instr, IceType_i32));
6728*03ce13f7SAndroid Build Coastguard Worker     }
6729*03ce13f7SAndroid Build Coastguard Worker     // Check each src variable against the map.
6730*03ce13f7SAndroid Build Coastguard Worker     FOREACH_VAR_IN_INST(Var, Instr) {
6731*03ce13f7SAndroid Build Coastguard Worker       SizeT VarNum = Var->getIndex();
6732*03ce13f7SAndroid Build Coastguard Worker       auto ComputationIter = KnownComputations.find(VarNum);
6733*03ce13f7SAndroid Build Coastguard Worker       if (ComputationIter == KnownComputations.end()) {
6734*03ce13f7SAndroid Build Coastguard Worker         continue;
6735*03ce13f7SAndroid Build Coastguard Worker       }
6736*03ce13f7SAndroid Build Coastguard Worker 
6737*03ce13f7SAndroid Build Coastguard Worker       ++ComputationIter->second.NumUses;
6738*03ce13f7SAndroid Build Coastguard Worker       switch (ComputationIter->second.ComputationType) {
6739*03ce13f7SAndroid Build Coastguard Worker       default:
6740*03ce13f7SAndroid Build Coastguard Worker         KnownComputations.erase(VarNum);
6741*03ce13f7SAndroid Build Coastguard Worker         continue;
6742*03ce13f7SAndroid Build Coastguard Worker       case IceType_i1:
6743*03ce13f7SAndroid Build Coastguard Worker         if (!BoolFolding::isValidConsumer(Instr)) {
6744*03ce13f7SAndroid Build Coastguard Worker           KnownComputations.erase(VarNum);
6745*03ce13f7SAndroid Build Coastguard Worker           continue;
6746*03ce13f7SAndroid Build Coastguard Worker         }
6747*03ce13f7SAndroid Build Coastguard Worker         break;
6748*03ce13f7SAndroid Build Coastguard Worker       case IceType_i32:
6749*03ce13f7SAndroid Build Coastguard Worker         if (IndexOfVarInInst(Var) != 1 || !IntFolding::isValidConsumer(Instr)) {
6750*03ce13f7SAndroid Build Coastguard Worker           KnownComputations.erase(VarNum);
6751*03ce13f7SAndroid Build Coastguard Worker           continue;
6752*03ce13f7SAndroid Build Coastguard Worker         }
6753*03ce13f7SAndroid Build Coastguard Worker         break;
6754*03ce13f7SAndroid Build Coastguard Worker       case IceType_f32:
6755*03ce13f7SAndroid Build Coastguard Worker       case IceType_f64:
6756*03ce13f7SAndroid Build Coastguard Worker         if (IndexOfVarInInst(Var) != 1 || !FpFolding::isValidConsumer(Instr)) {
6757*03ce13f7SAndroid Build Coastguard Worker           KnownComputations.erase(VarNum);
6758*03ce13f7SAndroid Build Coastguard Worker           continue;
6759*03ce13f7SAndroid Build Coastguard Worker         }
6760*03ce13f7SAndroid Build Coastguard Worker         break;
6761*03ce13f7SAndroid Build Coastguard Worker       }
6762*03ce13f7SAndroid Build Coastguard Worker 
6763*03ce13f7SAndroid Build Coastguard Worker       if (Instr.isLastUse(Var)) {
6764*03ce13f7SAndroid Build Coastguard Worker         ComputationIter->second.IsLiveOut = false;
6765*03ce13f7SAndroid Build Coastguard Worker       }
6766*03ce13f7SAndroid Build Coastguard Worker     }
6767*03ce13f7SAndroid Build Coastguard Worker   }
6768*03ce13f7SAndroid Build Coastguard Worker 
6769*03ce13f7SAndroid Build Coastguard Worker   for (auto Iter = KnownComputations.begin(), End = KnownComputations.end();
6770*03ce13f7SAndroid Build Coastguard Worker        Iter != End;) {
6771*03ce13f7SAndroid Build Coastguard Worker     // Disable the folding if its dest may be live beyond this block.
6772*03ce13f7SAndroid Build Coastguard Worker     if (Iter->second.IsLiveOut || Iter->second.NumUses > 1) {
6773*03ce13f7SAndroid Build Coastguard Worker       Iter = KnownComputations.erase(Iter);
6774*03ce13f7SAndroid Build Coastguard Worker       continue;
6775*03ce13f7SAndroid Build Coastguard Worker     }
6776*03ce13f7SAndroid Build Coastguard Worker 
6777*03ce13f7SAndroid Build Coastguard Worker     // Mark as "dead" rather than outright deleting. This is so that other
6778*03ce13f7SAndroid Build Coastguard Worker     // peephole style optimizations during or before lowering have access to
6779*03ce13f7SAndroid Build Coastguard Worker     // this instruction in undeleted form. See for example
6780*03ce13f7SAndroid Build Coastguard Worker     // tryOptimizedCmpxchgCmpBr().
6781*03ce13f7SAndroid Build Coastguard Worker     Iter->second.Instr->setDead();
6782*03ce13f7SAndroid Build Coastguard Worker     ++Iter;
6783*03ce13f7SAndroid Build Coastguard Worker   }
6784*03ce13f7SAndroid Build Coastguard Worker }
6785*03ce13f7SAndroid Build Coastguard Worker 
TargetDataARM32(GlobalContext * Ctx)6786*03ce13f7SAndroid Build Coastguard Worker TargetDataARM32::TargetDataARM32(GlobalContext *Ctx)
6787*03ce13f7SAndroid Build Coastguard Worker     : TargetDataLowering(Ctx) {}
6788*03ce13f7SAndroid Build Coastguard Worker 
lowerGlobals(const VariableDeclarationList & Vars,const std::string & SectionSuffix)6789*03ce13f7SAndroid Build Coastguard Worker void TargetDataARM32::lowerGlobals(const VariableDeclarationList &Vars,
6790*03ce13f7SAndroid Build Coastguard Worker                                    const std::string &SectionSuffix) {
6791*03ce13f7SAndroid Build Coastguard Worker   const bool IsPIC = false;
6792*03ce13f7SAndroid Build Coastguard Worker   switch (getFlags().getOutFileType()) {
6793*03ce13f7SAndroid Build Coastguard Worker   case FT_Elf: {
6794*03ce13f7SAndroid Build Coastguard Worker     ELFObjectWriter *Writer = Ctx->getObjectWriter();
6795*03ce13f7SAndroid Build Coastguard Worker     Writer->writeDataSection(Vars, llvm::ELF::R_ARM_ABS32, SectionSuffix,
6796*03ce13f7SAndroid Build Coastguard Worker                              IsPIC);
6797*03ce13f7SAndroid Build Coastguard Worker   } break;
6798*03ce13f7SAndroid Build Coastguard Worker   case FT_Asm:
6799*03ce13f7SAndroid Build Coastguard Worker   case FT_Iasm: {
6800*03ce13f7SAndroid Build Coastguard Worker     OstreamLocker _(Ctx);
6801*03ce13f7SAndroid Build Coastguard Worker     for (const VariableDeclaration *Var : Vars) {
6802*03ce13f7SAndroid Build Coastguard Worker       if (getFlags().matchTranslateOnly(Var->getName(), 0)) {
6803*03ce13f7SAndroid Build Coastguard Worker         emitGlobal(*Var, SectionSuffix);
6804*03ce13f7SAndroid Build Coastguard Worker       }
6805*03ce13f7SAndroid Build Coastguard Worker     }
6806*03ce13f7SAndroid Build Coastguard Worker   } break;
6807*03ce13f7SAndroid Build Coastguard Worker   }
6808*03ce13f7SAndroid Build Coastguard Worker }
6809*03ce13f7SAndroid Build Coastguard Worker 
6810*03ce13f7SAndroid Build Coastguard Worker namespace {
6811*03ce13f7SAndroid Build Coastguard Worker template <typename T> struct ConstantPoolEmitterTraits;
6812*03ce13f7SAndroid Build Coastguard Worker 
6813*03ce13f7SAndroid Build Coastguard Worker static_assert(sizeof(uint64_t) == 8,
6814*03ce13f7SAndroid Build Coastguard Worker               "uint64_t is supposed to be 8 bytes wide.");
6815*03ce13f7SAndroid Build Coastguard Worker 
6816*03ce13f7SAndroid Build Coastguard Worker // TODO(jpp): implement the following when implementing constant randomization:
6817*03ce13f7SAndroid Build Coastguard Worker //  * template <> struct ConstantPoolEmitterTraits<uint8_t>
6818*03ce13f7SAndroid Build Coastguard Worker //  * template <> struct ConstantPoolEmitterTraits<uint16_t>
6819*03ce13f7SAndroid Build Coastguard Worker //  * template <> struct ConstantPoolEmitterTraits<uint32_t>
6820*03ce13f7SAndroid Build Coastguard Worker template <> struct ConstantPoolEmitterTraits<float> {
6821*03ce13f7SAndroid Build Coastguard Worker   using ConstantType = ConstantFloat;
6822*03ce13f7SAndroid Build Coastguard Worker   static constexpr Type IceType = IceType_f32;
6823*03ce13f7SAndroid Build Coastguard Worker   // AsmTag and TypeName can't be constexpr because llvm::StringRef is unhappy
6824*03ce13f7SAndroid Build Coastguard Worker   // about them being constexpr.
6825*03ce13f7SAndroid Build Coastguard Worker   static const char AsmTag[];
6826*03ce13f7SAndroid Build Coastguard Worker   static const char TypeName[];
bitcastToUint64Ice::ARM32::__anon15914fd81a11::ConstantPoolEmitterTraits6827*03ce13f7SAndroid Build Coastguard Worker   static uint64_t bitcastToUint64(float Value) {
6828*03ce13f7SAndroid Build Coastguard Worker     static_assert(sizeof(Value) == sizeof(uint32_t),
6829*03ce13f7SAndroid Build Coastguard Worker                   "Float should be 4 bytes.");
6830*03ce13f7SAndroid Build Coastguard Worker     const uint32_t IntValue = Utils::bitCopy<uint32_t>(Value);
6831*03ce13f7SAndroid Build Coastguard Worker     return static_cast<uint64_t>(IntValue);
6832*03ce13f7SAndroid Build Coastguard Worker   }
6833*03ce13f7SAndroid Build Coastguard Worker };
6834*03ce13f7SAndroid Build Coastguard Worker const char ConstantPoolEmitterTraits<float>::AsmTag[] = ".long";
6835*03ce13f7SAndroid Build Coastguard Worker const char ConstantPoolEmitterTraits<float>::TypeName[] = "f32";
6836*03ce13f7SAndroid Build Coastguard Worker 
6837*03ce13f7SAndroid Build Coastguard Worker template <> struct ConstantPoolEmitterTraits<double> {
6838*03ce13f7SAndroid Build Coastguard Worker   using ConstantType = ConstantDouble;
6839*03ce13f7SAndroid Build Coastguard Worker   static constexpr Type IceType = IceType_f64;
6840*03ce13f7SAndroid Build Coastguard Worker   static const char AsmTag[];
6841*03ce13f7SAndroid Build Coastguard Worker   static const char TypeName[];
bitcastToUint64Ice::ARM32::__anon15914fd81a11::ConstantPoolEmitterTraits6842*03ce13f7SAndroid Build Coastguard Worker   static uint64_t bitcastToUint64(double Value) {
6843*03ce13f7SAndroid Build Coastguard Worker     static_assert(sizeof(double) == sizeof(uint64_t),
6844*03ce13f7SAndroid Build Coastguard Worker                   "Double should be 8 bytes.");
6845*03ce13f7SAndroid Build Coastguard Worker     return Utils::bitCopy<uint64_t>(Value);
6846*03ce13f7SAndroid Build Coastguard Worker   }
6847*03ce13f7SAndroid Build Coastguard Worker };
6848*03ce13f7SAndroid Build Coastguard Worker const char ConstantPoolEmitterTraits<double>::AsmTag[] = ".quad";
6849*03ce13f7SAndroid Build Coastguard Worker const char ConstantPoolEmitterTraits<double>::TypeName[] = "f64";
6850*03ce13f7SAndroid Build Coastguard Worker 
6851*03ce13f7SAndroid Build Coastguard Worker template <typename T>
emitConstant(Ostream & Str,const typename ConstantPoolEmitterTraits<T>::ConstantType * Const)6852*03ce13f7SAndroid Build Coastguard Worker void emitConstant(
6853*03ce13f7SAndroid Build Coastguard Worker     Ostream &Str,
6854*03ce13f7SAndroid Build Coastguard Worker     const typename ConstantPoolEmitterTraits<T>::ConstantType *Const) {
6855*03ce13f7SAndroid Build Coastguard Worker   using Traits = ConstantPoolEmitterTraits<T>;
6856*03ce13f7SAndroid Build Coastguard Worker   Str << Const->getLabelName();
6857*03ce13f7SAndroid Build Coastguard Worker   Str << ":\n\t" << Traits::AsmTag << "\t0x";
6858*03ce13f7SAndroid Build Coastguard Worker   T Value = Const->getValue();
6859*03ce13f7SAndroid Build Coastguard Worker   Str.write_hex(Traits::bitcastToUint64(Value));
6860*03ce13f7SAndroid Build Coastguard Worker   Str << "\t/* " << Traits::TypeName << " " << Value << " */\n";
6861*03ce13f7SAndroid Build Coastguard Worker }
6862*03ce13f7SAndroid Build Coastguard Worker 
emitConstantPool(GlobalContext * Ctx)6863*03ce13f7SAndroid Build Coastguard Worker template <typename T> void emitConstantPool(GlobalContext *Ctx) {
6864*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::dump()) {
6865*03ce13f7SAndroid Build Coastguard Worker     return;
6866*03ce13f7SAndroid Build Coastguard Worker   }
6867*03ce13f7SAndroid Build Coastguard Worker 
6868*03ce13f7SAndroid Build Coastguard Worker   using Traits = ConstantPoolEmitterTraits<T>;
6869*03ce13f7SAndroid Build Coastguard Worker   static constexpr size_t MinimumAlignment = 4;
6870*03ce13f7SAndroid Build Coastguard Worker   SizeT Align = std::max(MinimumAlignment, typeAlignInBytes(Traits::IceType));
6871*03ce13f7SAndroid Build Coastguard Worker   assert((Align % 4) == 0 && "Constants should be aligned");
6872*03ce13f7SAndroid Build Coastguard Worker   Ostream &Str = Ctx->getStrEmit();
6873*03ce13f7SAndroid Build Coastguard Worker   ConstantList Pool = Ctx->getConstantPool(Traits::IceType);
6874*03ce13f7SAndroid Build Coastguard Worker 
6875*03ce13f7SAndroid Build Coastguard Worker   Str << "\t.section\t.rodata.cst" << Align << ",\"aM\",%progbits," << Align
6876*03ce13f7SAndroid Build Coastguard Worker       << "\n"
6877*03ce13f7SAndroid Build Coastguard Worker       << "\t.align\t" << Align << "\n";
6878*03ce13f7SAndroid Build Coastguard Worker 
6879*03ce13f7SAndroid Build Coastguard Worker   for (Constant *C : Pool) {
6880*03ce13f7SAndroid Build Coastguard Worker     if (!C->getShouldBePooled()) {
6881*03ce13f7SAndroid Build Coastguard Worker       continue;
6882*03ce13f7SAndroid Build Coastguard Worker     }
6883*03ce13f7SAndroid Build Coastguard Worker 
6884*03ce13f7SAndroid Build Coastguard Worker     emitConstant<T>(Str, llvm::dyn_cast<typename Traits::ConstantType>(C));
6885*03ce13f7SAndroid Build Coastguard Worker   }
6886*03ce13f7SAndroid Build Coastguard Worker }
6887*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
6888*03ce13f7SAndroid Build Coastguard Worker 
lowerConstants()6889*03ce13f7SAndroid Build Coastguard Worker void TargetDataARM32::lowerConstants() {
6890*03ce13f7SAndroid Build Coastguard Worker   if (getFlags().getDisableTranslation())
6891*03ce13f7SAndroid Build Coastguard Worker     return;
6892*03ce13f7SAndroid Build Coastguard Worker   switch (getFlags().getOutFileType()) {
6893*03ce13f7SAndroid Build Coastguard Worker   case FT_Elf: {
6894*03ce13f7SAndroid Build Coastguard Worker     ELFObjectWriter *Writer = Ctx->getObjectWriter();
6895*03ce13f7SAndroid Build Coastguard Worker     Writer->writeConstantPool<ConstantFloat>(IceType_f32);
6896*03ce13f7SAndroid Build Coastguard Worker     Writer->writeConstantPool<ConstantDouble>(IceType_f64);
6897*03ce13f7SAndroid Build Coastguard Worker   } break;
6898*03ce13f7SAndroid Build Coastguard Worker   case FT_Asm:
6899*03ce13f7SAndroid Build Coastguard Worker   case FT_Iasm: {
6900*03ce13f7SAndroid Build Coastguard Worker     OstreamLocker _(Ctx);
6901*03ce13f7SAndroid Build Coastguard Worker     emitConstantPool<float>(Ctx);
6902*03ce13f7SAndroid Build Coastguard Worker     emitConstantPool<double>(Ctx);
6903*03ce13f7SAndroid Build Coastguard Worker     break;
6904*03ce13f7SAndroid Build Coastguard Worker   }
6905*03ce13f7SAndroid Build Coastguard Worker   }
6906*03ce13f7SAndroid Build Coastguard Worker }
6907*03ce13f7SAndroid Build Coastguard Worker 
lowerJumpTables()6908*03ce13f7SAndroid Build Coastguard Worker void TargetDataARM32::lowerJumpTables() {
6909*03ce13f7SAndroid Build Coastguard Worker   if (getFlags().getDisableTranslation())
6910*03ce13f7SAndroid Build Coastguard Worker     return;
6911*03ce13f7SAndroid Build Coastguard Worker   switch (getFlags().getOutFileType()) {
6912*03ce13f7SAndroid Build Coastguard Worker   case FT_Elf:
6913*03ce13f7SAndroid Build Coastguard Worker     if (!Ctx->getJumpTables().empty()) {
6914*03ce13f7SAndroid Build Coastguard Worker       llvm::report_fatal_error("ARM32 does not support jump tables yet.");
6915*03ce13f7SAndroid Build Coastguard Worker     }
6916*03ce13f7SAndroid Build Coastguard Worker     break;
6917*03ce13f7SAndroid Build Coastguard Worker   case FT_Asm:
6918*03ce13f7SAndroid Build Coastguard Worker     // Already emitted from Cfg
6919*03ce13f7SAndroid Build Coastguard Worker     break;
6920*03ce13f7SAndroid Build Coastguard Worker   case FT_Iasm: {
6921*03ce13f7SAndroid Build Coastguard Worker     // TODO(kschimpf): Fill this in when we get more information.
6922*03ce13f7SAndroid Build Coastguard Worker     break;
6923*03ce13f7SAndroid Build Coastguard Worker   }
6924*03ce13f7SAndroid Build Coastguard Worker   }
6925*03ce13f7SAndroid Build Coastguard Worker }
6926*03ce13f7SAndroid Build Coastguard Worker 
TargetHeaderARM32(GlobalContext * Ctx)6927*03ce13f7SAndroid Build Coastguard Worker TargetHeaderARM32::TargetHeaderARM32(GlobalContext *Ctx)
6928*03ce13f7SAndroid Build Coastguard Worker     : TargetHeaderLowering(Ctx), CPUFeatures(getFlags()) {}
6929*03ce13f7SAndroid Build Coastguard Worker 
lower()6930*03ce13f7SAndroid Build Coastguard Worker void TargetHeaderARM32::lower() {
6931*03ce13f7SAndroid Build Coastguard Worker   OstreamLocker _(Ctx);
6932*03ce13f7SAndroid Build Coastguard Worker   Ostream &Str = Ctx->getStrEmit();
6933*03ce13f7SAndroid Build Coastguard Worker   Str << ".syntax unified\n";
6934*03ce13f7SAndroid Build Coastguard Worker   // Emit build attributes in format: .eabi_attribute TAG, VALUE. See Sec. 2 of
6935*03ce13f7SAndroid Build Coastguard Worker   // "Addenda to, and Errata in the ABI for the ARM architecture"
6936*03ce13f7SAndroid Build Coastguard Worker   // http://infocenter.arm.com
6937*03ce13f7SAndroid Build Coastguard Worker   //                  /help/topic/com.arm.doc.ihi0045d/IHI0045D_ABI_addenda.pdf
6938*03ce13f7SAndroid Build Coastguard Worker   //
6939*03ce13f7SAndroid Build Coastguard Worker   // Tag_conformance should be be emitted first in a file-scope sub-subsection
6940*03ce13f7SAndroid Build Coastguard Worker   // of the first public subsection of the attributes.
6941*03ce13f7SAndroid Build Coastguard Worker   Str << ".eabi_attribute 67, \"2.09\"      @ Tag_conformance\n";
6942*03ce13f7SAndroid Build Coastguard Worker   // Chromebooks are at least A15, but do A9 for higher compat. For some
6943*03ce13f7SAndroid Build Coastguard Worker   // reason, the LLVM ARM asm parser has the .cpu directive override the mattr
6944*03ce13f7SAndroid Build Coastguard Worker   // specified on the commandline. So to test hwdiv, we need to set the .cpu
6945*03ce13f7SAndroid Build Coastguard Worker   // directive higher (can't just rely on --mattr=...).
6946*03ce13f7SAndroid Build Coastguard Worker   if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) {
6947*03ce13f7SAndroid Build Coastguard Worker     Str << ".cpu    cortex-a15\n";
6948*03ce13f7SAndroid Build Coastguard Worker   } else {
6949*03ce13f7SAndroid Build Coastguard Worker     Str << ".cpu    cortex-a9\n";
6950*03ce13f7SAndroid Build Coastguard Worker   }
6951*03ce13f7SAndroid Build Coastguard Worker   Str << ".eabi_attribute 6, 10   @ Tag_CPU_arch: ARMv7\n"
6952*03ce13f7SAndroid Build Coastguard Worker       << ".eabi_attribute 7, 65   @ Tag_CPU_arch_profile: App profile\n";
6953*03ce13f7SAndroid Build Coastguard Worker   Str << ".eabi_attribute 8, 1    @ Tag_ARM_ISA_use: Yes\n"
6954*03ce13f7SAndroid Build Coastguard Worker       << ".eabi_attribute 9, 2    @ Tag_THUMB_ISA_use: Thumb-2\n";
6955*03ce13f7SAndroid Build Coastguard Worker   Str << ".fpu    neon\n"
6956*03ce13f7SAndroid Build Coastguard Worker       << ".eabi_attribute 17, 1   @ Tag_ABI_PCS_GOT_use: permit directly\n"
6957*03ce13f7SAndroid Build Coastguard Worker       << ".eabi_attribute 20, 1   @ Tag_ABI_FP_denormal\n"
6958*03ce13f7SAndroid Build Coastguard Worker       << ".eabi_attribute 21, 1   @ Tag_ABI_FP_exceptions\n"
6959*03ce13f7SAndroid Build Coastguard Worker       << ".eabi_attribute 23, 3   @ Tag_ABI_FP_number_model: IEEE 754\n"
6960*03ce13f7SAndroid Build Coastguard Worker       << ".eabi_attribute 34, 1   @ Tag_CPU_unaligned_access\n"
6961*03ce13f7SAndroid Build Coastguard Worker       << ".eabi_attribute 24, 1   @ Tag_ABI_align_needed: 8-byte\n"
6962*03ce13f7SAndroid Build Coastguard Worker       << ".eabi_attribute 25, 1   @ Tag_ABI_align_preserved: 8-byte\n"
6963*03ce13f7SAndroid Build Coastguard Worker       << ".eabi_attribute 28, 1   @ Tag_ABI_VFP_args\n"
6964*03ce13f7SAndroid Build Coastguard Worker       << ".eabi_attribute 36, 1   @ Tag_FP_HP_extension\n"
6965*03ce13f7SAndroid Build Coastguard Worker       << ".eabi_attribute 38, 1   @ Tag_ABI_FP_16bit_format\n"
6966*03ce13f7SAndroid Build Coastguard Worker       << ".eabi_attribute 42, 1   @ Tag_MPextension_use\n"
6967*03ce13f7SAndroid Build Coastguard Worker       << ".eabi_attribute 68, 1   @ Tag_Virtualization_use\n";
6968*03ce13f7SAndroid Build Coastguard Worker   if (CPUFeatures.hasFeature(TargetARM32Features::HWDivArm)) {
6969*03ce13f7SAndroid Build Coastguard Worker     Str << ".eabi_attribute 44, 2   @ Tag_DIV_use\n";
6970*03ce13f7SAndroid Build Coastguard Worker   }
6971*03ce13f7SAndroid Build Coastguard Worker   // Technically R9 is used for TLS with Sandboxing, and we reserve it.
6972*03ce13f7SAndroid Build Coastguard Worker   // However, for compatibility with current NaCl LLVM, don't claim that.
6973*03ce13f7SAndroid Build Coastguard Worker   Str << ".eabi_attribute 14, 3   @ Tag_ABI_PCS_R9_use: Not used\n";
6974*03ce13f7SAndroid Build Coastguard Worker }
6975*03ce13f7SAndroid Build Coastguard Worker 
6976*03ce13f7SAndroid Build Coastguard Worker SmallBitVector TargetARM32::TypeToRegisterSet[RegARM32::RCARM32_NUM];
6977*03ce13f7SAndroid Build Coastguard Worker SmallBitVector TargetARM32::TypeToRegisterSetUnfiltered[RegARM32::RCARM32_NUM];
6978*03ce13f7SAndroid Build Coastguard Worker SmallBitVector TargetARM32::RegisterAliases[RegARM32::Reg_NUM];
6979*03ce13f7SAndroid Build Coastguard Worker 
6980*03ce13f7SAndroid Build Coastguard Worker } // end of namespace ARM32
6981*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
6982