xref: /llvm-project/llvm/lib/Transforms/Vectorize/SandboxVectorizer/Legality.cpp (revision ca998b071eba1c92bf8535964183c7c4c3b258c3)
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: Allow vectorization by using common flags.
59   // For now Pack if they don't have the same wrap flags.
60   bool CanHaveWrapFlags =
61       isa<OverflowingBinaryOperator>(I0) || isa<TruncInst>(I0);
62   if (CanHaveWrapFlags) {
63     bool NUW0 = I0->hasNoUnsignedWrap();
64     bool NSW0 = I0->hasNoSignedWrap();
65     if (any_of(drop_begin(Bndl), [NUW0, NSW0](auto *V) {
66           return cast<Instruction>(V)->hasNoUnsignedWrap() != NUW0 ||
67                  cast<Instruction>(V)->hasNoSignedWrap() != NSW0;
68         })) {
69       return ResultReason::DiffWrapFlags;
70     }
71   }
72 
73   // TODO: Missing checks
74 
75   return std::nullopt;
76 }
77 
78 #ifndef NDEBUG
79 static void dumpBndl(ArrayRef<Value *> Bndl) {
80   for (auto *V : Bndl)
81     dbgs() << *V << "\n";
82 }
83 #endif // NDEBUG
84 
85 const LegalityResult &LegalityAnalysis::canVectorize(ArrayRef<Value *> Bndl) {
86   // If Bndl contains values other than instructions, we need to Pack.
87   if (any_of(Bndl, [](auto *V) { return !isa<Instruction>(V); })) {
88     LLVM_DEBUG(dbgs() << "Not vectorizing: Not Instructions:\n";
89                dumpBndl(Bndl););
90     return createLegalityResult<Pack>(ResultReason::NotInstructions);
91   }
92 
93   if (auto ReasonOpt = notVectorizableBasedOnOpcodesAndTypes(Bndl))
94     return createLegalityResult<Pack>(*ReasonOpt);
95 
96   // TODO: Check for existing vectors containing values in Bndl.
97 
98   // TODO: Check with scheduler.
99 
100   return createLegalityResult<Widen>();
101 }
102 } // namespace llvm::sandboxir
103