1//===-- RISCVVectorUtils.h - RISC-V vector utilities ------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines RISC-V vector utilities shared across the backend,
10// including helpers for recognizing shuffle masks supported by vector
11// permutation instructions.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_LIB_TARGET_RISCV_RISCVVECTORUTILS_H
16#define LLVM_LIB_TARGET_RISCV_RISCVVECTORUTILS_H
17
18#include "llvm/ADT/ArrayRef.h"
19#include "llvm/Support/MathExtras.h"
20
21namespace llvm {
22
23inline bool isAlternating(const std::array<std::pair<int, int>, 2> &SrcInfo,
24 ArrayRef<int> Mask, unsigned Factor,
25 bool RequiredPolarity) {
26 int NumElts = Mask.size();
27 for (const auto &[Idx, M] : enumerate(First&: Mask)) {
28 if (M < 0)
29 continue;
30 int Src = M >= NumElts;
31 int Diff = (int)Idx - (M % NumElts);
32 bool C = Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
33 assert(C != (Src == SrcInfo[0].first && Diff == SrcInfo[0].second) &&
34 "Must match exactly one of the two slides");
35 if (RequiredPolarity != (C == (Idx / Factor) % 2))
36 return false;
37 }
38 return true;
39}
40
41/// Given a shuffle which can be represented as a pair of two slides,
42/// see if it is a pair-even idiom.
43/// Pair-even is:
44/// vs2: a0 a1 a2 a3
45/// vs1: b0 b1 b2 b3
46/// vd: a0 b0 a2 b2
47inline bool isPairEven(const std::array<std::pair<int, int>, 2> &SrcInfo,
48 ArrayRef<int> Mask, unsigned &Factor) {
49 Factor = SrcInfo[1].second;
50 return SrcInfo[0].second == 0 && isPowerOf2_32(Value: Factor) &&
51 Mask.size() % Factor == 0 &&
52 isAlternating(SrcInfo, Mask, Factor, RequiredPolarity: true);
53}
54
55/// Given a shuffle which can be represented as a pair of two slides,
56/// see if it is a pair-odd idiom.
57/// Pair-odd is:
58/// vs2: a0 a1 a2 a3
59/// vs1: b0 b1 b2 b3
60/// vd: a1 b1 a3 b3
61/// Note that the operand order is swapped due to the way we canonicalize
62/// the slides, so SrCInfo[0] is vs1, and SrcInfo[1] is vs2.
63inline bool isPairOdd(const std::array<std::pair<int, int>, 2> &SrcInfo,
64 ArrayRef<int> Mask, unsigned &Factor) {
65 Factor = -SrcInfo[1].second;
66 return SrcInfo[0].second == 0 && isPowerOf2_32(Value: Factor) &&
67 Mask.size() % Factor == 0 &&
68 isAlternating(SrcInfo, Mask, Factor, RequiredPolarity: false);
69}
70} // namespace llvm
71
72#endif // LLVM_LIB_TARGET_RISCV_RISCVVECTORUTILS_H
73