Explorar o código

Reduce the compile time of the typed_insts_test by a further 40% or so. (#3390)

Move the non-dependent portions of templates out into separate functions
so that we don't need to repeatedly generate code for them.
Richard Smith %!s(int64=2) %!d(string=hai) anos
pai
achega
abedf08816
Modificáronse 1 ficheiros con 47 adicións e 44 borrados
  1. 47 44
      toolchain/sem_ir/typed_insts_test.cpp

+ 47 - 44
toolchain/sem_ir/typed_insts_test.cpp

@@ -31,14 +31,17 @@ namespace {
   static_assert(Name::Kind == InstKind::Name);
 #include "toolchain/sem_ir/inst_kind.def"
 
-template <typename TypedInst>
-auto CommonFieldOrder() -> void {
-  Inst inst = InstTestHelper::MakeInst(TypedInst::Kind, Parse::Node(1),
-                                       TypeId(2), 3, 4);
-  EXPECT_EQ(inst.kind(), TypedInst::Kind);
+auto MakeInstWithNumberedFields(InstKind kind) -> Inst {
+  Inst inst = InstTestHelper::MakeInst(kind, Parse::Node(1), TypeId(2), 3, 4);
+  EXPECT_EQ(inst.kind(), kind);
   EXPECT_EQ(inst.parse_node(), Parse::Node(1));
   EXPECT_EQ(inst.type_id(), TypeId(2));
+  return inst;
+}
 
+template <typename TypedInst>
+auto CommonFieldOrder() -> void {
+  Inst inst = MakeInstWithNumberedFields(TypedInst::Kind);
   TypedInst typed = inst.As<TypedInst>();
   if constexpr (HasParseNode<TypedInst>) {
     EXPECT_EQ(typed.parse_node, Parse::Node(1));
@@ -57,24 +60,24 @@ TEST(TypedInstTest, CommonFieldOrder) {
 #include "toolchain/sem_ir/inst_kind.def"
 }
 
-template <typename TypedInst>
-auto RoundTrip() -> void {
-  Inst inst1 = InstTestHelper::MakeInst(TypedInst::Kind, Parse::Node(1),
-                                        TypeId(2), 3, 4);
-  EXPECT_EQ(inst1.kind(), TypedInst::Kind);
-  EXPECT_EQ(inst1.parse_node(), Parse::Node(1));
-  EXPECT_EQ(inst1.type_id(), TypeId(2));
-
-  TypedInst typed1 = inst1.As<TypedInst>();
-  Inst inst2 = typed1;
-
+auto ExpectEqInsts(const Inst& inst1, const Inst& inst2,
+                   bool compare_parse_node, bool compare_type_id) -> void {
   EXPECT_EQ(inst1.kind(), inst2.kind());
-  if constexpr (HasParseNode<TypedInst>) {
+  if (compare_parse_node) {
     EXPECT_EQ(inst1.parse_node(), inst2.parse_node());
   }
-  if constexpr (HasTypeId<TypedInst>) {
+  if (compare_type_id) {
     EXPECT_EQ(inst1.type_id(), inst2.type_id());
   }
+}
+
+template <typename TypedInst>
+auto RoundTrip() -> void {
+  Inst inst1 = MakeInstWithNumberedFields(TypedInst::Kind);
+  TypedInst typed1 = inst1.As<TypedInst>();
+  Inst inst2 = typed1;
+
+  ExpectEqInsts(inst1, inst2, HasParseNode<TypedInst>, HasTypeId<TypedInst>);
 
   // If the typed instruction has no padding, we should get exactly the same
   // thing if we convert back from an instruction.
@@ -87,9 +90,7 @@ auto RoundTrip() -> void {
   // because the fields not carried by the typed instruction are lost. But they
   // should be stable if we round-trip again.
   Inst inst3 = typed2;
-  if constexpr (std::has_unique_object_representations_v<Inst>) {
-    EXPECT_EQ(std::memcmp(&inst2, &inst3, sizeof(Inst)), 0);
-  }
+  ExpectEqInsts(inst2, inst3, true, true);
 }
 
 TEST(TypedInstTest, RoundTrip) {
@@ -101,31 +102,35 @@ TEST(TypedInstTest, RoundTrip) {
 #include "toolchain/sem_ir/inst_kind.def"
 }
 
-template <typename TypedInst>
-auto StructLayout() -> void {
-  TypedInst typed =
-      InstTestHelper::MakeInst(TypedInst::Kind, Parse::Node(1), TypeId(2), 3, 4)
-          .template As<TypedInst>();
-
+auto StructLayoutHelper(void* typed_inst, std::size_t typed_inst_size,
+                        bool has_parse_node, bool has_type_id) -> void {
   // Check that the memory representation of the typed instruction is what we
   // expect.
   // TODO: Struct layout is not guaranteed, and this test could fail in some
   // build environment. If so, we should disable it.
   int32_t fields[4] = {};
   int field = 0;
-  if constexpr (HasParseNode<TypedInst>) {
+  if (has_parse_node) {
     fields[field++] = 1;
   }
-  if constexpr (HasTypeId<TypedInst>) {
+  if (has_type_id) {
     fields[field++] = 2;
   }
   fields[field++] = 3;
   fields[field++] = 4;
 
-  ASSERT_LE(sizeof(TypedInst), sizeof(fields));
+  ASSERT_LE(typed_inst_size, sizeof(int32_t) * field);
+  EXPECT_EQ(std::memcmp(&fields, typed_inst, typed_inst_size), 0);
+}
+
+template <typename TypedInst>
+auto StructLayout() -> void {
   // We can only do this check if the typed instruction has no padding.
   if constexpr (std::has_unique_object_representations_v<TypedInst>) {
-    EXPECT_EQ(std::memcmp(&fields, &typed, sizeof(TypedInst)), 0);
+    TypedInst typed =
+        MakeInstWithNumberedFields(TypedInst::Kind).template As<TypedInst>();
+    StructLayoutHelper(&typed, sizeof(typed), HasParseNode<TypedInst>,
+                       HasTypeId<TypedInst>);
   }
 }
 
@@ -138,22 +143,20 @@ TEST(TypedInstTest, StructLayout) {
 #include "toolchain/sem_ir/inst_kind.def"
 }
 
-template <typename TypedInst>
-auto InstKindMatches() {
-  // TypedInst::Kind is an InstKind::Definition that extends InstKind, but
-  // has different definitions of the `ir_name()` and `terminator_kind()`
-  // methods. Here we test that values returned by the two different versions
-  // of those functions match.
-  InstKind as_kind = TypedInst::Kind;
-  EXPECT_EQ(TypedInst::Kind.ir_name(), as_kind.ir_name());
-  EXPECT_EQ(TypedInst::Kind.terminator_kind(), as_kind.terminator_kind());
+auto InstKindMatches(const InstKind::Definition& def, InstKind kind) {
+  EXPECT_EQ(def.ir_name(), kind.ir_name());
+  EXPECT_EQ(def.terminator_kind(), kind.terminator_kind());
 }
 
 TEST(TypedInstTest, InstKindMatches) {
-#define CARBON_SEM_IR_INST_KIND(Name) \
-  {                                   \
-    SCOPED_TRACE(#Name);              \
-    InstKindMatches<Name>();          \
+  // TypedInst::Kind is an InstKind::Definition that extends InstKind, but has
+  // different definitions of the `ir_name()` and `terminator_kind()` methods.
+  // Here we test that values returned by the two different versions of those
+  // functions match.
+#define CARBON_SEM_IR_INST_KIND(Name)        \
+  {                                          \
+    SCOPED_TRACE(#Name);                     \
+    InstKindMatches(Name::Kind, Name::Kind); \
   }
 #include "toolchain/sem_ir/inst_kind.def"
 }