xref: /llvm-project/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Legality.cpp (revision bf4b31ad54f6bf298210c201a0afe50469ebe98e)
1 //===- Legality.cpp -------------------------------------------------------===//
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 #include "llvm/Transforms/Vectorize/SandboxVectorizer/Legality.h"
10 #include "llvm/SandboxIR/Instruction.h"
11 #include "llvm/SandboxIR/Operator.h"
12 #include "llvm/SandboxIR/Utils.h"
13 #include "llvm/SandboxIR/Value.h"
14 #include "llvm/Support/Debug.h"
15 #include "llvm/Transforms/Vectorize/SandboxVectorizer/VecUtils.h"
16 
17 namespace llvm::sandboxir {
18 
19 #define DEBUG_TYPE "SBVec:Legality"
20 
21 #ifndef NDEBUG
22 void LegalityResult::dump() const {
23   print(dbgs());
24   dbgs() << "\n";
25 }
26 #endif // NDEBUG
27 
28 std::optional<ResultReason>
29 LegalityAnalysis::notVectorizableBasedOnOpcodesAndTypes(
30     ArrayRef<Value *> Bndl) {
31   auto *I0 = cast<Instruction>(Bndl[0]);
32   auto Opcode = I0->getOpcode();
33   // If they have different opcodes, then we cannot form a vector (for now).
34   if (any_of(drop_begin(Bndl), [Opcode](Value *V) {
35         return cast<Instruction>(V)->getOpcode() != Opcode;
36       }))
37     return ResultReason::DiffOpcodes;
38 
39   // If not the same scalar type, Pack. This will accept scalars and vectors as
40   // long as the element type is the same.
41   Type *ElmTy0 = VecUtils::getElementType(Utils::getExpectedType(I0));
42   if (any_of(drop_begin(Bndl), [ElmTy0](Value *V) {
43         return VecUtils::getElementType(Utils::getExpectedType(V)) != ElmTy0;
44       }))
45     return ResultReason::DiffTypes;
46 
47   // TODO: Allow vectorization of instrs with different flags as long as we
48   // change them to the least common one.
49   // For now pack if differnt FastMathFlags.
50   if (isa<FPMathOperator>(I0)) {
51     FastMathFlags FMF0 = cast<Instruction>(Bndl[0])->getFastMathFlags();
52     if (any_of(drop_begin(Bndl), [FMF0](auto *V) {
53           return cast<Instruction>(V)->getFastMathFlags() != FMF0;
54         }))
55       return ResultReason::DiffMathFlags;
56   }
57 
58   // TODO: Missing checks
59 
60   return std::nullopt;
61 }
62 
63 #ifndef NDEBUG
64 static void dumpBndl(ArrayRef<Value *> Bndl) {
65   for (auto *V : Bndl)
66     dbgs() << *V << "\n";
67 }
68 #endif // NDEBUG
69 
70 const LegalityResult &LegalityAnalysis::canVectorize(ArrayRef<Value *> Bndl) {
71   // If Bndl contains values other than instructions, we need to Pack.
72   if (any_of(Bndl, [](auto *V) { return !isa<Instruction>(V); })) {
73     LLVM_DEBUG(dbgs() << "Not vectorizing: Not Instructions:\n";
74                dumpBndl(Bndl););
75     return createLegalityResult<Pack>(ResultReason::NotInstructions);
76   }
77 
78   if (auto ReasonOpt = notVectorizableBasedOnOpcodesAndTypes(Bndl))
79     return createLegalityResult<Pack>(*ReasonOpt);
80 
81   // TODO: Check for existing vectors containing values in Bndl.
82 
83   // TODO: Check with scheduler.
84 
85   return createLegalityResult<Widen>();
86 }
87 } // namespace llvm::sandboxir
88