xref: /llvm-project/llvm/unittests/Target/AArch64/Immediates.cpp (revision 36a3f8f6471ba04b7ebf32a3393708b8fb32aecf)
1 #include "AArch64Subtarget.h"
2 #include "AArch64TargetMachine.h"
3 #include "llvm/IR/DataLayout.h"
4 #include "llvm/MC/TargetRegistry.h"
5 #include "llvm/Support/TargetSelect.h"
6 
7 #include "gtest/gtest.h"
8 #include <initializer_list>
9 #include <memory>
10 
11 using namespace llvm;
12 
13 namespace {
14 
15 struct TestCase {
16   int64_t Imm;
17   bool Result;
18 };
19 
20 const std::initializer_list<TestCase> Tests = {
21     // ScalableImm, Result
22     // No change, easily 'supported'
23     {0, true},
24 
25     // addvl increments by whole registers, range [-32,31]
26     // +(16 * vscale), one register's worth
27     {16, true},
28     // -(32 * 16 * vscale)
29     {-512, true},
30     // -(33 * 16 * vscale)
31     {-528, false},
32     // +(31 * 16 * vscale)
33     {496, true},
34     // +(32 * 16 * vscale)
35     {512, false},
36 
37     // inc[h|w|d] increments by the number of 16/32/64bit elements in a
38     // register. mult_imm is in the range [1,16]
39     // +(mult_imm * num_elts * vscale)
40     // +(1 * 8 * vscale), 16 bit
41     {8, true},
42     // +(15 * 8 * vscale), 16 bit
43     {120, true},
44     // +(1 * 4 * vscale), 32 bit
45     {4, true},
46     // +(7 * 4 * vscale), 32 bit
47     {28, true},
48     // +(1 * 2 * vscale), 64 bit
49     {2, true},
50     // +(13 * 2 * vscale), 64 bit
51     {26, true},
52     // +(17 * 8 * vscale), 16 bit, out of range.
53     {136, false},
54     // +(19 * 2 * vscale), 64 bit, out of range.
55     {38, false},
56     // +(21 * 4 * vscale), 32 bit, out of range.
57     {84, false},
58 
59     // dec[h|w|d] -- Same as above, but negative.
60     // -(mult_imm * num_elts * vscale)
61     // -(1 * 8 * vscale), 16 bit
62     {-8, true},
63     // -(15 * 8 * vscale), 16 bit
64     {-120, true},
65     // -(1 * 4 * vscale), 32 bit
66     {-4, true},
67     // -(7 * 4 * vscale), 32 bit
68     {-28, true},
69     // -(1 * 2 * vscale), 64 bit
70     {-2, true},
71     // -(13 * 2 * vscale), 64 bit
72     {-26, true},
73     // -(17 * 8 * vscale), 16 bit, out of range.
74     {-136, false},
75     // -(19 * 2 * vscale), 64 bit, out of range.
76     {-38, false},
77     // -(21 * 4 * vscale), 32 bit, out of range.
78     {-84, false},
79 
80     // Invalid; not divisible by the above powers of 2.
81     {5, false},
82 };
83 } // namespace
84 
TEST(Immediates,Immediates)85 TEST(Immediates, Immediates) {
86   LLVMInitializeAArch64TargetInfo();
87   LLVMInitializeAArch64Target();
88   LLVMInitializeAArch64TargetMC();
89 
90   std::string Error;
91   auto TT = Triple::normalize("aarch64");
92   const Target *T = TargetRegistry::lookupTarget(TT, Error);
93 
94   std::unique_ptr<TargetMachine> TM(T->createTargetMachine(
95       TT, "generic", "+sve2", TargetOptions(), std::nullopt, std::nullopt,
96       CodeGenOptLevel::Default));
97   AArch64Subtarget ST(TM->getTargetTriple(), TM->getTargetCPU(),
98                       TM->getTargetCPU(), TM->getTargetFeatureString(), *TM,
99                       true);
100 
101   auto *TLI = ST.getTargetLowering();
102 
103   for (const auto &Test : Tests) {
104     ASSERT_EQ(TLI->isLegalAddScalableImmediate(Test.Imm), Test.Result);
105   }
106 }
107