xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1bdd1243dSDimitry Andric //===-- RISCVLegalizerInfo.cpp ----------------------------------*- C++ -*-===//
2bdd1243dSDimitry Andric //
3bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bdd1243dSDimitry Andric //
7bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
8bdd1243dSDimitry Andric /// \file
906c3fb27SDimitry Andric /// This file implements the targeting of the Machinelegalizer class for RISC-V.
10bdd1243dSDimitry Andric /// \todo This should be generated by TableGen.
11bdd1243dSDimitry Andric //===----------------------------------------------------------------------===//
12bdd1243dSDimitry Andric 
13bdd1243dSDimitry Andric #include "RISCVLegalizerInfo.h"
14*0fca6ea1SDimitry Andric #include "MCTargetDesc/RISCVMatInt.h"
155f757f3fSDimitry Andric #include "RISCVMachineFunctionInfo.h"
1606c3fb27SDimitry Andric #include "RISCVSubtarget.h"
17*0fca6ea1SDimitry Andric #include "llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h"
185f757f3fSDimitry Andric #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
195f757f3fSDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
205f757f3fSDimitry Andric #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
21*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
225f757f3fSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
23bdd1243dSDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h"
24bdd1243dSDimitry Andric #include "llvm/CodeGen/ValueTypes.h"
25bdd1243dSDimitry Andric #include "llvm/IR/DerivedTypes.h"
26bdd1243dSDimitry Andric #include "llvm/IR/Type.h"
27bdd1243dSDimitry Andric 
28bdd1243dSDimitry Andric using namespace llvm;
295f757f3fSDimitry Andric using namespace LegalityPredicates;
305f757f3fSDimitry Andric using namespace LegalizeMutations;
31bdd1243dSDimitry Andric 
325f757f3fSDimitry Andric // Is this type supported by scalar FP arithmetic operations given the current
335f757f3fSDimitry Andric // subtarget.
345f757f3fSDimitry Andric static LegalityPredicate typeIsScalarFPArith(unsigned TypeIdx,
355f757f3fSDimitry Andric                                              const RISCVSubtarget &ST) {
365f757f3fSDimitry Andric   return [=, &ST](const LegalityQuery &Query) {
375f757f3fSDimitry Andric     return Query.Types[TypeIdx].isScalar() &&
38*0fca6ea1SDimitry Andric            ((ST.hasStdExtZfh() && Query.Types[TypeIdx].getSizeInBits() == 16) ||
39*0fca6ea1SDimitry Andric             (ST.hasStdExtF() && Query.Types[TypeIdx].getSizeInBits() == 32) ||
405f757f3fSDimitry Andric             (ST.hasStdExtD() && Query.Types[TypeIdx].getSizeInBits() == 64));
415f757f3fSDimitry Andric   };
425f757f3fSDimitry Andric }
435f757f3fSDimitry Andric 
44*0fca6ea1SDimitry Andric static LegalityPredicate
45*0fca6ea1SDimitry Andric typeIsLegalIntOrFPVec(unsigned TypeIdx,
46*0fca6ea1SDimitry Andric                       std::initializer_list<LLT> IntOrFPVecTys,
47*0fca6ea1SDimitry Andric                       const RISCVSubtarget &ST) {
48*0fca6ea1SDimitry Andric   LegalityPredicate P = [=, &ST](const LegalityQuery &Query) {
49*0fca6ea1SDimitry Andric     return ST.hasVInstructions() &&
50*0fca6ea1SDimitry Andric            (Query.Types[TypeIdx].getScalarSizeInBits() != 64 ||
51*0fca6ea1SDimitry Andric             ST.hasVInstructionsI64()) &&
52*0fca6ea1SDimitry Andric            (Query.Types[TypeIdx].getElementCount().getKnownMinValue() != 1 ||
53*0fca6ea1SDimitry Andric             ST.getELen() == 64);
54*0fca6ea1SDimitry Andric   };
55*0fca6ea1SDimitry Andric 
56*0fca6ea1SDimitry Andric   return all(typeInSet(TypeIdx, IntOrFPVecTys), P);
57*0fca6ea1SDimitry Andric }
58*0fca6ea1SDimitry Andric 
59*0fca6ea1SDimitry Andric static LegalityPredicate
60*0fca6ea1SDimitry Andric typeIsLegalBoolVec(unsigned TypeIdx, std::initializer_list<LLT> BoolVecTys,
61*0fca6ea1SDimitry Andric                    const RISCVSubtarget &ST) {
62*0fca6ea1SDimitry Andric   LegalityPredicate P = [=, &ST](const LegalityQuery &Query) {
63*0fca6ea1SDimitry Andric     return ST.hasVInstructions() &&
64*0fca6ea1SDimitry Andric            (Query.Types[TypeIdx].getElementCount().getKnownMinValue() != 1 ||
65*0fca6ea1SDimitry Andric             ST.getELen() == 64);
66*0fca6ea1SDimitry Andric   };
67*0fca6ea1SDimitry Andric   return all(typeInSet(TypeIdx, BoolVecTys), P);
68*0fca6ea1SDimitry Andric }
69*0fca6ea1SDimitry Andric 
705f757f3fSDimitry Andric RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
715f757f3fSDimitry Andric     : STI(ST), XLen(STI.getXLen()), sXLen(LLT::scalar(XLen)) {
725f757f3fSDimitry Andric   const LLT sDoubleXLen = LLT::scalar(2 * XLen);
735f757f3fSDimitry Andric   const LLT p0 = LLT::pointer(0, XLen);
745f757f3fSDimitry Andric   const LLT s1 = LLT::scalar(1);
755f757f3fSDimitry Andric   const LLT s8 = LLT::scalar(8);
765f757f3fSDimitry Andric   const LLT s16 = LLT::scalar(16);
775f757f3fSDimitry Andric   const LLT s32 = LLT::scalar(32);
785f757f3fSDimitry Andric   const LLT s64 = LLT::scalar(64);
7906c3fb27SDimitry Andric 
80*0fca6ea1SDimitry Andric   const LLT nxv1s1 = LLT::scalable_vector(1, s1);
81*0fca6ea1SDimitry Andric   const LLT nxv2s1 = LLT::scalable_vector(2, s1);
82*0fca6ea1SDimitry Andric   const LLT nxv4s1 = LLT::scalable_vector(4, s1);
83*0fca6ea1SDimitry Andric   const LLT nxv8s1 = LLT::scalable_vector(8, s1);
84*0fca6ea1SDimitry Andric   const LLT nxv16s1 = LLT::scalable_vector(16, s1);
85*0fca6ea1SDimitry Andric   const LLT nxv32s1 = LLT::scalable_vector(32, s1);
86*0fca6ea1SDimitry Andric   const LLT nxv64s1 = LLT::scalable_vector(64, s1);
87*0fca6ea1SDimitry Andric 
88297eecfbSDimitry Andric   const LLT nxv1s8 = LLT::scalable_vector(1, s8);
89297eecfbSDimitry Andric   const LLT nxv2s8 = LLT::scalable_vector(2, s8);
90297eecfbSDimitry Andric   const LLT nxv4s8 = LLT::scalable_vector(4, s8);
91297eecfbSDimitry Andric   const LLT nxv8s8 = LLT::scalable_vector(8, s8);
92297eecfbSDimitry Andric   const LLT nxv16s8 = LLT::scalable_vector(16, s8);
93297eecfbSDimitry Andric   const LLT nxv32s8 = LLT::scalable_vector(32, s8);
94297eecfbSDimitry Andric   const LLT nxv64s8 = LLT::scalable_vector(64, s8);
95297eecfbSDimitry Andric 
96297eecfbSDimitry Andric   const LLT nxv1s16 = LLT::scalable_vector(1, s16);
97297eecfbSDimitry Andric   const LLT nxv2s16 = LLT::scalable_vector(2, s16);
98297eecfbSDimitry Andric   const LLT nxv4s16 = LLT::scalable_vector(4, s16);
99297eecfbSDimitry Andric   const LLT nxv8s16 = LLT::scalable_vector(8, s16);
100297eecfbSDimitry Andric   const LLT nxv16s16 = LLT::scalable_vector(16, s16);
101297eecfbSDimitry Andric   const LLT nxv32s16 = LLT::scalable_vector(32, s16);
102297eecfbSDimitry Andric 
103297eecfbSDimitry Andric   const LLT nxv1s32 = LLT::scalable_vector(1, s32);
104297eecfbSDimitry Andric   const LLT nxv2s32 = LLT::scalable_vector(2, s32);
105297eecfbSDimitry Andric   const LLT nxv4s32 = LLT::scalable_vector(4, s32);
106297eecfbSDimitry Andric   const LLT nxv8s32 = LLT::scalable_vector(8, s32);
107297eecfbSDimitry Andric   const LLT nxv16s32 = LLT::scalable_vector(16, s32);
108297eecfbSDimitry Andric 
109297eecfbSDimitry Andric   const LLT nxv1s64 = LLT::scalable_vector(1, s64);
110297eecfbSDimitry Andric   const LLT nxv2s64 = LLT::scalable_vector(2, s64);
111297eecfbSDimitry Andric   const LLT nxv4s64 = LLT::scalable_vector(4, s64);
112297eecfbSDimitry Andric   const LLT nxv8s64 = LLT::scalable_vector(8, s64);
113297eecfbSDimitry Andric 
11406c3fb27SDimitry Andric   using namespace TargetOpcode;
11506c3fb27SDimitry Andric 
116*0fca6ea1SDimitry Andric   auto BoolVecTys = {nxv1s1, nxv2s1, nxv4s1, nxv8s1, nxv16s1, nxv32s1, nxv64s1};
117*0fca6ea1SDimitry Andric 
118*0fca6ea1SDimitry Andric   auto IntOrFPVecTys = {nxv1s8,   nxv2s8,  nxv4s8,  nxv8s8,  nxv16s8, nxv32s8,
119297eecfbSDimitry Andric                         nxv64s8,  nxv1s16, nxv2s16, nxv4s16, nxv8s16, nxv16s16,
120297eecfbSDimitry Andric                         nxv32s16, nxv1s32, nxv2s32, nxv4s32, nxv8s32, nxv16s32,
121297eecfbSDimitry Andric                         nxv1s64,  nxv2s64, nxv4s64, nxv8s64};
122297eecfbSDimitry Andric 
12306c3fb27SDimitry Andric   getActionDefinitionsBuilder({G_ADD, G_SUB, G_AND, G_OR, G_XOR})
1245f757f3fSDimitry Andric       .legalFor({s32, sXLen})
125*0fca6ea1SDimitry Andric       .legalIf(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST))
1265f757f3fSDimitry Andric       .widenScalarToNextPow2(0)
1275f757f3fSDimitry Andric       .clampScalar(0, s32, sXLen);
1285f757f3fSDimitry Andric 
1295f757f3fSDimitry Andric   getActionDefinitionsBuilder(
1305f757f3fSDimitry Andric       {G_UADDE, G_UADDO, G_USUBE, G_USUBO}).lower();
1315f757f3fSDimitry Andric 
1325f757f3fSDimitry Andric   getActionDefinitionsBuilder({G_SADDO, G_SSUBO}).minScalar(0, sXLen).lower();
1335f757f3fSDimitry Andric 
134*0fca6ea1SDimitry Andric   // TODO: Use Vector Single-Width Saturating Instructions for vector types.
135*0fca6ea1SDimitry Andric   getActionDefinitionsBuilder({G_UADDSAT, G_SADDSAT, G_USUBSAT, G_SSUBSAT})
136*0fca6ea1SDimitry Andric       .lower();
137*0fca6ea1SDimitry Andric 
1385f757f3fSDimitry Andric   auto &ShiftActions = getActionDefinitionsBuilder({G_ASHR, G_LSHR, G_SHL});
1395f757f3fSDimitry Andric   if (ST.is64Bit())
1405f757f3fSDimitry Andric     ShiftActions.customFor({{s32, s32}});
1415f757f3fSDimitry Andric   ShiftActions.legalFor({{s32, s32}, {s32, sXLen}, {sXLen, sXLen}})
1425f757f3fSDimitry Andric       .widenScalarToNextPow2(0)
1435f757f3fSDimitry Andric       .clampScalar(1, s32, sXLen)
1445f757f3fSDimitry Andric       .clampScalar(0, s32, sXLen)
145*0fca6ea1SDimitry Andric       .minScalarSameAs(1, 0)
146*0fca6ea1SDimitry Andric       .widenScalarToNextPow2(1);
1475f757f3fSDimitry Andric 
148*0fca6ea1SDimitry Andric   auto &ExtActions =
1495f757f3fSDimitry Andric       getActionDefinitionsBuilder({G_ZEXT, G_SEXT, G_ANYEXT})
150*0fca6ea1SDimitry Andric           .legalIf(all(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST),
151*0fca6ea1SDimitry Andric                        typeIsLegalIntOrFPVec(1, IntOrFPVecTys, ST)));
152*0fca6ea1SDimitry Andric   if (ST.is64Bit()) {
153*0fca6ea1SDimitry Andric     ExtActions.legalFor({{sXLen, s32}});
1545f757f3fSDimitry Andric     getActionDefinitionsBuilder(G_SEXT_INREG)
1555f757f3fSDimitry Andric         .customFor({sXLen})
1565f757f3fSDimitry Andric         .maxScalar(0, sXLen)
1575f757f3fSDimitry Andric         .lower();
1585f757f3fSDimitry Andric   } else {
1595f757f3fSDimitry Andric     getActionDefinitionsBuilder(G_SEXT_INREG).maxScalar(0, sXLen).lower();
1605f757f3fSDimitry Andric   }
161*0fca6ea1SDimitry Andric   ExtActions.customIf(typeIsLegalBoolVec(1, BoolVecTys, ST))
162*0fca6ea1SDimitry Andric       .maxScalar(0, sXLen);
1635f757f3fSDimitry Andric 
1645f757f3fSDimitry Andric   // Merge/Unmerge
1655f757f3fSDimitry Andric   for (unsigned Op : {G_MERGE_VALUES, G_UNMERGE_VALUES}) {
166cb14a3feSDimitry Andric     auto &MergeUnmergeActions = getActionDefinitionsBuilder(Op);
1675f757f3fSDimitry Andric     unsigned BigTyIdx = Op == G_MERGE_VALUES ? 0 : 1;
1685f757f3fSDimitry Andric     unsigned LitTyIdx = Op == G_MERGE_VALUES ? 1 : 0;
1695f757f3fSDimitry Andric     if (XLen == 32 && ST.hasStdExtD()) {
170cb14a3feSDimitry Andric       MergeUnmergeActions.legalIf(
171cb14a3feSDimitry Andric           all(typeIs(BigTyIdx, s64), typeIs(LitTyIdx, s32)));
1725f757f3fSDimitry Andric     }
1735f757f3fSDimitry Andric     MergeUnmergeActions.widenScalarToNextPow2(LitTyIdx, XLen)
1745f757f3fSDimitry Andric         .widenScalarToNextPow2(BigTyIdx, XLen)
1755f757f3fSDimitry Andric         .clampScalar(LitTyIdx, sXLen, sXLen)
1765f757f3fSDimitry Andric         .clampScalar(BigTyIdx, sXLen, sXLen);
1775f757f3fSDimitry Andric   }
1785f757f3fSDimitry Andric 
1795f757f3fSDimitry Andric   getActionDefinitionsBuilder({G_FSHL, G_FSHR}).lower();
1805f757f3fSDimitry Andric 
1815f757f3fSDimitry Andric   auto &RotateActions = getActionDefinitionsBuilder({G_ROTL, G_ROTR});
182647cbc5dSDimitry Andric   if (ST.hasStdExtZbb() || ST.hasStdExtZbkb()) {
1835f757f3fSDimitry Andric     RotateActions.legalFor({{s32, sXLen}, {sXLen, sXLen}});
1845f757f3fSDimitry Andric     // Widen s32 rotate amount to s64 so SDAG patterns will match.
1855f757f3fSDimitry Andric     if (ST.is64Bit())
1865f757f3fSDimitry Andric       RotateActions.widenScalarIf(all(typeIs(0, s32), typeIs(1, s32)),
1875f757f3fSDimitry Andric                                   changeTo(1, sXLen));
1885f757f3fSDimitry Andric   }
1895f757f3fSDimitry Andric   RotateActions.lower();
1905f757f3fSDimitry Andric 
1915f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_BITREVERSE).maxScalar(0, sXLen).lower();
1925f757f3fSDimitry Andric 
193*0fca6ea1SDimitry Andric   getActionDefinitionsBuilder(G_BITCAST).legalIf(
194*0fca6ea1SDimitry Andric       all(LegalityPredicates::any(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST),
195*0fca6ea1SDimitry Andric                                   typeIsLegalBoolVec(0, BoolVecTys, ST)),
196*0fca6ea1SDimitry Andric           LegalityPredicates::any(typeIsLegalIntOrFPVec(1, IntOrFPVecTys, ST),
197*0fca6ea1SDimitry Andric                                   typeIsLegalBoolVec(1, BoolVecTys, ST))));
198*0fca6ea1SDimitry Andric 
1995f757f3fSDimitry Andric   auto &BSWAPActions = getActionDefinitionsBuilder(G_BSWAP);
2001db9f3b2SDimitry Andric   if (ST.hasStdExtZbb() || ST.hasStdExtZbkb())
2015f757f3fSDimitry Andric     BSWAPActions.legalFor({sXLen}).clampScalar(0, sXLen, sXLen);
2025f757f3fSDimitry Andric   else
2035f757f3fSDimitry Andric     BSWAPActions.maxScalar(0, sXLen).lower();
2045f757f3fSDimitry Andric 
2055f757f3fSDimitry Andric   auto &CountZerosActions = getActionDefinitionsBuilder({G_CTLZ, G_CTTZ});
2065f757f3fSDimitry Andric   auto &CountZerosUndefActions =
2075f757f3fSDimitry Andric       getActionDefinitionsBuilder({G_CTLZ_ZERO_UNDEF, G_CTTZ_ZERO_UNDEF});
2085f757f3fSDimitry Andric   if (ST.hasStdExtZbb()) {
2095f757f3fSDimitry Andric     CountZerosActions.legalFor({{s32, s32}, {sXLen, sXLen}})
2105f757f3fSDimitry Andric         .clampScalar(0, s32, sXLen)
2115f757f3fSDimitry Andric         .widenScalarToNextPow2(0)
2125f757f3fSDimitry Andric         .scalarSameSizeAs(1, 0);
2135f757f3fSDimitry Andric   } else {
2145f757f3fSDimitry Andric     CountZerosActions.maxScalar(0, sXLen).scalarSameSizeAs(1, 0).lower();
2155f757f3fSDimitry Andric     CountZerosUndefActions.maxScalar(0, sXLen).scalarSameSizeAs(1, 0);
2165f757f3fSDimitry Andric   }
2175f757f3fSDimitry Andric   CountZerosUndefActions.lower();
2185f757f3fSDimitry Andric 
2195f757f3fSDimitry Andric   auto &CTPOPActions = getActionDefinitionsBuilder(G_CTPOP);
2205f757f3fSDimitry Andric   if (ST.hasStdExtZbb()) {
2215f757f3fSDimitry Andric     CTPOPActions.legalFor({{s32, s32}, {sXLen, sXLen}})
2225f757f3fSDimitry Andric         .clampScalar(0, s32, sXLen)
2235f757f3fSDimitry Andric         .widenScalarToNextPow2(0)
2245f757f3fSDimitry Andric         .scalarSameSizeAs(1, 0);
2255f757f3fSDimitry Andric   } else {
2265f757f3fSDimitry Andric     CTPOPActions.maxScalar(0, sXLen).scalarSameSizeAs(1, 0).lower();
2275f757f3fSDimitry Andric   }
2285f757f3fSDimitry Andric 
229*0fca6ea1SDimitry Andric   auto &ConstantActions = getActionDefinitionsBuilder(G_CONSTANT);
230*0fca6ea1SDimitry Andric   ConstantActions.legalFor({s32, p0});
231*0fca6ea1SDimitry Andric   if (ST.is64Bit())
232*0fca6ea1SDimitry Andric     ConstantActions.customFor({s64});
233*0fca6ea1SDimitry Andric   ConstantActions.widenScalarToNextPow2(0).clampScalar(0, s32, sXLen);
234*0fca6ea1SDimitry Andric 
235*0fca6ea1SDimitry Andric   // TODO: transform illegal vector types into legal vector type
236*0fca6ea1SDimitry Andric   getActionDefinitionsBuilder(
237*0fca6ea1SDimitry Andric       {G_IMPLICIT_DEF, G_CONSTANT_FOLD_BARRIER, G_FREEZE})
2385f757f3fSDimitry Andric       .legalFor({s32, sXLen, p0})
239*0fca6ea1SDimitry Andric       .legalIf(typeIsLegalBoolVec(0, BoolVecTys, ST))
240*0fca6ea1SDimitry Andric       .legalIf(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST))
2415f757f3fSDimitry Andric       .widenScalarToNextPow2(0)
2425f757f3fSDimitry Andric       .clampScalar(0, s32, sXLen);
2435f757f3fSDimitry Andric 
2445f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_ICMP)
2455f757f3fSDimitry Andric       .legalFor({{sXLen, sXLen}, {sXLen, p0}})
246*0fca6ea1SDimitry Andric       .legalIf(all(typeIsLegalBoolVec(0, BoolVecTys, ST),
247*0fca6ea1SDimitry Andric                    typeIsLegalIntOrFPVec(1, IntOrFPVecTys, ST)))
248*0fca6ea1SDimitry Andric       .widenScalarOrEltToNextPow2OrMinSize(1, 8)
2495f757f3fSDimitry Andric       .clampScalar(1, sXLen, sXLen)
2505f757f3fSDimitry Andric       .clampScalar(0, sXLen, sXLen);
2515f757f3fSDimitry Andric 
252*0fca6ea1SDimitry Andric   auto &SelectActions =
253*0fca6ea1SDimitry Andric       getActionDefinitionsBuilder(G_SELECT)
254*0fca6ea1SDimitry Andric           .legalFor({{s32, sXLen}, {p0, sXLen}})
255*0fca6ea1SDimitry Andric           .legalIf(all(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST),
256*0fca6ea1SDimitry Andric                        typeIsLegalBoolVec(1, BoolVecTys, ST)));
2575f757f3fSDimitry Andric   if (XLen == 64 || ST.hasStdExtD())
2585f757f3fSDimitry Andric     SelectActions.legalFor({{s64, sXLen}});
2595f757f3fSDimitry Andric   SelectActions.widenScalarToNextPow2(0)
2605f757f3fSDimitry Andric       .clampScalar(0, s32, (XLen == 64 || ST.hasStdExtD()) ? s64 : s32)
2615f757f3fSDimitry Andric       .clampScalar(1, sXLen, sXLen);
2625f757f3fSDimitry Andric 
2635f757f3fSDimitry Andric   auto &LoadStoreActions =
2645f757f3fSDimitry Andric       getActionDefinitionsBuilder({G_LOAD, G_STORE})
2655f757f3fSDimitry Andric           .legalForTypesWithMemDesc({{s32, p0, s8, 8},
2665f757f3fSDimitry Andric                                      {s32, p0, s16, 16},
2675f757f3fSDimitry Andric                                      {s32, p0, s32, 32},
2685f757f3fSDimitry Andric                                      {p0, p0, sXLen, XLen}});
2695f757f3fSDimitry Andric   auto &ExtLoadActions =
2705f757f3fSDimitry Andric       getActionDefinitionsBuilder({G_SEXTLOAD, G_ZEXTLOAD})
2715f757f3fSDimitry Andric           .legalForTypesWithMemDesc({{s32, p0, s8, 8}, {s32, p0, s16, 16}});
2725f757f3fSDimitry Andric   if (XLen == 64) {
2735f757f3fSDimitry Andric     LoadStoreActions.legalForTypesWithMemDesc({{s64, p0, s8, 8},
2745f757f3fSDimitry Andric                                                {s64, p0, s16, 16},
2755f757f3fSDimitry Andric                                                {s64, p0, s32, 32},
2765f757f3fSDimitry Andric                                                {s64, p0, s64, 64}});
2775f757f3fSDimitry Andric     ExtLoadActions.legalForTypesWithMemDesc(
2785f757f3fSDimitry Andric         {{s64, p0, s8, 8}, {s64, p0, s16, 16}, {s64, p0, s32, 32}});
2795f757f3fSDimitry Andric   } else if (ST.hasStdExtD()) {
2805f757f3fSDimitry Andric     LoadStoreActions.legalForTypesWithMemDesc({{s64, p0, s64, 64}});
2815f757f3fSDimitry Andric   }
2825f757f3fSDimitry Andric   LoadStoreActions.clampScalar(0, s32, sXLen).lower();
2835f757f3fSDimitry Andric   ExtLoadActions.widenScalarToNextPow2(0).clampScalar(0, s32, sXLen).lower();
2845f757f3fSDimitry Andric 
2855f757f3fSDimitry Andric   getActionDefinitionsBuilder({G_PTR_ADD, G_PTRMASK}).legalFor({{p0, sXLen}});
2865f757f3fSDimitry Andric 
2875f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_PTRTOINT)
2885f757f3fSDimitry Andric       .legalFor({{sXLen, p0}})
2895f757f3fSDimitry Andric       .clampScalar(0, sXLen, sXLen);
2905f757f3fSDimitry Andric 
2915f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_INTTOPTR)
2925f757f3fSDimitry Andric       .legalFor({{p0, sXLen}})
2935f757f3fSDimitry Andric       .clampScalar(1, sXLen, sXLen);
2945f757f3fSDimitry Andric 
2955f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_BRCOND).legalFor({sXLen}).minScalar(0, sXLen);
2965f757f3fSDimitry Andric 
2975f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_BRJT).legalFor({{p0, sXLen}});
2985f757f3fSDimitry Andric 
2995f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_BRINDIRECT).legalFor({p0});
3005f757f3fSDimitry Andric 
3015f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_PHI)
3025f757f3fSDimitry Andric       .legalFor({p0, sXLen})
3035f757f3fSDimitry Andric       .widenScalarToNextPow2(0)
3045f757f3fSDimitry Andric       .clampScalar(0, sXLen, sXLen);
3055f757f3fSDimitry Andric 
3065f757f3fSDimitry Andric   getActionDefinitionsBuilder({G_GLOBAL_VALUE, G_JUMP_TABLE, G_CONSTANT_POOL})
3075f757f3fSDimitry Andric       .legalFor({p0});
3085f757f3fSDimitry Andric 
309*0fca6ea1SDimitry Andric   if (ST.hasStdExtZmmul()) {
3105f757f3fSDimitry Andric     getActionDefinitionsBuilder(G_MUL)
3115f757f3fSDimitry Andric         .legalFor({s32, sXLen})
3125f757f3fSDimitry Andric         .widenScalarToNextPow2(0)
3135f757f3fSDimitry Andric         .clampScalar(0, s32, sXLen);
3145f757f3fSDimitry Andric 
3155f757f3fSDimitry Andric     // clang-format off
3165f757f3fSDimitry Andric     getActionDefinitionsBuilder({G_SMULH, G_UMULH})
3175f757f3fSDimitry Andric         .legalFor({sXLen})
3185f757f3fSDimitry Andric         .lower();
3195f757f3fSDimitry Andric     // clang-format on
3205f757f3fSDimitry Andric 
3215f757f3fSDimitry Andric     getActionDefinitionsBuilder({G_SMULO, G_UMULO}).minScalar(0, sXLen).lower();
3225f757f3fSDimitry Andric   } else {
3235f757f3fSDimitry Andric     getActionDefinitionsBuilder(G_MUL)
3245f757f3fSDimitry Andric         .libcallFor({sXLen, sDoubleXLen})
3255f757f3fSDimitry Andric         .widenScalarToNextPow2(0)
3265f757f3fSDimitry Andric         .clampScalar(0, sXLen, sDoubleXLen);
3275f757f3fSDimitry Andric 
3285f757f3fSDimitry Andric     getActionDefinitionsBuilder({G_SMULH, G_UMULH}).lowerFor({sXLen});
3295f757f3fSDimitry Andric 
3305f757f3fSDimitry Andric     getActionDefinitionsBuilder({G_SMULO, G_UMULO})
3315f757f3fSDimitry Andric         .minScalar(0, sXLen)
3325f757f3fSDimitry Andric         // Widen sXLen to sDoubleXLen so we can use a single libcall to get
3335f757f3fSDimitry Andric         // the low bits for the mul result and high bits to do the overflow
3345f757f3fSDimitry Andric         // check.
3355f757f3fSDimitry Andric         .widenScalarIf(typeIs(0, sXLen),
3365f757f3fSDimitry Andric                        LegalizeMutations::changeTo(0, sDoubleXLen))
3375f757f3fSDimitry Andric         .lower();
3385f757f3fSDimitry Andric   }
3395f757f3fSDimitry Andric 
3405f757f3fSDimitry Andric   if (ST.hasStdExtM()) {
3415f757f3fSDimitry Andric     getActionDefinitionsBuilder({G_UDIV, G_SDIV, G_UREM, G_SREM})
3425f757f3fSDimitry Andric         .legalFor({s32, sXLen})
3435f757f3fSDimitry Andric         .libcallFor({sDoubleXLen})
3445f757f3fSDimitry Andric         .clampScalar(0, s32, sDoubleXLen)
3455f757f3fSDimitry Andric         .widenScalarToNextPow2(0);
3465f757f3fSDimitry Andric   } else {
3475f757f3fSDimitry Andric     getActionDefinitionsBuilder({G_UDIV, G_SDIV, G_UREM, G_SREM})
3485f757f3fSDimitry Andric         .libcallFor({sXLen, sDoubleXLen})
3495f757f3fSDimitry Andric         .clampScalar(0, sXLen, sDoubleXLen)
3505f757f3fSDimitry Andric         .widenScalarToNextPow2(0);
3515f757f3fSDimitry Andric   }
3525f757f3fSDimitry Andric 
353*0fca6ea1SDimitry Andric   // TODO: Use libcall for sDoubleXLen.
354*0fca6ea1SDimitry Andric   getActionDefinitionsBuilder({G_UDIVREM, G_SDIVREM}).lower();
355*0fca6ea1SDimitry Andric 
3565f757f3fSDimitry Andric   auto &AbsActions = getActionDefinitionsBuilder(G_ABS);
3575f757f3fSDimitry Andric   if (ST.hasStdExtZbb())
3585f757f3fSDimitry Andric     AbsActions.customFor({s32, sXLen}).minScalar(0, sXLen);
3595f757f3fSDimitry Andric   AbsActions.lower();
3605f757f3fSDimitry Andric 
3615f757f3fSDimitry Andric   auto &MinMaxActions =
3625f757f3fSDimitry Andric       getActionDefinitionsBuilder({G_UMAX, G_UMIN, G_SMAX, G_SMIN});
3635f757f3fSDimitry Andric   if (ST.hasStdExtZbb())
3645f757f3fSDimitry Andric     MinMaxActions.legalFor({sXLen}).minScalar(0, sXLen);
3655f757f3fSDimitry Andric   MinMaxActions.lower();
3665f757f3fSDimitry Andric 
3675f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0});
3685f757f3fSDimitry Andric 
3695f757f3fSDimitry Andric   getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall();
3705f757f3fSDimitry Andric 
3715f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_DYN_STACKALLOC).lower();
3725f757f3fSDimitry Andric 
3735f757f3fSDimitry Andric   // FP Operations
3745f757f3fSDimitry Andric 
3755f757f3fSDimitry Andric   getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FMA, G_FNEG,
3765f757f3fSDimitry Andric                                G_FABS, G_FSQRT, G_FMAXNUM, G_FMINNUM})
3775f757f3fSDimitry Andric       .legalIf(typeIsScalarFPArith(0, ST));
3785f757f3fSDimitry Andric 
379*0fca6ea1SDimitry Andric   getActionDefinitionsBuilder(G_FREM)
380*0fca6ea1SDimitry Andric       .libcallFor({s32, s64})
381*0fca6ea1SDimitry Andric       .minScalar(0, s32)
382*0fca6ea1SDimitry Andric       .scalarize(0);
383*0fca6ea1SDimitry Andric 
3845f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_FCOPYSIGN)
3855f757f3fSDimitry Andric       .legalIf(all(typeIsScalarFPArith(0, ST), typeIsScalarFPArith(1, ST)));
3865f757f3fSDimitry Andric 
387*0fca6ea1SDimitry Andric   // FIXME: Use Zfhmin.
3885f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_FPTRUNC).legalIf(
3895f757f3fSDimitry Andric       [=, &ST](const LegalityQuery &Query) -> bool {
3905f757f3fSDimitry Andric         return (ST.hasStdExtD() && typeIs(0, s32)(Query) &&
391*0fca6ea1SDimitry Andric                 typeIs(1, s64)(Query)) ||
392*0fca6ea1SDimitry Andric                (ST.hasStdExtZfh() && typeIs(0, s16)(Query) &&
393*0fca6ea1SDimitry Andric                 typeIs(1, s32)(Query)) ||
394*0fca6ea1SDimitry Andric                (ST.hasStdExtZfh() && ST.hasStdExtD() && typeIs(0, s16)(Query) &&
3955f757f3fSDimitry Andric                 typeIs(1, s64)(Query));
3965f757f3fSDimitry Andric       });
3975f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_FPEXT).legalIf(
3985f757f3fSDimitry Andric       [=, &ST](const LegalityQuery &Query) -> bool {
3995f757f3fSDimitry Andric         return (ST.hasStdExtD() && typeIs(0, s64)(Query) &&
400*0fca6ea1SDimitry Andric                 typeIs(1, s32)(Query)) ||
401*0fca6ea1SDimitry Andric                (ST.hasStdExtZfh() && typeIs(0, s32)(Query) &&
402*0fca6ea1SDimitry Andric                 typeIs(1, s16)(Query)) ||
403*0fca6ea1SDimitry Andric                (ST.hasStdExtZfh() && ST.hasStdExtD() && typeIs(0, s64)(Query) &&
404*0fca6ea1SDimitry Andric                 typeIs(1, s16)(Query));
4055f757f3fSDimitry Andric       });
4065f757f3fSDimitry Andric 
4075f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_FCMP)
4085f757f3fSDimitry Andric       .legalIf(all(typeIs(0, sXLen), typeIsScalarFPArith(1, ST)))
4095f757f3fSDimitry Andric       .clampScalar(0, sXLen, sXLen);
4105f757f3fSDimitry Andric 
4115f757f3fSDimitry Andric   // TODO: Support vector version of G_IS_FPCLASS.
4125f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_IS_FPCLASS)
4135f757f3fSDimitry Andric       .customIf(all(typeIs(0, s1), typeIsScalarFPArith(1, ST)));
4145f757f3fSDimitry Andric 
4155f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_FCONSTANT)
4165f757f3fSDimitry Andric       .legalIf(typeIsScalarFPArith(0, ST))
4175f757f3fSDimitry Andric       .lowerFor({s32, s64});
4185f757f3fSDimitry Andric 
4195f757f3fSDimitry Andric   getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
4205f757f3fSDimitry Andric       .legalIf(all(typeInSet(0, {s32, sXLen}), typeIsScalarFPArith(1, ST)))
4215f757f3fSDimitry Andric       .widenScalarToNextPow2(0)
422*0fca6ea1SDimitry Andric       .clampScalar(0, s32, sXLen)
423*0fca6ea1SDimitry Andric       .libcall();
4245f757f3fSDimitry Andric 
4255f757f3fSDimitry Andric   getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
4265f757f3fSDimitry Andric       .legalIf(all(typeIsScalarFPArith(0, ST), typeInSet(1, {s32, sXLen})))
4275f757f3fSDimitry Andric       .widenScalarToNextPow2(1)
4285f757f3fSDimitry Andric       .clampScalar(1, s32, sXLen);
4295f757f3fSDimitry Andric 
4305f757f3fSDimitry Andric   // FIXME: We can do custom inline expansion like SelectionDAG.
4315f757f3fSDimitry Andric   // FIXME: Legal with Zfa.
4325f757f3fSDimitry Andric   getActionDefinitionsBuilder({G_FCEIL, G_FFLOOR})
4335f757f3fSDimitry Andric       .libcallFor({s32, s64});
4345f757f3fSDimitry Andric 
4355f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_VASTART).customFor({p0});
4365f757f3fSDimitry Andric 
4375f757f3fSDimitry Andric   // va_list must be a pointer, but most sized types are pretty easy to handle
4385f757f3fSDimitry Andric   // as the destination.
4395f757f3fSDimitry Andric   getActionDefinitionsBuilder(G_VAARG)
4405f757f3fSDimitry Andric       // TODO: Implement narrowScalar and widenScalar for G_VAARG for types
4415f757f3fSDimitry Andric       // outside the [s32, sXLen] range.
4425f757f3fSDimitry Andric       .clampScalar(0, s32, sXLen)
4435f757f3fSDimitry Andric       .lowerForCartesianProduct({s32, sXLen, p0}, {p0});
44406c3fb27SDimitry Andric 
445*0fca6ea1SDimitry Andric   getActionDefinitionsBuilder(G_VSCALE)
446*0fca6ea1SDimitry Andric       .clampScalar(0, sXLen, sXLen)
447*0fca6ea1SDimitry Andric       .customFor({sXLen});
448*0fca6ea1SDimitry Andric 
449*0fca6ea1SDimitry Andric   auto &SplatActions =
450*0fca6ea1SDimitry Andric       getActionDefinitionsBuilder(G_SPLAT_VECTOR)
451*0fca6ea1SDimitry Andric           .legalIf(all(typeIsLegalIntOrFPVec(0, IntOrFPVecTys, ST),
452*0fca6ea1SDimitry Andric                        typeIs(1, sXLen)))
453*0fca6ea1SDimitry Andric           .customIf(all(typeIsLegalBoolVec(0, BoolVecTys, ST), typeIs(1, s1)));
454*0fca6ea1SDimitry Andric   // Handle case of s64 element vectors on RV32. If the subtarget does not have
455*0fca6ea1SDimitry Andric   // f64, then try to lower it to G_SPLAT_VECTOR_SPLIT_64_VL. If the subtarget
456*0fca6ea1SDimitry Andric   // does have f64, then we don't know whether the type is an f64 or an i64,
457*0fca6ea1SDimitry Andric   // so mark the G_SPLAT_VECTOR as legal and decide later what to do with it,
458*0fca6ea1SDimitry Andric   // depending on how the instructions it consumes are legalized. They are not
459*0fca6ea1SDimitry Andric   // legalized yet since legalization is in reverse postorder, so we cannot
460*0fca6ea1SDimitry Andric   // make the decision at this moment.
461*0fca6ea1SDimitry Andric   if (XLen == 32) {
462*0fca6ea1SDimitry Andric     if (ST.hasVInstructionsF64() && ST.hasStdExtD())
463*0fca6ea1SDimitry Andric       SplatActions.legalIf(all(
464*0fca6ea1SDimitry Andric           typeInSet(0, {nxv1s64, nxv2s64, nxv4s64, nxv8s64}), typeIs(1, s64)));
465*0fca6ea1SDimitry Andric     else if (ST.hasVInstructionsI64())
466*0fca6ea1SDimitry Andric       SplatActions.customIf(all(
467*0fca6ea1SDimitry Andric           typeInSet(0, {nxv1s64, nxv2s64, nxv4s64, nxv8s64}), typeIs(1, s64)));
468bdd1243dSDimitry Andric   }
4695f757f3fSDimitry Andric 
470*0fca6ea1SDimitry Andric   SplatActions.clampScalar(1, sXLen, sXLen);
471*0fca6ea1SDimitry Andric 
472*0fca6ea1SDimitry Andric   getLegacyLegalizerInfo().computeTables();
4735f757f3fSDimitry Andric }
4745f757f3fSDimitry Andric 
4755f757f3fSDimitry Andric bool RISCVLegalizerInfo::legalizeIntrinsic(LegalizerHelper &Helper,
4765f757f3fSDimitry Andric                                            MachineInstr &MI) const {
4775f757f3fSDimitry Andric   Intrinsic::ID IntrinsicID = cast<GIntrinsic>(MI).getIntrinsicID();
4785f757f3fSDimitry Andric   switch (IntrinsicID) {
4795f757f3fSDimitry Andric   default:
4805f757f3fSDimitry Andric     return false;
4815f757f3fSDimitry Andric   case Intrinsic::vacopy: {
4825f757f3fSDimitry Andric     // vacopy arguments must be legal because of the intrinsic signature.
4835f757f3fSDimitry Andric     // No need to check here.
4845f757f3fSDimitry Andric 
4855f757f3fSDimitry Andric     MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
4865f757f3fSDimitry Andric     MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
4875f757f3fSDimitry Andric     MachineFunction &MF = *MI.getMF();
4885f757f3fSDimitry Andric     const DataLayout &DL = MIRBuilder.getDataLayout();
4895f757f3fSDimitry Andric     LLVMContext &Ctx = MF.getFunction().getContext();
4905f757f3fSDimitry Andric 
4915f757f3fSDimitry Andric     Register DstLst = MI.getOperand(1).getReg();
4925f757f3fSDimitry Andric     LLT PtrTy = MRI.getType(DstLst);
4935f757f3fSDimitry Andric 
4945f757f3fSDimitry Andric     // Load the source va_list
4955f757f3fSDimitry Andric     Align Alignment = DL.getABITypeAlign(getTypeForLLT(PtrTy, Ctx));
4965f757f3fSDimitry Andric     MachineMemOperand *LoadMMO = MF.getMachineMemOperand(
4975f757f3fSDimitry Andric         MachinePointerInfo(), MachineMemOperand::MOLoad, PtrTy, Alignment);
4985f757f3fSDimitry Andric     auto Tmp = MIRBuilder.buildLoad(PtrTy, MI.getOperand(2), *LoadMMO);
4995f757f3fSDimitry Andric 
5005f757f3fSDimitry Andric     // Store the result in the destination va_list
5015f757f3fSDimitry Andric     MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
5025f757f3fSDimitry Andric         MachinePointerInfo(), MachineMemOperand::MOStore, PtrTy, Alignment);
503*0fca6ea1SDimitry Andric     MIRBuilder.buildStore(Tmp, DstLst, *StoreMMO);
5045f757f3fSDimitry Andric 
5055f757f3fSDimitry Andric     MI.eraseFromParent();
5065f757f3fSDimitry Andric     return true;
5075f757f3fSDimitry Andric   }
5085f757f3fSDimitry Andric   }
5095f757f3fSDimitry Andric }
5105f757f3fSDimitry Andric 
5115f757f3fSDimitry Andric bool RISCVLegalizerInfo::legalizeShlAshrLshr(
5125f757f3fSDimitry Andric     MachineInstr &MI, MachineIRBuilder &MIRBuilder,
5135f757f3fSDimitry Andric     GISelChangeObserver &Observer) const {
5145f757f3fSDimitry Andric   assert(MI.getOpcode() == TargetOpcode::G_ASHR ||
5155f757f3fSDimitry Andric          MI.getOpcode() == TargetOpcode::G_LSHR ||
5165f757f3fSDimitry Andric          MI.getOpcode() == TargetOpcode::G_SHL);
5175f757f3fSDimitry Andric   MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
5185f757f3fSDimitry Andric   // If the shift amount is a G_CONSTANT, promote it to a 64 bit type so the
5195f757f3fSDimitry Andric   // imported patterns can select it later. Either way, it will be legal.
5205f757f3fSDimitry Andric   Register AmtReg = MI.getOperand(2).getReg();
5215f757f3fSDimitry Andric   auto VRegAndVal = getIConstantVRegValWithLookThrough(AmtReg, MRI);
5225f757f3fSDimitry Andric   if (!VRegAndVal)
5235f757f3fSDimitry Andric     return true;
5245f757f3fSDimitry Andric   // Check the shift amount is in range for an immediate form.
5255f757f3fSDimitry Andric   uint64_t Amount = VRegAndVal->Value.getZExtValue();
5265f757f3fSDimitry Andric   if (Amount > 31)
5275f757f3fSDimitry Andric     return true; // This will have to remain a register variant.
5285f757f3fSDimitry Andric   auto ExtCst = MIRBuilder.buildConstant(LLT::scalar(64), Amount);
5295f757f3fSDimitry Andric   Observer.changingInstr(MI);
5305f757f3fSDimitry Andric   MI.getOperand(2).setReg(ExtCst.getReg(0));
5315f757f3fSDimitry Andric   Observer.changedInstr(MI);
5325f757f3fSDimitry Andric   return true;
5335f757f3fSDimitry Andric }
5345f757f3fSDimitry Andric 
5355f757f3fSDimitry Andric bool RISCVLegalizerInfo::legalizeVAStart(MachineInstr &MI,
5365f757f3fSDimitry Andric                                          MachineIRBuilder &MIRBuilder) const {
5375f757f3fSDimitry Andric   // Stores the address of the VarArgsFrameIndex slot into the memory location
5385f757f3fSDimitry Andric   assert(MI.getOpcode() == TargetOpcode::G_VASTART);
5395f757f3fSDimitry Andric   MachineFunction *MF = MI.getParent()->getParent();
5405f757f3fSDimitry Andric   RISCVMachineFunctionInfo *FuncInfo = MF->getInfo<RISCVMachineFunctionInfo>();
5415f757f3fSDimitry Andric   int FI = FuncInfo->getVarArgsFrameIndex();
5425f757f3fSDimitry Andric   LLT AddrTy = MIRBuilder.getMRI()->getType(MI.getOperand(0).getReg());
5435f757f3fSDimitry Andric   auto FINAddr = MIRBuilder.buildFrameIndex(AddrTy, FI);
5445f757f3fSDimitry Andric   assert(MI.hasOneMemOperand());
5455f757f3fSDimitry Andric   MIRBuilder.buildStore(FINAddr, MI.getOperand(0).getReg(),
5465f757f3fSDimitry Andric                         *MI.memoperands()[0]);
5475f757f3fSDimitry Andric   MI.eraseFromParent();
5485f757f3fSDimitry Andric   return true;
5495f757f3fSDimitry Andric }
5505f757f3fSDimitry Andric 
551*0fca6ea1SDimitry Andric bool RISCVLegalizerInfo::shouldBeInConstantPool(APInt APImm,
552*0fca6ea1SDimitry Andric                                                 bool ShouldOptForSize) const {
553*0fca6ea1SDimitry Andric   assert(APImm.getBitWidth() == 32 || APImm.getBitWidth() == 64);
554*0fca6ea1SDimitry Andric   int64_t Imm = APImm.getSExtValue();
555*0fca6ea1SDimitry Andric   // All simm32 constants should be handled by isel.
556*0fca6ea1SDimitry Andric   // NOTE: The getMaxBuildIntsCost call below should return a value >= 2 making
557*0fca6ea1SDimitry Andric   // this check redundant, but small immediates are common so this check
558*0fca6ea1SDimitry Andric   // should have better compile time.
559*0fca6ea1SDimitry Andric   if (isInt<32>(Imm))
560*0fca6ea1SDimitry Andric     return false;
561*0fca6ea1SDimitry Andric 
562*0fca6ea1SDimitry Andric   // We only need to cost the immediate, if constant pool lowering is enabled.
563*0fca6ea1SDimitry Andric   if (!STI.useConstantPoolForLargeInts())
564*0fca6ea1SDimitry Andric     return false;
565*0fca6ea1SDimitry Andric 
566*0fca6ea1SDimitry Andric   RISCVMatInt::InstSeq Seq = RISCVMatInt::generateInstSeq(Imm, STI);
567*0fca6ea1SDimitry Andric   if (Seq.size() <= STI.getMaxBuildIntsCost())
568*0fca6ea1SDimitry Andric     return false;
569*0fca6ea1SDimitry Andric 
570*0fca6ea1SDimitry Andric   // Optimizations below are disabled for opt size. If we're optimizing for
571*0fca6ea1SDimitry Andric   // size, use a constant pool.
572*0fca6ea1SDimitry Andric   if (ShouldOptForSize)
573*0fca6ea1SDimitry Andric     return true;
574*0fca6ea1SDimitry Andric   //
575*0fca6ea1SDimitry Andric   // Special case. See if we can build the constant as (ADD (SLLI X, C), X) do
576*0fca6ea1SDimitry Andric   // that if it will avoid a constant pool.
577*0fca6ea1SDimitry Andric   // It will require an extra temporary register though.
578*0fca6ea1SDimitry Andric   // If we have Zba we can use (ADD_UW X, (SLLI X, 32)) to handle cases where
579*0fca6ea1SDimitry Andric   // low and high 32 bits are the same and bit 31 and 63 are set.
580*0fca6ea1SDimitry Andric   unsigned ShiftAmt, AddOpc;
581*0fca6ea1SDimitry Andric   RISCVMatInt::InstSeq SeqLo =
582*0fca6ea1SDimitry Andric       RISCVMatInt::generateTwoRegInstSeq(Imm, STI, ShiftAmt, AddOpc);
583*0fca6ea1SDimitry Andric   return !(!SeqLo.empty() && (SeqLo.size() + 2) <= STI.getMaxBuildIntsCost());
584*0fca6ea1SDimitry Andric }
585*0fca6ea1SDimitry Andric 
586*0fca6ea1SDimitry Andric bool RISCVLegalizerInfo::legalizeVScale(MachineInstr &MI,
587*0fca6ea1SDimitry Andric                                         MachineIRBuilder &MIB) const {
588*0fca6ea1SDimitry Andric   const LLT XLenTy(STI.getXLenVT());
589*0fca6ea1SDimitry Andric   Register Dst = MI.getOperand(0).getReg();
590*0fca6ea1SDimitry Andric 
591*0fca6ea1SDimitry Andric   // We define our scalable vector types for lmul=1 to use a 64 bit known
592*0fca6ea1SDimitry Andric   // minimum size. e.g. <vscale x 2 x i32>. VLENB is in bytes so we calculate
593*0fca6ea1SDimitry Andric   // vscale as VLENB / 8.
594*0fca6ea1SDimitry Andric   static_assert(RISCV::RVVBitsPerBlock == 64, "Unexpected bits per block!");
595*0fca6ea1SDimitry Andric   if (STI.getRealMinVLen() < RISCV::RVVBitsPerBlock)
596*0fca6ea1SDimitry Andric     // Support for VLEN==32 is incomplete.
597*0fca6ea1SDimitry Andric     return false;
598*0fca6ea1SDimitry Andric 
599*0fca6ea1SDimitry Andric   // We assume VLENB is a multiple of 8. We manually choose the best shift
600*0fca6ea1SDimitry Andric   // here because SimplifyDemandedBits isn't always able to simplify it.
601*0fca6ea1SDimitry Andric   uint64_t Val = MI.getOperand(1).getCImm()->getZExtValue();
602*0fca6ea1SDimitry Andric   if (isPowerOf2_64(Val)) {
603*0fca6ea1SDimitry Andric     uint64_t Log2 = Log2_64(Val);
604*0fca6ea1SDimitry Andric     if (Log2 < 3) {
605*0fca6ea1SDimitry Andric       auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {});
606*0fca6ea1SDimitry Andric       MIB.buildLShr(Dst, VLENB, MIB.buildConstant(XLenTy, 3 - Log2));
607*0fca6ea1SDimitry Andric     } else if (Log2 > 3) {
608*0fca6ea1SDimitry Andric       auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {});
609*0fca6ea1SDimitry Andric       MIB.buildShl(Dst, VLENB, MIB.buildConstant(XLenTy, Log2 - 3));
610*0fca6ea1SDimitry Andric     } else {
611*0fca6ea1SDimitry Andric       MIB.buildInstr(RISCV::G_READ_VLENB, {Dst}, {});
612*0fca6ea1SDimitry Andric     }
613*0fca6ea1SDimitry Andric   } else if ((Val % 8) == 0) {
614*0fca6ea1SDimitry Andric     // If the multiplier is a multiple of 8, scale it down to avoid needing
615*0fca6ea1SDimitry Andric     // to shift the VLENB value.
616*0fca6ea1SDimitry Andric     auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {});
617*0fca6ea1SDimitry Andric     MIB.buildMul(Dst, VLENB, MIB.buildConstant(XLenTy, Val / 8));
618*0fca6ea1SDimitry Andric   } else {
619*0fca6ea1SDimitry Andric     auto VLENB = MIB.buildInstr(RISCV::G_READ_VLENB, {XLenTy}, {});
620*0fca6ea1SDimitry Andric     auto VScale = MIB.buildLShr(XLenTy, VLENB, MIB.buildConstant(XLenTy, 3));
621*0fca6ea1SDimitry Andric     MIB.buildMul(Dst, VScale, MIB.buildConstant(XLenTy, Val));
622*0fca6ea1SDimitry Andric   }
623*0fca6ea1SDimitry Andric   MI.eraseFromParent();
624*0fca6ea1SDimitry Andric   return true;
625*0fca6ea1SDimitry Andric }
626*0fca6ea1SDimitry Andric 
627*0fca6ea1SDimitry Andric // Custom-lower extensions from mask vectors by using a vselect either with 1
628*0fca6ea1SDimitry Andric // for zero/any-extension or -1 for sign-extension:
629*0fca6ea1SDimitry Andric //   (vXiN = (s|z)ext vXi1:vmask) -> (vXiN = vselect vmask, (-1 or 1), 0)
630*0fca6ea1SDimitry Andric // Note that any-extension is lowered identically to zero-extension.
631*0fca6ea1SDimitry Andric bool RISCVLegalizerInfo::legalizeExt(MachineInstr &MI,
632*0fca6ea1SDimitry Andric                                      MachineIRBuilder &MIB) const {
633*0fca6ea1SDimitry Andric 
634*0fca6ea1SDimitry Andric   unsigned Opc = MI.getOpcode();
635*0fca6ea1SDimitry Andric   assert(Opc == TargetOpcode::G_ZEXT || Opc == TargetOpcode::G_SEXT ||
636*0fca6ea1SDimitry Andric          Opc == TargetOpcode::G_ANYEXT);
637*0fca6ea1SDimitry Andric 
638*0fca6ea1SDimitry Andric   MachineRegisterInfo &MRI = *MIB.getMRI();
639*0fca6ea1SDimitry Andric   Register Dst = MI.getOperand(0).getReg();
640*0fca6ea1SDimitry Andric   Register Src = MI.getOperand(1).getReg();
641*0fca6ea1SDimitry Andric 
642*0fca6ea1SDimitry Andric   LLT DstTy = MRI.getType(Dst);
643*0fca6ea1SDimitry Andric   int64_t ExtTrueVal = Opc == TargetOpcode::G_SEXT ? -1 : 1;
644*0fca6ea1SDimitry Andric   LLT DstEltTy = DstTy.getElementType();
645*0fca6ea1SDimitry Andric   auto SplatZero = MIB.buildSplatVector(DstTy, MIB.buildConstant(DstEltTy, 0));
646*0fca6ea1SDimitry Andric   auto SplatTrue =
647*0fca6ea1SDimitry Andric       MIB.buildSplatVector(DstTy, MIB.buildConstant(DstEltTy, ExtTrueVal));
648*0fca6ea1SDimitry Andric   MIB.buildSelect(Dst, Src, SplatTrue, SplatZero);
649*0fca6ea1SDimitry Andric 
650*0fca6ea1SDimitry Andric   MI.eraseFromParent();
651*0fca6ea1SDimitry Andric   return true;
652*0fca6ea1SDimitry Andric }
653*0fca6ea1SDimitry Andric 
654*0fca6ea1SDimitry Andric /// Return the type of the mask type suitable for masking the provided
655*0fca6ea1SDimitry Andric /// vector type.  This is simply an i1 element type vector of the same
656*0fca6ea1SDimitry Andric /// (possibly scalable) length.
657*0fca6ea1SDimitry Andric static LLT getMaskTypeFor(LLT VecTy) {
658*0fca6ea1SDimitry Andric   assert(VecTy.isVector());
659*0fca6ea1SDimitry Andric   ElementCount EC = VecTy.getElementCount();
660*0fca6ea1SDimitry Andric   return LLT::vector(EC, LLT::scalar(1));
661*0fca6ea1SDimitry Andric }
662*0fca6ea1SDimitry Andric 
663*0fca6ea1SDimitry Andric /// Creates an all ones mask suitable for masking a vector of type VecTy with
664*0fca6ea1SDimitry Andric /// vector length VL.
665*0fca6ea1SDimitry Andric static MachineInstrBuilder buildAllOnesMask(LLT VecTy, const SrcOp &VL,
666*0fca6ea1SDimitry Andric                                             MachineIRBuilder &MIB,
667*0fca6ea1SDimitry Andric                                             MachineRegisterInfo &MRI) {
668*0fca6ea1SDimitry Andric   LLT MaskTy = getMaskTypeFor(VecTy);
669*0fca6ea1SDimitry Andric   return MIB.buildInstr(RISCV::G_VMSET_VL, {MaskTy}, {VL});
670*0fca6ea1SDimitry Andric }
671*0fca6ea1SDimitry Andric 
672*0fca6ea1SDimitry Andric /// Gets the two common "VL" operands: an all-ones mask and the vector length.
673*0fca6ea1SDimitry Andric /// VecTy is a scalable vector type.
674*0fca6ea1SDimitry Andric static std::pair<MachineInstrBuilder, Register>
675*0fca6ea1SDimitry Andric buildDefaultVLOps(const DstOp &Dst, MachineIRBuilder &MIB,
676*0fca6ea1SDimitry Andric                   MachineRegisterInfo &MRI) {
677*0fca6ea1SDimitry Andric   LLT VecTy = Dst.getLLTTy(MRI);
678*0fca6ea1SDimitry Andric   assert(VecTy.isScalableVector() && "Expecting scalable container type");
679*0fca6ea1SDimitry Andric   Register VL(RISCV::X0);
680*0fca6ea1SDimitry Andric   MachineInstrBuilder Mask = buildAllOnesMask(VecTy, VL, MIB, MRI);
681*0fca6ea1SDimitry Andric   return {Mask, VL};
682*0fca6ea1SDimitry Andric }
683*0fca6ea1SDimitry Andric 
684*0fca6ea1SDimitry Andric static MachineInstrBuilder
685*0fca6ea1SDimitry Andric buildSplatPartsS64WithVL(const DstOp &Dst, const SrcOp &Passthru, Register Lo,
686*0fca6ea1SDimitry Andric                          Register Hi, Register VL, MachineIRBuilder &MIB,
687*0fca6ea1SDimitry Andric                          MachineRegisterInfo &MRI) {
688*0fca6ea1SDimitry Andric   // TODO: If the Hi bits of the splat are undefined, then it's fine to just
689*0fca6ea1SDimitry Andric   // splat Lo even if it might be sign extended. I don't think we have
690*0fca6ea1SDimitry Andric   // introduced a case where we're build a s64 where the upper bits are undef
691*0fca6ea1SDimitry Andric   // yet.
692*0fca6ea1SDimitry Andric 
693*0fca6ea1SDimitry Andric   // Fall back to a stack store and stride x0 vector load.
694*0fca6ea1SDimitry Andric   // TODO: need to lower G_SPLAT_VECTOR_SPLIT_I64. This is done in
695*0fca6ea1SDimitry Andric   // preprocessDAG in SDAG.
696*0fca6ea1SDimitry Andric   return MIB.buildInstr(RISCV::G_SPLAT_VECTOR_SPLIT_I64_VL, {Dst},
697*0fca6ea1SDimitry Andric                         {Passthru, Lo, Hi, VL});
698*0fca6ea1SDimitry Andric }
699*0fca6ea1SDimitry Andric 
700*0fca6ea1SDimitry Andric static MachineInstrBuilder
701*0fca6ea1SDimitry Andric buildSplatSplitS64WithVL(const DstOp &Dst, const SrcOp &Passthru,
702*0fca6ea1SDimitry Andric                          const SrcOp &Scalar, Register VL,
703*0fca6ea1SDimitry Andric                          MachineIRBuilder &MIB, MachineRegisterInfo &MRI) {
704*0fca6ea1SDimitry Andric   assert(Scalar.getLLTTy(MRI) == LLT::scalar(64) && "Unexpected VecTy!");
705*0fca6ea1SDimitry Andric   auto Unmerge = MIB.buildUnmerge(LLT::scalar(32), Scalar);
706*0fca6ea1SDimitry Andric   return buildSplatPartsS64WithVL(Dst, Passthru, Unmerge.getReg(0),
707*0fca6ea1SDimitry Andric                                   Unmerge.getReg(1), VL, MIB, MRI);
708*0fca6ea1SDimitry Andric }
709*0fca6ea1SDimitry Andric 
710*0fca6ea1SDimitry Andric // Lower splats of s1 types to G_ICMP. For each mask vector type, we have a
711*0fca6ea1SDimitry Andric // legal equivalently-sized i8 type, so we can use that as a go-between.
712*0fca6ea1SDimitry Andric // Splats of s1 types that have constant value can be legalized as VMSET_VL or
713*0fca6ea1SDimitry Andric // VMCLR_VL.
714*0fca6ea1SDimitry Andric bool RISCVLegalizerInfo::legalizeSplatVector(MachineInstr &MI,
715*0fca6ea1SDimitry Andric                                              MachineIRBuilder &MIB) const {
716*0fca6ea1SDimitry Andric   assert(MI.getOpcode() == TargetOpcode::G_SPLAT_VECTOR);
717*0fca6ea1SDimitry Andric 
718*0fca6ea1SDimitry Andric   MachineRegisterInfo &MRI = *MIB.getMRI();
719*0fca6ea1SDimitry Andric 
720*0fca6ea1SDimitry Andric   Register Dst = MI.getOperand(0).getReg();
721*0fca6ea1SDimitry Andric   Register SplatVal = MI.getOperand(1).getReg();
722*0fca6ea1SDimitry Andric 
723*0fca6ea1SDimitry Andric   LLT VecTy = MRI.getType(Dst);
724*0fca6ea1SDimitry Andric   LLT XLenTy(STI.getXLenVT());
725*0fca6ea1SDimitry Andric 
726*0fca6ea1SDimitry Andric   // Handle case of s64 element vectors on rv32
727*0fca6ea1SDimitry Andric   if (XLenTy.getSizeInBits() == 32 &&
728*0fca6ea1SDimitry Andric       VecTy.getElementType().getSizeInBits() == 64) {
729*0fca6ea1SDimitry Andric     auto [_, VL] = buildDefaultVLOps(Dst, MIB, MRI);
730*0fca6ea1SDimitry Andric     buildSplatSplitS64WithVL(Dst, MIB.buildUndef(VecTy), SplatVal, VL, MIB,
731*0fca6ea1SDimitry Andric                              MRI);
732*0fca6ea1SDimitry Andric     MI.eraseFromParent();
733*0fca6ea1SDimitry Andric     return true;
734*0fca6ea1SDimitry Andric   }
735*0fca6ea1SDimitry Andric 
736*0fca6ea1SDimitry Andric   // All-zeros or all-ones splats are handled specially.
737*0fca6ea1SDimitry Andric   MachineInstr &SplatValMI = *MRI.getVRegDef(SplatVal);
738*0fca6ea1SDimitry Andric   if (isAllOnesOrAllOnesSplat(SplatValMI, MRI)) {
739*0fca6ea1SDimitry Andric     auto VL = buildDefaultVLOps(VecTy, MIB, MRI).second;
740*0fca6ea1SDimitry Andric     MIB.buildInstr(RISCV::G_VMSET_VL, {Dst}, {VL});
741*0fca6ea1SDimitry Andric     MI.eraseFromParent();
742*0fca6ea1SDimitry Andric     return true;
743*0fca6ea1SDimitry Andric   }
744*0fca6ea1SDimitry Andric   if (isNullOrNullSplat(SplatValMI, MRI)) {
745*0fca6ea1SDimitry Andric     auto VL = buildDefaultVLOps(VecTy, MIB, MRI).second;
746*0fca6ea1SDimitry Andric     MIB.buildInstr(RISCV::G_VMCLR_VL, {Dst}, {VL});
747*0fca6ea1SDimitry Andric     MI.eraseFromParent();
748*0fca6ea1SDimitry Andric     return true;
749*0fca6ea1SDimitry Andric   }
750*0fca6ea1SDimitry Andric 
751*0fca6ea1SDimitry Andric   // Handle non-constant mask splat (i.e. not sure if it's all zeros or all
752*0fca6ea1SDimitry Andric   // ones) by promoting it to an s8 splat.
753*0fca6ea1SDimitry Andric   LLT InterEltTy = LLT::scalar(8);
754*0fca6ea1SDimitry Andric   LLT InterTy = VecTy.changeElementType(InterEltTy);
755*0fca6ea1SDimitry Andric   auto ZExtSplatVal = MIB.buildZExt(InterEltTy, SplatVal);
756*0fca6ea1SDimitry Andric   auto And =
757*0fca6ea1SDimitry Andric       MIB.buildAnd(InterEltTy, ZExtSplatVal, MIB.buildConstant(InterEltTy, 1));
758*0fca6ea1SDimitry Andric   auto LHS = MIB.buildSplatVector(InterTy, And);
759*0fca6ea1SDimitry Andric   auto ZeroSplat =
760*0fca6ea1SDimitry Andric       MIB.buildSplatVector(InterTy, MIB.buildConstant(InterEltTy, 0));
761*0fca6ea1SDimitry Andric   MIB.buildICmp(CmpInst::Predicate::ICMP_NE, Dst, LHS, ZeroSplat);
762*0fca6ea1SDimitry Andric   MI.eraseFromParent();
763*0fca6ea1SDimitry Andric   return true;
764*0fca6ea1SDimitry Andric }
765*0fca6ea1SDimitry Andric 
7661db9f3b2SDimitry Andric bool RISCVLegalizerInfo::legalizeCustom(
7671db9f3b2SDimitry Andric     LegalizerHelper &Helper, MachineInstr &MI,
7681db9f3b2SDimitry Andric     LostDebugLocObserver &LocObserver) const {
7695f757f3fSDimitry Andric   MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
7705f757f3fSDimitry Andric   GISelChangeObserver &Observer = Helper.Observer;
771*0fca6ea1SDimitry Andric   MachineFunction &MF = *MI.getParent()->getParent();
7725f757f3fSDimitry Andric   switch (MI.getOpcode()) {
7735f757f3fSDimitry Andric   default:
7745f757f3fSDimitry Andric     // No idea what to do.
7755f757f3fSDimitry Andric     return false;
7765f757f3fSDimitry Andric   case TargetOpcode::G_ABS:
7775f757f3fSDimitry Andric     return Helper.lowerAbsToMaxNeg(MI);
778*0fca6ea1SDimitry Andric   // TODO: G_FCONSTANT
779*0fca6ea1SDimitry Andric   case TargetOpcode::G_CONSTANT: {
780*0fca6ea1SDimitry Andric     const Function &F = MF.getFunction();
781*0fca6ea1SDimitry Andric     // TODO: if PSI and BFI are present, add " ||
782*0fca6ea1SDimitry Andric     // llvm::shouldOptForSize(*CurMBB, PSI, BFI)".
783*0fca6ea1SDimitry Andric     bool ShouldOptForSize = F.hasOptSize() || F.hasMinSize();
784*0fca6ea1SDimitry Andric     const ConstantInt *ConstVal = MI.getOperand(1).getCImm();
785*0fca6ea1SDimitry Andric     if (!shouldBeInConstantPool(ConstVal->getValue(), ShouldOptForSize))
786*0fca6ea1SDimitry Andric       return true;
787*0fca6ea1SDimitry Andric     return Helper.lowerConstant(MI);
788*0fca6ea1SDimitry Andric   }
7895f757f3fSDimitry Andric   case TargetOpcode::G_SHL:
7905f757f3fSDimitry Andric   case TargetOpcode::G_ASHR:
7915f757f3fSDimitry Andric   case TargetOpcode::G_LSHR:
7925f757f3fSDimitry Andric     return legalizeShlAshrLshr(MI, MIRBuilder, Observer);
7935f757f3fSDimitry Andric   case TargetOpcode::G_SEXT_INREG: {
7945f757f3fSDimitry Andric     // Source size of 32 is sext.w.
7955f757f3fSDimitry Andric     int64_t SizeInBits = MI.getOperand(2).getImm();
7965f757f3fSDimitry Andric     if (SizeInBits == 32)
7975f757f3fSDimitry Andric       return true;
7985f757f3fSDimitry Andric 
7995f757f3fSDimitry Andric     return Helper.lower(MI, 0, /* Unused hint type */ LLT()) ==
8005f757f3fSDimitry Andric            LegalizerHelper::Legalized;
8015f757f3fSDimitry Andric   }
8025f757f3fSDimitry Andric   case TargetOpcode::G_IS_FPCLASS: {
8035f757f3fSDimitry Andric     Register GISFPCLASS = MI.getOperand(0).getReg();
8045f757f3fSDimitry Andric     Register Src = MI.getOperand(1).getReg();
8055f757f3fSDimitry Andric     const MachineOperand &ImmOp = MI.getOperand(2);
8065f757f3fSDimitry Andric     MachineIRBuilder MIB(MI);
8075f757f3fSDimitry Andric 
8085f757f3fSDimitry Andric     // Turn LLVM IR's floating point classes to that in RISC-V,
8095f757f3fSDimitry Andric     // by simply rotating the 10-bit immediate right by two bits.
8105f757f3fSDimitry Andric     APInt GFpClassImm(10, static_cast<uint64_t>(ImmOp.getImm()));
8115f757f3fSDimitry Andric     auto FClassMask = MIB.buildConstant(sXLen, GFpClassImm.rotr(2).zext(XLen));
8125f757f3fSDimitry Andric     auto ConstZero = MIB.buildConstant(sXLen, 0);
8135f757f3fSDimitry Andric 
8145f757f3fSDimitry Andric     auto GFClass = MIB.buildInstr(RISCV::G_FCLASS, {sXLen}, {Src});
8155f757f3fSDimitry Andric     auto And = MIB.buildAnd(sXLen, GFClass, FClassMask);
8165f757f3fSDimitry Andric     MIB.buildICmp(CmpInst::ICMP_NE, GISFPCLASS, And, ConstZero);
8175f757f3fSDimitry Andric 
8185f757f3fSDimitry Andric     MI.eraseFromParent();
8195f757f3fSDimitry Andric     return true;
8205f757f3fSDimitry Andric   }
8215f757f3fSDimitry Andric   case TargetOpcode::G_VASTART:
8225f757f3fSDimitry Andric     return legalizeVAStart(MI, MIRBuilder);
823*0fca6ea1SDimitry Andric   case TargetOpcode::G_VSCALE:
824*0fca6ea1SDimitry Andric     return legalizeVScale(MI, MIRBuilder);
825*0fca6ea1SDimitry Andric   case TargetOpcode::G_ZEXT:
826*0fca6ea1SDimitry Andric   case TargetOpcode::G_SEXT:
827*0fca6ea1SDimitry Andric   case TargetOpcode::G_ANYEXT:
828*0fca6ea1SDimitry Andric     return legalizeExt(MI, MIRBuilder);
829*0fca6ea1SDimitry Andric   case TargetOpcode::G_SPLAT_VECTOR:
830*0fca6ea1SDimitry Andric     return legalizeSplatVector(MI, MIRBuilder);
8315f757f3fSDimitry Andric   }
8325f757f3fSDimitry Andric 
8335f757f3fSDimitry Andric   llvm_unreachable("expected switch to return");
8345f757f3fSDimitry Andric }
835