Skip to content

Commit 5aa8e43

Browse files
authored
[VP] Add missing functional_intrinsic properties and add static_assert. NFC (#66199)
Some VP intrinsic definitions were missing the VP_PROPERTY_FUNCTIONAL_INTRINSIC property. This patch fills them in, and adds a static_assert that all VP intrinsics have an equivalent opcode or intrinsic defined so we don't forget them in future. Some VP intrinsics don't have an equivalent, namely merge and strided load/store. For those, a new property was added to mark that they don't have a non-VP equivalent. This adds a helper method to get the ID of the functionally equivalent intrinsic, similar to the existing getFunctionalOpcodeForVP and getConstrainedIntrinsicIDForVP method.
1 parent c354ee8 commit 5aa8e43

File tree

2 files changed

+69
-5
lines changed

2 files changed

+69
-5
lines changed

llvm/include/llvm/IR/VPIntrinsics.def

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@
118118
#define VP_PROPERTY_FUNCTIONAL_INTRINSIC(INTRIN)
119119
#endif
120120

121+
// This VP Intrinsic has no functionally-equivalent non-VP opcode or intrinsic.
122+
#ifndef VP_PROPERTY_NO_FUNCTIONAL
123+
#define VP_PROPERTY_NO_FUNCTIONAL
124+
#endif
125+
121126
// This VP Intrinsic is a memory operation
122127
// The pointer arg is at POINTERPOS and the data arg is at DATAPOS.
123128
#ifndef VP_PROPERTY_MEMOP
@@ -235,27 +240,32 @@ END_REGISTER_VP(vp_umax, VP_UMAX)
235240
BEGIN_REGISTER_VP_INTRINSIC(vp_abs, 2, 3)
236241
BEGIN_REGISTER_VP_SDNODE(VP_ABS, -1, vp_abs, 1, 2)
237242
HELPER_MAP_VPID_TO_VPSD(vp_abs, VP_ABS)
243+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(abs)
238244
VP_PROPERTY_FUNCTIONAL_SDOPC(ABS)
239245
END_REGISTER_VP(vp_abs, VP_ABS)
240246

241247
// llvm.vp.bswap(x,mask,vlen)
242248
BEGIN_REGISTER_VP(vp_bswap, 1, 2, VP_BSWAP, -1)
249+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(bswap)
243250
VP_PROPERTY_FUNCTIONAL_SDOPC(BSWAP)
244251
END_REGISTER_VP(vp_bswap, VP_BSWAP)
245252

246253
// llvm.vp.bitreverse(x,mask,vlen)
247254
BEGIN_REGISTER_VP(vp_bitreverse, 1, 2, VP_BITREVERSE, -1)
255+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(bitreverse)
248256
VP_PROPERTY_FUNCTIONAL_SDOPC(BITREVERSE)
249257
END_REGISTER_VP(vp_bitreverse, VP_BITREVERSE)
250258

251259
// llvm.vp.ctpop(x,mask,vlen)
252260
BEGIN_REGISTER_VP(vp_ctpop, 1, 2, VP_CTPOP, -1)
261+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(ctpop)
253262
VP_PROPERTY_FUNCTIONAL_SDOPC(CTPOP)
254263
END_REGISTER_VP(vp_ctpop, VP_CTPOP)
255264

256265
// llvm.vp.ctlz(x,is_zero_poison,mask,vlen)
257266
BEGIN_REGISTER_VP_INTRINSIC(vp_ctlz, 2, 3)
258267
BEGIN_REGISTER_VP_SDNODE(VP_CTLZ, -1, vp_ctlz, 1, 2)
268+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(ctlz)
259269
VP_PROPERTY_FUNCTIONAL_SDOPC(CTLZ)
260270
END_REGISTER_VP_SDNODE(VP_CTLZ)
261271
BEGIN_REGISTER_VP_SDNODE(VP_CTLZ_ZERO_UNDEF, -1, vp_ctlz_zero_undef, 1, 2)
@@ -265,6 +275,7 @@ END_REGISTER_VP_INTRINSIC(vp_ctlz)
265275
// llvm.vp.cttz(x,is_zero_poison,mask,vlen)
266276
BEGIN_REGISTER_VP_INTRINSIC(vp_cttz, 2, 3)
267277
BEGIN_REGISTER_VP_SDNODE(VP_CTTZ, -1, vp_cttz, 1, 2)
278+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(cttz)
268279
VP_PROPERTY_FUNCTIONAL_SDOPC(CTTZ)
269280
END_REGISTER_VP_SDNODE(VP_CTTZ)
270281
BEGIN_REGISTER_VP_SDNODE(VP_CTTZ_ZERO_UNDEF, -1, vp_cttz_zero_undef, 1, 2)
@@ -273,11 +284,13 @@ END_REGISTER_VP_INTRINSIC(vp_cttz)
273284

274285
// llvm.vp.fshl(x,y,z,mask,vlen)
275286
BEGIN_REGISTER_VP(vp_fshl, 3, 4, VP_FSHL, -1)
287+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(fshl)
276288
VP_PROPERTY_FUNCTIONAL_SDOPC(FSHL)
277289
END_REGISTER_VP(vp_fshl, VP_FSHL)
278290

279291
// llvm.vp.fshr(x,y,z,mask,vlen)
280292
BEGIN_REGISTER_VP(vp_fshr, 3, 4, VP_FSHR, -1)
293+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(fshr)
281294
VP_PROPERTY_FUNCTIONAL_SDOPC(FSHR)
282295
END_REGISTER_VP(vp_fshr, VP_FSHR)
283296
///// } Integer Arithmetic
@@ -323,23 +336,27 @@ END_REGISTER_VP(vp_fneg, VP_FNEG)
323336

324337
// llvm.vp.fabs(x,mask,vlen)
325338
BEGIN_REGISTER_VP(vp_fabs, 1, 2, VP_FABS, -1)
339+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(fabs)
326340
VP_PROPERTY_FUNCTIONAL_SDOPC(FABS)
327341
END_REGISTER_VP(vp_fabs, VP_FABS)
328342

329343
// llvm.vp.sqrt(x,mask,vlen)
330344
BEGIN_REGISTER_VP(vp_sqrt, 1, 2, VP_SQRT, -1)
345+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(sqrt)
331346
VP_PROPERTY_FUNCTIONAL_SDOPC(FSQRT)
332347
END_REGISTER_VP(vp_sqrt, VP_SQRT)
333348

334349
// llvm.vp.fma(x,y,z,mask,vlen)
335350
BEGIN_REGISTER_VP(vp_fma, 3, 4, VP_FMA, -1)
336351
VP_PROPERTY_CONSTRAINEDFP(1, 1, experimental_constrained_fma)
352+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(fma)
337353
VP_PROPERTY_FUNCTIONAL_SDOPC(FMA)
338354
END_REGISTER_VP(vp_fma, VP_FMA)
339355

340356
// llvm.vp.fmuladd(x,y,z,mask,vlen)
341357
BEGIN_REGISTER_VP(vp_fmuladd, 3, 4, VP_FMULADD, -1)
342358
VP_PROPERTY_CONSTRAINEDFP(1, 1, experimental_constrained_fmuladd)
359+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(fmuladd)
343360
VP_PROPERTY_FUNCTIONAL_SDOPC(FMAD)
344361
END_REGISTER_VP(vp_fmuladd, VP_FMULADD)
345362

@@ -366,36 +383,43 @@ END_REGISTER_VP(vp_maxnum, VP_FMAXNUM)
366383

367384
// llvm.vp.ceil(x,mask,vlen)
368385
BEGIN_REGISTER_VP(vp_ceil, 1, 2, VP_FCEIL, -1)
386+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(ceil)
369387
VP_PROPERTY_FUNCTIONAL_SDOPC(FCEIL)
370388
END_REGISTER_VP(vp_ceil, VP_FCEIL)
371389

372390
// llvm.vp.floor(x,mask,vlen)
373391
BEGIN_REGISTER_VP(vp_floor, 1, 2, VP_FFLOOR, -1)
392+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(floor)
374393
VP_PROPERTY_FUNCTIONAL_SDOPC(FFLOOR)
375394
END_REGISTER_VP(vp_floor, VP_FFLOOR)
376395

377396
// llvm.vp.round(x,mask,vlen)
378397
BEGIN_REGISTER_VP(vp_round, 1, 2, VP_FROUND, -1)
398+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(round)
379399
VP_PROPERTY_FUNCTIONAL_SDOPC(FROUND)
380400
END_REGISTER_VP(vp_round, VP_FROUND)
381401

382402
// llvm.vp.roundeven(x,mask,vlen)
383403
BEGIN_REGISTER_VP(vp_roundeven, 1, 2, VP_FROUNDEVEN, -1)
404+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(roundeven)
384405
VP_PROPERTY_FUNCTIONAL_SDOPC(FROUNDEVEN)
385406
END_REGISTER_VP(vp_roundeven, VP_FROUNDEVEN)
386407

387408
// llvm.vp.roundtozero(x,mask,vlen)
388409
BEGIN_REGISTER_VP(vp_roundtozero, 1, 2, VP_FROUNDTOZERO, -1)
410+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(trunc)
389411
VP_PROPERTY_FUNCTIONAL_SDOPC(FTRUNC)
390412
END_REGISTER_VP(vp_roundtozero, VP_FROUNDTOZERO)
391413

392414
// llvm.vp.rint(x,mask,vlen)
393415
BEGIN_REGISTER_VP(vp_rint, 1, 2, VP_FRINT, -1)
416+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(rint)
394417
VP_PROPERTY_FUNCTIONAL_SDOPC(FRINT)
395418
END_REGISTER_VP(vp_rint, VP_FRINT)
396419

397420
// llvm.vp.nearbyint(x,mask,vlen)
398421
BEGIN_REGISTER_VP(vp_nearbyint, 1, 2, VP_FNEARBYINT, -1)
422+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(nearbyint)
399423
VP_PROPERTY_FUNCTIONAL_SDOPC(FNEARBYINT)
400424
END_REGISTER_VP(vp_nearbyint, VP_FNEARBYINT)
401425

@@ -499,6 +523,7 @@ END_REGISTER_VP_INTRINSIC(vp_icmp)
499523

500524
// llvm.vp.is.fpclass(on_true,on_false,mask,vlen)
501525
BEGIN_REGISTER_VP(vp_is_fpclass, 2, 3, VP_IS_FPCLASS, 0)
526+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(is_fpclass)
502527
END_REGISTER_VP(vp_is_fpclass, VP_IS_FPCLASS)
503528

504529
///// Memory Operations {
@@ -515,6 +540,7 @@ END_REGISTER_VP(vp_store, VP_STORE)
515540
// llvm.experimental.vp.strided.store(val,ptr,stride,mask,vlen)
516541
BEGIN_REGISTER_VP_INTRINSIC(experimental_vp_strided_store, 3, 4)
517542
// chain = EXPERIMENTAL_VP_STRIDED_STORE chain,val,base,offset,stride,mask,evl
543+
VP_PROPERTY_NO_FUNCTIONAL
518544
BEGIN_REGISTER_VP_SDNODE(EXPERIMENTAL_VP_STRIDED_STORE, 1, experimental_vp_strided_store, 5, 6)
519545
HELPER_MAP_VPID_TO_VPSD(experimental_vp_strided_store, EXPERIMENTAL_VP_STRIDED_STORE)
520546
VP_PROPERTY_MEMOP(1, 0)
@@ -542,6 +568,7 @@ END_REGISTER_VP(vp_load, VP_LOAD)
542568
// llvm.experimental.vp.strided.load(ptr,stride,mask,vlen)
543569
BEGIN_REGISTER_VP_INTRINSIC(experimental_vp_strided_load, 2, 3)
544570
// chain = EXPERIMENTAL_VP_STRIDED_LOAD chain,base,offset,stride,mask,evl
571+
VP_PROPERTY_NO_FUNCTIONAL
545572
BEGIN_REGISTER_VP_SDNODE(EXPERIMENTAL_VP_STRIDED_LOAD, -1, experimental_vp_strided_load, 4, 5)
546573
HELPER_MAP_VPID_TO_VPSD(experimental_vp_strided_load, EXPERIMENTAL_VP_STRIDED_LOAD)
547574
VP_PROPERTY_MEMOP(0, std::nullopt)
@@ -668,9 +695,11 @@ END_REGISTER_VP(vp_select, VP_SELECT)
668695

669696
// llvm.vp.merge(cond,on_true,on_false,pivot)
670697
BEGIN_REGISTER_VP(vp_merge, std::nullopt, 3, VP_MERGE, -1)
698+
VP_PROPERTY_NO_FUNCTIONAL
671699
END_REGISTER_VP(vp_merge, VP_MERGE)
672700

673701
BEGIN_REGISTER_VP(experimental_vp_splice, 3, 5, EXPERIMENTAL_VP_SPLICE, -1)
702+
VP_PROPERTY_FUNCTIONAL_INTRINSIC(experimental_vector_splice)
674703
END_REGISTER_VP(experimental_vp_splice, EXPERIMENTAL_VP_SPLICE)
675704

676705
///// } Shuffles
@@ -689,5 +718,6 @@ END_REGISTER_VP(experimental_vp_splice, EXPERIMENTAL_VP_SPLICE)
689718
#undef VP_PROPERTY_FUNCTIONAL_INTRINSIC
690719
#undef VP_PROPERTY_FUNCTIONAL_OPC
691720
#undef VP_PROPERTY_FUNCTIONAL_SDOPC
721+
#undef VP_PROPERTY_NO_FUNCTIONAL
692722
#undef VP_PROPERTY_MEMOP
693723
#undef VP_PROPERTY_REDUCTION

llvm/lib/IR/IntrinsicInst.cpp

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ std::optional<unsigned> VPIntrinsic::getMemoryDataParamPos(Intrinsic::ID VPID) {
503503
return std::nullopt;
504504
}
505505

506-
bool VPIntrinsic::isVPIntrinsic(Intrinsic::ID ID) {
506+
constexpr bool isVPIntrinsic(Intrinsic::ID ID) {
507507
switch (ID) {
508508
default:
509509
break;
@@ -515,34 +515,68 @@ bool VPIntrinsic::isVPIntrinsic(Intrinsic::ID ID) {
515515
return false;
516516
}
517517

518+
bool VPIntrinsic::isVPIntrinsic(Intrinsic::ID ID) {
519+
return ::isVPIntrinsic(ID);
520+
}
521+
518522
// Equivalent non-predicated opcode
523+
constexpr static std::optional<unsigned>
524+
getFunctionalOpcodeForVP(Intrinsic::ID ID) {
525+
switch (ID) {
526+
default:
527+
break;
528+
#define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
529+
#define VP_PROPERTY_FUNCTIONAL_OPC(OPC) return Instruction::OPC;
530+
#define END_REGISTER_VP_INTRINSIC(VPID) break;
531+
#include "llvm/IR/VPIntrinsics.def"
532+
}
533+
return std::nullopt;
534+
}
535+
519536
std::optional<unsigned>
520537
VPIntrinsic::getFunctionalOpcodeForVP(Intrinsic::ID ID) {
538+
return ::getFunctionalOpcodeForVP(ID);
539+
}
540+
541+
// Equivalent non-predicated intrinsic ID
542+
constexpr static std::optional<Intrinsic::ID>
543+
getFunctionalIntrinsicIDForVP(Intrinsic::ID ID) {
521544
switch (ID) {
522545
default:
523546
break;
524547
#define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
525-
#define VP_PROPERTY_FUNCTIONAL_OPC(OPC) return Instruction::OPC;
548+
#define VP_PROPERTY_FUNCTIONAL_INTRINSIC(INTRIN) return Intrinsic::INTRIN;
526549
#define END_REGISTER_VP_INTRINSIC(VPID) break;
527550
#include "llvm/IR/VPIntrinsics.def"
528551
}
529552
return std::nullopt;
530553
}
531554

532-
// Equivalent non-predicated intrinsic
533555
std::optional<Intrinsic::ID>
534556
VPIntrinsic::getFunctionalIntrinsicIDForVP(Intrinsic::ID ID) {
557+
return ::getFunctionalIntrinsicIDForVP(ID);
558+
}
559+
560+
constexpr static bool doesVPHaveNoFunctionalEquivalent(Intrinsic::ID ID) {
535561
switch (ID) {
536562
default:
537563
break;
538564
#define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
539-
#define VP_PROPERTY_FUNCTIONAL_INTRINSIC(INTRIN) return Intrinsic::INTRIN;
565+
#define VP_PROPERTY_NO_FUNCTIONAL return true;
540566
#define END_REGISTER_VP_INTRINSIC(VPID) break;
541567
#include "llvm/IR/VPIntrinsics.def"
542568
}
543-
return std::nullopt;
569+
return false;
544570
}
545571

572+
// All VP intrinsics should have an equivalent non-VP opcode or intrinsic
573+
// defined, or be marked that they don't have one.
574+
#define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) \
575+
static_assert(doesVPHaveNoFunctionalEquivalent(Intrinsic::VPID) || \
576+
getFunctionalOpcodeForVP(Intrinsic::VPID) || \
577+
getFunctionalIntrinsicIDForVP(Intrinsic::VPID));
578+
#include "llvm/IR/VPIntrinsics.def"
579+
546580
// Equivalent non-predicated constrained intrinsic
547581
std::optional<Intrinsic::ID>
548582
VPIntrinsic::getConstrainedIntrinsicIDForVP(Intrinsic::ID ID) {

0 commit comments

Comments
 (0)