xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/TargetBuiltins/Hexagon.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===------ Hexagon.cpp - Emit LLVM Code for builtins ---------------------===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric //
9*700637cbSDimitry Andric // This contains code to emit Builtin calls as LLVM code.
10*700637cbSDimitry Andric //
11*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
12*700637cbSDimitry Andric 
13*700637cbSDimitry Andric #include "CodeGenFunction.h"
14*700637cbSDimitry Andric #include "clang/Basic/TargetBuiltins.h"
15*700637cbSDimitry Andric #include "llvm/IR/IntrinsicsHexagon.h"
16*700637cbSDimitry Andric 
17*700637cbSDimitry Andric using namespace clang;
18*700637cbSDimitry Andric using namespace CodeGen;
19*700637cbSDimitry Andric using namespace llvm;
20*700637cbSDimitry Andric 
21*700637cbSDimitry Andric static std::pair<Intrinsic::ID, unsigned>
getIntrinsicForHexagonNonClangBuiltin(unsigned BuiltinID)22*700637cbSDimitry Andric getIntrinsicForHexagonNonClangBuiltin(unsigned BuiltinID) {
23*700637cbSDimitry Andric   struct Info {
24*700637cbSDimitry Andric     unsigned BuiltinID;
25*700637cbSDimitry Andric     Intrinsic::ID IntrinsicID;
26*700637cbSDimitry Andric     unsigned VecLen;
27*700637cbSDimitry Andric   };
28*700637cbSDimitry Andric   static Info Infos[] = {
29*700637cbSDimitry Andric #define CUSTOM_BUILTIN_MAPPING(x,s) \
30*700637cbSDimitry Andric   { Hexagon::BI__builtin_HEXAGON_##x, Intrinsic::hexagon_##x, s },
31*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(L2_loadrub_pci, 0)
32*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(L2_loadrb_pci, 0)
33*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(L2_loadruh_pci, 0)
34*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(L2_loadrh_pci, 0)
35*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(L2_loadri_pci, 0)
36*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(L2_loadrd_pci, 0)
37*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(L2_loadrub_pcr, 0)
38*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(L2_loadrb_pcr, 0)
39*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(L2_loadruh_pcr, 0)
40*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(L2_loadrh_pcr, 0)
41*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(L2_loadri_pcr, 0)
42*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(L2_loadrd_pcr, 0)
43*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(S2_storerb_pci, 0)
44*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(S2_storerh_pci, 0)
45*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(S2_storerf_pci, 0)
46*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(S2_storeri_pci, 0)
47*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(S2_storerd_pci, 0)
48*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(S2_storerb_pcr, 0)
49*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(S2_storerh_pcr, 0)
50*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(S2_storerf_pcr, 0)
51*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(S2_storeri_pcr, 0)
52*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(S2_storerd_pcr, 0)
53*700637cbSDimitry Andric     // Legacy builtins that take a vector in place of a vector predicate.
54*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(V6_vmaskedstoreq, 64)
55*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(V6_vmaskedstorenq, 64)
56*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(V6_vmaskedstorentq, 64)
57*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(V6_vmaskedstorentnq, 64)
58*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(V6_vmaskedstoreq_128B, 128)
59*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(V6_vmaskedstorenq_128B, 128)
60*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(V6_vmaskedstorentq_128B, 128)
61*700637cbSDimitry Andric     CUSTOM_BUILTIN_MAPPING(V6_vmaskedstorentnq_128B, 128)
62*700637cbSDimitry Andric #include "clang/Basic/BuiltinsHexagonMapCustomDep.def"
63*700637cbSDimitry Andric #undef CUSTOM_BUILTIN_MAPPING
64*700637cbSDimitry Andric   };
65*700637cbSDimitry Andric 
66*700637cbSDimitry Andric   auto CmpInfo = [] (Info A, Info B) { return A.BuiltinID < B.BuiltinID; };
67*700637cbSDimitry Andric   static const bool SortOnce = (llvm::sort(Infos, CmpInfo), true);
68*700637cbSDimitry Andric   (void)SortOnce;
69*700637cbSDimitry Andric 
70*700637cbSDimitry Andric   const Info *F = llvm::lower_bound(Infos, Info{BuiltinID, 0, 0}, CmpInfo);
71*700637cbSDimitry Andric   if (F == std::end(Infos) || F->BuiltinID != BuiltinID)
72*700637cbSDimitry Andric     return {Intrinsic::not_intrinsic, 0};
73*700637cbSDimitry Andric 
74*700637cbSDimitry Andric   return {F->IntrinsicID, F->VecLen};
75*700637cbSDimitry Andric }
76*700637cbSDimitry Andric 
EmitHexagonBuiltinExpr(unsigned BuiltinID,const CallExpr * E)77*700637cbSDimitry Andric Value *CodeGenFunction::EmitHexagonBuiltinExpr(unsigned BuiltinID,
78*700637cbSDimitry Andric                                                const CallExpr *E) {
79*700637cbSDimitry Andric   Intrinsic::ID ID;
80*700637cbSDimitry Andric   unsigned VecLen;
81*700637cbSDimitry Andric   std::tie(ID, VecLen) = getIntrinsicForHexagonNonClangBuiltin(BuiltinID);
82*700637cbSDimitry Andric 
83*700637cbSDimitry Andric   auto MakeCircOp = [this, E](unsigned IntID, bool IsLoad) {
84*700637cbSDimitry Andric     // The base pointer is passed by address, so it needs to be loaded.
85*700637cbSDimitry Andric     Address A = EmitPointerWithAlignment(E->getArg(0));
86*700637cbSDimitry Andric     Address BP = Address(A.emitRawPointer(*this), Int8PtrTy, A.getAlignment());
87*700637cbSDimitry Andric     llvm::Value *Base = Builder.CreateLoad(BP);
88*700637cbSDimitry Andric     // The treatment of both loads and stores is the same: the arguments for
89*700637cbSDimitry Andric     // the builtin are the same as the arguments for the intrinsic.
90*700637cbSDimitry Andric     // Load:
91*700637cbSDimitry Andric     //   builtin(Base, Inc, Mod, Start) -> intr(Base, Inc, Mod, Start)
92*700637cbSDimitry Andric     //   builtin(Base, Mod, Start)      -> intr(Base, Mod, Start)
93*700637cbSDimitry Andric     // Store:
94*700637cbSDimitry Andric     //   builtin(Base, Inc, Mod, Val, Start) -> intr(Base, Inc, Mod, Val, Start)
95*700637cbSDimitry Andric     //   builtin(Base, Mod, Val, Start)      -> intr(Base, Mod, Val, Start)
96*700637cbSDimitry Andric     SmallVector<llvm::Value*,5> Ops = { Base };
97*700637cbSDimitry Andric     for (unsigned i = 1, e = E->getNumArgs(); i != e; ++i)
98*700637cbSDimitry Andric       Ops.push_back(EmitScalarExpr(E->getArg(i)));
99*700637cbSDimitry Andric 
100*700637cbSDimitry Andric     llvm::Value *Result = Builder.CreateCall(CGM.getIntrinsic(IntID), Ops);
101*700637cbSDimitry Andric     // The load intrinsics generate two results (Value, NewBase), stores
102*700637cbSDimitry Andric     // generate one (NewBase). The new base address needs to be stored.
103*700637cbSDimitry Andric     llvm::Value *NewBase = IsLoad ? Builder.CreateExtractValue(Result, 1)
104*700637cbSDimitry Andric                                   : Result;
105*700637cbSDimitry Andric     llvm::Value *LV = EmitScalarExpr(E->getArg(0));
106*700637cbSDimitry Andric     Address Dest = EmitPointerWithAlignment(E->getArg(0));
107*700637cbSDimitry Andric     llvm::Value *RetVal =
108*700637cbSDimitry Andric         Builder.CreateAlignedStore(NewBase, LV, Dest.getAlignment());
109*700637cbSDimitry Andric     if (IsLoad)
110*700637cbSDimitry Andric       RetVal = Builder.CreateExtractValue(Result, 0);
111*700637cbSDimitry Andric     return RetVal;
112*700637cbSDimitry Andric   };
113*700637cbSDimitry Andric 
114*700637cbSDimitry Andric   // Handle the conversion of bit-reverse load intrinsics to bit code.
115*700637cbSDimitry Andric   // The intrinsic call after this function only reads from memory and the
116*700637cbSDimitry Andric   // write to memory is dealt by the store instruction.
117*700637cbSDimitry Andric   auto MakeBrevLd = [this, E](unsigned IntID, llvm::Type *DestTy) {
118*700637cbSDimitry Andric     // The intrinsic generates one result, which is the new value for the base
119*700637cbSDimitry Andric     // pointer. It needs to be returned. The result of the load instruction is
120*700637cbSDimitry Andric     // passed to intrinsic by address, so the value needs to be stored.
121*700637cbSDimitry Andric     llvm::Value *BaseAddress = EmitScalarExpr(E->getArg(0));
122*700637cbSDimitry Andric 
123*700637cbSDimitry Andric     // Expressions like &(*pt++) will be incremented per evaluation.
124*700637cbSDimitry Andric     // EmitPointerWithAlignment and EmitScalarExpr evaluates the expression
125*700637cbSDimitry Andric     // per call.
126*700637cbSDimitry Andric     Address DestAddr = EmitPointerWithAlignment(E->getArg(1));
127*700637cbSDimitry Andric     DestAddr = DestAddr.withElementType(Int8Ty);
128*700637cbSDimitry Andric     llvm::Value *DestAddress = DestAddr.emitRawPointer(*this);
129*700637cbSDimitry Andric 
130*700637cbSDimitry Andric     // Operands are Base, Dest, Modifier.
131*700637cbSDimitry Andric     // The intrinsic format in LLVM IR is defined as
132*700637cbSDimitry Andric     // { ValueType, i8* } (i8*, i32).
133*700637cbSDimitry Andric     llvm::Value *Result = Builder.CreateCall(
134*700637cbSDimitry Andric         CGM.getIntrinsic(IntID), {BaseAddress, EmitScalarExpr(E->getArg(2))});
135*700637cbSDimitry Andric 
136*700637cbSDimitry Andric     // The value needs to be stored as the variable is passed by reference.
137*700637cbSDimitry Andric     llvm::Value *DestVal = Builder.CreateExtractValue(Result, 0);
138*700637cbSDimitry Andric 
139*700637cbSDimitry Andric     // The store needs to be truncated to fit the destination type.
140*700637cbSDimitry Andric     // While i32 and i64 are natively supported on Hexagon, i8 and i16 needs
141*700637cbSDimitry Andric     // to be handled with stores of respective destination type.
142*700637cbSDimitry Andric     DestVal = Builder.CreateTrunc(DestVal, DestTy);
143*700637cbSDimitry Andric 
144*700637cbSDimitry Andric     Builder.CreateAlignedStore(DestVal, DestAddress, DestAddr.getAlignment());
145*700637cbSDimitry Andric     // The updated value of the base pointer is returned.
146*700637cbSDimitry Andric     return Builder.CreateExtractValue(Result, 1);
147*700637cbSDimitry Andric   };
148*700637cbSDimitry Andric 
149*700637cbSDimitry Andric   auto V2Q = [this, VecLen] (llvm::Value *Vec) {
150*700637cbSDimitry Andric     Intrinsic::ID ID = VecLen == 128 ? Intrinsic::hexagon_V6_vandvrt_128B
151*700637cbSDimitry Andric                                      : Intrinsic::hexagon_V6_vandvrt;
152*700637cbSDimitry Andric     return Builder.CreateCall(CGM.getIntrinsic(ID),
153*700637cbSDimitry Andric                               {Vec, Builder.getInt32(-1)});
154*700637cbSDimitry Andric   };
155*700637cbSDimitry Andric   auto Q2V = [this, VecLen] (llvm::Value *Pred) {
156*700637cbSDimitry Andric     Intrinsic::ID ID = VecLen == 128 ? Intrinsic::hexagon_V6_vandqrt_128B
157*700637cbSDimitry Andric                                      : Intrinsic::hexagon_V6_vandqrt;
158*700637cbSDimitry Andric     return Builder.CreateCall(CGM.getIntrinsic(ID),
159*700637cbSDimitry Andric                               {Pred, Builder.getInt32(-1)});
160*700637cbSDimitry Andric   };
161*700637cbSDimitry Andric 
162*700637cbSDimitry Andric   switch (BuiltinID) {
163*700637cbSDimitry Andric   // These intrinsics return a tuple {Vector, VectorPred} in LLVM IR,
164*700637cbSDimitry Andric   // and the corresponding C/C++ builtins use loads/stores to update
165*700637cbSDimitry Andric   // the predicate.
166*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_V6_vaddcarry:
167*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_V6_vaddcarry_128B:
168*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_V6_vsubcarry:
169*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_V6_vsubcarry_128B: {
170*700637cbSDimitry Andric     // Get the type from the 0-th argument.
171*700637cbSDimitry Andric     llvm::Type *VecType = ConvertType(E->getArg(0)->getType());
172*700637cbSDimitry Andric     Address PredAddr =
173*700637cbSDimitry Andric         EmitPointerWithAlignment(E->getArg(2)).withElementType(VecType);
174*700637cbSDimitry Andric     llvm::Value *PredIn = V2Q(Builder.CreateLoad(PredAddr));
175*700637cbSDimitry Andric     llvm::Value *Result = Builder.CreateCall(CGM.getIntrinsic(ID),
176*700637cbSDimitry Andric         {EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1)), PredIn});
177*700637cbSDimitry Andric 
178*700637cbSDimitry Andric     llvm::Value *PredOut = Builder.CreateExtractValue(Result, 1);
179*700637cbSDimitry Andric     Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.emitRawPointer(*this),
180*700637cbSDimitry Andric                                PredAddr.getAlignment());
181*700637cbSDimitry Andric     return Builder.CreateExtractValue(Result, 0);
182*700637cbSDimitry Andric   }
183*700637cbSDimitry Andric   // These are identical to the builtins above, except they don't consume
184*700637cbSDimitry Andric   // input carry, only generate carry-out. Since they still produce two
185*700637cbSDimitry Andric   // outputs, generate the store of the predicate, but no load.
186*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_V6_vaddcarryo:
187*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_V6_vaddcarryo_128B:
188*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_V6_vsubcarryo:
189*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_V6_vsubcarryo_128B: {
190*700637cbSDimitry Andric     // Get the type from the 0-th argument.
191*700637cbSDimitry Andric     llvm::Type *VecType = ConvertType(E->getArg(0)->getType());
192*700637cbSDimitry Andric     Address PredAddr =
193*700637cbSDimitry Andric         EmitPointerWithAlignment(E->getArg(2)).withElementType(VecType);
194*700637cbSDimitry Andric     llvm::Value *Result = Builder.CreateCall(CGM.getIntrinsic(ID),
195*700637cbSDimitry Andric         {EmitScalarExpr(E->getArg(0)), EmitScalarExpr(E->getArg(1))});
196*700637cbSDimitry Andric 
197*700637cbSDimitry Andric     llvm::Value *PredOut = Builder.CreateExtractValue(Result, 1);
198*700637cbSDimitry Andric     Builder.CreateAlignedStore(Q2V(PredOut), PredAddr.emitRawPointer(*this),
199*700637cbSDimitry Andric                                PredAddr.getAlignment());
200*700637cbSDimitry Andric     return Builder.CreateExtractValue(Result, 0);
201*700637cbSDimitry Andric   }
202*700637cbSDimitry Andric 
203*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_V6_vmaskedstoreq:
204*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_V6_vmaskedstorenq:
205*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_V6_vmaskedstorentq:
206*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_V6_vmaskedstorentnq:
207*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_V6_vmaskedstoreq_128B:
208*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_V6_vmaskedstorenq_128B:
209*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_V6_vmaskedstorentq_128B:
210*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_V6_vmaskedstorentnq_128B: {
211*700637cbSDimitry Andric     SmallVector<llvm::Value*,4> Ops;
212*700637cbSDimitry Andric     const Expr *PredOp = E->getArg(0);
213*700637cbSDimitry Andric     // There will be an implicit cast to a boolean vector. Strip it.
214*700637cbSDimitry Andric     if (auto *Cast = dyn_cast<ImplicitCastExpr>(PredOp)) {
215*700637cbSDimitry Andric       if (Cast->getCastKind() == CK_BitCast)
216*700637cbSDimitry Andric         PredOp = Cast->getSubExpr();
217*700637cbSDimitry Andric       Ops.push_back(V2Q(EmitScalarExpr(PredOp)));
218*700637cbSDimitry Andric     }
219*700637cbSDimitry Andric     for (int i = 1, e = E->getNumArgs(); i != e; ++i)
220*700637cbSDimitry Andric       Ops.push_back(EmitScalarExpr(E->getArg(i)));
221*700637cbSDimitry Andric     return Builder.CreateCall(CGM.getIntrinsic(ID), Ops);
222*700637cbSDimitry Andric   }
223*700637cbSDimitry Andric 
224*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_L2_loadrub_pci:
225*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_L2_loadrb_pci:
226*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_L2_loadruh_pci:
227*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_L2_loadrh_pci:
228*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_L2_loadri_pci:
229*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_L2_loadrd_pci:
230*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_L2_loadrub_pcr:
231*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_L2_loadrb_pcr:
232*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_L2_loadruh_pcr:
233*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_L2_loadrh_pcr:
234*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_L2_loadri_pcr:
235*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_L2_loadrd_pcr:
236*700637cbSDimitry Andric     return MakeCircOp(ID, /*IsLoad=*/true);
237*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_S2_storerb_pci:
238*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_S2_storerh_pci:
239*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_S2_storerf_pci:
240*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_S2_storeri_pci:
241*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_S2_storerd_pci:
242*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_S2_storerb_pcr:
243*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_S2_storerh_pcr:
244*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_S2_storerf_pcr:
245*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_S2_storeri_pcr:
246*700637cbSDimitry Andric   case Hexagon::BI__builtin_HEXAGON_S2_storerd_pcr:
247*700637cbSDimitry Andric     return MakeCircOp(ID, /*IsLoad=*/false);
248*700637cbSDimitry Andric   case Hexagon::BI__builtin_brev_ldub:
249*700637cbSDimitry Andric     return MakeBrevLd(Intrinsic::hexagon_L2_loadrub_pbr, Int8Ty);
250*700637cbSDimitry Andric   case Hexagon::BI__builtin_brev_ldb:
251*700637cbSDimitry Andric     return MakeBrevLd(Intrinsic::hexagon_L2_loadrb_pbr, Int8Ty);
252*700637cbSDimitry Andric   case Hexagon::BI__builtin_brev_lduh:
253*700637cbSDimitry Andric     return MakeBrevLd(Intrinsic::hexagon_L2_loadruh_pbr, Int16Ty);
254*700637cbSDimitry Andric   case Hexagon::BI__builtin_brev_ldh:
255*700637cbSDimitry Andric     return MakeBrevLd(Intrinsic::hexagon_L2_loadrh_pbr, Int16Ty);
256*700637cbSDimitry Andric   case Hexagon::BI__builtin_brev_ldw:
257*700637cbSDimitry Andric     return MakeBrevLd(Intrinsic::hexagon_L2_loadri_pbr, Int32Ty);
258*700637cbSDimitry Andric   case Hexagon::BI__builtin_brev_ldd:
259*700637cbSDimitry Andric     return MakeBrevLd(Intrinsic::hexagon_L2_loadrd_pbr, Int64Ty);
260*700637cbSDimitry Andric   } // switch
261*700637cbSDimitry Andric 
262*700637cbSDimitry Andric   return nullptr;
263*700637cbSDimitry Andric }
264