瀏覽代碼

Don't re-evaluate imported constants. (#5217)

Trust that import_ref produces constants that are already in their
evaluated form. We still do one pass over the operands to map them into
their canonical constant values. Even that is mostly unnecessary, but
there are a few instructions produced by importing that still need it
for now.
Richard Smith 1 年之前
父節點
當前提交
8b9f1a8966
共有 3 個文件被更改,包括 23 次插入1 次删除
  1. 15 0
      toolchain/check/eval.cpp
  2. 7 0
      toolchain/check/eval.h
  3. 1 1
      toolchain/check/import_ref.cpp

+ 15 - 0
toolchain/check/eval.cpp

@@ -363,6 +363,9 @@ static auto GetConstantValue(EvalContext& eval_context,
 // If the given instruction is constant, returns its constant value.
 static auto GetConstantValue(EvalContext& eval_context, SemIR::InstId inst_id,
                              Phase* phase) -> SemIR::InstId {
+  if (!inst_id.has_value()) {
+    return SemIR::InstId::None;
+  }
   auto const_id = eval_context.GetConstantValue(inst_id);
   *phase =
       LatestPhase(*phase, GetPhase(eval_context.constant_values(), const_id));
@@ -735,6 +738,18 @@ static auto ReplaceAllFieldsWithConstantValues(EvalContext& eval_context,
   return true;
 }
 
+auto AddImportedConstant(Context& context, SemIR::Inst inst)
+    -> SemIR::ConstantId {
+  EvalContext eval_context(&context, SemIR::InstId::None);
+  Phase phase = Phase::Concrete;
+  // TODO: Can we avoid doing this replacement? It may do things that are
+  // undesirable during importing, such as resolving specifics.
+  if (!ReplaceAllFieldsWithConstantValues(eval_context, &inst, &phase)) {
+    return SemIR::ConstantId::NotConstant;
+  }
+  return MakeConstantResult(context, inst, phase);
+}
+
 // Performs an index into a homogeneous aggregate, retrieving the specified
 // element.
 static auto PerformArrayIndex(EvalContext& eval_context, SemIR::ArrayIndex inst)

+ 7 - 0
toolchain/check/eval.h

@@ -11,6 +11,13 @@
 
 namespace Carbon::Check {
 
+// Adds a `ConstantId` for a constant that has been imported from another IR.
+// Does not evaluate the instruction, instead trusting that it is already in a
+// suitable form, but does canonicalize the operands if necessary.
+// TODO: Rely on import to canonicalize the operands to avoid this work.
+auto AddImportedConstant(Context& context, SemIR::Inst inst)
+    -> SemIR::ConstantId;
+
 // Determines the phase of the instruction `inst`, and returns its constant
 // value if it has constant phase. If it has runtime phase, returns
 // `SemIR::ConstantId::NotConstant`.

+ 1 - 1
toolchain/check/import_ref.cpp

@@ -1332,7 +1332,7 @@ static auto RetryOrDone(ImportRefResolver& resolver, SemIR::ConstantId const_id)
 // that there is no new work.
 static auto ResolveAsUntyped(ImportContext& context, SemIR::Inst inst)
     -> ResolveResult {
-  auto result = TryEvalInst(context.local_context(), SemIR::InstId::None, inst);
+  auto result = AddImportedConstant(context.local_context(), inst);
   CARBON_CHECK(result.is_constant(), "{0} is not constant", inst);
   return ResolveResult::Done(result);
 }