]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r304460, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / ARM / ARMLegalizerInfo.cpp
1 //===- ARMLegalizerInfo.cpp --------------------------------------*- C++ -*-==//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// This file implements the targeting of the Machinelegalizer class for ARM.
11 /// \todo This should be generated by TableGen.
12 //===----------------------------------------------------------------------===//
13
14 #include "ARMLegalizerInfo.h"
15 #include "ARMSubtarget.h"
16 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
17 #include "llvm/CodeGen/MachineRegisterInfo.h"
18 #include "llvm/CodeGen/ValueTypes.h"
19 #include "llvm/IR/DerivedTypes.h"
20 #include "llvm/IR/Type.h"
21 #include "llvm/Target/TargetOpcodes.h"
22
23 using namespace llvm;
24
25 #ifndef LLVM_BUILD_GLOBAL_ISEL
26 #error "You shouldn't build this"
27 #endif
28
29 ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
30   using namespace TargetOpcode;
31
32   const LLT p0 = LLT::pointer(0, 32);
33
34   const LLT s1 = LLT::scalar(1);
35   const LLT s8 = LLT::scalar(8);
36   const LLT s16 = LLT::scalar(16);
37   const LLT s32 = LLT::scalar(32);
38   const LLT s64 = LLT::scalar(64);
39
40   setAction({G_FRAME_INDEX, p0}, Legal);
41
42   for (unsigned Op : {G_LOAD, G_STORE}) {
43     for (auto Ty : {s1, s8, s16, s32, p0})
44       setAction({Op, Ty}, Legal);
45     setAction({Op, 1, p0}, Legal);
46   }
47
48   for (unsigned Op : {G_ADD, G_SUB, G_MUL}) {
49     for (auto Ty : {s1, s8, s16})
50       setAction({Op, Ty}, WidenScalar);
51     setAction({Op, s32}, Legal);
52   }
53
54   for (unsigned Op : {G_SDIV, G_UDIV}) {
55     for (auto Ty : {s8, s16})
56       // FIXME: We need WidenScalar here, but in the case of targets with
57       // software division we'll also need Libcall afterwards. Treat as Custom
58       // until we have better support for chaining legalization actions.
59       setAction({Op, Ty}, Custom);
60     if (ST.hasDivideInARMMode())
61       setAction({Op, s32}, Legal);
62     else
63       setAction({Op, s32}, Libcall);
64   }
65
66   for (unsigned Op : {G_SEXT, G_ZEXT}) {
67     setAction({Op, s32}, Legal);
68     for (auto Ty : {s1, s8, s16})
69       setAction({Op, 1, Ty}, Legal);
70   }
71
72   setAction({G_GEP, p0}, Legal);
73   setAction({G_GEP, 1, s32}, Legal);
74
75   setAction({G_CONSTANT, s32}, Legal);
76
77   if (!ST.useSoftFloat() && ST.hasVFP2()) {
78     setAction({G_FADD, s32}, Legal);
79     setAction({G_FADD, s64}, Legal);
80
81     setAction({G_LOAD, s64}, Legal);
82     setAction({G_STORE, s64}, Legal);
83   } else {
84     for (auto Ty : {s32, s64})
85       setAction({G_FADD, Ty}, Libcall);
86   }
87
88   for (unsigned Op : {G_FREM, G_FPOW})
89     for (auto Ty : {s32, s64})
90       setAction({Op, Ty}, Libcall);
91
92   computeTables();
93 }
94
95 bool ARMLegalizerInfo::legalizeCustom(MachineInstr &MI,
96                                       MachineRegisterInfo &MRI,
97                                       MachineIRBuilder &MIRBuilder) const {
98   using namespace TargetOpcode;
99
100   switch (MI.getOpcode()) {
101   default:
102     return false;
103   case G_SDIV:
104   case G_UDIV: {
105     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
106     if (Ty != LLT::scalar(16) && Ty != LLT::scalar(8))
107       return false;
108
109     // We need to widen to 32 bits and then maybe, if the target requires,
110     // transform into a libcall.
111     LegalizerHelper Helper(MIRBuilder.getMF());
112
113     MachineInstr *NewMI = nullptr;
114     Helper.MIRBuilder.recordInsertions([&](MachineInstr *MI) {
115       // Store the new, 32-bit div instruction.
116       if (MI->getOpcode() == G_SDIV || MI->getOpcode() == G_UDIV)
117         NewMI = MI;
118     });
119
120     auto Result = Helper.widenScalar(MI, 0, LLT::scalar(32));
121     Helper.MIRBuilder.stopRecordingInsertions();
122     if (Result == LegalizerHelper::UnableToLegalize) {
123       return false;
124     }
125     assert(NewMI && "Couldn't find widened instruction");
126     assert((NewMI->getOpcode() == G_SDIV || NewMI->getOpcode() == G_UDIV) &&
127            "Unexpected widened instruction");
128     assert(MRI.getType(NewMI->getOperand(0).getReg()).getSizeInBits() == 32 &&
129            "Unexpected type for the widened instruction");
130
131     Result = Helper.legalizeInstrStep(*NewMI);
132     if (Result == LegalizerHelper::UnableToLegalize) {
133       return false;
134     }
135     return true;
136   }
137   }
138 }