1 //===- ARMLegalizerInfo.cpp --------------------------------------*- C++ -*-==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// This file implements the targeting of the Machinelegalizer class for ARM.
11 /// \todo This should be generated by TableGen.
12 //===----------------------------------------------------------------------===//
14 #include "ARMLegalizerInfo.h"
15 #include "ARMCallLowering.h"
16 #include "ARMSubtarget.h"
17 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
18 #include "llvm/CodeGen/LowLevelType.h"
19 #include "llvm/CodeGen/MachineRegisterInfo.h"
20 #include "llvm/CodeGen/ValueTypes.h"
21 #include "llvm/IR/DerivedTypes.h"
22 #include "llvm/IR/Type.h"
23 #include "llvm/Target/TargetOpcodes.h"
27 #ifndef LLVM_BUILD_GLOBAL_ISEL
28 #error "You shouldn't build this"
31 ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
32 using namespace TargetOpcode;
34 const LLT p0 = LLT::pointer(0, 32);
36 const LLT s1 = LLT::scalar(1);
37 const LLT s8 = LLT::scalar(8);
38 const LLT s16 = LLT::scalar(16);
39 const LLT s32 = LLT::scalar(32);
40 const LLT s64 = LLT::scalar(64);
42 setAction({G_FRAME_INDEX, p0}, Legal);
44 for (unsigned Op : {G_LOAD, G_STORE}) {
45 for (auto Ty : {s1, s8, s16, s32, p0})
46 setAction({Op, Ty}, Legal);
47 setAction({Op, 1, p0}, Legal);
50 for (unsigned Op : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR}) {
51 for (auto Ty : {s1, s8, s16})
52 setAction({Op, Ty}, WidenScalar);
53 setAction({Op, s32}, Legal);
56 for (unsigned Op : {G_SDIV, G_UDIV}) {
57 for (auto Ty : {s8, s16})
58 setAction({Op, Ty}, WidenScalar);
59 if (ST.hasDivideInARMMode())
60 setAction({Op, s32}, Legal);
62 setAction({Op, s32}, Libcall);
65 // FIXME: Support s8 and s16 as well
66 for (unsigned Op : {G_SREM, G_UREM})
67 if (ST.hasDivideInARMMode())
68 setAction({Op, s32}, Lower);
69 else if (ST.isTargetAEABI() || ST.isTargetGNUAEABI() ||
70 ST.isTargetMuslAEABI())
71 setAction({Op, s32}, Custom);
73 setAction({Op, s32}, Libcall);
75 for (unsigned Op : {G_SEXT, G_ZEXT}) {
76 setAction({Op, s32}, Legal);
77 for (auto Ty : {s1, s8, s16})
78 setAction({Op, 1, Ty}, Legal);
81 setAction({G_GEP, p0}, Legal);
82 setAction({G_GEP, 1, s32}, Legal);
84 setAction({G_SELECT, s32}, Legal);
85 setAction({G_SELECT, p0}, Legal);
86 setAction({G_SELECT, 1, s1}, Legal);
88 setAction({G_CONSTANT, s32}, Legal);
90 setAction({G_ICMP, s1}, Legal);
91 for (auto Ty : {s8, s16})
92 setAction({G_ICMP, 1, Ty}, WidenScalar);
93 for (auto Ty : {s32, p0})
94 setAction({G_ICMP, 1, Ty}, Legal);
96 if (!ST.useSoftFloat() && ST.hasVFP2()) {
97 setAction({G_FADD, s32}, Legal);
98 setAction({G_FADD, s64}, Legal);
100 setAction({G_LOAD, s64}, Legal);
101 setAction({G_STORE, s64}, Legal);
103 for (auto Ty : {s32, s64})
104 setAction({G_FADD, Ty}, Libcall);
107 for (unsigned Op : {G_FREM, G_FPOW})
108 for (auto Ty : {s32, s64})
109 setAction({Op, Ty}, Libcall);
114 bool ARMLegalizerInfo::legalizeCustom(MachineInstr &MI,
115 MachineRegisterInfo &MRI,
116 MachineIRBuilder &MIRBuilder) const {
117 using namespace TargetOpcode;
119 switch (MI.getOpcode()) {
124 unsigned OriginalResult = MI.getOperand(0).getReg();
125 auto Size = MRI.getType(OriginalResult).getSizeInBits();
130 MI.getOpcode() == G_SREM ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
132 // Our divmod libcalls return a struct containing the quotient and the
133 // remainder. We need to create a virtual register for it.
134 auto &Ctx = MIRBuilder.getMF().getFunction()->getContext();
135 Type *ArgTy = Type::getInt32Ty(Ctx);
136 StructType *RetTy = StructType::get(Ctx, {ArgTy, ArgTy}, /* Packed */ true);
137 auto RetVal = MRI.createGenericVirtualRegister(
138 getLLTForType(*RetTy, MIRBuilder.getMF().getDataLayout()));
140 auto Status = replaceWithLibcall(MI, MIRBuilder, Libcall, {RetVal, RetTy},
141 {{MI.getOperand(1).getReg(), ArgTy},
142 {MI.getOperand(2).getReg(), ArgTy}});
143 if (Status != LegalizerHelper::Legalized)
146 // The remainder is the second result of divmod. Split the return value into
147 // a new, unused register for the quotient and the destination of the
148 // original instruction for the remainder.
149 MIRBuilder.buildUnmerge(
150 {MRI.createGenericVirtualRegister(LLT::scalar(32)), OriginalResult},
153 return LegalizerHelper::Legalized;