]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/ARM/ARMLegalizerInfo.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r301441, 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, s32})
50       setAction({Op, Ty}, Legal);
51
52   for (unsigned Op : {G_SDIV, G_UDIV}) {
53     for (auto Ty : {s8, s16})
54       // FIXME: We need WidenScalar here, but in the case of targets with
55       // software division we'll also need Libcall afterwards. Treat as Custom
56       // until we have better support for chaining legalization actions.
57       setAction({Op, Ty}, Custom);
58     if (ST.hasDivideInARMMode())
59       setAction({Op, s32}, Legal);
60     else
61       setAction({Op, s32}, Libcall);
62   }
63
64   for (unsigned Op : {G_SEXT, G_ZEXT}) {
65     setAction({Op, s32}, Legal);
66     for (auto Ty : {s1, s8, s16})
67       setAction({Op, 1, Ty}, Legal);
68   }
69
70   setAction({G_GEP, p0}, Legal);
71   setAction({G_GEP, 1, s32}, Legal);
72
73   setAction({G_CONSTANT, s32}, Legal);
74
75   if (!ST.useSoftFloat() && ST.hasVFP2()) {
76     setAction({G_FADD, s32}, Legal);
77     setAction({G_FADD, s64}, Legal);
78
79     setAction({G_LOAD, s64}, Legal);
80     setAction({G_STORE, s64}, Legal);
81   } else {
82     for (auto Ty : {s32, s64})
83       setAction({G_FADD, Ty}, Libcall);
84   }
85
86   for (unsigned Op : {G_FREM, G_FPOW})
87     for (auto Ty : {s32, s64})
88       setAction({Op, Ty}, Libcall);
89
90   computeTables();
91 }
92
93 bool ARMLegalizerInfo::legalizeCustom(MachineInstr &MI,
94                                       MachineRegisterInfo &MRI,
95                                       MachineIRBuilder &MIRBuilder) const {
96   using namespace TargetOpcode;
97
98   switch (MI.getOpcode()) {
99   default:
100     return false;
101   case G_SDIV:
102   case G_UDIV: {
103     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
104     if (Ty != LLT::scalar(16) && Ty != LLT::scalar(8))
105       return false;
106
107     // We need to widen to 32 bits and then maybe, if the target requires,
108     // transform into a libcall.
109     LegalizerHelper Helper(MIRBuilder.getMF());
110
111     MachineInstr *NewMI = nullptr;
112     Helper.MIRBuilder.recordInsertions([&](MachineInstr *MI) {
113       // Store the new, 32-bit div instruction.
114       if (MI->getOpcode() == G_SDIV || MI->getOpcode() == G_UDIV)
115         NewMI = MI;
116     });
117
118     auto Result = Helper.widenScalar(MI, 0, LLT::scalar(32));
119     Helper.MIRBuilder.stopRecordingInsertions();
120     if (Result == LegalizerHelper::UnableToLegalize) {
121       return false;
122     }
123     assert(NewMI && "Couldn't find widened instruction");
124     assert((NewMI->getOpcode() == G_SDIV || NewMI->getOpcode() == G_UDIV) &&
125            "Unexpected widened instruction");
126     assert(MRI.getType(NewMI->getOperand(0).getReg()).getSizeInBits() == 32 &&
127            "Unexpected type for the widened instruction");
128
129     Result = Helper.legalizeInstrStep(*NewMI);
130     if (Result == LegalizerHelper::UnableToLegalize) {
131       return false;
132     }
133     return true;
134   }
135   }
136 }