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