1 //===- llvm/unittest/CodeGen/GlobalISel/LegalizerInfoTest.cpp -------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
11 #include "llvm/Target/TargetOpcodes.h"
12 #include "gtest/gtest.h"
13 
14 using namespace llvm;
15 
16 // Define a couple of pretty printers to help debugging when things go wrong.
17 namespace llvm {
18 std::ostream &
19 operator<<(std::ostream &OS, const llvm::LegalizerInfo::LegalizeAction Act) {
20   switch (Act) {
21   case LegalizerInfo::Lower: OS << "Lower"; break;
22   case LegalizerInfo::Legal: OS << "Legal"; break;
23   case LegalizerInfo::NarrowScalar: OS << "NarrowScalar"; break;
24   case LegalizerInfo::WidenScalar:  OS << "WidenScalar"; break;
25   case LegalizerInfo::FewerElements:  OS << "FewerElements"; break;
26   case LegalizerInfo::MoreElements:  OS << "MoreElements"; break;
27   case LegalizerInfo::Libcall: OS << "Libcall"; break;
28   case LegalizerInfo::Custom: OS << "Custom"; break;
29   case LegalizerInfo::Unsupported: OS << "Unsupported"; break;
30   case LegalizerInfo::NotFound: OS << "NotFound";
31   }
32   return OS;
33 }
34 
35 std::ostream &
36 operator<<(std::ostream &OS, const llvm::LLT Ty) {
37   std::string Repr;
38   raw_string_ostream SS{Repr};
39   Ty.print(SS);
40   OS << SS.str();
41   return OS;
42 }
43 }
44 
45 namespace {
46 
47 
48 TEST(LegalizerInfoTest, ScalarRISC) {
49   using namespace TargetOpcode;
50   LegalizerInfo L;
51   // Typical RISCy set of operations based on AArch64.
52   L.setAction({G_ADD, LLT::scalar(8)}, LegalizerInfo::WidenScalar);
53   L.setAction({G_ADD, LLT::scalar(16)}, LegalizerInfo::WidenScalar);
54   L.setAction({G_ADD, LLT::scalar(32)}, LegalizerInfo::Legal);
55   L.setAction({G_ADD, LLT::scalar(64)}, LegalizerInfo::Legal);
56   L.computeTables();
57 
58   // Check we infer the correct types and actually do what we're told.
59   ASSERT_EQ(L.getAction({G_ADD, LLT::scalar(8)}),
60             std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32)));
61   ASSERT_EQ(L.getAction({G_ADD, LLT::scalar(16)}),
62             std::make_pair(LegalizerInfo::WidenScalar, LLT::scalar(32)));
63   ASSERT_EQ(L.getAction({G_ADD, LLT::scalar(32)}),
64             std::make_pair(LegalizerInfo::Legal, LLT::scalar(32)));
65   ASSERT_EQ(L.getAction({G_ADD, LLT::scalar(64)}),
66             std::make_pair(LegalizerInfo::Legal, LLT::scalar(64)));
67 
68   // Make sure the default for over-sized types applies.
69   ASSERT_EQ(L.getAction({G_ADD, LLT::scalar(128)}),
70             std::make_pair(LegalizerInfo::NarrowScalar, LLT::scalar(64)));
71 }
72 
73 TEST(LegalizerInfoTest, VectorRISC) {
74   using namespace TargetOpcode;
75   LegalizerInfo L;
76   // Typical RISCy set of operations based on ARM.
77   L.setScalarInVectorAction(G_ADD, LLT::scalar(8), LegalizerInfo::Legal);
78   L.setScalarInVectorAction(G_ADD, LLT::scalar(16), LegalizerInfo::Legal);
79   L.setScalarInVectorAction(G_ADD, LLT::scalar(32), LegalizerInfo::Legal);
80 
81   L.setAction({G_ADD, LLT::vector(8, 8)}, LegalizerInfo::Legal);
82   L.setAction({G_ADD, LLT::vector(16, 8)}, LegalizerInfo::Legal);
83   L.setAction({G_ADD, LLT::vector(4, 16)}, LegalizerInfo::Legal);
84   L.setAction({G_ADD, LLT::vector(8, 16)}, LegalizerInfo::Legal);
85   L.setAction({G_ADD, LLT::vector(2, 32)}, LegalizerInfo::Legal);
86   L.setAction({G_ADD, LLT::vector(4, 32)}, LegalizerInfo::Legal);
87   L.computeTables();
88 
89   // Check we infer the correct types and actually do what we're told for some
90   // simple cases.
91   ASSERT_EQ(L.getAction({G_ADD, LLT::vector(2, 8)}),
92             std::make_pair(LegalizerInfo::MoreElements, LLT::vector(8, 8)));
93   ASSERT_EQ(L.getAction({G_ADD, LLT::vector(8, 8)}),
94             std::make_pair(LegalizerInfo::Legal, LLT::vector(8, 8)));
95   ASSERT_EQ(
96       L.getAction({G_ADD, LLT::vector(8, 32)}),
97       std::make_pair(LegalizerInfo::FewerElements, LLT::vector(4, 32)));
98 }
99 
100 TEST(LegalizerInfoTest, MultipleTypes) {
101   using namespace TargetOpcode;
102   LegalizerInfo L;
103   LLT p0 = LLT::pointer(0, 64);
104   LLT s32 = LLT::scalar(32);
105   LLT s64 = LLT::scalar(64);
106 
107   // Typical RISCy set of operations based on AArch64.
108   L.setAction({G_PTRTOINT, 0, s64}, LegalizerInfo::Legal);
109   L.setAction({G_PTRTOINT, 1, p0}, LegalizerInfo::Legal);
110 
111   L.setAction({G_PTRTOINT, 0, s32}, LegalizerInfo::WidenScalar);
112   L.computeTables();
113 
114   // Check we infer the correct types and actually do what we're told.
115   ASSERT_EQ(L.getAction({G_PTRTOINT, 0, s64}),
116             std::make_pair(LegalizerInfo::Legal, s64));
117   ASSERT_EQ(L.getAction({G_PTRTOINT, 1, p0}),
118             std::make_pair(LegalizerInfo::Legal, p0));
119 }
120 }
121