Skip to content

Conversation

@ai-mannamalai
Copy link
Contributor

  • Delcare Arith dialect as as illegal in conversion target


RewritePatternSet patterns(context);
ConversionTarget target(*context);
target.addIllegalDialect<arith::ArithDialect>();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we be expecting arithmetic operations in the output of this pass though? this pass intends to arithmetize / pack, so that we aren't working on the cleartext data types but are working on ciphertext types with rotations and SIMD operations (including arithmetic adds and muls)

Maybe we should just make all ops in the arith dialect BUT the ones supported by ciphertext semantics illegal? (e.g. index_cast would be illegal, but constants / muls / adds would be legal)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we want to do that the following mechanism in MLIR is useful:

  /// Register the operations of the given dialects as dynamically legal, i.e.
  /// requiring custom handling by the callback.
  template <typename... Names>
  void addDynamicallyLegalDialect(const DynamicLegalityCallbackFn &callback,
                                  StringRef name, Names... names) {
    SmallVector<StringRef, 2> dialectNames({name, names...});
    setDialectAction(dialectNames, LegalizationAction::Dynamic);
    setLegalityCallback(dialectNames, callback);
  }
  template <typename... Args>
  void addDynamicallyLegalDialect(DynamicLegalityCallbackFn callback) {
    addDynamicallyLegalDialect(std::move(callback),
                               Args::getDialectNamespace()...);
  }

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes! at least to me that's the right approach

Copy link
Collaborator

@j2kun j2kun Aug 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is a solution to #1992, with or without dynamic legality. The problem is that the type converter didn't support a type that showed up in the input, and that caused a crash because the context-aware dialect conversion stuff is just not super robust in that way. Making arith illegal (or making certain ops dynamically illegal) won't solve the underlying problem, and instead would just make this pass crash on a variety of inputs because arith ops are supported in the output.

I'm inclined to think the "right" solution here is, as a first step of the pass, to walk the IR and verify all types encountered are supported by the type converter. E.g., use walkAndValidateTypes on the root operation and the condition can be "is this type in a list of approved types," which is manually synced with the type converter.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I didn't realize the failure was caused by the IndexType. I see Alex mentioned that in the issue.

E.g., use walkAndValidateTypes on the root operation and the condition can be "is this type in a list of approved types," which is manually synced with the type converter.

Shouldn't the fix happen in the framework to prevent users from accidentally not adding the walker?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if the framework can tell what types are supported in the caller's type converter...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But even if it's not supported, shouldn't it fail with something slightly more elegant than segfault?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just saying I don't think we can solve this generally in the framework, because what is supported is dependent on the user of the framework. Instead we'll have to do a slightly more specific but still easy thing (walk the IR and validate types), and it will avoid the segfault

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@asraa @j2kun - made an update to check for invalid types; how does it look ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! The walker looks fine, but I suggested another fix where instead we use the info from the registered type conversion instead of using a list of invalid types (that might go stale)

@ai-mannamalai ai-mannamalai force-pushed the main-illegal branch 2 times, most recently from db64992 to 011f5aa Compare August 12, 2025 23:12
Copy link
Collaborator

@asraa asraa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@j2kun why can't something like this work, where we call on the type converter to see if a valid conversion for the value is registered?

    // check for invalid types and bail out of the pass
    auto isValidValue = [&](const Value value) -> LogicalResult {
      auto contextualAttr = typeConverter.getContextualAttr(value);
      if (failed(contextualAttr)) {
        return failure();
      }
      Type result =
          typeConverter.convertType(value.getType(), contextualAttr.value());
      return result != nullptr ? success() : failure();
    };
    if (!walkAndValidateValues(module, isValidValue).succeeded()) {
      module->emitError() << "invalid type in module";
      return signalPassFailure();
    }

@ai-mannamalai
Copy link
Contributor Author

let me integrate this; @asraa and see

- use value validation since types on values have additional context
@ai-mannamalai
Copy link
Contributor Author

ai-mannamalai commented Aug 16, 2025 via email

@ai-mannamalai
Copy link
Contributor Author

memref present in the IR is trapped by the above code; e.g. run

$ bazelisk run --//:enable_openmp=0 //tools:heir-opt -- --mlir-to-cggi=data-type=Integer --scheme-to-tfhe-rs --convert-to-ciphertext-semantics `pwd`/tests/Examples/tfhe_rust_hl/cpu/add_round_key.mlir

need to see if the checks are overzealous which causes some regression test failure

@ai-mannamalai
Copy link
Contributor Author

I find the ops like arith.mulf, arith.addf are being flagged by the new pass. Is this expected ?

@ai-mannamalai
Copy link
Contributor Author

added a new test; testing against the regression suite should pass now

@ai-mannamalai
Copy link
Contributor Author

errors look like,

/home/heiruser/heir/tests/Examples/tfhe_rust_hl/cpu/add_round_key.mlir:0:0: error: invalid attribute at value:
<block argument> of type 'memref<16x!tfhe_rust.eui8>' at index: 1
/home/heiruser/heir/tests/Examples/tfhe_rust_hl/cpu/add_round_key.mlir:0:0: error: invalid type in module

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is a bit confusing, because it runs the full CGGI pipeline and converts to tfhe_rs before applying the convert-to-ciphertext-semantics pass (which is for non-CGGI schemes).

Could you instead try cloning a test like https://github.com/google/heir/blob/1263704af22e8a0c85a1b513e26f1eeb885fb965/tests/Transforms/convert_to_ciphertext_semantics/tensor_extract.mlir and replacing the tensor types/ops with memref equivalents? Then use --verify-diagnostics as in

// RUN: heir-opt %s --verify-diagnostics 2>&1
to ensure messages from emitError are properly emitted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure; let me take a look

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants