AutomataTest.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. //===- unittest/TableGen/AutomataTest.cpp - DFA tests ---------------------===//
  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. #include "llvm/ADT/ArrayRef.h"
  9. #include "llvm/ADT/STLExtras.h"
  10. #include "llvm/Support/Debug.h"
  11. #include "llvm/Support/Automaton.h"
  12. #include "gmock/gmock.h"
  13. #include "gtest/gtest.h"
  14. using namespace llvm;
  15. using testing::ContainerEq;
  16. using testing::UnorderedElementsAre;
  17. // Bring in the enums created by SearchableTables.td.
  18. #define GET_SymKind_DECL
  19. #define GET_BinRequirementKindEnum_DECL
  20. #include "AutomataTables.inc"
  21. // And bring in the automata from Automata.td.
  22. #define GET_SimpleAutomaton_DECL
  23. #define GET_TupleAutomaton_DECL
  24. #define GET_NfaAutomaton_DECL
  25. #define GET_BinPackerAutomaton_DECL
  26. #include "AutomataAutomata.inc"
  27. TEST(Automata, SimpleAutomatonAcceptsFromInitialState) {
  28. Automaton<SymKind> A(makeArrayRef(SimpleAutomatonTransitions));
  29. EXPECT_TRUE(A.add(SK_a));
  30. A.reset();
  31. EXPECT_TRUE(A.add(SK_b));
  32. A.reset();
  33. EXPECT_TRUE(A.add(SK_c));
  34. A.reset();
  35. EXPECT_FALSE(A.add(SK_d));
  36. }
  37. TEST(Automata, SimpleAutomatonAcceptsSequences) {
  38. Automaton<SymKind> A(makeArrayRef(SimpleAutomatonTransitions));
  39. // Test sequence <a b>
  40. A.reset();
  41. EXPECT_TRUE(A.add(SK_a));
  42. EXPECT_TRUE(A.add(SK_b));
  43. // Test sequence <a c> is rejected (c cannot get bit 0b10);
  44. A.reset();
  45. EXPECT_TRUE(A.add(SK_a));
  46. EXPECT_FALSE(A.add(SK_c));
  47. // Symmetric test: sequence <c a> is rejected.
  48. A.reset();
  49. EXPECT_TRUE(A.add(SK_c));
  50. EXPECT_FALSE(A.add(SK_a));
  51. }
  52. TEST(Automata, TupleAutomatonAccepts) {
  53. Automaton<TupleAutomatonAction> A(makeArrayRef(TupleAutomatonTransitions));
  54. A.reset();
  55. EXPECT_TRUE(
  56. A.add(TupleAutomatonAction{SK_a, SK_b, "yeet"}));
  57. A.reset();
  58. EXPECT_FALSE(
  59. A.add(TupleAutomatonAction{SK_a, SK_a, "yeet"}));
  60. A.reset();
  61. EXPECT_FALSE(
  62. A.add(TupleAutomatonAction{SK_a, SK_b, "feet"}));
  63. A.reset();
  64. EXPECT_TRUE(
  65. A.add(TupleAutomatonAction{SK_b, SK_b, "foo"}));
  66. }
  67. TEST(Automata, NfaAutomatonAccepts) {
  68. Automaton<SymKind> A(makeArrayRef(NfaAutomatonTransitions));
  69. // Test sequences <a a>, <a b>, <b a>, <b b>. All should be accepted.
  70. A.reset();
  71. EXPECT_TRUE(A.add(SK_a));
  72. EXPECT_TRUE(A.add(SK_a));
  73. A.reset();
  74. EXPECT_TRUE(A.add(SK_a));
  75. EXPECT_TRUE(A.add(SK_b));
  76. A.reset();
  77. EXPECT_TRUE(A.add(SK_b));
  78. EXPECT_TRUE(A.add(SK_a));
  79. A.reset();
  80. EXPECT_TRUE(A.add(SK_b));
  81. EXPECT_TRUE(A.add(SK_b));
  82. // Expect that <b b b> is not accepted.
  83. A.reset();
  84. EXPECT_TRUE(A.add(SK_b));
  85. EXPECT_TRUE(A.add(SK_b));
  86. EXPECT_FALSE(A.add(SK_b));
  87. }
  88. TEST(Automata, BinPackerAutomatonAccepts) {
  89. Automaton<BinPackerAutomatonAction> A(makeArrayRef(BinPackerAutomatonTransitions));
  90. // Expect that we can pack two double-bins in 0-4, then no more in 0-4.
  91. A.reset();
  92. EXPECT_TRUE(A.add(BRK_0_to_4_dbl));
  93. EXPECT_TRUE(A.add(BRK_0_to_4_dbl));
  94. EXPECT_FALSE(A.add(BRK_0_to_4));
  95. // Expect that we can pack two double-bins in 0-4, two more in 0-6 then no
  96. // more.
  97. A.reset();
  98. EXPECT_TRUE(A.add(BRK_0_to_4_dbl));
  99. EXPECT_TRUE(A.add(BRK_0_to_4_dbl));
  100. EXPECT_TRUE(A.add(BRK_0_to_6));
  101. EXPECT_TRUE(A.add(BRK_0_to_6));
  102. EXPECT_FALSE(A.add(BRK_0_to_6));
  103. // Expect that we can pack BRK_0_to_6 five times to occupy five bins, then
  104. // cannot allocate any double-bins.
  105. A.reset();
  106. for (unsigned I = 0; I < 5; ++I)
  107. EXPECT_TRUE(A.add(BRK_0_to_6));
  108. EXPECT_FALSE(A.add(BRK_0_to_6_dbl));
  109. }
  110. // The state we defined in TableGen uses the least significant 6 bits to represent a bin state.
  111. #define BINS(a, b, c, d, e, f) \
  112. ((a << 5) | (b << 4) | (c << 3) | (d << 2) | (e << 1) | (f << 0))
  113. TEST(Automata, BinPackerAutomatonExplains) {
  114. Automaton<BinPackerAutomatonAction> A(makeArrayRef(BinPackerAutomatonTransitions),
  115. makeArrayRef(BinPackerAutomatonTransitionInfo));
  116. // Pack two double-bins in 0-4, then a single bin in 0-6.
  117. EXPECT_TRUE(A.add(BRK_0_to_4_dbl));
  118. EXPECT_TRUE(A.add(BRK_0_to_4_dbl));
  119. EXPECT_TRUE(A.add(BRK_0_to_6));
  120. EXPECT_THAT(
  121. A.getNfaPaths(),
  122. UnorderedElementsAre(
  123. // Allocate {0,1} first, then 6.
  124. ContainerEq(NfaPath{BINS(0, 0, 0, 0, 1, 1), BINS(0, 0, 1, 1, 1, 1),
  125. BINS(1, 0, 1, 1, 1, 1)}),
  126. // Allocate {0,1} first, then 5.
  127. ContainerEq(NfaPath{BINS(0, 0, 0, 0, 1, 1), BINS(0, 0, 1, 1, 1, 1),
  128. BINS(0, 1, 1, 1, 1, 1)}),
  129. // Allocate {2,3} first, then 6.
  130. ContainerEq(NfaPath{BINS(0, 0, 1, 1, 0, 0), BINS(0, 0, 1, 1, 1, 1),
  131. BINS(1, 0, 1, 1, 1, 1)}),
  132. // Allocate {2,3} first, then 5.
  133. ContainerEq(NfaPath{BINS(0, 0, 1, 1, 0, 0), BINS(0, 0, 1, 1, 1, 1),
  134. BINS(0, 1, 1, 1, 1, 1)})));
  135. }