| //===- llvm/unittest/CodeGen/GlobalISel/LegalizerInfoTest.cpp -------------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" | 
 | #include "llvm/CodeGen/TargetOpcodes.h" | 
 | #include "gtest/gtest.h" | 
 |  | 
 | using namespace llvm; | 
 | using namespace LegalizeActions; | 
 |  | 
 | // Define a couple of pretty printers to help debugging when things go wrong. | 
 | namespace llvm { | 
 | std::ostream & | 
 | operator<<(std::ostream &OS, const LegalizeAction Act) { | 
 |   switch (Act) { | 
 |   case Lower: OS << "Lower"; break; | 
 |   case Legal: OS << "Legal"; break; | 
 |   case NarrowScalar: OS << "NarrowScalar"; break; | 
 |   case WidenScalar:  OS << "WidenScalar"; break; | 
 |   case FewerElements:  OS << "FewerElements"; break; | 
 |   case MoreElements:  OS << "MoreElements"; break; | 
 |   case Libcall: OS << "Libcall"; break; | 
 |   case Custom: OS << "Custom"; break; | 
 |   case Unsupported: OS << "Unsupported"; break; | 
 |   case NotFound: OS << "NotFound"; break; | 
 |   case UseLegacyRules: OS << "UseLegacyRules"; break; | 
 |   } | 
 |   return OS; | 
 | } | 
 |  | 
 | std::ostream & | 
 | operator<<(std::ostream &OS, const llvm::LLT Ty) { | 
 |   std::string Repr; | 
 |   raw_string_ostream SS{Repr}; | 
 |   Ty.print(SS); | 
 |   OS << SS.str(); | 
 |   return OS; | 
 | } | 
 | } | 
 |  | 
 | namespace { | 
 |  | 
 |  | 
 | TEST(LegalizerInfoTest, ScalarRISC) { | 
 |   using namespace TargetOpcode; | 
 |   LegalizerInfo L; | 
 |   // Typical RISCy set of operations based on AArch64. | 
 |   for (unsigned Op : {G_ADD, G_SUB}) { | 
 |     for (unsigned Size : {32, 64}) | 
 |       L.setAction({Op, 0, LLT::scalar(Size)}, Legal); | 
 |     L.setLegalizeScalarToDifferentSizeStrategy( | 
 |         Op, 0, LegalizerInfo::widenToLargerTypesAndNarrowToLargest); | 
 |   } | 
 |  | 
 |   L.computeTables(); | 
 |  | 
 |   for (unsigned opcode : {G_ADD, G_SUB}) { | 
 |     // Check we infer the correct types and actually do what we're told. | 
 |     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(8)}}), | 
 |               LegalizeActionStep(WidenScalar, 0, LLT::scalar(32))); | 
 |     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(16)}}), | 
 |               LegalizeActionStep(WidenScalar, 0, LLT::scalar(32))); | 
 |     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(32)}}), | 
 |               LegalizeActionStep(Legal, 0, LLT{})); | 
 |     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(64)}}), | 
 |               LegalizeActionStep(Legal, 0, LLT{})); | 
 |  | 
 |     // Make sure the default for over-sized types applies. | 
 |     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(128)}}), | 
 |               LegalizeActionStep(NarrowScalar, 0, LLT::scalar(64))); | 
 |     // Make sure we also handle unusual sizes | 
 |     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(1)}}), | 
 |               LegalizeActionStep(WidenScalar, 0, LLT::scalar(32))); | 
 |     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(31)}}), | 
 |               LegalizeActionStep(WidenScalar, 0, LLT::scalar(32))); | 
 |     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(33)}}), | 
 |               LegalizeActionStep(WidenScalar, 0, LLT::scalar(64))); | 
 |     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(63)}}), | 
 |               LegalizeActionStep(WidenScalar, 0, LLT::scalar(64))); | 
 |     ASSERT_EQ(L.getAction({opcode, {LLT::scalar(65)}}), | 
 |               LegalizeActionStep(NarrowScalar, 0, LLT::scalar(64))); | 
 |   } | 
 | } | 
 |  | 
 | TEST(LegalizerInfoTest, VectorRISC) { | 
 |   using namespace TargetOpcode; | 
 |   LegalizerInfo L; | 
 |   // Typical RISCy set of operations based on ARM. | 
 |   L.setAction({G_ADD, LLT::vector(8, 8)}, Legal); | 
 |   L.setAction({G_ADD, LLT::vector(16, 8)}, Legal); | 
 |   L.setAction({G_ADD, LLT::vector(4, 16)}, Legal); | 
 |   L.setAction({G_ADD, LLT::vector(8, 16)}, Legal); | 
 |   L.setAction({G_ADD, LLT::vector(2, 32)}, Legal); | 
 |   L.setAction({G_ADD, LLT::vector(4, 32)}, Legal); | 
 |  | 
 |   L.setLegalizeVectorElementToDifferentSizeStrategy( | 
 |       G_ADD, 0, LegalizerInfo::widenToLargerTypesUnsupportedOtherwise); | 
 |  | 
 |   L.setAction({G_ADD, 0, LLT::scalar(32)}, Legal); | 
 |  | 
 |   L.computeTables(); | 
 |  | 
 |   // Check we infer the correct types and actually do what we're told for some | 
 |   // simple cases. | 
 |   ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(8, 8)}}), | 
 |             LegalizeActionStep(Legal, 0, LLT{})); | 
 |   ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(8, 7)}}), | 
 |             LegalizeActionStep(WidenScalar, 0, LLT::vector(8, 8))); | 
 |   ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(2, 8)}}), | 
 |             LegalizeActionStep(MoreElements, 0, LLT::vector(8, 8))); | 
 |   ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(8, 32)}}), | 
 |             LegalizeActionStep(FewerElements, 0, LLT::vector(4, 32))); | 
 |   // Check a few non-power-of-2 sizes: | 
 |   ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(3, 3)}}), | 
 |             LegalizeActionStep(WidenScalar, 0, LLT::vector(3, 8))); | 
 |   ASSERT_EQ(L.getAction({G_ADD, {LLT::vector(3, 8)}}), | 
 |             LegalizeActionStep(MoreElements, 0, LLT::vector(8, 8))); | 
 | } | 
 |  | 
 | TEST(LegalizerInfoTest, MultipleTypes) { | 
 |   using namespace TargetOpcode; | 
 |   LegalizerInfo L; | 
 |   LLT p0 = LLT::pointer(0, 64); | 
 |   LLT s64 = LLT::scalar(64); | 
 |  | 
 |   // Typical RISCy set of operations based on AArch64. | 
 |   L.setAction({G_PTRTOINT, 0, s64}, Legal); | 
 |   L.setAction({G_PTRTOINT, 1, p0}, Legal); | 
 |  | 
 |   L.setLegalizeScalarToDifferentSizeStrategy( | 
 |       G_PTRTOINT, 0, LegalizerInfo::widenToLargerTypesAndNarrowToLargest); | 
 |  | 
 |   L.computeTables(); | 
 |  | 
 |   // Check we infer the correct types and actually do what we're told. | 
 |   ASSERT_EQ(L.getAction({G_PTRTOINT, {s64, p0}}), | 
 |             LegalizeActionStep(Legal, 0, LLT{})); | 
 |  | 
 |   // Make sure we also handle unusual sizes | 
 |   ASSERT_EQ( | 
 |       L.getAction({G_PTRTOINT, {LLT::scalar(65), s64}}), | 
 |       LegalizeActionStep(NarrowScalar, 0, s64)); | 
 |   ASSERT_EQ( | 
 |       L.getAction({G_PTRTOINT, {s64, LLT::pointer(0, 32)}}), | 
 |       LegalizeActionStep(Unsupported, 1, LLT::pointer(0, 32))); | 
 | } | 
 |  | 
 | TEST(LegalizerInfoTest, MultipleSteps) { | 
 |   using namespace TargetOpcode; | 
 |   LegalizerInfo L; | 
 |   LLT s32 = LLT::scalar(32); | 
 |   LLT s64 = LLT::scalar(64); | 
 |  | 
 |   L.setLegalizeScalarToDifferentSizeStrategy( | 
 |       G_UREM, 0, LegalizerInfo::widenToLargerTypesUnsupportedOtherwise); | 
 |   L.setAction({G_UREM, 0, s32}, Lower); | 
 |   L.setAction({G_UREM, 0, s64}, Lower); | 
 |  | 
 |   L.computeTables(); | 
 |  | 
 |   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(16)}}), | 
 |             LegalizeActionStep(WidenScalar, 0, LLT::scalar(32))); | 
 |   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(32)}}), | 
 |             LegalizeActionStep(Lower, 0, LLT::scalar(32))); | 
 | } | 
 |  | 
 | TEST(LegalizerInfoTest, SizeChangeStrategy) { | 
 |   using namespace TargetOpcode; | 
 |   LegalizerInfo L; | 
 |   for (unsigned Size : {1, 8, 16, 32}) | 
 |     L.setAction({G_UREM, 0, LLT::scalar(Size)}, Legal); | 
 |  | 
 |   L.setLegalizeScalarToDifferentSizeStrategy( | 
 |       G_UREM, 0, LegalizerInfo::widenToLargerTypesUnsupportedOtherwise); | 
 |   L.computeTables(); | 
 |  | 
 |   // Check we infer the correct types and actually do what we're told. | 
 |   for (unsigned Size : {1, 8, 16, 32}) { | 
 |     ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(Size)}}), | 
 |               LegalizeActionStep(Legal, 0, LLT{})); | 
 |   } | 
 |   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(2)}}), | 
 |             LegalizeActionStep(WidenScalar, 0, LLT::scalar(8))); | 
 |   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(7)}}), | 
 |             LegalizeActionStep(WidenScalar, 0, LLT::scalar(8))); | 
 |   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(9)}}), | 
 |             LegalizeActionStep(WidenScalar, 0, LLT::scalar(16))); | 
 |   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(17)}}), | 
 |             LegalizeActionStep(WidenScalar, 0, LLT::scalar(32))); | 
 |   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(31)}}), | 
 |             LegalizeActionStep(WidenScalar, 0, LLT::scalar(32))); | 
 |   ASSERT_EQ(L.getAction({G_UREM, {LLT::scalar(33)}}), | 
 |             LegalizeActionStep(Unsupported, 0, LLT::scalar(33))); | 
 | } | 
 | } |