diff --git a/clang/test/CodeGen/unique-internal-linkage-names.cpp b/clang/test/CodeGen/unique-internal-linkage-names.cpp index 3ad3bdc9f1bbb3..b731ed07f4a765 100644 --- a/clang/test/CodeGen/unique-internal-linkage-names.cpp +++ b/clang/test/CodeGen/unique-internal-linkage-names.cpp @@ -53,15 +53,15 @@ int mver_call() { // PLAIN: define weak_odr i32 ()* @_ZL4mverv.resolver() // PLAIN: define internal i32 @_ZL4mverv() // PLAIN: define internal i32 @_ZL4mverv.sse4.2() -// UNIQUE: @_ZL4glob.__uniq.{{[0-9a-f]+}} = internal global -// UNIQUE: @_ZZ8retAnonMvE5fGlob.__uniq.{{[0-9a-f]+}} = internal global -// UNIQUE: @_ZN12_GLOBAL__N_16anon_mE.__uniq.{{[0-9a-f]+}} = internal global -// UNIQUE: define internal i32 @_ZL3foov.__uniq.{{[0-9a-f]+}}() -// UNIQUE: define internal i32 @_ZN12_GLOBAL__N_14getMEv.__uniq.{{[0-9a-f]+}} +// UNIQUE: @_ZL4glob.__uniq.{{[0-9]+}} = internal global +// UNIQUE: @_ZZ8retAnonMvE5fGlob.__uniq.{{[0-9]+}} = internal global +// UNIQUE: @_ZN12_GLOBAL__N_16anon_mE.__uniq.{{[0-9]+}} = internal global +// UNIQUE: define internal i32 @_ZL3foov.__uniq.{{[0-9]+}}() +// UNIQUE: define internal i32 @_ZN12_GLOBAL__N_14getMEv.__uniq.{{[0-9]+}} // UNIQUE: define weak_odr i32 ()* @_ZL4mverv.resolver() -// UNIQUE: define internal i32 @_ZL4mverv.__uniq.{{[0-9a-f]+}}() -// UNIQUE: define internal i32 @_ZL4mverv.sse4.2.__uniq.{{[0-9a-f]+}} -// UNIQUEO1: define internal i32 @_ZL3foov.__uniq.{{[0-9a-f]+}}() +// UNIQUE: define internal i32 @_ZL4mverv.__uniq.{{[0-9]+}}() +// UNIQUE: define internal i32 @_ZL4mverv.sse4.2.__uniq.{{[0-9]+}} +// UNIQUEO1: define internal i32 @_ZL3foov.__uniq.{{[0-9]+}}() // UNIQUEO1: define weak_odr i32 ()* @_ZL4mverv.resolver() -// UNIQUEO1: define internal i32 @_ZL4mverv.__uniq.{{[0-9a-f]+}}() -// UNIQUEO1: define internal i32 @_ZL4mverv.sse4.2.__uniq.{{[0-9a-f]+}} +// UNIQUEO1: define internal i32 @_ZL4mverv.__uniq.{{[0-9]+}}() +// UNIQUEO1: define internal i32 @_ZL4mverv.sse4.2.__uniq.{{[0-9]+}} diff --git a/flang/lib/Semantics/check-directive-structure.h b/flang/lib/Semantics/check-directive-structure.h index 822cdca9b66a96..062f85b63b85a5 100644 --- a/flang/lib/Semantics/check-directive-structure.h +++ b/flang/lib/Semantics/check-directive-structure.h @@ -232,8 +232,6 @@ class DirectiveStructureChecker : public virtual BaseChecker { // Check that only clauses in set are after the specific clauses. void CheckOnlyAllowedAfter(C clause, common::EnumSet set); - void CheckRequired(C clause); - void CheckRequireAtLeastOneOf(); void CheckAllowed(C clause); @@ -326,6 +324,8 @@ DirectiveStructureChecker::ClauseSetToString( template void DirectiveStructureChecker::CheckRequireAtLeastOneOf() { + if (GetContext().requiredClauses.empty()) + return; for (auto cl : GetContext().actualClauses) { if (GetContext().requiredClauses.test(cl)) return; @@ -447,17 +447,6 @@ void DirectiveStructureChecker::SayNotMatching( .Attach(beginSource, "Does not match directive"_en_US); } -// Check that at least one of the required clauses is present on the directive. -template -void DirectiveStructureChecker::CheckRequired(C c) { - if (!FindClause(c)) { - context_.Say(GetContext().directiveSource, - "At least one %s clause must appear on the %s directive"_err_en_US, - parser::ToUpperCaseLetters(getClauseName(c).str()), - ContextDirectiveAsFortran()); - } -} - // Check the value of the clause is a positive parameter. template void DirectiveStructureChecker diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/any.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/any.version.pass.cpp index 7ea99df8df3428..cd393b2b404b95 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/any.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/any.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/array.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/array.version.pass.cpp index 4cc0f8c8c8081c..b0dedfb4a7b0e8 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/array.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/array.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp index 16e4e375381952..b964e0c6921e28 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/atomic.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // UNSUPPORTED: libcpp-has-no-threads diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/barrier.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/barrier.version.pass.cpp index f485b794885874..b193095403e9af 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/barrier.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/barrier.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // UNSUPPORTED: libcpp-has-no-threads diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/bit.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/bit.version.pass.cpp index c88e80a81d6742..4ae4949d4ff201 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/bit.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/bit.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/chrono.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/chrono.version.pass.cpp index e0e699634f7092..58af9a474b37c3 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/chrono.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/chrono.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/cmath.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/cmath.version.pass.cpp index eabf7e7028b140..5a1017102239d6 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/cmath.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/cmath.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/compare.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/compare.version.pass.cpp index 76f9a101bd11ed..14a19e0972849c 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/compare.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/compare.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/complex.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/complex.version.pass.cpp index 48515287773540..c48a1894eada50 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/complex.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/complex.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.pass.cpp index 442301c804f9c5..4ca51bdd8c34f9 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/concepts.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/cstddef.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/cstddef.version.pass.cpp index cba6bec13ccaf8..c2b970a0c753a9 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/cstddef.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/cstddef.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp index 54fe25726fd2cb..ec2036141e873d 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/deque.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/exception.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/exception.version.pass.cpp index 4a420c611e2641..d14e9a7f7130c4 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/exception.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/exception.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/execution.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/execution.version.pass.cpp index 54d2995a6b722e..8b2a75568a9ec2 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/execution.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/execution.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/filesystem.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/filesystem.version.pass.cpp index 815c00d694ee8e..44850780d3158b 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/filesystem.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/filesystem.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp index a890aff5691c2b..2fc17258651833 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/forward_list.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.pass.cpp index 6fa1ac6ada5b3e..6e65a8fbd77479 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/iomanip.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/iomanip.version.pass.cpp index 45df7e509e637e..38d8f27ff1b05d 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/iomanip.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/iomanip.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // UNSUPPORTED: libcpp-has-no-localization diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/istream.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/istream.version.pass.cpp index 60dde8e60279de..9ea01ebe06dff3 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/istream.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/istream.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // UNSUPPORTED: libcpp-has-no-localization diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.pass.cpp index f36d28594516a9..27318c51a0a094 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/iterator.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/latch.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/latch.version.pass.cpp index ebeebec3237789..29e8fd617bbfe5 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/latch.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/latch.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // UNSUPPORTED: libcpp-has-no-threads diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/limits.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/limits.version.pass.cpp index 72d0e0b7c22409..fecb03d1867b82 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/limits.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/limits.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp index fa455cf0d4bfbc..92d0c0f2379174 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/list.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/locale.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/locale.version.pass.cpp index 6f63f67670b1e4..f9620763c7629b 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/locale.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/locale.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // UNSUPPORTED: libcpp-has-no-localization diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp index 4410a5a6a6132b..85c5b46d7e3f37 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/map.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.pass.cpp index 71ab699ef18924..7be4372b8d7ea3 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/mutex.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/mutex.version.pass.cpp index 9896953457a3b7..9e76cfb757459f 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/mutex.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/mutex.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/new.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/new.version.pass.cpp index c937438c753402..5fbb8afe14ab17 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/new.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/new.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/numbers.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/numbers.version.pass.cpp index 96619ab92c6f48..9e6b1fa8654048 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/numbers.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/numbers.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/numeric.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/numeric.version.pass.cpp index f6c76977b545dd..afdb176bea437b 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/numeric.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/numeric.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/optional.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/optional.version.pass.cpp index d3a3ca7b9950f8..58c3a0e0dc54ee 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/optional.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/optional.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/ostream.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/ostream.version.pass.cpp index 2bc25a4d74d47b..586cd8ec6d5717 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/ostream.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/ostream.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // UNSUPPORTED: libcpp-has-no-localization diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/regex.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/regex.version.pass.cpp index 14935710f32097..df1506a05e6eb0 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/regex.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/regex.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // UNSUPPORTED: libcpp-has-no-localization diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/scoped_allocator.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/scoped_allocator.version.pass.cpp index 1ce7999ace2117..2e8f78d930e152 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/scoped_allocator.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/scoped_allocator.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/semaphore.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/semaphore.version.pass.cpp index 463122161a76bd..febeb6f6c61557 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/semaphore.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/semaphore.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // UNSUPPORTED: libcpp-has-no-threads diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp index 8dd54c86571b04..57fdd5b21f4011 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/set.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/shared_mutex.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/shared_mutex.version.pass.cpp index c6151749b7c2fd..953fd0a37790a8 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/shared_mutex.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/shared_mutex.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // UNSUPPORTED: libcpp-has-no-threads diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/span.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/span.version.pass.cpp index c8750fd446cbf9..0ff32da4ad3579 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/span.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/span.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp index 25f6659e0d221e..1daadbaaf346fb 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.pass.cpp index 6a82e02c366ead..a55ac8473f9af2 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/thread.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/thread.version.pass.cpp index 284eabf9f7c878..c84c12490d899c 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/thread.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/thread.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // UNSUPPORTED: libcpp-has-no-threads diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/tuple.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/tuple.version.pass.cpp index 4b95dd6d67f8b3..ef9f61428782fe 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/tuple.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/tuple.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp index 9afaa1bcd047c9..04c6aaa81fd702 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/type_traits.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp index b0ba18cb143c18..b8e20ff848ba43 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/unordered_map.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp index d57f82b77f6884..89692c766ab7c4 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/unordered_set.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp index b2842a592cd190..ab495be78e9a1a 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/variant.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/variant.version.pass.cpp index 10c7aa9dcc7d28..6d198d1121f744 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/variant.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/variant.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp index d6a7937b4c7038..e4fed01f4a08c9 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/vector.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp index a75d6db28b22f0..664c8fe758393c 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp @@ -8,6 +8,8 @@ // // WARNING: This test was generated by generate_feature_test_macro_components.py // and should not be edited manually. +// +// clang-format off // diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index a58c41663066f7..daa40f2a15ac22 100755 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -933,6 +933,8 @@ def produce_tests(): // // WARNING: This test was generated by {script_name} // and should not be edited manually. +// +// clang-format off {markup} // <{header}> diff --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst index 81734dd30cd247..f661684d9b74ce 100644 --- a/llvm/docs/AMDGPUUsage.rst +++ b/llvm/docs/AMDGPUUsage.rst @@ -4732,7 +4732,12 @@ in table :ref:`amdgpu-amdhsa-memory-model-code-sequences-gfx6-gfx9-table`. - generic - private 1. buffer/global/flat_load - constant - - volatile & !nontemporal + - !volatile & nontemporal + + 1. buffer/global/flat_load + glc=1 slc=1 + + - volatile 1. buffer/global/flat_load glc=1 @@ -4750,17 +4755,17 @@ in table :ref:`amdgpu-amdhsa-memory-model-code-sequences-gfx6-gfx9-table`. be reordered by hardware. - - !volatile & nontemporal - - 1. buffer/global/flat_load - glc=1 slc=1 - load *none* *none* - local 1. ds_load store *none* *none* - global - !volatile & !nontemporal - generic - private 1. buffer/global/flat_store - constant - - volatile & !nontemporal + - !volatile & nontemporal + + 1. buffer/global/flat_store + glc=1 slc=1 + + - volatile 1. buffer/global/flat_store 2. s_waitcnt vmcnt(0) @@ -4777,11 +4782,6 @@ in table :ref:`amdgpu-amdhsa-memory-model-code-sequences-gfx6-gfx9-table`. be reordered by hardware. - - !volatile & nontemporal - - 1. buffer/global/flat_store - glc=1 slc=1 - store *none* *none* - local 1. ds_store **Unordered Atomic** ------------------------------------------------------------------------------------ @@ -6034,7 +6034,12 @@ table :ref:`amdgpu-amdhsa-memory-model-code-sequences-gfx10-table`. - generic - private 1. buffer/global/flat_load - constant - - volatile & !nontemporal + - !volatile & nontemporal + + 1. buffer/global/flat_load + slc=1 + + - volatile 1. buffer/global/flat_load glc=1 dlc=1 @@ -6052,17 +6057,17 @@ table :ref:`amdgpu-amdhsa-memory-model-code-sequences-gfx10-table`. be reordered by hardware. - - !volatile & nontemporal - - 1. buffer/global/flat_load - slc=1 - load *none* *none* - local 1. ds_load store *none* *none* - global - !volatile & !nontemporal - generic - private 1. buffer/global/flat_store - constant - - volatile & !nontemporal + - !volatile & nontemporal + + 1. buffer/global/flat_store + slc=1 + + - volatile 1. buffer/global/flat_store 2. s_waitcnt vscnt(0) @@ -6079,11 +6084,6 @@ table :ref:`amdgpu-amdhsa-memory-model-code-sequences-gfx10-table`. be reordered by hardware. - - !volatile & nontemporal - - 1. buffer/global/flat_store - slc=1 - store *none* *none* - local 1. ds_store **Unordered Atomic** ------------------------------------------------------------------------------------ diff --git a/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h b/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h index dcd35253c5f20f..ca4c40db48b999 100644 --- a/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -297,6 +297,12 @@ template struct simplify_type> { } }; +/// Factory function for creating intrusive ref counted pointers. +template +IntrusiveRefCntPtr makeIntrusiveRefCnt(Args &&...A) { + return IntrusiveRefCntPtr(new T(std::forward(A)...)); +} + } // end namespace llvm #endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H diff --git a/llvm/include/llvm/Config/llvm-config.h.cmake b/llvm/include/llvm/Config/llvm-config.h.cmake index 6c725abbe218a5..6db75bb9337178 100644 --- a/llvm/include/llvm/Config/llvm-config.h.cmake +++ b/llvm/include/llvm/Config/llvm-config.h.cmake @@ -16,7 +16,7 @@ /* Indicate that this is LLVM compiled from the amd-gfx branch. */ #define LLVM_HAVE_BRANCH_AMD_GFX -#define LLVM_MAIN_REVISION 376703 +#define LLVM_MAIN_REVISION 376726 /* Define if LLVM_ENABLE_DUMP is enabled */ #cmakedefine LLVM_ENABLE_DUMP diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h index 42751beb06851a..795a980878e268 100644 --- a/llvm/include/llvm/Passes/StandardInstrumentations.h +++ b/llvm/include/llvm/Passes/StandardInstrumentations.h @@ -152,7 +152,7 @@ class PreservedCFGCheckerInstrumentation { // 8. To compare two IR representations (of type \p T). template class ChangeReporter { protected: - ChangeReporter() {} + ChangeReporter(bool RunInVerboseMode) : VerboseMode(RunInVerboseMode) {} public: virtual ~ChangeReporter(); @@ -204,6 +204,9 @@ template class ChangeReporter { std::vector BeforeStack; // Is this the first IR seen? bool InitialIR = true; + + // Run in verbose mode, printing everything? + const bool VerboseMode; }; // An abstract template base class that handles printing banners and @@ -211,7 +214,7 @@ template class ChangeReporter { template class TextChangeReporter : public ChangeReporter { protected: - TextChangeReporter(); + TextChangeReporter(bool Verbose); // Print a module dump of the first IR that is changed. void handleInitialIR(Any IR) override; @@ -235,7 +238,8 @@ class TextChangeReporter : public ChangeReporter { // included in this representation but it is massaged before reporting. class IRChangedPrinter : public TextChangeReporter { public: - IRChangedPrinter() {} + IRChangedPrinter(bool VerboseMode) + : TextChangeReporter(VerboseMode) {} ~IRChangedPrinter() override; void registerCallbacks(PassInstrumentationCallbacks &PIC); @@ -274,9 +278,7 @@ class StandardInstrumentations { bool VerifyEach; public: - StandardInstrumentations(bool DebugLogging, bool VerifyEach = false) - : PrintPass(DebugLogging), OptNone(DebugLogging), Verify(DebugLogging), - VerifyEach(VerifyEach) {} + StandardInstrumentations(bool DebugLogging, bool VerifyEach = false); void registerCallbacks(PassInstrumentationCallbacks &PIC); diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp index d6351a01ef27d4..04ff0af2f80429 100644 --- a/llvm/lib/Passes/StandardInstrumentations.cpp +++ b/llvm/lib/Passes/StandardInstrumentations.cpp @@ -64,10 +64,17 @@ static cl::opt // can be combined, allowing only changed IRs for certain passes on certain // functions to be reported in different formats, with the rest being // reported as filtered out. The -print-before-changed option will print -// the IR as it was before each pass that changed it. -static cl::opt PrintChanged("print-changed", - cl::desc("Print changed IRs"), - cl::init(false), cl::Hidden); +// the IR as it was before each pass that changed it. The optional +// value of quiet will only report when the IR changes, suppressing +// all other messages, including the initial IR. +enum ChangePrinter { NoChangePrinter, PrintChangedVerbose, PrintChangedQuiet }; +static cl::opt PrintChanged( + "print-changed", cl::desc("Print changed IRs"), cl::Hidden, + cl::ValueOptional, cl::init(NoChangePrinter), + cl::values(clEnumValN(PrintChangedQuiet, "quiet", "Run in quiet mode"), + // Sentinel value for unspecified option. + clEnumValN(PrintChangedVerbose, "", ""))); + // An option that supports the -print-changed option. See // the description for -print-changed for an explanation of the use // of this option. Note that this option has no effect without -print-changed. @@ -287,7 +294,8 @@ void ChangeReporter::saveIRBeforePass(Any IR, StringRef PassID) { // Is this the initial IR? if (InitialIR) { InitialIR = false; - handleInitialIR(IR); + if (VerboseMode) + handleInitialIR(IR); } // Save the IR representation on the stack. @@ -311,11 +319,13 @@ void ChangeReporter::handleIRAfterPass(Any IR, StringRef PassID) { if (Name == "") Name = " (module)"; - if (isIgnored(PassID)) - handleIgnored(PassID, Name); - else if (!isInteresting(IR, PassID)) - handleFiltered(PassID, Name); - else { + if (isIgnored(PassID)) { + if (VerboseMode) + handleIgnored(PassID, Name); + } else if (!isInteresting(IR, PassID)) { + if (VerboseMode) + handleFiltered(PassID, Name); + } else { // Get the before rep from the stack IRUnitT &Before = BeforeStack.back(); // Create the after rep @@ -323,9 +333,10 @@ void ChangeReporter::handleIRAfterPass(Any IR, StringRef PassID) { generateIRRepresentation(IR, PassID, After); // Was there a change in IR? - if (same(Before, After)) - omitAfter(PassID, Name); - else + if (same(Before, After)) { + if (VerboseMode) + omitAfter(PassID, Name); + } else handleAfter(PassID, Name, Before, After, IR); } BeforeStack.pop_back(); @@ -339,7 +350,8 @@ void ChangeReporter::handleInvalidatedPass(StringRef PassID) { // a pass for a filtered function is invalidated since we do not // get the IR in the call. Also, the output is just alternate // forms of the banner anyway. - handleInvalidated(PassID); + if (VerboseMode) + handleInvalidated(PassID); BeforeStack.pop_back(); } @@ -360,8 +372,8 @@ void ChangeReporter::registerRequiredCallbacks( } template -TextChangeReporter::TextChangeReporter() - : ChangeReporter(), Out(dbgs()) {} +TextChangeReporter::TextChangeReporter(bool Verbose) + : ChangeReporter(Verbose), Out(dbgs()) {} template void TextChangeReporter::handleInitialIR(Any IR) { @@ -403,7 +415,7 @@ void TextChangeReporter::handleIgnored(StringRef PassID, IRChangedPrinter::~IRChangedPrinter() {} void IRChangedPrinter::registerCallbacks(PassInstrumentationCallbacks &PIC) { - if (PrintChanged) + if (PrintChanged != NoChangePrinter) TextChangeReporter::registerRequiredCallbacks(PIC); } @@ -856,6 +868,12 @@ void VerifyInstrumentation::registerCallbacks( }); } +StandardInstrumentations::StandardInstrumentations(bool DebugLogging, + bool VerifyEach) + : PrintPass(DebugLogging), OptNone(DebugLogging), + PrintChangedIR(PrintChanged != PrintChangedQuiet), Verify(DebugLogging), + VerifyEach(VerifyEach) {} + void StandardInstrumentations::registerCallbacks( PassInstrumentationCallbacks &PIC) { PrintIR.registerCallbacks(PIC); diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.td b/llvm/lib/Target/AMDGPU/SIInstrInfo.td index e48138e56d71cb..78600bebdad22e 100644 --- a/llvm/lib/Target/AMDGPU/SIInstrInfo.td +++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.td @@ -1587,7 +1587,7 @@ class getIns32 { // Returns the input arguments for VOP3 instructions for the given SrcVT. class getIns64 { dag ret = @@ -1602,7 +1602,7 @@ class getIns64 { + // getInst64 handles clamp and omod. implicit mutex between vop3p and omod + dag base = getIns64 .ret; + dag opsel = (ins op_sel0:$op_sel); + dag vop3pFields = (ins op_sel_hi0:$op_sel_hi, neg_lo0:$neg_lo, neg_hi0:$neg_hi); + dag ret = !con(base, + !if(HasOpSel, opsel,(ins)), + !if(IsVOP3P, vop3pFields,(ins))); +} -// The modifiers (except clamp) are dummy operands for the benefit of -// printing and parsing. They defer their values to looking at the -// srcN_modifiers for what to print. class getInsVOP3P { - dag ret = !if (!eq(NumSrcArgs, 2), - !if (HasClamp, - (ins Src0Mod:$src0_modifiers, Src0RC:$src0, - Src1Mod:$src1_modifiers, Src1RC:$src1, - clampmod0:$clamp, - op_sel0:$op_sel, op_sel_hi0:$op_sel_hi, - neg_lo0:$neg_lo, neg_hi0:$neg_hi), - (ins Src0Mod:$src0_modifiers, Src0RC:$src0, - Src1Mod:$src1_modifiers, Src1RC:$src1, - op_sel0:$op_sel, op_sel_hi0:$op_sel_hi, - neg_lo0:$neg_lo, neg_hi0:$neg_hi)), - // else NumSrcArgs == 3 - !if (HasClamp, - (ins Src0Mod:$src0_modifiers, Src0RC:$src0, - Src1Mod:$src1_modifiers, Src1RC:$src1, - Src2Mod:$src2_modifiers, Src2RC:$src2, - clampmod0:$clamp, - op_sel0:$op_sel, op_sel_hi0:$op_sel_hi, - neg_lo0:$neg_lo, neg_hi0:$neg_hi), - (ins Src0Mod:$src0_modifiers, Src0RC:$src0, - Src1Mod:$src1_modifiers, Src1RC:$src1, - Src2Mod:$src2_modifiers, Src2RC:$src2, - op_sel0:$op_sel, op_sel_hi0:$op_sel_hi, - neg_lo0:$neg_lo, neg_hi0:$neg_hi)) - ); + dag ret = getInsVOP3Base.ret; } -class getInsVOP3OpSel { - dag ret = !if (!eq(NumSrcArgs, 2), - !if (HasClamp, - (ins Src0Mod:$src0_modifiers, Src0RC:$src0, - Src1Mod:$src1_modifiers, Src1RC:$src1, - clampmod0:$clamp, - op_sel0:$op_sel), - (ins Src0Mod:$src0_modifiers, Src0RC:$src0, - Src1Mod:$src1_modifiers, Src1RC:$src1, - op_sel0:$op_sel)), - // else NumSrcArgs == 3 - !if (HasClamp, - (ins Src0Mod:$src0_modifiers, Src0RC:$src0, - Src1Mod:$src1_modifiers, Src1RC:$src1, - Src2Mod:$src2_modifiers, Src2RC:$src2, - clampmod0:$clamp, - op_sel0:$op_sel), - (ins Src0Mod:$src0_modifiers, Src0RC:$src0, - Src1Mod:$src1_modifiers, Src1RC:$src1, - Src2Mod:$src2_modifiers, Src2RC:$src2, - op_sel0:$op_sel)) - ); +class getInsVOP3OpSel { + dag ret = getInsVOP3Base.ret; } -class getInsDPP { dag ret = !if (!eq(NumSrcArgs, 0), // VOP1 without input operands (V_NOP) - (ins dpp_ctrl:$dpp_ctrl, row_mask:$row_mask, - bank_mask:$bank_mask, bound_ctrl:$bound_ctrl), + (ins ), !if (!eq(NumSrcArgs, 1), !if (HasModifiers, // VOP1_DPP with modifiers (ins DstRC:$old, Src0Mod:$src0_modifiers, - Src0RC:$src0, dpp_ctrl:$dpp_ctrl, row_mask:$row_mask, - bank_mask:$bank_mask, bound_ctrl:$bound_ctrl) + Src0RC:$src0) /* else */, // VOP1_DPP without modifiers - (ins DstRC:$old, Src0RC:$src0, - dpp_ctrl:$dpp_ctrl, row_mask:$row_mask, - bank_mask:$bank_mask, bound_ctrl:$bound_ctrl) - /* endif */) - /* NumSrcArgs == 2 */, + (ins DstRC:$old, Src0RC:$src0) + /* endif */), !if (HasModifiers, // VOP2_DPP with modifiers (ins DstRC:$old, Src0Mod:$src0_modifiers, Src0RC:$src0, - Src1Mod:$src1_modifiers, Src1RC:$src1, - dpp_ctrl:$dpp_ctrl, row_mask:$row_mask, - bank_mask:$bank_mask, bound_ctrl:$bound_ctrl) + Src1Mod:$src1_modifiers, Src1RC:$src1) /* else */, // VOP2_DPP without modifiers (ins DstRC:$old, - Src0RC:$src0, Src1RC:$src1, dpp_ctrl:$dpp_ctrl, - row_mask:$row_mask, bank_mask:$bank_mask, - bound_ctrl:$bound_ctrl) - /* endif */))); + Src0RC:$src0, Src1RC:$src1) + ))); +} + +class getInsDPP { + dag ret = !con(getInsDPPBase.ret, + (ins dpp_ctrl:$dpp_ctrl, row_mask:$row_mask, + bank_mask:$bank_mask, bound_ctrl:$bound_ctrl)); } class getInsDPP16 { + int NumSrcArgs, bit HasModifiers, + Operand Src0Mod, Operand Src1Mod> { dag ret = !con(getInsDPP.ret, (ins FI:$fi)); @@ -1775,30 +1743,9 @@ class getInsDPP16 { - dag ret = !if (!eq(NumSrcArgs, 0), - // VOP1 without input operands (V_NOP) - (ins dpp8:$dpp8, FI:$fi), - !if (!eq(NumSrcArgs, 1), - !if (HasModifiers, - // VOP1_DPP with modifiers - (ins DstRC:$old, Src0Mod:$src0_modifiers, - Src0RC:$src0, dpp8:$dpp8, FI:$fi) - /* else */, - // VOP1_DPP without modifiers - (ins DstRC:$old, Src0RC:$src0, dpp8:$dpp8, FI:$fi) - /* endif */) - /* NumSrcArgs == 2 */, - !if (HasModifiers, - // VOP2_DPP with modifiers - (ins DstRC:$old, - Src0Mod:$src0_modifiers, Src0RC:$src0, - Src1Mod:$src1_modifiers, Src1RC:$src1, - dpp8:$dpp8, FI:$fi) - /* else */, - // VOP2_DPP without modifiers - (ins DstRC:$old, - Src0RC:$src0, Src1RC:$src1, dpp8:$dpp8, FI:$fi) - /* endif */))); + dag ret = !con(getInsDPPBase.ret, + (ins dpp8:$dpp8, FI:$fi)); } @@ -1916,6 +1863,7 @@ class getAsmVOP3P { @@ -1962,22 +1910,12 @@ class getAsmDPP16 .ret#"$fi"; } -class getAsmDPP8 { - string dst = !if(HasDst, - !if(!eq(DstVT.Size, 1), - "$sdst", - "$vdst"), - ""); // use $sdst for VOPC - string src0 = !if(!eq(NumSrcArgs, 1), "$src0_modifiers", "$src0_modifiers,"); - string src1 = !if(!eq(NumSrcArgs, 1), "", - !if(!eq(NumSrcArgs, 2), " $src1_modifiers", - " $src1_modifiers,")); - string args = !if(!not(HasModifiers), - getAsm32<0, NumSrcArgs, DstVT>.ret, - ", "#src0#src1); - string ret = dst#args#" $dpp8$fi"; +class getAsmDPP8 + : getAsmDPP { + let ret = dst#args#" $dpp8$fi"; } + class getAsmSDWA { string dst = !if(HasDst, !if(!eq(DstVT.Size, 1), @@ -2167,11 +2105,10 @@ class VOPProfile _ArgVT, bit _EnableF32SrcMods = 0, NumSrcArgs, HasClamp, Src0PackedMod, Src1PackedMod, Src2PackedMod>.ret; field dag InsVOP3OpSel = getInsVOP3OpSel.ret, - getOpSelMod.ret, - getOpSelMod.ret>.ret; + NumSrcArgs, HasClamp, HasOMod, + getOpSelMod.ret, + getOpSelMod.ret, + getOpSelMod.ret>.ret; field dag InsDPP = !if(HasExtDPP, getInsDPP.ret, @@ -2189,7 +2126,7 @@ class VOPProfile _ArgVT, bit _EnableF32SrcMods = 0, field string Asm64 = getAsm64.ret; field string AsmVOP3P = getAsmVOP3P.ret; field string AsmVOP3OpSel = getAsmVOP3OpSel.ret; diff --git a/llvm/lib/Target/AMDGPU/VOP3Instructions.td b/llvm/lib/Target/AMDGPU/VOP3Instructions.td index f349a0f54fa7c5..9bdcdd376269ed 100644 --- a/llvm/lib/Target/AMDGPU/VOP3Instructions.td +++ b/llvm/lib/Target/AMDGPU/VOP3Instructions.td @@ -182,6 +182,7 @@ class VOP3_Profile : VOPProf " " # !if(Features.HasOpSel, getAsmVOP3OpSel.ret, diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 2349b43f30c6ba..03db9911c86718 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -374,6 +374,48 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM, // We must custom-lower SPLAT_VECTOR vXi64 on RV32 if (!Subtarget.is64Bit()) setOperationAction(ISD::SPLAT_VECTOR, MVT::i64, Custom); + + // Expand various CCs to best match the RVV ISA, which natively supports UNE + // but no other unordered comparisons, and supports all ordered comparisons + // except ONE. Additionally, we expand GT,OGT,GE,OGE for optimization + // purposes; they are expanded to their swapped-operand CCs (LT,OLT,LE,OLE), + // and we pattern-match those back to the "original", swapping operands once + // more. This way we catch both operations and both "vf" and "fv" forms with + // fewer patterns. + ISD::CondCode VFPCCToExpand[] = { + ISD::SETO, ISD::SETONE, ISD::SETUEQ, ISD::SETUGT, + ISD::SETUGE, ISD::SETULT, ISD::SETULE, ISD::SETUO, + ISD::SETGT, ISD::SETOGT, ISD::SETGE, ISD::SETOGE, + }; + + if (Subtarget.hasStdExtZfh()) { + for (auto VT : {RISCVVMVTs::vfloat16mf4_t, RISCVVMVTs::vfloat16mf2_t, + RISCVVMVTs::vfloat16m1_t, RISCVVMVTs::vfloat16m2_t, + RISCVVMVTs::vfloat16m4_t, RISCVVMVTs::vfloat16m8_t}) { + setOperationAction(ISD::SPLAT_VECTOR, VT, Legal); + for (auto CC : VFPCCToExpand) + setCondCodeAction(CC, VT, Expand); + } + } + + if (Subtarget.hasStdExtF()) { + for (auto VT : {RISCVVMVTs::vfloat32mf2_t, RISCVVMVTs::vfloat32m1_t, + RISCVVMVTs::vfloat32m2_t, RISCVVMVTs::vfloat32m4_t, + RISCVVMVTs::vfloat32m8_t}) { + setOperationAction(ISD::SPLAT_VECTOR, VT, Legal); + for (auto CC : VFPCCToExpand) + setCondCodeAction(CC, VT, Expand); + } + } + + if (Subtarget.hasStdExtD()) { + for (auto VT : {RISCVVMVTs::vfloat64m1_t, RISCVVMVTs::vfloat64m2_t, + RISCVVMVTs::vfloat64m4_t, RISCVVMVTs::vfloat64m8_t}) { + setOperationAction(ISD::SPLAT_VECTOR, VT, Legal); + for (auto CC : VFPCCToExpand) + setCondCodeAction(CC, VT, Expand); + } + } } // Function alignments. diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td index 0ef798937a66fd..404c3050e60124 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVSDPatterns.td @@ -192,6 +192,45 @@ multiclass VPatIntegerSetCCSDNode_VX_VI; } +multiclass VPatFPSetCCSDNode_VV { + foreach fvti = AllFloatVectors in + def : Pat<(fvti.Mask (setcc (fvti.Vector fvti.RegClass:$rs1), + (fvti.Vector fvti.RegClass:$rs2), + cc)), + (!cast(instruction_name#"_VV_"#fvti.LMul.MX) + fvti.RegClass:$rs1, fvti.RegClass:$rs2, VLMax, fvti.SEW)>; +} + +multiclass VPatFPSetCCSDNode_VF { + foreach fvti = AllFloatVectors in + def : Pat<(fvti.Mask (setcc (fvti.Vector fvti.RegClass:$rs1), + (fvti.Vector (splat_vector fvti.ScalarRegClass:$rs2)), + cc)), + (!cast(instruction_name#"_VF_"#fvti.LMul.MX) + fvti.RegClass:$rs1, + ToFPR32.ret, + VLMax, fvti.SEW)>; +} + +multiclass VPatFPSetCCSDNode_FV { + foreach fvti = AllFloatVectors in + def : Pat<(fvti.Mask (setcc (fvti.Vector (splat_vector fvti.ScalarRegClass:$rs2)), + (fvti.Vector fvti.RegClass:$rs1), + cc)), + (!cast(swapped_op_instruction_name#"_VF_"#fvti.LMul.MX) + fvti.RegClass:$rs1, + ToFPR32.ret, + VLMax, fvti.SEW)>; +} + +multiclass VPatFPSetCCSDNode_VV_VF_FV { + defm : VPatFPSetCCSDNode_VV; + defm : VPatFPSetCCSDNode_VF; + defm : VPatFPSetCCSDNode_FV; +} + //===----------------------------------------------------------------------===// // Patterns. //===----------------------------------------------------------------------===// @@ -299,6 +338,23 @@ foreach mti = AllMasks in { } // Predicates = [HasStdExtV] +let Predicates = [HasStdExtV, HasStdExtF] in { + +// 14.11. Vector Floating-Point Compare Instructions +defm "" : VPatFPSetCCSDNode_VV_VF_FV; +defm "" : VPatFPSetCCSDNode_VV_VF_FV; + +defm "" : VPatFPSetCCSDNode_VV_VF_FV; +defm "" : VPatFPSetCCSDNode_VV_VF_FV; + +defm "" : VPatFPSetCCSDNode_VV_VF_FV; +defm "" : VPatFPSetCCSDNode_VV_VF_FV; + +defm "" : VPatFPSetCCSDNode_VV_VF_FV; +defm "" : VPatFPSetCCSDNode_VV_VF_FV; + +} // Predicates = [HasStdExtV, HasStdExtF] + //===----------------------------------------------------------------------===// // Vector Splats //===----------------------------------------------------------------------===// @@ -333,3 +389,16 @@ foreach vti = AllIntegerVectors in { } } } // Predicates = [HasStdExtV, IsRV32] + +let Predicates = [HasStdExtV, HasStdExtF] in { +foreach fvti = AllFloatVectors in { + def : Pat<(fvti.Vector (splat_vector fvti.ScalarRegClass:$rs1)), + (!cast("PseudoVFMV_V_F_"#fvti.LMul.MX) + ToFPR32.ret, + VLMax, fvti.SEW)>; + + def : Pat<(fvti.Vector (splat_vector (fvti.Scalar fpimm0))), + (!cast("PseudoVMV_V_I_"#fvti.LMul.MX) + 0, VLMax, fvti.SEW)>; +} +} // Predicates = [HasStdExtV, HasStdExtF] diff --git a/llvm/lib/Transforms/Utils/UniqueInternalLinkageNames.cpp b/llvm/lib/Transforms/Utils/UniqueInternalLinkageNames.cpp index 385bf8bb429aeb..29ad0b6fcae50a 100644 --- a/llvm/lib/Transforms/Utils/UniqueInternalLinkageNames.cpp +++ b/llvm/lib/Transforms/Utils/UniqueInternalLinkageNames.cpp @@ -27,9 +27,12 @@ static bool uniqueifyInternalLinkageNames(Module &M) { Md5.final(R); SmallString<32> Str; llvm::MD5::stringifyResult(R, Str); + // Convert MD5hash to Decimal. Demangler suffixes can either contain numbers + // or characters but not both. + APInt IntHash = APInt(128, Str.str(), 16); // Prepend "__uniq" before the hash for tools like profilers to understand that // this symbol is of internal linkage type. - std::string ModuleNameHash = (Twine(".__uniq.") + Twine(Str)).str(); + std::string ModuleNameHash = (Twine(".__uniq.") + Twine(IntHash.toString(10, false))).str(); bool Changed = false; // Append the module hash to all internal linkage functions. diff --git a/llvm/test/CodeGen/AMDGPU/lit.local.cfg b/llvm/test/CodeGen/AMDGPU/lit.local.cfg index 42f23b00ea9b2e..2a665f06be72e5 100644 --- a/llvm/test/CodeGen/AMDGPU/lit.local.cfg +++ b/llvm/test/CodeGen/AMDGPU/lit.local.cfg @@ -1,12 +1,2 @@ -from lit.llvm.subst import ToolSubst - if not 'AMDGPU' in config.root.targets: config.unsupported = True - -fc = ToolSubst('FileCheck', unresolved='fatal') -# Insert this first. Then, we'll first update the blank FileCheck command; then, -# the default substitution of FileCheck will replace it to its full path. -config.substitutions.insert(0, (fc.regex, - 'FileCheck --allow-unused-prefixes=false')) - - diff --git a/llvm/test/CodeGen/ARM/speculation-hardening-sls.ll b/llvm/test/CodeGen/ARM/speculation-hardening-sls.ll index e62012faed881b..7fe5a9ba2eb0cc 100644 --- a/llvm/test/CodeGen/ARM/speculation-hardening-sls.ll +++ b/llvm/test/CodeGen/ARM/speculation-hardening-sls.ll @@ -1,9 +1,9 @@ -; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,ISBDSB,ISBDSBDAGISEL -dump-input-context=100 -; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,ISBDSB,ISBDSBDAGISEL -dump-input-context=100 -; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,SB,SBDAGISEL -dump-input-context=100 -; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,SB,SBDAGISEL -dump-input-context=100 -; RUN: llc -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,NOHARDEN,NOHARDENARM -dump-input-context=100 -; RUN: llc -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,NOHARDEN,NOHARDENTHUMB +; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,ISBDSB -dump-input-context=100 +; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,ISBDSB -dump-input-context=100 +; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,SB -dump-input-context=100 +; RUN: llc -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,SB -dump-input-context=100 +; RUN: llc -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,NOHARDENARM -dump-input-context=100 +; RUN: llc -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,NOHARDENTHUMB ; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,ISBDSB ; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr -mattr=harden-sls-blr -verify-machineinstrs -mtriple=thumbv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,THUMB,HARDENTHUMB,HARDEN,ISBDSB ; RUN: llc -global-isel -global-isel-abort=0 -mattr=harden-sls-retbr -mattr=harden-sls-blr -mattr=+sb -verify-machineinstrs -mtriple=armv8-linux-gnueabi < %s | FileCheck %s --check-prefixes=CHECK,ARM,HARDEN,SB diff --git a/llvm/test/CodeGen/NVPTX/f16-instructions.ll b/llvm/test/CodeGen/NVPTX/f16-instructions.ll index 3856cb63350df0..b06316b4880a25 100644 --- a/llvm/test/CodeGen/NVPTX/f16-instructions.ll +++ b/llvm/test/CodeGen/NVPTX/f16-instructions.ll @@ -1,12 +1,12 @@ ; ## Full FP16 support enabled by default. ; RUN: llc < %s -mtriple=nvptx64-nvidia-cuda -mcpu=sm_53 -asm-verbose=false \ ; RUN: -O0 -disable-post-ra -frame-pointer=all -verify-machineinstrs \ -; RUN: | FileCheck -check-prefixes CHECK,CHECK-NOFTZ,CHECK-F16,CHECK-F16-NOFTZ %s +; RUN: | FileCheck -check-prefixes CHECK,CHECK-NOFTZ,CHECK-F16-NOFTZ %s ; ## Full FP16 with FTZ ; RUN: llc < %s -mtriple=nvptx64-nvidia-cuda -mcpu=sm_53 -asm-verbose=false \ ; RUN: -O0 -disable-post-ra -frame-pointer=all -verify-machineinstrs \ ; RUN: -denormal-fp-math-f32=preserve-sign \ -; RUN: | FileCheck -check-prefixes CHECK,CHECK-F16,CHECK-F16-FTZ %s +; RUN: | FileCheck -check-prefixes CHECK,CHECK-F16-FTZ %s ; ## FP16 support explicitly disabled. ; RUN: llc < %s -mtriple=nvptx64-nvidia-cuda -mcpu=sm_53 -asm-verbose=false \ ; RUN: -O0 -disable-post-ra -frame-pointer=all --nvptx-no-f16-math \ diff --git a/llvm/test/CodeGen/PowerPC/lit.local.cfg b/llvm/test/CodeGen/PowerPC/lit.local.cfg index 19bfd981b645c4..1dbbf92fcf5e3c 100644 --- a/llvm/test/CodeGen/PowerPC/lit.local.cfg +++ b/llvm/test/CodeGen/PowerPC/lit.local.cfg @@ -1,12 +1,4 @@ -from lit.llvm.subst import ToolSubst - if not 'PowerPC' in config.root.targets: config.unsupported = True config.suffixes.add('.py') - -fc = ToolSubst('FileCheck', unresolved='fatal') -# Insert this first. Then, we'll first update the blank FileCheck command; then, -# the default substitution of FileCheck will replace it to its full path. -config.substitutions.insert(0, (fc.regex, - 'FileCheck --allow-unused-prefixes=false')) diff --git a/llvm/test/CodeGen/RISCV/rvv/setcc-fp-rv32.ll b/llvm/test/CodeGen/RISCV/rvv/setcc-fp-rv32.ll new file mode 100644 index 00000000000000..3fefbb727413b1 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/setcc-fp-rv32.ll @@ -0,0 +1,2748 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+d,+experimental-zfh,+experimental-v -target-abi=ilp32d \ +; RUN: -verify-machineinstrs < %s | FileCheck %s + +; FIXME: The scalar/vector operations ('fv' tests) should swap operands and +; condition codes accordingly in order to generate a 'vf' instruction. + +define @fcmp_oeq_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_oeq_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp oeq %va, %vb + ret %vc +} + +define @fcmp_oeq_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_oeq_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %va, %splat + ret %vc +} + +define @fcmp_oeq_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_oeq_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %splat, %va + ret %vc +} + +define @fcmp_oeq_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_oeq_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp oeq %va, %vb + ret %vc +} + +define @fcmp_oeq_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_oeq_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %va, %splat + ret %vc +} + +define @fcmp_ogt_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_ogt_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vv v0, v18, v16 +; CHECK-NEXT: ret + %vc = fcmp ogt %va, %vb + ret %vc +} + +define @fcmp_ogt_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ogt_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %va, %splat + ret %vc +} + +define @fcmp_ogt_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ogt_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %splat, %va + ret %vc +} + +define @fcmp_ogt_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ogt_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vv v0, v18, v16 +; CHECK-NEXT: ret + %vc = fcmp ogt %va, %vb + ret %vc +} + +define @fcmp_ogt_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_ogt_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %va, %splat + ret %vc +} + +define @fcmp_oge_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_oge_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vv v0, v18, v16 +; CHECK-NEXT: ret + %vc = fcmp oge %va, %vb + ret %vc +} + +define @fcmp_oge_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_oge_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %va, %splat + ret %vc +} + +define @fcmp_oge_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_oge_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %splat, %va + ret %vc +} + +define @fcmp_oge_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_oge_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vv v0, v18, v16 +; CHECK-NEXT: ret + %vc = fcmp oge %va, %vb + ret %vc +} + +define @fcmp_oge_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_oge_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %va, %splat + ret %vc +} + +define @fcmp_olt_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_olt_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp olt %va, %vb + ret %vc +} + +define @fcmp_olt_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_olt_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %va, %splat + ret %vc +} + +define @fcmp_olt_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_olt_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %splat, %va + ret %vc +} + +define @fcmp_olt_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_olt_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp olt %va, %vb + ret %vc +} + +define @fcmp_olt_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_olt_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %va, %splat + ret %vc +} + +define @fcmp_ole_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_ole_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp ole %va, %vb + ret %vc +} + +define @fcmp_ole_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ole_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %va, %splat + ret %vc +} + +define @fcmp_ole_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ole_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %splat, %va + ret %vc +} + +define @fcmp_ole_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ole_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp ole %va, %vb + ret %vc +} + +define @fcmp_ole_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_ole_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %va, %splat + ret %vc +} + +define @fcmp_one_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_one_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vv v25, v16, v18 +; CHECK-NEXT: vmfeq.vv v26, v18, v18 +; CHECK-NEXT: vmfeq.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v27, v26 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp one %va, %vb + ret %vc +} + +define @fcmp_one_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_one_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfne.vf v25, v16, fa0 +; CHECK-NEXT: vmfeq.vf v28, v26, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v26, v28 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %va, %splat + ret %vc +} + +define @fcmp_one_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_one_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfne.vf v25, v16, fa0 +; CHECK-NEXT: vmfeq.vf v28, v26, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v28, v26 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %splat, %va + ret %vc +} + +define @fcmp_one_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_one_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp one %va, %vb + ret %vc +} + +define @fcmp_one_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_one_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %va, %splat + ret %vc +} + +define @fcmp_ord_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_ord_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vv v25, v18, v18 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %vc = fcmp ord %va, %vb + ret %vc +} + +define @fcmp_ord_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ord_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfeq.vf v25, v26, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %va, %splat + ret %vc +} + +define @fcmp_ord_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ord_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfeq.vf v25, v26, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %splat, %va + ret %vc +} + +define @fcmp_ord_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ord_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vv v25, v18, v18 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %vc = fcmp ord %va, %vb + ret %vc +} + +define @fcmp_ord_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_ord_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfeq.vf v25, v26, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %va, %splat + ret %vc +} + +define @fcmp_ueq_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_ueq_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vv v25, v16, v18 +; CHECK-NEXT: vmfne.vv v26, v18, v18 +; CHECK-NEXT: vmfne.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v27, v26 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ueq %va, %vb + ret %vc +} + +define @fcmp_ueq_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ueq_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfeq.vf v25, v16, fa0 +; CHECK-NEXT: vmfne.vf v28, v26, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v26, v28 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %va, %splat + ret %vc +} + +define @fcmp_ueq_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ueq_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfeq.vf v25, v16, fa0 +; CHECK-NEXT: vmfne.vf v28, v26, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v28, v26 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %splat, %va + ret %vc +} + +define @fcmp_ueq_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ueq_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp ueq %va, %vb + ret %vc +} + +define @fcmp_ueq_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_ueq_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %va, %splat + ret %vc +} + +define @fcmp_ugt_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_ugt_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vv v25, v16, v18 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ugt %va, %vb + ret %vc +} + +define @fcmp_ugt_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ugt_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %va, %splat + ret %vc +} + +define @fcmp_ugt_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ugt_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfge.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %splat, %va + ret %vc +} + +define @fcmp_ugt_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ugt_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vv v0, v18, v16 +; CHECK-NEXT: ret + %vc = fcmp ugt %va, %vb + ret %vc +} + +define @fcmp_ugt_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_ugt_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %va, %splat + ret %vc +} + +define @fcmp_uge_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_uge_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vv v25, v16, v18 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp uge %va, %vb + ret %vc +} + +define @fcmp_uge_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_uge_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %va, %splat + ret %vc +} + +define @fcmp_uge_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_uge_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfgt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %splat, %va + ret %vc +} + +define @fcmp_uge_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_uge_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vv v0, v18, v16 +; CHECK-NEXT: ret + %vc = fcmp uge %va, %vb + ret %vc +} + +define @fcmp_uge_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_uge_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %va, %splat + ret %vc +} + +define @fcmp_ult_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_ult_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vv v25, v18, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ult %va, %vb + ret %vc +} + +define @fcmp_ult_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ult_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfge.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %va, %splat + ret %vc +} + +define @fcmp_ult_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ult_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %splat, %va + ret %vc +} + +define @fcmp_ult_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ult_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp ult %va, %vb + ret %vc +} + +define @fcmp_ult_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_ult_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %va, %splat + ret %vc +} + +define @fcmp_ule_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_ule_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vv v25, v18, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ule %va, %vb + ret %vc +} + +define @fcmp_ule_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ule_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfgt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %va, %splat + ret %vc +} + +define @fcmp_ule_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ule_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %splat, %va + ret %vc +} + +define @fcmp_ule_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ule_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp ule %va, %vb + ret %vc +} + +define @fcmp_ule_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_ule_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %va, %splat + ret %vc +} + +define @fcmp_une_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_une_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp une %va, %vb + ret %vc +} + +define @fcmp_une_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_une_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %va, %splat + ret %vc +} + +define @fcmp_une_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_une_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %splat, %va + ret %vc +} + +define @fcmp_une_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_une_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp une %va, %vb + ret %vc +} + +define @fcmp_une_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_une_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %va, %splat + ret %vc +} + +define @fcmp_uno_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_uno_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vv v25, v18, v18 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %vc = fcmp uno %va, %vb + ret %vc +} + +define @fcmp_uno_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_uno_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfne.vf v25, v26, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %va, %splat + ret %vc +} + +define @fcmp_uno_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_uno_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfne.vf v25, v26, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %splat, %va + ret %vc +} + +define @fcmp_uno_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_uno_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vv v25, v18, v18 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %vc = fcmp uno %va, %vb + ret %vc +} + +define @fcmp_uno_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_uno_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfne.vf v25, v26, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %va, %splat + ret %vc +} + +define @fcmp_oeq_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_oeq_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp oeq %va, %vb + ret %vc +} + +define @fcmp_oeq_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_oeq_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %va, %splat + ret %vc +} + +define @fcmp_oeq_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_oeq_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %splat, %va + ret %vc +} + +define @fcmp_oeq_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_oeq_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp oeq %va, %vb + ret %vc +} + +define @fcmp_oeq_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_oeq_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %va, %splat + ret %vc +} + +define @fcmp_ogt_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_ogt_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vv v0, v20, v16 +; CHECK-NEXT: ret + %vc = fcmp ogt %va, %vb + ret %vc +} + +define @fcmp_ogt_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ogt_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %va, %splat + ret %vc +} + +define @fcmp_ogt_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ogt_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %splat, %va + ret %vc +} + +define @fcmp_ogt_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ogt_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vv v0, v20, v16 +; CHECK-NEXT: ret + %vc = fcmp ogt %va, %vb + ret %vc +} + +define @fcmp_ogt_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_ogt_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %va, %splat + ret %vc +} + +define @fcmp_oge_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_oge_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vv v0, v20, v16 +; CHECK-NEXT: ret + %vc = fcmp oge %va, %vb + ret %vc +} + +define @fcmp_oge_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_oge_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %va, %splat + ret %vc +} + +define @fcmp_oge_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_oge_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %splat, %va + ret %vc +} + +define @fcmp_oge_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_oge_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vv v0, v20, v16 +; CHECK-NEXT: ret + %vc = fcmp oge %va, %vb + ret %vc +} + +define @fcmp_oge_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_oge_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %va, %splat + ret %vc +} + +define @fcmp_olt_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_olt_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp olt %va, %vb + ret %vc +} + +define @fcmp_olt_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_olt_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %va, %splat + ret %vc +} + +define @fcmp_olt_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_olt_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %splat, %va + ret %vc +} + +define @fcmp_olt_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_olt_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp olt %va, %vb + ret %vc +} + +define @fcmp_olt_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_olt_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %va, %splat + ret %vc +} + +define @fcmp_ole_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_ole_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp ole %va, %vb + ret %vc +} + +define @fcmp_ole_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ole_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %va, %splat + ret %vc +} + +define @fcmp_ole_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ole_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %splat, %va + ret %vc +} + +define @fcmp_ole_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ole_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp ole %va, %vb + ret %vc +} + +define @fcmp_ole_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_ole_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %va, %splat + ret %vc +} + +define @fcmp_one_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_one_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vv v25, v16, v20 +; CHECK-NEXT: vmfeq.vv v26, v20, v20 +; CHECK-NEXT: vmfeq.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v27, v26 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp one %va, %vb + ret %vc +} + +define @fcmp_one_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_one_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfne.vf v25, v16, fa0 +; CHECK-NEXT: vmfeq.vf v26, v28, fa0 +; CHECK-NEXT: vmfeq.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v27, v26 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %va, %splat + ret %vc +} + +define @fcmp_one_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_one_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfne.vf v25, v16, fa0 +; CHECK-NEXT: vmfeq.vf v26, v28, fa0 +; CHECK-NEXT: vmfeq.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v26, v27 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %splat, %va + ret %vc +} + +define @fcmp_one_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_one_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp one %va, %vb + ret %vc +} + +define @fcmp_one_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_one_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %va, %splat + ret %vc +} + +define @fcmp_ord_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_ord_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vv v25, v20, v20 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %vc = fcmp ord %va, %vb + ret %vc +} + +define @fcmp_ord_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ord_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfeq.vf v25, v28, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %va, %splat + ret %vc +} + +define @fcmp_ord_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ord_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfeq.vf v25, v28, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %splat, %va + ret %vc +} + +define @fcmp_ord_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ord_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vv v25, v20, v20 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %vc = fcmp ord %va, %vb + ret %vc +} + +define @fcmp_ord_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_ord_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfeq.vf v25, v28, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %va, %splat + ret %vc +} + +define @fcmp_ueq_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_ueq_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vv v25, v16, v20 +; CHECK-NEXT: vmfne.vv v26, v20, v20 +; CHECK-NEXT: vmfne.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v27, v26 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ueq %va, %vb + ret %vc +} + +define @fcmp_ueq_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ueq_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfeq.vf v25, v16, fa0 +; CHECK-NEXT: vmfne.vf v26, v28, fa0 +; CHECK-NEXT: vmfne.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v27, v26 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %va, %splat + ret %vc +} + +define @fcmp_ueq_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ueq_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfeq.vf v25, v16, fa0 +; CHECK-NEXT: vmfne.vf v26, v28, fa0 +; CHECK-NEXT: vmfne.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v26, v27 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %splat, %va + ret %vc +} + +define @fcmp_ueq_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ueq_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp ueq %va, %vb + ret %vc +} + +define @fcmp_ueq_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_ueq_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %va, %splat + ret %vc +} + +define @fcmp_ugt_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_ugt_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vv v25, v16, v20 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ugt %va, %vb + ret %vc +} + +define @fcmp_ugt_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ugt_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %va, %splat + ret %vc +} + +define @fcmp_ugt_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ugt_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfge.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %splat, %va + ret %vc +} + +define @fcmp_ugt_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ugt_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vv v0, v20, v16 +; CHECK-NEXT: ret + %vc = fcmp ugt %va, %vb + ret %vc +} + +define @fcmp_ugt_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_ugt_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %va, %splat + ret %vc +} + +define @fcmp_uge_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_uge_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vv v25, v16, v20 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp uge %va, %vb + ret %vc +} + +define @fcmp_uge_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_uge_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %va, %splat + ret %vc +} + +define @fcmp_uge_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_uge_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfgt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %splat, %va + ret %vc +} + +define @fcmp_uge_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_uge_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vv v0, v20, v16 +; CHECK-NEXT: ret + %vc = fcmp uge %va, %vb + ret %vc +} + +define @fcmp_uge_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_uge_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %va, %splat + ret %vc +} + +define @fcmp_ult_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_ult_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vv v25, v20, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ult %va, %vb + ret %vc +} + +define @fcmp_ult_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ult_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfge.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %va, %splat + ret %vc +} + +define @fcmp_ult_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ult_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %splat, %va + ret %vc +} + +define @fcmp_ult_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ult_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp ult %va, %vb + ret %vc +} + +define @fcmp_ult_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_ult_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %va, %splat + ret %vc +} + +define @fcmp_ule_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_ule_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vv v25, v20, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ule %va, %vb + ret %vc +} + +define @fcmp_ule_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ule_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfgt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %va, %splat + ret %vc +} + +define @fcmp_ule_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ule_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %splat, %va + ret %vc +} + +define @fcmp_ule_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ule_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp ule %va, %vb + ret %vc +} + +define @fcmp_ule_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_ule_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %va, %splat + ret %vc +} + +define @fcmp_une_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_une_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp une %va, %vb + ret %vc +} + +define @fcmp_une_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_une_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %va, %splat + ret %vc +} + +define @fcmp_une_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_une_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %splat, %va + ret %vc +} + +define @fcmp_une_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_une_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp une %va, %vb + ret %vc +} + +define @fcmp_une_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_une_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %va, %splat + ret %vc +} + +define @fcmp_uno_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_uno_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vv v25, v20, v20 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %vc = fcmp uno %va, %vb + ret %vc +} + +define @fcmp_uno_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_uno_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfne.vf v25, v28, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %va, %splat + ret %vc +} + +define @fcmp_uno_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_uno_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfne.vf v25, v28, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %splat, %va + ret %vc +} + +define @fcmp_uno_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_uno_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vv v25, v20, v20 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %vc = fcmp uno %va, %vb + ret %vc +} + +define @fcmp_uno_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_uno_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfne.vf v25, v28, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %va, %splat + ret %vc +} + +define @fcmp_oeq_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_oeq_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfeq.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp oeq %va, %vb + ret %vc +} + +define @fcmp_oeq_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_oeq_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %va, %splat + ret %vc +} + +define @fcmp_oeq_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_oeq_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %splat, %va + ret %vc +} + +define @fcmp_oeq_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_oeq_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfeq.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp oeq %va, %vb + ret %vc +} + +define @fcmp_oeq_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_oeq_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %va, %splat + ret %vc +} + +define @fcmp_ogt_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_ogt_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmflt.vv v0, v8, v16 +; CHECK-NEXT: ret + %vc = fcmp ogt %va, %vb + ret %vc +} + +define @fcmp_ogt_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ogt_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %va, %splat + ret %vc +} + +define @fcmp_ogt_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ogt_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %splat, %va + ret %vc +} + +define @fcmp_ogt_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ogt_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmflt.vv v0, v8, v16 +; CHECK-NEXT: ret + %vc = fcmp ogt %va, %vb + ret %vc +} + +define @fcmp_ogt_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_ogt_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %va, %splat + ret %vc +} + +define @fcmp_oge_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_oge_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfle.vv v0, v8, v16 +; CHECK-NEXT: ret + %vc = fcmp oge %va, %vb + ret %vc +} + +define @fcmp_oge_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_oge_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %va, %splat + ret %vc +} + +define @fcmp_oge_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_oge_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %splat, %va + ret %vc +} + +define @fcmp_oge_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_oge_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfle.vv v0, v8, v16 +; CHECK-NEXT: ret + %vc = fcmp oge %va, %vb + ret %vc +} + +define @fcmp_oge_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_oge_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %va, %splat + ret %vc +} + +define @fcmp_olt_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_olt_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmflt.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp olt %va, %vb + ret %vc +} + +define @fcmp_olt_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_olt_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %va, %splat + ret %vc +} + +define @fcmp_olt_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_olt_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %splat, %va + ret %vc +} + +define @fcmp_olt_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_olt_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmflt.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp olt %va, %vb + ret %vc +} + +define @fcmp_olt_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_olt_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %va, %splat + ret %vc +} + +define @fcmp_ole_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_ole_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfle.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp ole %va, %vb + ret %vc +} + +define @fcmp_ole_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ole_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %va, %splat + ret %vc +} + +define @fcmp_ole_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ole_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %splat, %va + ret %vc +} + +define @fcmp_ole_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ole_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfle.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp ole %va, %vb + ret %vc +} + +define @fcmp_ole_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_ole_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %va, %splat + ret %vc +} + +define @fcmp_one_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_one_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v25, v16, v8 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vmfeq.vv v27, v8, v8 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v26, v27 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp one %va, %vb + ret %vc +} + +define @fcmp_one_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_one_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfne.vf v25, v16, fa0 +; CHECK-NEXT: vmfeq.vf v26, v8, fa0 +; CHECK-NEXT: vmfeq.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v27, v26 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %va, %splat + ret %vc +} + +define @fcmp_one_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_one_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfne.vf v25, v16, fa0 +; CHECK-NEXT: vmfeq.vf v26, v8, fa0 +; CHECK-NEXT: vmfeq.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v26, v27 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %splat, %va + ret %vc +} + +define @fcmp_one_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_one_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp one %va, %vb + ret %vc +} + +define @fcmp_one_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_one_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %va, %splat + ret %vc +} + +define @fcmp_ord_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_ord_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfeq.vv v25, v16, v16 +; CHECK-NEXT: vmfeq.vv v26, v8, v8 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ord %va, %vb + ret %vc +} + +define @fcmp_ord_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ord_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfeq.vf v25, v8, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %va, %splat + ret %vc +} + +define @fcmp_ord_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ord_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfeq.vf v25, v8, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %splat, %va + ret %vc +} + +define @fcmp_ord_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ord_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfeq.vv v25, v16, v16 +; CHECK-NEXT: vmfeq.vv v26, v8, v8 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ord %va, %vb + ret %vc +} + +define @fcmp_ord_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_ord_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfeq.vf v25, v8, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %va, %splat + ret %vc +} + +define @fcmp_ueq_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_ueq_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfeq.vv v25, v16, v8 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vmfne.vv v27, v8, v8 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v26, v27 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ueq %va, %vb + ret %vc +} + +define @fcmp_ueq_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ueq_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfeq.vf v25, v16, fa0 +; CHECK-NEXT: vmfne.vf v26, v8, fa0 +; CHECK-NEXT: vmfne.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v27, v26 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %va, %splat + ret %vc +} + +define @fcmp_ueq_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ueq_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfeq.vf v25, v16, fa0 +; CHECK-NEXT: vmfne.vf v26, v8, fa0 +; CHECK-NEXT: vmfne.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v26, v27 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %splat, %va + ret %vc +} + +define @fcmp_ueq_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ueq_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfeq.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp ueq %va, %vb + ret %vc +} + +define @fcmp_ueq_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_ueq_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %va, %splat + ret %vc +} + +define @fcmp_ugt_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_ugt_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfle.vv v25, v16, v8 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ugt %va, %vb + ret %vc +} + +define @fcmp_ugt_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ugt_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfle.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %va, %splat + ret %vc +} + +define @fcmp_ugt_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ugt_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfge.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %splat, %va + ret %vc +} + +define @fcmp_ugt_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ugt_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmflt.vv v0, v8, v16 +; CHECK-NEXT: ret + %vc = fcmp ugt %va, %vb + ret %vc +} + +define @fcmp_ugt_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_ugt_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %va, %splat + ret %vc +} + +define @fcmp_uge_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_uge_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmflt.vv v25, v16, v8 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp uge %va, %vb + ret %vc +} + +define @fcmp_uge_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_uge_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmflt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %va, %splat + ret %vc +} + +define @fcmp_uge_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_uge_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfgt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %splat, %va + ret %vc +} + +define @fcmp_uge_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_uge_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfle.vv v0, v8, v16 +; CHECK-NEXT: ret + %vc = fcmp uge %va, %vb + ret %vc +} + +define @fcmp_uge_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_uge_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %va, %splat + ret %vc +} + +define @fcmp_ult_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_ult_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfle.vv v25, v8, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ult %va, %vb + ret %vc +} + +define @fcmp_ult_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ult_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfge.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %va, %splat + ret %vc +} + +define @fcmp_ult_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ult_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfle.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %splat, %va + ret %vc +} + +define @fcmp_ult_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ult_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmflt.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp ult %va, %vb + ret %vc +} + +define @fcmp_ult_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_ult_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %va, %splat + ret %vc +} + +define @fcmp_ule_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_ule_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmflt.vv v25, v8, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ule %va, %vb + ret %vc +} + +define @fcmp_ule_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ule_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfgt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %va, %splat + ret %vc +} + +define @fcmp_ule_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ule_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmflt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %splat, %va + ret %vc +} + +define @fcmp_ule_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ule_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfle.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp ule %va, %vb + ret %vc +} + +define @fcmp_ule_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_ule_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %va, %splat + ret %vc +} + +define @fcmp_une_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_une_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp une %va, %vb + ret %vc +} + +define @fcmp_une_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_une_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %va, %splat + ret %vc +} + +define @fcmp_une_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_une_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %splat, %va + ret %vc +} + +define @fcmp_une_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_une_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp une %va, %vb + ret %vc +} + +define @fcmp_une_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_une_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %va, %splat + ret %vc +} + +define @fcmp_uno_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_uno_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v25, v16, v16 +; CHECK-NEXT: vmfne.vv v26, v8, v8 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp uno %va, %vb + ret %vc +} + +define @fcmp_uno_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_uno_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfne.vf v25, v8, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %va, %splat + ret %vc +} + +define @fcmp_uno_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_uno_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfne.vf v25, v8, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %splat, %va + ret %vc +} + +define @fcmp_uno_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_uno_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v25, v16, v16 +; CHECK-NEXT: vmfne.vv v26, v8, v8 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp uno %va, %vb + ret %vc +} + +define @fcmp_uno_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_uno_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfne.vf v25, v8, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %va, %splat + ret %vc +} + +attributes #0 = { "no-nans-fp-math"="true" } diff --git a/llvm/test/CodeGen/RISCV/rvv/setcc-fp-rv64.ll b/llvm/test/CodeGen/RISCV/rvv/setcc-fp-rv64.ll new file mode 100644 index 00000000000000..0129169fa93de0 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/setcc-fp-rv64.ll @@ -0,0 +1,2748 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv64 -mattr=+d,+experimental-zfh,+experimental-v -target-abi=lp64d \ +; RUN: -verify-machineinstrs < %s | FileCheck %s + +; FIXME: The scalar/vector operations ('fv' tests) should swap operands and +; condition codes accordingly in order to generate a 'vf' instruction. + +define @fcmp_oeq_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_oeq_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp oeq %va, %vb + ret %vc +} + +define @fcmp_oeq_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_oeq_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %va, %splat + ret %vc +} + +define @fcmp_oeq_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_oeq_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %splat, %va + ret %vc +} + +define @fcmp_oeq_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_oeq_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp oeq %va, %vb + ret %vc +} + +define @fcmp_oeq_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_oeq_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %va, %splat + ret %vc +} + +define @fcmp_ogt_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_ogt_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vv v0, v18, v16 +; CHECK-NEXT: ret + %vc = fcmp ogt %va, %vb + ret %vc +} + +define @fcmp_ogt_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ogt_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %va, %splat + ret %vc +} + +define @fcmp_ogt_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ogt_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %splat, %va + ret %vc +} + +define @fcmp_ogt_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ogt_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vv v0, v18, v16 +; CHECK-NEXT: ret + %vc = fcmp ogt %va, %vb + ret %vc +} + +define @fcmp_ogt_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_ogt_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %va, %splat + ret %vc +} + +define @fcmp_oge_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_oge_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vv v0, v18, v16 +; CHECK-NEXT: ret + %vc = fcmp oge %va, %vb + ret %vc +} + +define @fcmp_oge_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_oge_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %va, %splat + ret %vc +} + +define @fcmp_oge_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_oge_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %splat, %va + ret %vc +} + +define @fcmp_oge_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_oge_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vv v0, v18, v16 +; CHECK-NEXT: ret + %vc = fcmp oge %va, %vb + ret %vc +} + +define @fcmp_oge_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_oge_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %va, %splat + ret %vc +} + +define @fcmp_olt_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_olt_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp olt %va, %vb + ret %vc +} + +define @fcmp_olt_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_olt_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %va, %splat + ret %vc +} + +define @fcmp_olt_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_olt_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %splat, %va + ret %vc +} + +define @fcmp_olt_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_olt_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp olt %va, %vb + ret %vc +} + +define @fcmp_olt_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_olt_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %va, %splat + ret %vc +} + +define @fcmp_ole_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_ole_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp ole %va, %vb + ret %vc +} + +define @fcmp_ole_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ole_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %va, %splat + ret %vc +} + +define @fcmp_ole_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ole_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %splat, %va + ret %vc +} + +define @fcmp_ole_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ole_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp ole %va, %vb + ret %vc +} + +define @fcmp_ole_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_ole_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %va, %splat + ret %vc +} + +define @fcmp_one_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_one_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vv v25, v16, v18 +; CHECK-NEXT: vmfeq.vv v26, v18, v18 +; CHECK-NEXT: vmfeq.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v27, v26 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp one %va, %vb + ret %vc +} + +define @fcmp_one_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_one_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfne.vf v25, v16, fa0 +; CHECK-NEXT: vmfeq.vf v28, v26, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v26, v28 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %va, %splat + ret %vc +} + +define @fcmp_one_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_one_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfne.vf v25, v16, fa0 +; CHECK-NEXT: vmfeq.vf v28, v26, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v28, v26 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %splat, %va + ret %vc +} + +define @fcmp_one_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_one_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp one %va, %vb + ret %vc +} + +define @fcmp_one_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_one_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %va, %splat + ret %vc +} + +define @fcmp_ord_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_ord_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vv v25, v18, v18 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %vc = fcmp ord %va, %vb + ret %vc +} + +define @fcmp_ord_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ord_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfeq.vf v25, v26, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %va, %splat + ret %vc +} + +define @fcmp_ord_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ord_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfeq.vf v25, v26, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %splat, %va + ret %vc +} + +define @fcmp_ord_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ord_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vv v25, v18, v18 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %vc = fcmp ord %va, %vb + ret %vc +} + +define @fcmp_ord_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_ord_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfeq.vf v25, v26, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %va, %splat + ret %vc +} + +define @fcmp_ueq_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_ueq_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vv v25, v16, v18 +; CHECK-NEXT: vmfne.vv v26, v18, v18 +; CHECK-NEXT: vmfne.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v27, v26 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ueq %va, %vb + ret %vc +} + +define @fcmp_ueq_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ueq_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfeq.vf v25, v16, fa0 +; CHECK-NEXT: vmfne.vf v28, v26, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v26, v28 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %va, %splat + ret %vc +} + +define @fcmp_ueq_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ueq_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfeq.vf v25, v16, fa0 +; CHECK-NEXT: vmfne.vf v28, v26, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v28, v26 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %splat, %va + ret %vc +} + +define @fcmp_ueq_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ueq_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp ueq %va, %vb + ret %vc +} + +define @fcmp_ueq_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_ueq_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %va, %splat + ret %vc +} + +define @fcmp_ugt_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_ugt_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vv v25, v16, v18 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ugt %va, %vb + ret %vc +} + +define @fcmp_ugt_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ugt_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %va, %splat + ret %vc +} + +define @fcmp_ugt_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ugt_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfge.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %splat, %va + ret %vc +} + +define @fcmp_ugt_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ugt_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vv v0, v18, v16 +; CHECK-NEXT: ret + %vc = fcmp ugt %va, %vb + ret %vc +} + +define @fcmp_ugt_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_ugt_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %va, %splat + ret %vc +} + +define @fcmp_uge_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_uge_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vv v25, v16, v18 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp uge %va, %vb + ret %vc +} + +define @fcmp_uge_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_uge_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %va, %splat + ret %vc +} + +define @fcmp_uge_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_uge_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfgt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %splat, %va + ret %vc +} + +define @fcmp_uge_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_uge_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vv v0, v18, v16 +; CHECK-NEXT: ret + %vc = fcmp uge %va, %vb + ret %vc +} + +define @fcmp_uge_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_uge_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %va, %splat + ret %vc +} + +define @fcmp_ult_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_ult_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vv v25, v18, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ult %va, %vb + ret %vc +} + +define @fcmp_ult_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ult_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfge.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %va, %splat + ret %vc +} + +define @fcmp_ult_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ult_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %splat, %va + ret %vc +} + +define @fcmp_ult_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ult_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp ult %va, %vb + ret %vc +} + +define @fcmp_ult_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_ult_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %va, %splat + ret %vc +} + +define @fcmp_ule_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_ule_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vv v25, v18, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ule %va, %vb + ret %vc +} + +define @fcmp_ule_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ule_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfgt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %va, %splat + ret %vc +} + +define @fcmp_ule_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_ule_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmflt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %splat, %va + ret %vc +} + +define @fcmp_ule_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ule_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp ule %va, %vb + ret %vc +} + +define @fcmp_ule_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_ule_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %va, %splat + ret %vc +} + +define @fcmp_une_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_une_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp une %va, %vb + ret %vc +} + +define @fcmp_une_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_une_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %va, %splat + ret %vc +} + +define @fcmp_une_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_une_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %splat, %va + ret %vc +} + +define @fcmp_une_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_une_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vv v0, v16, v18 +; CHECK-NEXT: ret + %vc = fcmp une %va, %vb + ret %vc +} + +define @fcmp_une_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_une_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %va, %splat + ret %vc +} + +define @fcmp_uno_vv_nxv8f16( %va, %vb) { +; CHECK-LABEL: fcmp_uno_vv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vv v25, v18, v18 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %vc = fcmp uno %va, %vb + ret %vc +} + +define @fcmp_uno_vf_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_uno_vf_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfne.vf v25, v26, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %va, %splat + ret %vc +} + +define @fcmp_uno_fv_nxv8f16( %va, half %b) { +; CHECK-LABEL: fcmp_uno_fv_nxv8f16: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfne.vf v25, v26, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %splat, %va + ret %vc +} + +define @fcmp_uno_vv_nxv8f16_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_uno_vv_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vmfne.vv v25, v18, v18 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %vc = fcmp uno %va, %vb + ret %vc +} + +define @fcmp_uno_vf_nxv8f16_nonans( %va, half %b) #0 { +; CHECK-LABEL: fcmp_uno_vf_nxv8f16_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; CHECK-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; CHECK-NEXT: vfmv.v.f v26, fa0 +; CHECK-NEXT: vmfne.vf v25, v26, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, half %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %va, %splat + ret %vc +} + +define @fcmp_oeq_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_oeq_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp oeq %va, %vb + ret %vc +} + +define @fcmp_oeq_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_oeq_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %va, %splat + ret %vc +} + +define @fcmp_oeq_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_oeq_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %splat, %va + ret %vc +} + +define @fcmp_oeq_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_oeq_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp oeq %va, %vb + ret %vc +} + +define @fcmp_oeq_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_oeq_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %va, %splat + ret %vc +} + +define @fcmp_ogt_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_ogt_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vv v0, v20, v16 +; CHECK-NEXT: ret + %vc = fcmp ogt %va, %vb + ret %vc +} + +define @fcmp_ogt_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ogt_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %va, %splat + ret %vc +} + +define @fcmp_ogt_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ogt_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %splat, %va + ret %vc +} + +define @fcmp_ogt_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ogt_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vv v0, v20, v16 +; CHECK-NEXT: ret + %vc = fcmp ogt %va, %vb + ret %vc +} + +define @fcmp_ogt_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_ogt_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %va, %splat + ret %vc +} + +define @fcmp_oge_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_oge_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vv v0, v20, v16 +; CHECK-NEXT: ret + %vc = fcmp oge %va, %vb + ret %vc +} + +define @fcmp_oge_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_oge_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %va, %splat + ret %vc +} + +define @fcmp_oge_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_oge_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %splat, %va + ret %vc +} + +define @fcmp_oge_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_oge_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vv v0, v20, v16 +; CHECK-NEXT: ret + %vc = fcmp oge %va, %vb + ret %vc +} + +define @fcmp_oge_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_oge_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %va, %splat + ret %vc +} + +define @fcmp_olt_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_olt_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp olt %va, %vb + ret %vc +} + +define @fcmp_olt_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_olt_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %va, %splat + ret %vc +} + +define @fcmp_olt_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_olt_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %splat, %va + ret %vc +} + +define @fcmp_olt_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_olt_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp olt %va, %vb + ret %vc +} + +define @fcmp_olt_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_olt_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %va, %splat + ret %vc +} + +define @fcmp_ole_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_ole_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp ole %va, %vb + ret %vc +} + +define @fcmp_ole_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ole_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %va, %splat + ret %vc +} + +define @fcmp_ole_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ole_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %splat, %va + ret %vc +} + +define @fcmp_ole_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ole_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp ole %va, %vb + ret %vc +} + +define @fcmp_ole_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_ole_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %va, %splat + ret %vc +} + +define @fcmp_one_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_one_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vv v25, v16, v20 +; CHECK-NEXT: vmfeq.vv v26, v20, v20 +; CHECK-NEXT: vmfeq.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v27, v26 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp one %va, %vb + ret %vc +} + +define @fcmp_one_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_one_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfne.vf v25, v16, fa0 +; CHECK-NEXT: vmfeq.vf v26, v28, fa0 +; CHECK-NEXT: vmfeq.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v27, v26 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %va, %splat + ret %vc +} + +define @fcmp_one_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_one_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfne.vf v25, v16, fa0 +; CHECK-NEXT: vmfeq.vf v26, v28, fa0 +; CHECK-NEXT: vmfeq.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v26, v27 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %splat, %va + ret %vc +} + +define @fcmp_one_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_one_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp one %va, %vb + ret %vc +} + +define @fcmp_one_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_one_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %va, %splat + ret %vc +} + +define @fcmp_ord_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_ord_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vv v25, v20, v20 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %vc = fcmp ord %va, %vb + ret %vc +} + +define @fcmp_ord_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ord_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfeq.vf v25, v28, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %va, %splat + ret %vc +} + +define @fcmp_ord_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ord_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfeq.vf v25, v28, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %splat, %va + ret %vc +} + +define @fcmp_ord_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ord_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vv v25, v20, v20 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %vc = fcmp ord %va, %vb + ret %vc +} + +define @fcmp_ord_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_ord_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfeq.vf v25, v28, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %va, %splat + ret %vc +} + +define @fcmp_ueq_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_ueq_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vv v25, v16, v20 +; CHECK-NEXT: vmfne.vv v26, v20, v20 +; CHECK-NEXT: vmfne.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v27, v26 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ueq %va, %vb + ret %vc +} + +define @fcmp_ueq_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ueq_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfeq.vf v25, v16, fa0 +; CHECK-NEXT: vmfne.vf v26, v28, fa0 +; CHECK-NEXT: vmfne.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v27, v26 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %va, %splat + ret %vc +} + +define @fcmp_ueq_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ueq_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfeq.vf v25, v16, fa0 +; CHECK-NEXT: vmfne.vf v26, v28, fa0 +; CHECK-NEXT: vmfne.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v26, v27 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %splat, %va + ret %vc +} + +define @fcmp_ueq_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ueq_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp ueq %va, %vb + ret %vc +} + +define @fcmp_ueq_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_ueq_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %va, %splat + ret %vc +} + +define @fcmp_ugt_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_ugt_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vv v25, v16, v20 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ugt %va, %vb + ret %vc +} + +define @fcmp_ugt_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ugt_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %va, %splat + ret %vc +} + +define @fcmp_ugt_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ugt_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfge.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %splat, %va + ret %vc +} + +define @fcmp_ugt_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ugt_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vv v0, v20, v16 +; CHECK-NEXT: ret + %vc = fcmp ugt %va, %vb + ret %vc +} + +define @fcmp_ugt_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_ugt_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %va, %splat + ret %vc +} + +define @fcmp_uge_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_uge_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vv v25, v16, v20 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp uge %va, %vb + ret %vc +} + +define @fcmp_uge_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_uge_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %va, %splat + ret %vc +} + +define @fcmp_uge_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_uge_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfgt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %splat, %va + ret %vc +} + +define @fcmp_uge_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_uge_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vv v0, v20, v16 +; CHECK-NEXT: ret + %vc = fcmp uge %va, %vb + ret %vc +} + +define @fcmp_uge_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_uge_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %va, %splat + ret %vc +} + +define @fcmp_ult_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_ult_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vv v25, v20, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ult %va, %vb + ret %vc +} + +define @fcmp_ult_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ult_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfge.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %va, %splat + ret %vc +} + +define @fcmp_ult_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ult_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %splat, %va + ret %vc +} + +define @fcmp_ult_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ult_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp ult %va, %vb + ret %vc +} + +define @fcmp_ult_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_ult_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %va, %splat + ret %vc +} + +define @fcmp_ule_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_ule_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vv v25, v20, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ule %va, %vb + ret %vc +} + +define @fcmp_ule_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ule_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfgt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %va, %splat + ret %vc +} + +define @fcmp_ule_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_ule_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmflt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %splat, %va + ret %vc +} + +define @fcmp_ule_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ule_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp ule %va, %vb + ret %vc +} + +define @fcmp_ule_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_ule_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %va, %splat + ret %vc +} + +define @fcmp_une_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_une_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp une %va, %vb + ret %vc +} + +define @fcmp_une_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_une_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %va, %splat + ret %vc +} + +define @fcmp_une_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_une_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %splat, %va + ret %vc +} + +define @fcmp_une_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_une_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vv v0, v16, v20 +; CHECK-NEXT: ret + %vc = fcmp une %va, %vb + ret %vc +} + +define @fcmp_une_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_une_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %va, %splat + ret %vc +} + +define @fcmp_uno_vv_nxv8f32( %va, %vb) { +; CHECK-LABEL: fcmp_uno_vv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vv v25, v20, v20 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %vc = fcmp uno %va, %vb + ret %vc +} + +define @fcmp_uno_vf_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_uno_vf_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfne.vf v25, v28, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %va, %splat + ret %vc +} + +define @fcmp_uno_fv_nxv8f32( %va, float %b) { +; CHECK-LABEL: fcmp_uno_fv_nxv8f32: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfne.vf v25, v28, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %splat, %va + ret %vc +} + +define @fcmp_uno_vv_nxv8f32_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_uno_vv_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vmfne.vv v25, v20, v20 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %vc = fcmp uno %va, %vb + ret %vc +} + +define @fcmp_uno_vf_nxv8f32_nonans( %va, float %b) #0 { +; CHECK-LABEL: fcmp_uno_vf_nxv8f32_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; CHECK-NEXT: vfmv.v.f v28, fa0 +; CHECK-NEXT: vmfne.vf v25, v28, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, float %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %va, %splat + ret %vc +} + +define @fcmp_oeq_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_oeq_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfeq.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp oeq %va, %vb + ret %vc +} + +define @fcmp_oeq_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_oeq_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %va, %splat + ret %vc +} + +define @fcmp_oeq_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_oeq_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %splat, %va + ret %vc +} + +define @fcmp_oeq_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_oeq_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfeq.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp oeq %va, %vb + ret %vc +} + +define @fcmp_oeq_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_oeq_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oeq %va, %splat + ret %vc +} + +define @fcmp_ogt_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_ogt_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmflt.vv v0, v8, v16 +; CHECK-NEXT: ret + %vc = fcmp ogt %va, %vb + ret %vc +} + +define @fcmp_ogt_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ogt_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %va, %splat + ret %vc +} + +define @fcmp_ogt_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ogt_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %splat, %va + ret %vc +} + +define @fcmp_ogt_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ogt_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmflt.vv v0, v8, v16 +; CHECK-NEXT: ret + %vc = fcmp ogt %va, %vb + ret %vc +} + +define @fcmp_ogt_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_ogt_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ogt %va, %splat + ret %vc +} + +define @fcmp_oge_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_oge_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfle.vv v0, v8, v16 +; CHECK-NEXT: ret + %vc = fcmp oge %va, %vb + ret %vc +} + +define @fcmp_oge_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_oge_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %va, %splat + ret %vc +} + +define @fcmp_oge_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_oge_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %splat, %va + ret %vc +} + +define @fcmp_oge_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_oge_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfle.vv v0, v8, v16 +; CHECK-NEXT: ret + %vc = fcmp oge %va, %vb + ret %vc +} + +define @fcmp_oge_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_oge_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp oge %va, %splat + ret %vc +} + +define @fcmp_olt_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_olt_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmflt.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp olt %va, %vb + ret %vc +} + +define @fcmp_olt_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_olt_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %va, %splat + ret %vc +} + +define @fcmp_olt_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_olt_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %splat, %va + ret %vc +} + +define @fcmp_olt_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_olt_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmflt.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp olt %va, %vb + ret %vc +} + +define @fcmp_olt_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_olt_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp olt %va, %splat + ret %vc +} + +define @fcmp_ole_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_ole_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfle.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp ole %va, %vb + ret %vc +} + +define @fcmp_ole_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ole_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %va, %splat + ret %vc +} + +define @fcmp_ole_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ole_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %splat, %va + ret %vc +} + +define @fcmp_ole_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ole_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfle.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp ole %va, %vb + ret %vc +} + +define @fcmp_ole_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_ole_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ole %va, %splat + ret %vc +} + +define @fcmp_one_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_one_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v25, v16, v8 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vmfeq.vv v27, v8, v8 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v26, v27 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp one %va, %vb + ret %vc +} + +define @fcmp_one_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_one_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfne.vf v25, v16, fa0 +; CHECK-NEXT: vmfeq.vf v26, v8, fa0 +; CHECK-NEXT: vmfeq.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v27, v26 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %va, %splat + ret %vc +} + +define @fcmp_one_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_one_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfne.vf v25, v16, fa0 +; CHECK-NEXT: vmfeq.vf v26, v8, fa0 +; CHECK-NEXT: vmfeq.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v26, v26, v27 +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %splat, %va + ret %vc +} + +define @fcmp_one_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_one_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp one %va, %vb + ret %vc +} + +define @fcmp_one_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_one_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp one %va, %splat + ret %vc +} + +define @fcmp_ord_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_ord_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfeq.vv v25, v16, v16 +; CHECK-NEXT: vmfeq.vv v26, v8, v8 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ord %va, %vb + ret %vc +} + +define @fcmp_ord_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ord_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfeq.vf v25, v8, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %va, %splat + ret %vc +} + +define @fcmp_ord_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ord_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfeq.vf v25, v8, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %splat, %va + ret %vc +} + +define @fcmp_ord_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ord_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfeq.vv v25, v16, v16 +; CHECK-NEXT: vmfeq.vv v26, v8, v8 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ord %va, %vb + ret %vc +} + +define @fcmp_ord_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_ord_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfeq.vf v25, v8, fa0 +; CHECK-NEXT: vmfeq.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmand.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ord %va, %splat + ret %vc +} + +define @fcmp_ueq_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_ueq_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfeq.vv v25, v16, v8 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vmfne.vv v27, v8, v8 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v26, v27 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ueq %va, %vb + ret %vc +} + +define @fcmp_ueq_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ueq_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfeq.vf v25, v16, fa0 +; CHECK-NEXT: vmfne.vf v26, v8, fa0 +; CHECK-NEXT: vmfne.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v27, v26 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %va, %splat + ret %vc +} + +define @fcmp_ueq_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ueq_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfeq.vf v25, v16, fa0 +; CHECK-NEXT: vmfne.vf v26, v8, fa0 +; CHECK-NEXT: vmfne.vv v27, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v26, v26, v27 +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %splat, %va + ret %vc +} + +define @fcmp_ueq_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ueq_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfeq.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp ueq %va, %vb + ret %vc +} + +define @fcmp_ueq_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_ueq_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfeq.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ueq %va, %splat + ret %vc +} + +define @fcmp_ugt_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_ugt_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfle.vv v25, v16, v8 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ugt %va, %vb + ret %vc +} + +define @fcmp_ugt_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ugt_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfle.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %va, %splat + ret %vc +} + +define @fcmp_ugt_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ugt_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfge.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %splat, %va + ret %vc +} + +define @fcmp_ugt_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ugt_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmflt.vv v0, v8, v16 +; CHECK-NEXT: ret + %vc = fcmp ugt %va, %vb + ret %vc +} + +define @fcmp_ugt_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_ugt_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfgt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ugt %va, %splat + ret %vc +} + +define @fcmp_uge_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_uge_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmflt.vv v25, v16, v8 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp uge %va, %vb + ret %vc +} + +define @fcmp_uge_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_uge_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmflt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %va, %splat + ret %vc +} + +define @fcmp_uge_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_uge_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfgt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %splat, %va + ret %vc +} + +define @fcmp_uge_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_uge_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfle.vv v0, v8, v16 +; CHECK-NEXT: ret + %vc = fcmp uge %va, %vb + ret %vc +} + +define @fcmp_uge_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_uge_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfge.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uge %va, %splat + ret %vc +} + +define @fcmp_ult_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_ult_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfle.vv v25, v8, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ult %va, %vb + ret %vc +} + +define @fcmp_ult_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ult_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfge.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %va, %splat + ret %vc +} + +define @fcmp_ult_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ult_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfle.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %splat, %va + ret %vc +} + +define @fcmp_ult_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ult_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmflt.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp ult %va, %vb + ret %vc +} + +define @fcmp_ult_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_ult_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmflt.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ult %va, %splat + ret %vc +} + +define @fcmp_ule_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_ule_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmflt.vv v25, v8, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp ule %va, %vb + ret %vc +} + +define @fcmp_ule_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ule_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfgt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %va, %splat + ret %vc +} + +define @fcmp_ule_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_ule_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmflt.vf v25, v16, fa0 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmset.m v26 +; CHECK-NEXT: vmxor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %splat, %va + ret %vc +} + +define @fcmp_ule_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_ule_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfle.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp ule %va, %vb + ret %vc +} + +define @fcmp_ule_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_ule_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfle.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp ule %va, %splat + ret %vc +} + +define @fcmp_une_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_une_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp une %va, %vb + ret %vc +} + +define @fcmp_une_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_une_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %va, %splat + ret %vc +} + +define @fcmp_une_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_une_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %splat, %va + ret %vc +} + +define @fcmp_une_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_une_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v0, v16, v8 +; CHECK-NEXT: ret + %vc = fcmp une %va, %vb + ret %vc +} + +define @fcmp_une_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_une_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vmfne.vf v0, v16, fa0 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp une %va, %splat + ret %vc +} + +define @fcmp_uno_vv_nxv8f64( %va, %vb) { +; CHECK-LABEL: fcmp_uno_vv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v25, v16, v16 +; CHECK-NEXT: vmfne.vv v26, v8, v8 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp uno %va, %vb + ret %vc +} + +define @fcmp_uno_vf_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_uno_vf_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfne.vf v25, v8, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %va, %splat + ret %vc +} + +define @fcmp_uno_fv_nxv8f64( %va, double %b) { +; CHECK-LABEL: fcmp_uno_fv_nxv8f64: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfne.vf v25, v8, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %splat, %va + ret %vc +} + +define @fcmp_uno_vv_nxv8f64_nonans( %va, %vb) #0 { +; CHECK-LABEL: fcmp_uno_vv_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; CHECK-NEXT: vle64.v v8, (a0) +; CHECK-NEXT: vmfne.vv v25, v16, v16 +; CHECK-NEXT: vmfne.vv v26, v8, v8 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v25, v26 +; CHECK-NEXT: ret + %vc = fcmp uno %va, %vb + ret %vc +} + +define @fcmp_uno_vf_nxv8f64_nonans( %va, double %b) #0 { +; CHECK-LABEL: fcmp_uno_vf_nxv8f64_nonans: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vfmv.v.f v8, fa0 +; CHECK-NEXT: vmfne.vf v25, v8, fa0 +; CHECK-NEXT: vmfne.vv v26, v16, v16 +; CHECK-NEXT: vsetvli a0, zero, e8,m1,ta,mu +; CHECK-NEXT: vmor.mm v0, v26, v25 +; CHECK-NEXT: ret + %head = insertelement undef, double %b, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vc = fcmp uno %va, %splat + ret %vc +} + +attributes #0 = { "no-nans-fp-math"="true" } diff --git a/llvm/test/CodeGen/RISCV/rvv/vsplats-fp.ll b/llvm/test/CodeGen/RISCV/rvv/vsplats-fp.ll new file mode 100644 index 00000000000000..72d1c85de17052 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/vsplats-fp.ll @@ -0,0 +1,109 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+f,+d,+experimental-zfh,+experimental-v -target-abi ilp32d -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefix=RV32V +; RUN: llc -mtriple=riscv64 -mattr=+f,+d,+experimental-zfh,+experimental-v -target-abi lp64d -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefix=RV64V + +define @vsplat_nxv8f16(half %f) { +; RV32V-LABEL: vsplat_nxv8f16: +; RV32V: # %bb.0: +; RV32V-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; RV32V-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; RV32V-NEXT: vfmv.v.f v16, fa0 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vsplat_nxv8f16: +; RV64V: # %bb.0: +; RV64V-NEXT: # kill: def $f10_h killed $f10_h def $f10_f +; RV64V-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; RV64V-NEXT: vfmv.v.f v16, fa0 +; RV64V-NEXT: ret + %head = insertelement undef, half %f, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + ret %splat +} + +define @vsplat_zero_nxv8f16() { +; RV32V-LABEL: vsplat_zero_nxv8f16: +; RV32V: # %bb.0: +; RV32V-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; RV32V-NEXT: vmv.v.i v16, 0 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vsplat_zero_nxv8f16: +; RV64V: # %bb.0: +; RV64V-NEXT: vsetvli a0, zero, e16,m2,ta,mu +; RV64V-NEXT: vmv.v.i v16, 0 +; RV64V-NEXT: ret + %head = insertelement undef, half zeroinitializer, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + ret %splat +} + +define @vsplat_nxv8f32(float %f) { +; RV32V-LABEL: vsplat_nxv8f32: +; RV32V: # %bb.0: +; RV32V-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; RV32V-NEXT: vfmv.v.f v16, fa0 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vsplat_nxv8f32: +; RV64V: # %bb.0: +; RV64V-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; RV64V-NEXT: vfmv.v.f v16, fa0 +; RV64V-NEXT: ret + %head = insertelement undef, float %f, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + ret %splat +} + +define @vsplat_zero_nxv8f32() { +; RV32V-LABEL: vsplat_zero_nxv8f32: +; RV32V: # %bb.0: +; RV32V-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; RV32V-NEXT: vmv.v.i v16, 0 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vsplat_zero_nxv8f32: +; RV64V: # %bb.0: +; RV64V-NEXT: vsetvli a0, zero, e32,m4,ta,mu +; RV64V-NEXT: vmv.v.i v16, 0 +; RV64V-NEXT: ret + %head = insertelement undef, float zeroinitializer, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + ret %splat +} + +define @vsplat_nxv8f64(double %f) { +; RV32V-LABEL: vsplat_nxv8f64: +; RV32V: # %bb.0: +; RV32V-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; RV32V-NEXT: vfmv.v.f v16, fa0 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vsplat_nxv8f64: +; RV64V: # %bb.0: +; RV64V-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; RV64V-NEXT: vfmv.v.f v16, fa0 +; RV64V-NEXT: ret + %head = insertelement undef, double %f, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + ret %splat +} + +define @vsplat_zero_nxv8f64() { +; RV32V-LABEL: vsplat_zero_nxv8f64: +; RV32V: # %bb.0: +; RV32V-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; RV32V-NEXT: vmv.v.i v16, 0 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vsplat_zero_nxv8f64: +; RV64V: # %bb.0: +; RV64V-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; RV64V-NEXT: vmv.v.i v16, 0 +; RV64V-NEXT: ret + %head = insertelement undef, double zeroinitializer, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + ret %splat +} diff --git a/llvm/test/CodeGen/X86/lit.local.cfg b/llvm/test/CodeGen/X86/lit.local.cfg index 20e38ef77e318b..c8625f4d9d2487 100644 --- a/llvm/test/CodeGen/X86/lit.local.cfg +++ b/llvm/test/CodeGen/X86/lit.local.cfg @@ -1,10 +1,2 @@ -from lit.llvm.subst import ToolSubst - if not 'X86' in config.root.targets: config.unsupported = True - -fc = ToolSubst('FileCheck', unresolved='fatal') -# Insert this first. Then, we'll first update the blank FileCheck command; then, -# the default substitution of FileCheck will replace it to its full path. -config.substitutions.insert(0, (fc.regex, - 'FileCheck --allow-unused-prefixes=false')) diff --git a/llvm/test/CodeGen/lit.local.cfg b/llvm/test/CodeGen/lit.local.cfg new file mode 100644 index 00000000000000..2499077fdcd715 --- /dev/null +++ b/llvm/test/CodeGen/lit.local.cfg @@ -0,0 +1,7 @@ +from lit.llvm.subst import ToolSubst + +fc = ToolSubst('FileCheck', unresolved='fatal') +# Insert this first. Then, we'll first update the blank FileCheck command; then, +# the default substitution of FileCheck will replace it to its full path. +config.substitutions.insert(0, (fc.regex, + 'FileCheck --allow-unused-prefixes=false')) diff --git a/llvm/test/Other/change-printer.ll b/llvm/test/Other/change-printer.ll index d05c151f48bd28..dff2ef45850fbe 100644 --- a/llvm/test/Other/change-printer.ll +++ b/llvm/test/Other/change-printer.ll @@ -5,6 +5,9 @@ ; Simple functionality check. ; RUN: opt -S -print-changed -passes=instsimplify 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-SIMPLE ; +; Simple functionality check. +; RUN: opt -S -print-changed= -passes=instsimplify 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-SIMPLE +; ; Check that only the passes that change the IR are printed and that the ; others (including g) are filtered out. ; RUN: opt -S -print-changed -passes=instsimplify -filter-print-funcs=f 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-FUNC-FILTER @@ -44,6 +47,53 @@ ; Check that the reporting of IRs with -print-before-changed respects -print-module-scope ; RUN: opt -S -print-changed -print-before-changed -passes=instsimplify -print-module-scope 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-PRINT-MOD-SCOPE-BEFORE ; +; Simple checks of -print-changed=quiet functionality +; +; Simple functionality check. +; RUN: opt -S -print-changed=quiet -passes=instsimplify 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-QUIET-SIMPLE +; +; Check that only the passes that change the IR are printed and that the +; others (including g) are filtered out. +; RUN: opt -S -print-changed=quiet -passes=instsimplify -filter-print-funcs=f 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-QUIET-FUNC-FILTER +; +; Check that the reporting of IRs respects -print-module-scope +; RUN: opt -S -print-changed=quiet -passes=instsimplify -print-module-scope 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-QUIET-PRINT-MOD-SCOPE +; +; Check that the reporting of IRs respects -print-module-scope +; RUN: opt -S -print-changed=quiet -passes=instsimplify -filter-print-funcs=f -print-module-scope 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-QUIET-FUNC-FILTER-MOD-SCOPE +; +; Check that reporting of multiple functions happens +; RUN: opt -S -print-changed=quiet -passes=instsimplify -filter-print-funcs="f,g" 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-QUIET-FILTER-MULT-FUNC +; +; Check that the reporting of IRs respects -filter-passes +; RUN: opt -S -print-changed=quiet -passes="instsimplify,no-op-function" -filter-passes="NoOpFunctionPass" 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-QUIET-FILTER-PASSES-NONE --allow-empty +; +; Check that the reporting of IRs respects -filter-passes with multiple passes +; RUN: opt -S -print-changed=quiet -passes="instsimplify" -filter-passes="NoOpFunctionPass,InstSimplifyPass" 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-QUIET-FILTER-PASSES +; +; Check that the reporting of IRs respects -filter-passes with multiple passes +; RUN: opt -S -print-changed=quiet -passes="instsimplify,no-op-function" -filter-passes="NoOpFunctionPass,InstSimplifyPass" 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-QUIET-FILTER-MULT-PASSES +; +; Check that the reporting of IRs respects both -filter-passes and -filter-print-funcs +; RUN: opt -S -print-changed=quiet -passes="instsimplify,no-op-function" -filter-passes="NoOpFunctionPass,InstSimplifyPass" -filter-print-funcs=f 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-QUIET-FILTER-FUNC-PASSES +; +; Check that the reporting of IRs respects -filter-passes, -filter-print-funcs and -print-module-scope +; RUN: opt -S -print-changed=quiet -passes="instsimplify,no-op-function" -filter-passes="NoOpFunctionPass,InstSimplifyPass" -filter-print-funcs=f -print-module-scope 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-QUIET-FILTER-FUNC-PASSES-MOD-SCOPE +; +; Check that repeated passes that change the IR are printed and that the +; others (including g) are filtered out. Note that the second time +; instsimplify is run on f, it does not change the IR +; RUN: opt -S -print-changed=quiet -passes="instsimplify,instsimplify" -filter-print-funcs=f 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-QUIET-MULT-PASSES-FILTER-FUNC +; +; Simple print-before-changed functionality check. +; RUN: opt -S -print-changed=quiet -print-before-changed -passes=instsimplify 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-SIMPLE-BEFORE-QUIET +; +; Check print-before-changed obeys the function filtering +; RUN: opt -S -print-changed=quiet -print-before-changed -passes=instsimplify -filter-print-funcs=f 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-FUNC-FILTER-BEFORE-QUIET +; +; Check that the reporting of IRs with -print-before-changed respects -print-module-scope +; RUN: opt -S -print-changed=quiet -print-before-changed -passes=instsimplify -print-module-scope 2>&1 -o /dev/null < %s | FileCheck %s --check-prefix=CHECK-PRINT-MOD-SCOPE-BEFORE-QUIET +; define i32 @g() { entry: @@ -173,3 +223,104 @@ entry: ; CHECK-PRINT-MOD-SCOPE-BEFORE-NEXT: ModuleID = {{.+}} ; CHECK-PRINT-MOD-SCOPE-BEFORE: *** IR Dump After InstSimplifyPass *** (function: f) ; CHECK-PRINT-MOD-SCOPE-BEFORE-NEXT: ModuleID = {{.+}} + +; CHECK-QUIET-SIMPLE-NOT: *** IR Dump {{.*(At Start:|no change|ignored|filtered out)}} *** +; CHECK-QUIET-SIMPLE: *** IR Dump After InstSimplifyPass *** (function: g) +; CHECK-QUIET-SIMPLE-NEXT: define i32 @g() +; CHECK-QUIET-SIMPLE-NOT: *** IR Dump {{.*(no change|ignored|filtered out)}} *** +; CHECK-QUIET-SIMPLE: *** IR Dump After InstSimplifyPass *** (function: f) +; CHECK-QUIET-SIMPLE-NEXT: define i32 @f() +; CHECK-QUIET-SIMPLE-NOT: *** IR + +; CHECK-QUIET-FUNC-FILTER-NOT: *** IR Dump {{.*(At Start:|no change|ignored|filtered out)}} *** +; CHECK-QUIET-FUNC-FILTER: *** IR Dump After InstSimplifyPass *** (function: f) +; CHECK-QUIET-FUNC-FILTER-NEXT: define i32 @f() +; CHECK-QUIET-FUNC-FILTER-NOT: *** IR + +; CHECK-QUIET-PRINT-MOD-SCOPE-NOT: *** IR Dump {{.*(At Start:|no change|ignored|filtered out)}} *** +; CHECK-QUIET-PRINT-MOD-SCOPE: *** IR Dump After InstSimplifyPass *** (function: g) +; CHECK-QUIET-PRINT-MOD-SCOPE-NEXT: ModuleID = {{.+}} +; CHECK-QUIET-PRINT-MOD-SCOPE: *** IR Dump After InstSimplifyPass *** (function: f) +; CHECK-QUIET-PRINT-MOD-SCOPE-NEXT: ModuleID = {{.+}} +; CHECK-QUIET-PRINT-MOD-SCOPE-NOT: *** IR + +; CHECK-QUIET-FUNC-FILTER-MOD-SCOPE-NOT: *** IR Dump {{.*(At Start:|no change|ignored|filtered out)}} *** +; CHECK-QUIET-FUNC-FILTER-MOD-SCOPE: *** IR Dump After InstSimplifyPass *** (function: f) +; CHECK-QUIET-FUNC-FILTER-MOD-SCOPE-NEXT: ModuleID = {{.+}} +; CHECK-QUIET-FUNC-FILTER-MOD-SCOPE-NOT: *** IR + +; CHECK-QUIET-FILTER-MULT-FUNC-NOT: *** IR Dump {{.*(At Start:|no change|ignored|filtered out)}} *** +; CHECK-QUIET-FILTER-MULT-FUNC: *** IR Dump After InstSimplifyPass *** (function: g) +; CHECK-QUIET-FILTER-MULT-FUNC-NEXT: define i32 @g() +; CHECK-QUIET-FILTER-MULT-FUNC: *** IR Dump After InstSimplifyPass *** (function: f) +; CHECK-QUIET-FILTER-MULT-FUNC-NEXT: define i32 @f() +; CHECK-QUIET-FILTER-MULT-FUNC-NOT: *** IR + +; CHECK-QUIET-FILTER-PASSES-NONE-NOT: *** IR + +; CHECK-QUIET-FILTER-PASSES-NOT: *** IR Dump {{.*(At Start:|no change|ignored|filtered out)}} *** +; CHECK-QUIET-FILTER-PASSES: *** IR Dump After InstSimplifyPass *** (function: g) +; CHECK-QUIET-FILTER-PASSES-NEXT: define i32 @g() +; CHECK-QUIET-FILTER-PASSES-NOT: *** IR Dump {{.*(At Start:|no change|ignored|filtered out)}} *** +; CHECK-QUIET-FILTER-PASSES: *** IR Dump After InstSimplifyPass *** (function: f) +; CHECK-QUIET-FILTER-PASSES-NEXT: define i32 @f() +; CHECK-QUIET-FILTER-PASSES-NOT: *** IR + +; CHECK-QUIET-FILTER-MULT-PASSES-NOT: *** IR Dump {{.*(At Start:|no change|ignored|filtered out)}} *** +; CHECK-QUIET-FILTER-MULT-PASSES: *** IR Dump After InstSimplifyPass *** (function: g) +; CHECK-QUIET-FILTER-MULT-PASSES-NEXT: define i32 @g() +; CHECK-QUIET-FILTER-MULT-PASSES-NOT: *** IR Dump {{.*(At Start:|no change|ignored|filtered out)}} *** +; CHECK-QUIET-FILTER-MULT-PASSES: *** IR Dump After InstSimplifyPass *** (function: f) +; CHECK-QUIET-FILTER-MULT-PASSES-NEXT: define i32 @f() +; CHECK-QUIET-FILTER-MULT-PASSES-NOT: *** IR + +; CHECK-QUIET-FILTER-FUNC-PASSES-NOT: *** IR Dump {{.*(At Start:|no change|ignored|filtered out)}} *** +; CHECK-QUIET-FILTER-FUNC-PASSES: *** IR Dump After InstSimplifyPass *** (function: f) +; CHECK-QUIET-FILTER-FUNC-PASSES-NEXT: define i32 @f() +; CHECK-QUIET-FILTER-FUNC-PASSES-NOT: *** IR + +; CHECK-QUIET-FILTER-FUNC-PASSES-MOD-SCOPE-NOT: *** IR Dump {{.*(At Start:|no change|ignored|filtered out)}} *** +; CHECK-QUIET-FILTER-FUNC-PASSES-MOD-SCOPE: *** IR Dump After InstSimplifyPass *** (function: f) +; CHECK-QUIET-FILTER-FUNC-PASSES-MOD-SCOPE-NEXT: ModuleID = {{.+}} +; CHECK-QUIET-FILTER-FUNC-PASSES-MOD-SCOPE-NOT: *** IR + +; CHECK-QUIET-MULT-PASSES-FILTER-FUNC-NOT: *** IR Dump {{.*(At Start:|no change|ignored|filtered out)}} *** +; CHECK-QUIET-MULT-PASSES-FILTER-FUNC: *** IR Dump After InstSimplifyPass *** (function: f) +; CHECK-QUIET-MULT-PASSES-FILTER-FUNC-NEXT: define i32 @f() +; CHECK-QUIET-MULT-PASSES-FILTER-FUNC-NOT: *** IR + +; CHECK-SIMPLE-BEFORE-QUIET-NOT: *** IR Dump {{.*(At Start:|no change|ignored|filtered out)}} *** +; CHECK-SIMPLE-BEFORE-QUIET: *** IR Dump Before InstSimplifyPass *** (function: g) +; CHECK-SIMPLE-BEFORE-QUIET-NEXT: define i32 @g() +; CHECK-SIMPLE-BEFORE-QUIET-NOT: *** IR Dump {{.*(no change|ignored|filtered out)}} *** +; CHECK-SIMPLE-BEFORE-QUIET: *** IR Dump After InstSimplifyPass *** (function: g) +; CHECK-SIMPLE-BEFORE-QUIET-NEXT: define i32 @g() +; CHECK-SIMPLE-BEFORE-QUIET-NOT: *** IR Dump {{.*(no change|ignored|filtered out)}} *** +; CHECK-SIMPLE-BEFORE-QUIET: *** IR Dump Before InstSimplifyPass *** (function: f) +; CHECK-SIMPLE-BEFORE-QUIET-NEXT: define i32 @f() +; CHECK-SIMPLE-BEFORE-QUIET-NOT: *** IR Dump {{.*(no change|ignored|filtered out)}} *** +; CHECK-SIMPLE-BEFORE-QUIET: *** IR Dump After InstSimplifyPass *** (function: f) +; CHECK-SIMPLE-BEFORE-QUIET-NEXT: define i32 @f() +; CHECK-SIMPLE-BEFORE-QUIET-NOT: *** IR + +; CHECK-FUNC-FILTER-BEFORE-QUIET-NOT: *** IR Dump {{.*(At Start:|no change|ignored|filtered out)}} *** +; CHECK-FUNC-FILTER-BEFORE-QUIET: *** IR Dump Before InstSimplifyPass *** (function: f) +; CHECK-FUNC-FILTER-BEFORE-QUIET-NEXT: define i32 @f() +; CHECK-FUNC-FILTER-BEFORE-QUIET-NOT: *** IR Dump {{.*(no change|ignored|filtered out)}} *** +; CHECK-FUNC-FILTER-BEFORE-QUIET: *** IR Dump After InstSimplifyPass *** (function: f) +; CHECK-FUNC-FILTER-BEFORE-QUIET-NEXT: define i32 @f() +; CHECK-FUNC-FILTER-BEFORE-QUIET-NOT: *** IR + +; CHECK-PRINT-MOD-SCOPE-BEFORE-QUIET-NOT: *** IR Dump {{.*(At Start:|no change|ignored|filtered out)}} *** +; CHECK-PRINT-MOD-SCOPE-BEFORE-QUIET: *** IR Dump Before InstSimplifyPass *** (function: g) +; CHECK-PRINT-MOD-SCOPE-BEFORE-QUIET-NEXT: ModuleID = {{.+}} +; CHECK-PRINT-MOD-SCOPE-BEFORE-QUIET-NOT: *** IR Dump {{.*(no change|ignored|filtered out)}} *** +; CHECK-PRINT-MOD-SCOPE-BEFORE-QUIET: *** IR Dump After InstSimplifyPass *** (function: g) +; CHECK-PRINT-MOD-SCOPE-BEFORE-QUIET-NEXT: ModuleID = {{.+}} +; CHECK-PRINT-MOD-SCOPE-BEFORE-QUIET-NOT: *** IR Dump {{.*(no change|ignored|filtered out)}} *** +; CHECK-PRINT-MOD-SCOPE-BEFORE-QUIET: *** IR Dump Before InstSimplifyPass *** (function: f) +; CHECK-PRINT-MOD-SCOPE-BEFORE-QUIET-NEXT: ModuleID = {{.+}} +; CHECK-PRINT-MOD-SCOPE-BEFORE-QUIET-NOT: *** IR Dump {{.*(no change|ignored|filtered out)}} *** +; CHECK-PRINT-MOD-SCOPE-BEFORE-QUIET: *** IR Dump After InstSimplifyPass *** (function: f) +; CHECK-PRINT-MOD-SCOPE-BEFORE-QUIET-NEXT: ModuleID = {{.+}} +; CHECK-PRINT-MOD-SCOPE-BEFORE-QUIET-NOT: *** IR diff --git a/llvm/test/Transforms/UniqueInternalLinkageNames/unique_symbol_names.ll b/llvm/test/Transforms/UniqueInternalLinkageNames/unique_symbol_names.ll index bf15daebda383e..492c716a0bb112 100644 --- a/llvm/test/Transforms/UniqueInternalLinkageNames/unique_symbol_names.ll +++ b/llvm/test/Transforms/UniqueInternalLinkageNames/unique_symbol_names.ll @@ -10,5 +10,5 @@ entry: ret i32 0 } -; CHECK: @glob.__uniq.6ae72bb15a7d1834b42ae042a58f7a4d = internal global -; CHECK: define internal i32 @foo.__uniq.6ae72bb15a7d1834b42ae042a58f7a4d() +; CHECK: @glob.__uniq.142098474322525230676991677820000238157 = internal global +; CHECK: define internal i32 @foo.__uniq.142098474322525230676991677820000238157() diff --git a/llvm/test/tools/llvm-elfabi/fail-file-write.test b/llvm/test/tools/llvm-elfabi/fail-file-write.test index 3590409234fb25..c3c479e7388727 100644 --- a/llvm/test/tools/llvm-elfabi/fail-file-write.test +++ b/llvm/test/tools/llvm-elfabi/fail-file-write.test @@ -15,4 +15,4 @@ Arch: AArch64 Symbols: {} ... -# ERR: Permission denied when trying to open `{{.*}}.TestDir/Output.TestFile` for writing +# ERR: {{.*}}Permission denied{{.*}} when trying to open `{{.*}}.TestDir/Output.TestFile` for writing diff --git a/llvm/test/tools/llvm-profdata/csprof-dump.test b/llvm/test/tools/llvm-profdata/csprof-dump.test index 39643dc38f20f0..a03b9d8a003e17 100644 --- a/llvm/test/tools/llvm-profdata/csprof-dump.test +++ b/llvm/test/tools/llvm-profdata/csprof-dump.test @@ -27,5 +27,5 @@ Roundtrip test: RUN: llvm-profdata merge -o %t.0.profdata %S/Inputs/CSIR_profile.proftext RUN: llvm-profdata merge -text -o %t.0.proftext %t.0.profdata -RUN: diff %t.0.proftext %S/Inputs/CSIR_profile.proftext +RUN: diff -b %t.0.proftext %S/Inputs/CSIR_profile.proftext diff --git a/llvm/test/tools/llvm-profdata/instr-remap.test b/llvm/test/tools/llvm-profdata/instr-remap.test index 159b7374ac35c4..27fddf60958121 100644 --- a/llvm/test/tools/llvm-profdata/instr-remap.test +++ b/llvm/test/tools/llvm-profdata/instr-remap.test @@ -1,2 +1,2 @@ ; RUN: llvm-profdata merge -text %S/Inputs/instr-remap.proftext -r %S/Inputs/instr-remap.remap -o %t.output -; RUN: diff %S/Inputs/instr-remap.expected %t.output +; RUN: diff -b %S/Inputs/instr-remap.expected %t.output diff --git a/llvm/tools/llvm-link/llvm-link.cpp b/llvm/tools/llvm-link/llvm-link.cpp index 61d0c1561054c9..158b168107f175 100644 --- a/llvm/tools/llvm-link/llvm-link.cpp +++ b/llvm/tools/llvm-link/llvm-link.cpp @@ -456,7 +456,8 @@ int main(int argc, char **argv) { errs() << "Here's the assembly:\n" << *Composite; std::error_code EC; - ToolOutputFile Out(OutputFilename, EC, sys::fs::OF_None); + ToolOutputFile Out(OutputFilename, EC, + OutputAssembly ? sys::fs::OF_Text : sys::fs::OF_None); if (EC) { WithColor::error() << EC.message() << '\n'; return 1; diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp index 122ffe73bf0fd2..ad188b6a5e9290 100644 --- a/llvm/tools/llvm-profdata/llvm-profdata.cpp +++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -296,7 +296,9 @@ static void writeInstrProfile(StringRef OutputFilename, ProfileFormat OutputFormat, InstrProfWriter &Writer) { std::error_code EC; - raw_fd_ostream Output(OutputFilename.data(), EC, sys::fs::OF_None); + raw_fd_ostream Output(OutputFilename.data(), EC, + OutputFormat == PF_Text ? sys::fs::OF_Text + : sys::fs::OF_None); if (EC) exitWithErrorCode(EC, OutputFilename); diff --git a/llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp b/llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp index f69239162e3af5..5dbc1b53d3fed8 100644 --- a/llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp +++ b/llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp @@ -53,6 +53,22 @@ TYPED_TEST(IntrusiveRefCntPtrTest, InteropsWithUniquePtr) { EXPECT_EQ(0, NumInstances); } +TYPED_TEST(IntrusiveRefCntPtrTest, MakeIntrusiveRefCnt) { + EXPECT_EQ(0, NumInstances); + { + auto S1 = makeIntrusiveRefCnt(); + auto S2 = makeIntrusiveRefCnt(); + EXPECT_EQ(2, NumInstances); + static_assert( + std::is_same>::value, + "Non-const type mismatch"); + static_assert( + std::is_same>::value, + "Const type mismatch"); + } + EXPECT_EQ(0, NumInstances); +} + struct InterceptRefCounted : public RefCountedBase { InterceptRefCounted(bool *Released, bool *Retained) : Released(Released), Retained(Retained) {} diff --git a/mlir/cmake/modules/AddMLIRPythonExtension.cmake b/mlir/cmake/modules/AddMLIRPythonExtension.cmake index 290b4a23aa3151..dbbe71e22b132f 100644 --- a/mlir/cmake/modules/AddMLIRPythonExtension.cmake +++ b/mlir/cmake/modules/AddMLIRPythonExtension.cmake @@ -136,17 +136,27 @@ function(add_mlir_python_extension libname extname) endfunction() -function(add_mlir_dialect_python_bindings tblgen_target filename dialectname) - set(LLVM_TARGET_DEFINITIONS ${filename}) - mlir_tablegen("${dialectname}.py" -gen-python-op-bindings - -bind-dialect=${dialectname}) - add_public_tablegen_target(${tblgen_target}) +function(add_mlir_dialect_python_bindings tblgen_target) + cmake_parse_arguments(ARG + "" + "TD_FILE;DIALECT_NAME" + "DEPENDS" + ${ARGN}) + + set(LLVM_TARGET_DEFINITIONS ${ARG_TD_FILE}) + mlir_tablegen("${ARG_DIALECT_NAME}.py" -gen-python-op-bindings + -bind-dialect=${ARG_DIALECT_NAME}) + add_public_tablegen_target( + ${tblgen_target}) + if(ARG_DEPENDS) + add_dependencies(${tblgen_target} ${ARG_DEPENDS}) + endif() add_custom_command( TARGET ${tblgen_target} POST_BUILD - COMMENT "Copying generated python source \"dialects/${dialectname}.py\"" + COMMENT "Copying generated python source \"dialects/${ARG_DIALECT_NAME}.py\"" COMMAND "${CMAKE_COMMAND}" -E copy_if_different - "${CMAKE_CURRENT_BINARY_DIR}/${dialectname}.py" - "${PROJECT_BINARY_DIR}/python/mlir/dialects/${dialectname}.py") + "${CMAKE_CURRENT_BINARY_DIR}/${ARG_DIALECT_NAME}.py" + "${PROJECT_BINARY_DIR}/python/mlir/dialects/${ARG_DIALECT_NAME}.py") endfunction() diff --git a/mlir/docs/OpDefinitions.md b/mlir/docs/OpDefinitions.md index bfd3d43c60b965..dd522904dd7348 100644 --- a/mlir/docs/OpDefinitions.md +++ b/mlir/docs/OpDefinitions.md @@ -1536,6 +1536,171 @@ responsible for parsing/printing the types in `Dialect::printType` and - The `extraClassDeclaration` field is used to include extra code in the class declaration. +### Type builder methods + +For each type, there are a few builders(`get`/`getChecked`) automatically +generated based on the parameters of the type. For example, given the following +type definition: + +```tablegen +def MyType : ... { + let parameters = (ins "int":$intParam); +} +``` + +The following builders are generated: + +```c++ +// Type builders are named `get`, and return a new instance of a type for a +// given set of parameters. +static MyType get(MLIRContext *context, int intParam); + +// If `genVerifyInvariantsDecl` is set to 1, the following method is also +// generated. +static MyType getChecked(Location loc, int intParam); +``` + +If these autogenerated methods are not desired, such as when they conflict with +a custom builder method, a type can set `skipDefaultBuilders` to 1 to signal +that they should not be generated. + +#### Custom type builder methods + +The default build methods may cover a majority of the simple cases related to +type construction, but when they cannot satisfy a type's needs, you can define +additional convenience get methods in the `builders` field as follows: + +```tablegen +def MyType : ... { + let parameters = (ins "int":$intParam); + + let builders = [ + TypeBuilder<(ins "int":$intParam)>, + TypeBuilder<(ins CArg<"int", "0">:$intParam)>, + TypeBuilder<(ins CArg<"int", "0">:$intParam), [{ + // Write the body of the `get` builder inline here. + return Base::get($_ctxt, intParam); + }]>, + TypeBuilderWithInferredContext<(ins "Type":$typeParam), [{ + // This builder states that it can infer an MLIRContext instance from + // its arguments. + return Base::get(typeParam.getContext(), ...); + }]>, + ]; +} +``` + +The `builders` field is a list of custom builders that are added to the type +class. In this example, we provide a several different convenience builders that +are useful in different scenarios. The `ins` prefix is common to many function +declarations in ODS, which use a TableGen [`dag`](#tablegen-syntax). What +follows is a comma-separated list of types (quoted string or CArg) and names +prefixed with the `$` sign. The use of `CArg` allows for providing a default +value to that argument. Let's take a look at each of these builders individually + +The first builder will generate the declaration of a builder method that looks +like: + +```tablegen + let builders = [ + TypeBuilder<(ins "int":$intParam)>, + ]; +``` + +```c++ +class MyType : /*...*/ { + /*...*/ + static MyType get(::mlir::MLIRContext *context, int intParam); +}; +``` + +This builder is identical to the one that will be automatically generated for +`MyType`. The `context` parameter is implicitly added by the generator, and is +used when building the file Type instance (with `Base::get`). The distinction +here is that we can provide the implementation of this `get` method. With this +style of builder definition only the declaration is generated, the implementor +of MyType will need to provide a definition of `MyType::get`. + +The second builder will generate the declaration of a builder method that looks +like: + +```tablegen + let builders = [ + TypeBuilder<(ins CArg<"int", "0">:$intParam)>, + ]; +``` + +```c++ +class MyType : /*...*/ { + /*...*/ + static MyType get(::mlir::MLIRContext *context, int intParam = 0); +}; +``` + +The constraints here are identical to the first builder example except for the +fact that `intParam` now has a default value attached. + +The third builder will generate the declaration of a builder method that looks +like: + +```tablegen + let builders = [ + TypeBuilder<(ins CArg<"int", "0">:$intParam), [{ + // Write the body of the `get` builder inline here. + return Base::get($_ctxt, intParam); + }]>, + ]; +``` + +```c++ +class MyType : /*...*/ { + /*...*/ + static MyType get(::mlir::MLIRContext *context, int intParam = 0); +}; + +MyType MyType::get(::mlir::MLIRContext *context, int intParam) { + // Write the body of the `get` builder inline here. + return Base::get(context, intParam); +} +``` + +This is identical to the second builder example. The difference is that now, a +definition for the builder method will be generated automatically using the +provided code block as the body. When specifying the body inline, `$_ctxt` may +be used to access the `MLIRContext *` parameter. + +The fourth builder will generate the declaration of a builder method that looks +like: + +```tablegen + let builders = [ + TypeBuilderWithInferredContext<(ins "Type":$typeParam), [{ + // This builder states that it can infer an MLIRContext instance from + // its arguments. + return Base::get(typeParam.getContext(), ...); + }]>, + ]; +``` + +```c++ +class MyType : /*...*/ { + /*...*/ + static MyType get(Type typeParam); +}; + +MyType MyType::get(Type typeParam) { + // This builder states that it can infer an MLIRContext instance from its + // arguments. + return Base::get(typeParam.getContext(), ...); +} +``` + +In this builder example, the main difference from the third builder example +three is that the `MLIRContext` parameter is no longer added. This is because +the builder type used `TypeBuilderWithInferredContext` implies that the context +parameter is not necessary as it can be inferred from the arguments to the +builder. + ## Debugging Tips ### Run `mlir-tblgen` to see the generated content diff --git a/mlir/include/mlir-c/AffineExpr.h b/mlir/include/mlir-c/AffineExpr.h index 93b8e832b44f5b..ec445682c0110a 100644 --- a/mlir/include/mlir-c/AffineExpr.h +++ b/mlir/include/mlir-c/AffineExpr.h @@ -10,7 +10,6 @@ #ifndef MLIR_C_AFFINEEXPR_H #define MLIR_C_AFFINEEXPR_H -#include "mlir-c/AffineMap.h" #include "mlir-c/IR.h" #ifdef __cplusplus @@ -45,6 +44,16 @@ DEFINE_C_API_STRUCT(MlirAffineExpr, const void); MLIR_CAPI_EXPORTED MlirContext mlirAffineExprGetContext(MlirAffineExpr affineExpr); +/// Returns `true` if the two affine expressions are equal. +MLIR_CAPI_EXPORTED bool mlirAffineExprEqual(MlirAffineExpr lhs, + MlirAffineExpr rhs); + +/// Returns `true` if the given affine expression is a null expression. Note +/// constant zero is not a null expression. +inline bool mlirAffineExprIsNull(MlirAffineExpr affineExpr) { + return affineExpr.ptr == NULL; +} + /** Prints an affine expression by sending chunks of the string representation * and forwarding `userData to `callback`. Note that the callback may be called * several times with consecutive chunks of the string. */ @@ -82,6 +91,9 @@ MLIR_CAPI_EXPORTED bool mlirAffineExprIsFunctionOfDim(MlirAffineExpr affineExpr, // Affine Dimension Expression. //===----------------------------------------------------------------------===// +/// Checks whether the given affine expression is a dimension expression. +MLIR_CAPI_EXPORTED bool mlirAffineExprIsADim(MlirAffineExpr affineExpr); + /// Creates an affine dimension expression with 'position' in the context. MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineDimExprGet(MlirContext ctx, intptr_t position); @@ -94,6 +106,9 @@ mlirAffineDimExprGetPosition(MlirAffineExpr affineExpr); // Affine Symbol Expression. //===----------------------------------------------------------------------===// +/// Checks whether the given affine expression is a symbol expression. +MLIR_CAPI_EXPORTED bool mlirAffineExprIsASymbol(MlirAffineExpr affineExpr); + /// Creates an affine symbol expression with 'position' in the context. MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineSymbolExprGet(MlirContext ctx, intptr_t position); @@ -106,6 +121,9 @@ mlirAffineSymbolExprGetPosition(MlirAffineExpr affineExpr); // Affine Constant Expression. //===----------------------------------------------------------------------===// +/// Checks whether the given affine expression is a constant expression. +MLIR_CAPI_EXPORTED bool mlirAffineExprIsAConstant(MlirAffineExpr affineExpr); + /// Creates an affine constant expression with 'constant' in the context. MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineConstantExprGet(MlirContext ctx, int64_t constant); @@ -173,6 +191,9 @@ MLIR_CAPI_EXPORTED MlirAffineExpr mlirAffineCeilDivExprGet(MlirAffineExpr lhs, // Affine Binary Operation Expression. //===----------------------------------------------------------------------===// +/// Checks whether the given affine expression is binary. +MLIR_CAPI_EXPORTED bool mlirAffineExprIsABinary(MlirAffineExpr affineExpr); + /** Returns the left hand side affine expression of the given affine binary * operation expression. */ MLIR_CAPI_EXPORTED MlirAffineExpr diff --git a/mlir/include/mlir-c/AffineMap.h b/mlir/include/mlir-c/AffineMap.h index c52fe682625101..bf0c7c7b538137 100644 --- a/mlir/include/mlir-c/AffineMap.h +++ b/mlir/include/mlir-c/AffineMap.h @@ -10,6 +10,7 @@ #ifndef MLIR_C_AFFINEMAP_H #define MLIR_C_AFFINEMAP_H +#include "mlir-c/AffineExpr.h" #include "mlir-c/IR.h" #ifdef __cplusplus @@ -67,9 +68,18 @@ MLIR_CAPI_EXPORTED MlirAffineMap mlirAffineMapEmptyGet(MlirContext ctx); /** Creates a zero result affine map of the given dimensions and symbols in the * context. The affine map is owned by the context. */ +MLIR_CAPI_EXPORTED MlirAffineMap mlirAffineMapZeroResultGet( + MlirContext ctx, intptr_t dimCount, intptr_t symbolCount); + +/** Creates an affine map with results defined by the given list of affine + * expressions. The map resulting map also has the requested number of input + * dimensions and symbols, regardless of them being used in the results. + */ MLIR_CAPI_EXPORTED MlirAffineMap mlirAffineMapGet(MlirContext ctx, intptr_t dimCount, - intptr_t symbolCount); + intptr_t symbolCount, + intptr_t nAffineExprs, + MlirAffineExpr *affineExprs); /** Creates a single constant result affine map in the context. The affine map * is owned by the context. */ @@ -124,6 +134,10 @@ MLIR_CAPI_EXPORTED intptr_t mlirAffineMapGetNumSymbols(MlirAffineMap affineMap); /// Returns the number of results of the given affine map. MLIR_CAPI_EXPORTED intptr_t mlirAffineMapGetNumResults(MlirAffineMap affineMap); +/// Returns the result at the given position. +MLIR_CAPI_EXPORTED MlirAffineExpr +mlirAffineMapGetResult(MlirAffineMap affineMap, intptr_t pos); + /** Returns the number of inputs (dimensions + symbols) of the given affine * map. */ MLIR_CAPI_EXPORTED intptr_t mlirAffineMapGetNumInputs(MlirAffineMap affineMap); diff --git a/mlir/include/mlir-c/Bindings/Python/Interop.h b/mlir/include/mlir-c/Bindings/Python/Interop.h index ae9d3a84a0a3c3..d1eda42023452d 100644 --- a/mlir/include/mlir-c/Bindings/Python/Interop.h +++ b/mlir/include/mlir-c/Bindings/Python/Interop.h @@ -23,10 +23,12 @@ #include +#include "mlir-c/AffineExpr.h" #include "mlir-c/AffineMap.h" #include "mlir-c/IR.h" #include "mlir-c/Pass.h" +#define MLIR_PYTHON_CAPSULE_AFFINE_EXPR "mlir.ir.AffineExpr._CAPIPtr" #define MLIR_PYTHON_CAPSULE_AFFINE_MAP "mlir.ir.AffineMap._CAPIPtr" #define MLIR_PYTHON_CAPSULE_ATTRIBUTE "mlir.ir.Attribute._CAPIPtr" #define MLIR_PYTHON_CAPSULE_CONTEXT "mlir.ir.Context._CAPIPtr" @@ -72,6 +74,25 @@ extern "C" { #endif +/** Creates a capsule object encapsulating the raw C-API MlirAffineExpr. The + * returned capsule does not extend or affect ownership of any Python objects + * that reference the expression in any way. + */ +static inline PyObject *mlirPythonAffineExprToCapsule(MlirAffineExpr expr) { + return PyCapsule_New(MLIR_PYTHON_GET_WRAPPED_POINTER(expr), + MLIR_PYTHON_CAPSULE_AFFINE_EXPR, NULL); +} + +/** Extracts an MlirAffineExpr from a capsule as produced from + * mlirPythonAffineExprToCapsule. If the capsule is not of the right type, then + * a null expression is returned (as checked via mlirAffineExprIsNull). In such + * a case, the Python APIs will have already set an error. */ +static inline MlirAffineExpr mlirPythonCapsuleToAffineExpr(PyObject *capsule) { + void *ptr = PyCapsule_GetPointer(capsule, MLIR_PYTHON_CAPSULE_AFFINE_EXPR); + MlirAffineExpr expr = {ptr}; + return expr; +} + /** Creates a capsule object encapsulating the raw C-API MlirAttribute. * The returned capsule does not extend or affect ownership of any Python * objects that reference the attribute in any way. diff --git a/mlir/include/mlir-c/BuiltinTypes.h b/mlir/include/mlir-c/BuiltinTypes.h index 77898be41565ea..9712d58ad87aee 100644 --- a/mlir/include/mlir-c/BuiltinTypes.h +++ b/mlir/include/mlir-c/BuiltinTypes.h @@ -225,7 +225,13 @@ MLIR_CAPI_EXPORTED bool mlirTypeIsAUnrankedMemRef(MlirType type); * same context as element type. The type is owned by the context. */ MLIR_CAPI_EXPORTED MlirType mlirMemRefTypeGet( MlirType elementType, intptr_t rank, const int64_t *shape, intptr_t numMaps, - MlirAttribute const *affineMaps, unsigned memorySpace); + MlirAffineMap const *affineMaps, unsigned memorySpace); + +/** Same as "mlirMemRefTypeGet" but returns a nullptr-wrapping MlirType o + * illegal arguments, emitting appropriate diagnostics. */ +MLIR_CAPI_EXPORTED MlirType mlirMemRefTypeGetChecked( + MlirType elementType, intptr_t rank, const int64_t *shape, intptr_t numMaps, + MlirAffineMap const *affineMaps, unsigned memorySpace, MlirLocation loc); /** Creates a MemRef type with the given rank, shape, memory space and element * type in the same context as the element type. The type has no affine maps, diff --git a/mlir/include/mlir-c/Dialect/Linalg.h b/mlir/include/mlir-c/Dialect/Linalg.h new file mode 100644 index 00000000000000..56258ac19af455 --- /dev/null +++ b/mlir/include/mlir-c/Dialect/Linalg.h @@ -0,0 +1,25 @@ +//===-- mlir-c/Dialect/Linalg.h - C API for Linalg dialect --------*- C -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM +// Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_C_DIALECT_LINALG_H +#define MLIR_C_DIALECT_LINALG_H + +#include "mlir-c/Registration.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MLIR_DECLARE_CAPI_DIALECT_REGISTRATION(Linalg, linalg); + +#ifdef __cplusplus +} +#endif + +#endif // MLIR_C_DIALECT_LINALG_H diff --git a/mlir/include/mlir-c/Dialect/SCF.h b/mlir/include/mlir-c/Dialect/SCF.h new file mode 100644 index 00000000000000..c1b25677969bf6 --- /dev/null +++ b/mlir/include/mlir-c/Dialect/SCF.h @@ -0,0 +1,25 @@ +//===-- mlir-c/Dialect/SCF.h - C API for SCF dialect --------------*- C -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM +// Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_C_DIALECT_SCF_H +#define MLIR_C_DIALECT_SCF_H + +#include "mlir-c/Registration.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MLIR_DECLARE_CAPI_DIALECT_REGISTRATION(SCF, scf); + +#ifdef __cplusplus +} +#endif + +#endif // MLIR_C_DIALECT_SCF_H diff --git a/mlir/include/mlir-c/Dialect/Shape.h b/mlir/include/mlir-c/Dialect/Shape.h new file mode 100644 index 00000000000000..f64da801610b23 --- /dev/null +++ b/mlir/include/mlir-c/Dialect/Shape.h @@ -0,0 +1,25 @@ +//===-- mlir-c/Dialect/Shape.h - C API for Shape dialect ----------*- C -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM +// Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_C_DIALECT_SHAPE_H +#define MLIR_C_DIALECT_SHAPE_H + +#include "mlir-c/Registration.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MLIR_DECLARE_CAPI_DIALECT_REGISTRATION(Shape, shape); + +#ifdef __cplusplus +} +#endif + +#endif // MLIR_C_DIALECT_SHAPE_H diff --git a/mlir/include/mlir-c/StandardDialect.h b/mlir/include/mlir-c/Dialect/Standard.h similarity index 52% rename from mlir/include/mlir-c/StandardDialect.h rename to mlir/include/mlir-c/Dialect/Standard.h index 191872103104ef..200962177cb950 100644 --- a/mlir/include/mlir-c/StandardDialect.h +++ b/mlir/include/mlir-c/Dialect/Standard.h @@ -1,4 +1,4 @@ -//===-- mlir-c/StandardDialect.h - C API for Standard dialect -----*- C -*-===// +//===-- mlir-c/Dialect/Standard.h - C API for Standard dialect ----*- C -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM // Exceptions. @@ -15,29 +15,19 @@ // //===----------------------------------------------------------------------===// -#ifndef MLIR_C_STANDARDDIALECT_H -#define MLIR_C_STANDARDDIALECT_H +#ifndef MLIR_C_DIALECT_STANDARD_H +#define MLIR_C_DIALECT_STANDARD_H -#include "mlir-c/IR.h" +#include "mlir-c/Registration.h" #ifdef __cplusplus extern "C" { #endif -/** Registers the Standard dialect with the given context. This allows the - * dialect to be loaded dynamically if needed when parsing. */ -MLIR_CAPI_EXPORTED void mlirContextRegisterStandardDialect(MlirContext context); - -/** Loads the Standard dialect into the given context. The dialect does _not_ - * have to be registered in advance. */ -MLIR_CAPI_EXPORTED MlirDialect -mlirContextLoadStandardDialect(MlirContext context); - -/// Returns the namespace of the Standard dialect, suitable for loading it. -MLIR_CAPI_EXPORTED MlirStringRef mlirStandardDialectGetNamespace(); +MLIR_DECLARE_CAPI_DIALECT_REGISTRATION(Standard, std); #ifdef __cplusplus } #endif -#endif // MLIR_C_STANDARDDIALECT_H +#endif // MLIR_C_DIALECT_STANDARD_H diff --git a/mlir/include/mlir-c/Dialect/Tensor.h b/mlir/include/mlir-c/Dialect/Tensor.h new file mode 100644 index 00000000000000..f749782486f1b9 --- /dev/null +++ b/mlir/include/mlir-c/Dialect/Tensor.h @@ -0,0 +1,25 @@ +//===-- mlir-c/Dialect/Tensor.h - C API for Tensor dialect --------*- C -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM +// Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_C_DIALECT_TENSOR_H +#define MLIR_C_DIALECT_TENSOR_H + +#include "mlir-c/Registration.h" + +#ifdef __cplusplus +extern "C" { +#endif + +MLIR_DECLARE_CAPI_DIALECT_REGISTRATION(Tensor, tensor); + +#ifdef __cplusplus +} +#endif + +#endif // MLIR_C_DIALECT_TENSOR_H diff --git a/mlir/include/mlir-c/Registration.h b/mlir/include/mlir-c/Registration.h index 6bb885ef642ae4..7fde05d50bd974 100644 --- a/mlir/include/mlir-c/Registration.h +++ b/mlir/include/mlir-c/Registration.h @@ -16,9 +16,58 @@ extern "C" { #endif -/** Registers all dialects known to core MLIR with the provided Context. - * This is needed before creating IR for these Dialects. - */ +//===----------------------------------------------------------------------===// +// Dialect registration declarations. +// Registration entry-points for each dialect are declared using the common +// MLIR_DECLARE_DIALECT_REGISTRATION_CAPI macro, which takes the dialect +// API name (i.e. "Standard", "Tensor", "Linalg") and namespace (i.e. "std", +// "tensor", "linalg"). The following declarations are produced: +// +// /// Registers the dialect with the given context. This allows the +// /// dialect to be loaded dynamically if needed when parsing. */ +// void mlirContextRegister{NAME}Dialect(MlirContext); +// +// /// Loads the dialect into the given context. The dialect does _not_ +// /// have to be registered in advance. +// MlirDialect mlirContextLoad{NAME}Dialect(MlirContext context); +// +// /// Returns the namespace of the Standard dialect, suitable for loading it. +// MlirStringRef mlir{NAME}DialectGetNamespace(); +// +// /// Gets the above hook methods in struct form for a dialect by namespace. +// /// This is intended to facilitate dynamic lookup and registration of +// /// dialects via a plugin facility based on shared library symbol lookup. +// const MlirDialectRegistrationHooks *mlirGetDialectHooks__{NAMESPACE}__(); +// +// This is done via a common macro to facilitate future expansion to +// registration schemes. +//===----------------------------------------------------------------------===// + +#define MLIR_DECLARE_CAPI_DIALECT_REGISTRATION(Name, Namespace) \ + MLIR_CAPI_EXPORTED void mlirContextRegister##Name##Dialect( \ + MlirContext context); \ + MLIR_CAPI_EXPORTED MlirDialect mlirContextLoad##Name##Dialect( \ + MlirContext context); \ + MLIR_CAPI_EXPORTED MlirStringRef mlir##Name##DialectGetNamespace(); \ + MLIR_CAPI_EXPORTED const MlirDialectRegistrationHooks \ + *mlirGetDialectHooks__##Namespace##__() + +/// Hooks for dynamic discovery of dialects. +typedef void (*MlirContextRegisterDialectHook)(MlirContext context); +typedef MlirDialect (*MlirContextLoadDialectHook)(MlirContext context); +typedef MlirStringRef (*MlirDialectGetNamespaceHook)(); + +/// Structure of dialect registration hooks. +struct MlirDialectRegistrationHooks { + MlirContextRegisterDialectHook registerHook; + MlirContextLoadDialectHook loadHook; + MlirDialectGetNamespaceHook getNamespaceHook; +}; +typedef struct MlirDialectRegistrationHooks MlirDialectRegistrationHooks; + +/// Registers all dialects known to core MLIR with the provided Context. +/// This is needed before creating IR for these Dialects. +/// TODO: Remove this function once the real registration API is finished. MLIR_CAPI_EXPORTED void mlirRegisterAllDialects(MlirContext context); #ifdef __cplusplus diff --git a/mlir/include/mlir/CAPI/Registration.h b/mlir/include/mlir/CAPI/Registration.h new file mode 100644 index 00000000000000..da63afb4c515ae --- /dev/null +++ b/mlir/include/mlir/CAPI/Registration.h @@ -0,0 +1,40 @@ +//===- Registration.h - C API Registration implementation ------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_CAPI_REGISTRATION_H +#define MLIR_CAPI_REGISTRATION_H + +#include "mlir-c/IR.h" +#include "mlir-c/Registration.h" +#include "mlir/CAPI/IR.h" +#include "mlir/CAPI/Support.h" + +//===----------------------------------------------------------------------===// +// Corrolary to MLIR_DECLARE_CAPI_DIALECT_REGISTRATION that defines an impl. +// Takes the same name passed to the above and the fully qualified class name +// of the dialect class. +//===----------------------------------------------------------------------===// + +#define MLIR_DEFINE_CAPI_DIALECT_REGISTRATION(Name, Namespace, ClassName) \ + void mlirContextRegister##Name##Dialect(MlirContext context) { \ + unwrap(context)->getDialectRegistry().insert(); \ + } \ + MlirDialect mlirContextLoad##Name##Dialect(MlirContext context) { \ + return wrap(unwrap(context)->getOrLoadDialect()); \ + } \ + MlirStringRef mlir##Name##DialectGetNamespace() { \ + return wrap(ClassName::getDialectNamespace()); \ + } \ + const MlirDialectRegistrationHooks *mlirGetDialectHooks__##Namespace##__() { \ + static MlirDialectRegistrationHooks hooks = { \ + mlirContextRegister##Name##Dialect, mlirContextLoad##Name##Dialect, \ + mlir##Name##DialectGetNamespace}; \ + return &hooks; \ + } + +#endif // MLIR_CAPI_REGISTRATION_H diff --git a/mlir/include/mlir/Conversion/AsyncToLLVM/AsyncToLLVM.h b/mlir/include/mlir/Conversion/AsyncToLLVM/AsyncToLLVM.h index abb5d216028f4f..938c5cbbebce37 100644 --- a/mlir/include/mlir/Conversion/AsyncToLLVM/AsyncToLLVM.h +++ b/mlir/include/mlir/Conversion/AsyncToLLVM/AsyncToLLVM.h @@ -13,13 +13,29 @@ namespace mlir { +class ConversionTarget; class ModuleOp; template class OperationPass; +class MLIRContext; +class OwningRewritePatternList; +class TypeConverter; /// Create a pass to convert Async operations to the LLVM dialect. std::unique_ptr> createConvertAsyncToLLVMPass(); +/// Populates patterns for async structural type conversions. +/// +/// A "structural" type conversion is one where the underlying ops are +/// completely agnostic to the actual types involved and simply need to update +/// their types. An example of this is async.execute -- the async.execute op and +/// the corresponding async.yield ops need to update their types accordingly to +/// the TypeConverter, but otherwise don't care what type conversions are +/// happening. +void populateAsyncStructuralTypeConversionsAndLegality( + MLIRContext *context, TypeConverter &typeConverter, + OwningRewritePatternList &patterns, ConversionTarget &target); + } // namespace mlir #endif // MLIR_CONVERSION_ASYNCTOLLVM_ASYNCTOLLVM_H diff --git a/mlir/include/mlir/Dialect/ArmSVE/ArmSVE.td b/mlir/include/mlir/Dialect/ArmSVE/ArmSVE.td index b1a42e99126c1d..3bfbccf618d6f5 100644 --- a/mlir/include/mlir/Dialect/ArmSVE/ArmSVE.td +++ b/mlir/include/mlir/Dialect/ArmSVE/ArmSVE.td @@ -74,7 +74,7 @@ def ScalableVectorType : ArmSVE_Type<"ScalableVector"> { VectorType vector; if ($_parser.parseType(vector)) return Type(); - return get(ctxt, vector.getShape(), vector.getElementType()); + return get($_ctxt, vector.getShape(), vector.getElementType()); }]; let extraClassDeclaration = [{ diff --git a/mlir/include/mlir/Dialect/Vector/VectorOps.td b/mlir/include/mlir/Dialect/Vector/VectorOps.td index 6bfa89939b04e0..8bc21b17903775 100644 --- a/mlir/include/mlir/Dialect/Vector/VectorOps.td +++ b/mlir/include/mlir/Dialect/Vector/VectorOps.td @@ -1318,7 +1318,7 @@ def Vector_TransferWriteOp : def Vector_MaskedLoadOp : Vector_Op<"maskedload">, - Arguments<(ins AnyMemRef:$base, + Arguments<(ins Arg:$base, Variadic:$indices, VectorOfRankAndType<[1], [I1]>:$mask, VectorOfRank<[1]>:$pass_thru)>, @@ -1370,7 +1370,7 @@ def Vector_MaskedLoadOp : def Vector_MaskedStoreOp : Vector_Op<"maskedstore">, - Arguments<(ins AnyMemRef:$base, + Arguments<(ins Arg:$base, Variadic:$indices, VectorOfRankAndType<[1], [I1]>:$mask, VectorOfRank<[1]>:$value)> { @@ -1418,7 +1418,7 @@ def Vector_MaskedStoreOp : def Vector_GatherOp : Vector_Op<"gather">, - Arguments<(ins AnyMemRef:$base, + Arguments<(ins Arg:$base, VectorOfRankAndType<[1], [AnyInteger]>:$indices, VectorOfRankAndType<[1], [I1]>:$mask, VectorOfRank<[1]>:$pass_thru)>, @@ -1475,7 +1475,7 @@ def Vector_GatherOp : def Vector_ScatterOp : Vector_Op<"scatter">, - Arguments<(ins AnyMemRef:$base, + Arguments<(ins Arg:$base, VectorOfRankAndType<[1], [AnyInteger]>:$indices, VectorOfRankAndType<[1], [I1]>:$mask, VectorOfRank<[1]>:$value)> { @@ -1531,7 +1531,7 @@ def Vector_ScatterOp : def Vector_ExpandLoadOp : Vector_Op<"expandload">, - Arguments<(ins AnyMemRef:$base, + Arguments<(ins Arg:$base, Variadic:$indices, VectorOfRankAndType<[1], [I1]>:$mask, VectorOfRank<[1]>:$pass_thru)>, @@ -1586,7 +1586,7 @@ def Vector_ExpandLoadOp : def Vector_CompressStoreOp : Vector_Op<"compressstore">, - Arguments<(ins AnyMemRef:$base, + Arguments<(ins Arg:$base, Variadic:$indices, VectorOfRankAndType<[1], [I1]>:$mask, VectorOfRank<[1]>:$value)> { diff --git a/mlir/include/mlir/IR/BuiltinTypes.h b/mlir/include/mlir/IR/BuiltinTypes.h index d9d1a6e4e68c76..835f46dc229578 100644 --- a/mlir/include/mlir/IR/BuiltinTypes.h +++ b/mlir/include/mlir/IR/BuiltinTypes.h @@ -29,119 +29,15 @@ class TypeRange; namespace detail { struct BaseMemRefTypeStorage; -struct ComplexTypeStorage; -struct FunctionTypeStorage; -struct IntegerTypeStorage; struct MemRefTypeStorage; -struct OpaqueTypeStorage; struct RankedTensorTypeStorage; struct ShapedTypeStorage; -struct TupleTypeStorage; struct UnrankedMemRefTypeStorage; struct UnrankedTensorTypeStorage; struct VectorTypeStorage; } // namespace detail -//===----------------------------------------------------------------------===// -// ComplexType -//===----------------------------------------------------------------------===// - -/// The 'complex' type represents a complex number with a parameterized element -/// type, which is composed of a real and imaginary value of that element type. -/// -/// The element must be a floating point or integer scalar type. -/// -class ComplexType - : public Type::TypeBase { -public: - using Base::Base; - - /// Get or create a ComplexType with the provided element type. - static ComplexType get(Type elementType); - - /// Get or create a ComplexType with the provided element type. This emits - /// and error at the specified location and returns null if the element type - /// isn't supported. - static ComplexType getChecked(Location location, Type elementType); - - /// Verify the construction of an integer type. - static LogicalResult verifyConstructionInvariants(Location loc, - Type elementType); - - Type getElementType(); -}; - -//===----------------------------------------------------------------------===// -// IntegerType -//===----------------------------------------------------------------------===// - -/// Integer types can have arbitrary bitwidth up to a large fixed limit. -class IntegerType - : public Type::TypeBase { -public: - using Base::Base; - - /// Signedness semantics. - enum SignednessSemantics : uint32_t { - Signless, /// No signedness semantics - Signed, /// Signed integer - Unsigned, /// Unsigned integer - }; - - /// Get or create a new IntegerType of the given width within the context. - /// The created IntegerType is signless (i.e., no signedness semantics). - /// Assume the width is within the allowed range and assert on failures. Use - /// getChecked to handle failures gracefully. - static IntegerType get(MLIRContext *context, unsigned width); - - /// Get or create a new IntegerType of the given width within the context. - /// The created IntegerType has signedness semantics as indicated via - /// `signedness`. Assume the width is within the allowed range and assert on - /// failures. Use getChecked to handle failures gracefully. - static IntegerType get(MLIRContext *context, unsigned width, - SignednessSemantics signedness); - - /// Get or create a new IntegerType of the given width within the context, - /// defined at the given, potentially unknown, location. The created - /// IntegerType is signless (i.e., no signedness semantics). If the width is - /// outside the allowed range, emit errors and return a null type. - static IntegerType getChecked(Location location, unsigned width); - - /// Get or create a new IntegerType of the given width within the context, - /// defined at the given, potentially unknown, location. The created - /// IntegerType has signedness semantics as indicated via `signedness`. If the - /// width is outside the allowed range, emit errors and return a null type. - static IntegerType getChecked(Location location, unsigned width, - SignednessSemantics signedness); - - /// Verify the construction of an integer type. - static LogicalResult - verifyConstructionInvariants(Location loc, unsigned width, - SignednessSemantics signedness); - - /// Return the bitwidth of this integer type. - unsigned getWidth() const; - - /// Return the signedness semantics of this integer type. - SignednessSemantics getSignedness() const; - - /// Return true if this is a signless integer type. - bool isSignless() const { return getSignedness() == Signless; } - /// Return true if this is a signed integer type. - bool isSigned() const { return getSignedness() == Signed; } - /// Return true if this is an unsigned integer type. - bool isUnsigned() const { return getSignedness() == Unsigned; } - - /// Get or create a new IntegerType with the same signedness as `this` and a - /// bitwidth scaled by `scale`. - /// Return null if the scaled element type cannot be represented. - IntegerType scaleElementBitwidth(unsigned scale); - - /// Integer representation maximal bitwidth. - static constexpr unsigned kMaxWidth = (1 << 24) - 1; // Aligned with LLVM -}; - //===----------------------------------------------------------------------===// // FloatType //===----------------------------------------------------------------------===// @@ -170,68 +66,6 @@ class FloatType : public Type { const llvm::fltSemantics &getFloatSemantics(); }; -//===----------------------------------------------------------------------===// -// FunctionType -//===----------------------------------------------------------------------===// - -/// Function types map from a list of inputs to a list of results. -class FunctionType - : public Type::TypeBase { -public: - using Base::Base; - - static FunctionType get(MLIRContext *context, TypeRange inputs, - TypeRange results); - - /// Input types. - unsigned getNumInputs() const; - Type getInput(unsigned i) const { return getInputs()[i]; } - ArrayRef getInputs() const; - - /// Result types. - unsigned getNumResults() const; - Type getResult(unsigned i) const { return getResults()[i]; } - ArrayRef getResults() const; - - /// Returns a new function type without the specified arguments and results. - FunctionType getWithoutArgsAndResults(ArrayRef argIndices, - ArrayRef resultIndices); -}; - -//===----------------------------------------------------------------------===// -// OpaqueType -//===----------------------------------------------------------------------===// - -/// Opaque types represent types of non-registered dialects. These are types -/// represented in their raw string form, and can only usefully be tested for -/// type equality. -class OpaqueType - : public Type::TypeBase { -public: - using Base::Base; - - /// Get or create a new OpaqueType with the provided dialect and string data. - static OpaqueType get(MLIRContext *context, Identifier dialect, - StringRef typeData); - - /// Get or create a new OpaqueType with the provided dialect and string data. - /// If the given identifier is not a valid namespace for a dialect, then a - /// null type is returned. - static OpaqueType getChecked(Location location, Identifier dialect, - StringRef typeData); - - /// Returns the dialect namespace of the opaque type. - Identifier getDialectNamespace() const; - - /// Returns the raw type data of the opaque type. - StringRef getTypeData() const; - - /// Verify the construction of an opaque type. - static LogicalResult verifyConstructionInvariants(Location loc, - Identifier dialect, - StringRef typeData); -}; - //===----------------------------------------------------------------------===// // ShapedType //===----------------------------------------------------------------------===// @@ -444,9 +278,7 @@ class BaseMemRefType : public ShapedType { using ShapedType::ShapedType; /// Return true if the specified element type is ok in a memref. - static bool isValidElementType(Type type) { - return type.isIntOrIndexOrFloat() || type.isa(); - } + static bool isValidElementType(Type type); /// Methods for support type inquiry through isa, cast, and dyn_cast. static bool classof(Type type); @@ -584,51 +416,6 @@ class UnrankedMemRefType ArrayRef getShape() const { return llvm::None; } }; - -//===----------------------------------------------------------------------===// -// TupleType -//===----------------------------------------------------------------------===// - -/// Tuple types represent a collection of other types. Note: This type merely -/// provides a common mechanism for representing tuples in MLIR. It is up to -/// dialect authors to provides operations for manipulating them, e.g. -/// extract_tuple_element. When possible, users should prefer multi-result -/// operations in the place of tuples. -class TupleType - : public Type::TypeBase { -public: - using Base::Base; - - /// Get or create a new TupleType with the provided element types. Assumes the - /// arguments define a well-formed type. - static TupleType get(MLIRContext *context, TypeRange elementTypes); - - /// Get or create an empty tuple type. - static TupleType get(MLIRContext *context); - - /// Return the elements types for this tuple. - ArrayRef getTypes() const; - - /// Accumulate the types contained in this tuple and tuples nested within it. - /// Note that this only flattens nested tuples, not any other container type, - /// e.g. a tuple, tuple>> is flattened to - /// (i32, tensor, f32, i64) - void getFlattenedTypes(SmallVectorImpl &types); - - /// Return the number of held types. - size_t size() const; - - /// Iterate over the held elements. - using iterator = ArrayRef::iterator; - iterator begin() const { return getTypes().begin(); } - iterator end() const { return getTypes().end(); } - - /// Return the element type at index 'index'. - Type getType(size_t index) const { - assert(index < size() && "invalid index for tuple type"); - return getTypes()[index]; - } -}; } // end namespace mlir //===----------------------------------------------------------------------===// @@ -647,6 +434,10 @@ inline bool BaseMemRefType::classof(Type type) { return type.isa(); } +inline bool BaseMemRefType::isValidElementType(Type type) { + return type.isIntOrIndexOrFloat() || type.isa(); +} + inline bool FloatType::classof(Type type) { return type.isa(); } diff --git a/mlir/include/mlir/IR/BuiltinTypes.td b/mlir/include/mlir/IR/BuiltinTypes.td index b540554fb11e4b..1c225b9b405b3f 100644 --- a/mlir/include/mlir/IR/BuiltinTypes.td +++ b/mlir/include/mlir/IR/BuiltinTypes.td @@ -25,6 +25,42 @@ class Builtin_Type : TypeDef { let mnemonic = ?; } +//===----------------------------------------------------------------------===// +// ComplexType +//===----------------------------------------------------------------------===// + +def Builtin_Complex : Builtin_Type<"Complex"> { + let summary = "Complex number with a parameterized element type"; + let description = [{ + Syntax: + + ``` + complex-type ::= `complex` `<` type `>` + ``` + + The value of `complex` type represents a complex number with a parameterized + element type, which is composed of a real and imaginary value of that + element type. The element must be a floating point or integer scalar type. + + Examples: + + ```mlir + complex + complex + ``` + }]; + let parameters = (ins "Type":$elementType); + let builders = [ + TypeBuilderWithInferredContext<(ins "Type":$elementType), [{ + return Base::get(elementType.getContext(), elementType); + }], [{ + return Base::getChecked($_loc, elementType); + }]> + ]; + let skipDefaultBuilders = 1; + let genVerifyInvariantsDecl = 1; +} + //===----------------------------------------------------------------------===// // FloatType //===----------------------------------------------------------------------===// @@ -65,6 +101,48 @@ def Builtin_Float64 : Builtin_FloatType<"Float64"> { let summary = "64-bit floating-point type"; } +//===----------------------------------------------------------------------===// +// FunctionType +//===----------------------------------------------------------------------===// + +def Builtin_Function : Builtin_Type<"Function"> { + let summary = "Map from a list of inputs to a list of results"; + let description = [{ + Syntax: + + ``` + // Function types may have multiple results. + function-result-type ::= type-list-parens | non-function-type + function-type ::= type-list-parens `->` function-result-type + ``` + + The function type can be thought of as a function signature. It consists of + a list of formal parameter types and a list of formal result types. + ``` + }]; + let parameters = (ins "ArrayRef":$inputs, "ArrayRef":$results); + let builders = [ + TypeBuilder<(ins CArg<"TypeRange">:$inputs, CArg<"TypeRange">:$results), [{ + return Base::get($_ctxt, inputs, results); + }]> + ]; + let skipDefaultBuilders = 1; + let genStorageClass = 0; + let extraClassDeclaration = [{ + /// Input types. + unsigned getNumInputs() const; + Type getInput(unsigned i) const { return getInputs()[i]; } + + /// Result types. + unsigned getNumResults() const; + Type getResult(unsigned i) const { return getResults()[i]; } + + /// Returns a new function type without the specified arguments and results. + FunctionType getWithoutArgsAndResults(ArrayRef argIndices, + ArrayRef resultIndices); + }]; +} + //===----------------------------------------------------------------------===// // IndexType //===----------------------------------------------------------------------===// @@ -96,6 +174,70 @@ def Builtin_Index : Builtin_Type<"Index"> { }]; } +//===----------------------------------------------------------------------===// +// IntegerType +//===----------------------------------------------------------------------===// + +def Builtin_Integer : Builtin_Type<"Integer"> { + let summary = "Integer type with arbitrary precision up to a fixed limit"; + let description = [{ + Syntax: + + ``` + // Sized integers like i1, i4, i8, i16, i32. + signed-integer-type ::= `si` [1-9][0-9]* + unsigned-integer-type ::= `ui` [1-9][0-9]* + signless-integer-type ::= `i` [1-9][0-9]* + integer-type ::= signed-integer-type | + unsigned-integer-type | + signless-integer-type + ``` + + Integer types have a designated bit width and may optionally have signedness + semantics. + + **Rationale:** low precision integers (like `i2`, `i4` etc) are useful for + low-precision inference chips, and arbitrary precision integers are useful + for hardware synthesis (where a 13 bit multiplier is a lot cheaper/smaller + than a 16 bit one). + }]; + let parameters = (ins "unsigned":$width, "SignednessSemantics":$signedness); + let builders = [ + TypeBuilder<(ins "unsigned":$width, + CArg<"SignednessSemantics", "Signless">:$signedness)> + ]; + + // IntegerType uses a special storage class that compacts parameters to save + // memory. + let genStorageClass = 0; + let skipDefaultBuilders = 1; + let genVerifyInvariantsDecl = 1; + let extraClassDeclaration = [{ + /// Signedness semantics. + enum SignednessSemantics : uint32_t { + Signless, /// No signedness semantics + Signed, /// Signed integer + Unsigned, /// Unsigned integer + }; + + /// Return true if this is a signless integer type. + bool isSignless() const { return getSignedness() == Signless; } + /// Return true if this is a signed integer type. + bool isSigned() const { return getSignedness() == Signed; } + /// Return true if this is an unsigned integer type. + bool isUnsigned() const { return getSignedness() == Unsigned; } + + /// Get or create a new IntegerType with the same signedness as `this` and a + /// bitwidth scaled by `scale`. + /// Return null if the scaled element type cannot be represented. + IntegerType scaleElementBitwidth(unsigned scale); + + /// Integer representation maximal bitwidth. + /// Note: This is aligned with the maximum width of llvm::IntegerType. + static constexpr unsigned kMaxWidth = (1 << 24) - 1; + }]; +} + //===----------------------------------------------------------------------===// // NoneType //===----------------------------------------------------------------------===// @@ -111,4 +253,102 @@ def Builtin_None : Builtin_Type<"None"> { }]; } +//===----------------------------------------------------------------------===// +// OpaqueType +//===----------------------------------------------------------------------===// + +def Builtin_Opaque : Builtin_Type<"Opaque"> { + let summary = "Type of a non-registered dialect"; + let description = [{ + Syntax: + + ``` + opaque-type ::= `opaque` `<` type `>` + ``` + + Opaque types represent types of non-registered dialects. These are types + represented in their raw string form, and can only usefully be tested for + type equality. + + Examples: + + ```mlir + opaque<"llvm", "struct<(i32, float)>"> + opaque<"pdl", "value"> + ``` + }]; + let parameters = (ins + "Identifier":$dialectNamespace, + StringRefParameter<"">:$typeData + ); + let genVerifyInvariantsDecl = 1; +} + +//===----------------------------------------------------------------------===// +// TupleType +//===----------------------------------------------------------------------===// + +def Builtin_Tuple : Builtin_Type<"Tuple"> { + let summary = "Fixed-sized collection of other types"; + let description = [{ + Syntax: + + ``` + tuple-type ::= `tuple` `<` (type ( `,` type)*)? `>` + ``` + + The value of `tuple` type represents a fixed-size collection of elements, + where each element may be of a different type. + + **Rationale:** Though this type is first class in the type system, MLIR + provides no standard operations for operating on `tuple` types + ([rationale](Rationale/Rationale.md#tuple-types)). + + Examples: + + ```mlir + // Empty tuple. + tuple<> + + // Single element + tuple + + // Many elements. + tuple, i5> + ``` + }]; + let parameters = (ins "ArrayRef":$types); + let builders = [ + TypeBuilder<(ins "TypeRange":$elementTypes), [{ + return Base::get($_ctxt, elementTypes); + }]>, + TypeBuilder<(ins), [{ + return Base::get($_ctxt, TypeRange()); + }]> + ]; + let skipDefaultBuilders = 1; + let genStorageClass = 0; + let extraClassDeclaration = [{ + /// Accumulate the types contained in this tuple and tuples nested within + /// it. Note that this only flattens nested tuples, not any other container + /// type, e.g. a tuple, tuple>> is + /// flattened to (i32, tensor, f32, i64) + void getFlattenedTypes(SmallVectorImpl &types); + + /// Return the number of held types. + size_t size() const; + + /// Iterate over the held elements. + using iterator = ArrayRef::iterator; + iterator begin() const { return getTypes().begin(); } + iterator end() const { return getTypes().end(); } + + /// Return the element type at index 'index'. + Type getType(size_t index) const { + assert(index < size() && "invalid index for tuple type"); + return getTypes()[index]; + } + }]; +} + #endif // BUILTIN_TYPES diff --git a/mlir/include/mlir/IR/OpBase.td b/mlir/include/mlir/IR/OpBase.td index dc3e8a6367cded..73ddbc1d56eb90 100644 --- a/mlir/include/mlir/IR/OpBase.td +++ b/mlir/include/mlir/IR/OpBase.td @@ -2430,6 +2430,73 @@ def replaceWithValue; // Data type generation //===----------------------------------------------------------------------===// +// Class for defining a custom type getter. +// +// TableGen generates several generic getter methods for each type by default, +// corresponding to the specified dag parameters. If the default generated ones +// cannot cover some use case, custom getters can be defined using instances of +// this class. +// +// The signature of the `get` is always either: +// +// ```c++ +// static get(MLIRContext *context, ...) { +// ... +// } +// ``` +// +// or: +// +// ```c++ +// static get(MLIRContext *context, ...); +// ``` +// +// To define a custom getter, the parameter list and body should be passed +// in as separate template arguments to this class. The parameter list is a +// TableGen DAG with `ins` operation with named arguments, which has either: +// - string initializers ("Type":$name) to represent a typed parameter, or +// - CArg-typed initializers (CArg<"Type", "default">:$name) to represent a +// typed parameter that may have a default value. +// The type string is used verbatim to produce code and, therefore, must be a +// valid C++ type. It is used inside the C++ namespace of the parent Type's +// dialect; explicit namespace qualification like `::mlir` may be necessary if +// Types are not placed inside the `mlir` namespace. The default value string is +// used verbatim to produce code and must be a valid C++ initializer the given +// type. For example, the following signature specification +// +// ``` +// TypeBuilder<(ins "int":$integerArg, CArg<"float", "3.0f">:$floatArg)> +// ``` +// +// has an integer parameter and a float parameter with a default value. +// +// If an empty string is passed in for `body`, then *only* the builder +// declaration will be generated; this provides a way to define complicated +// builders entirely in C++. +// +// `checkedBody` is similar to `body`, but is the code block used when +// generating a `getChecked` method. +class TypeBuilder { + dag dagParams = parameters; + code body = bodyCode; + code checkedBody = checkedBodyCode; + + // The context parameter can be inferred from one of the other parameters and + // is not implicitly added to the parameter list. + bit hasInferredContextParam = 0; +} + +// A class of TypeBuilder that is able to infer the MLIRContext parameter from +// one of the other builder parameters. Instances of this builder do not have +// `MLIRContext *` implicitly added to the parameter list. +class TypeBuilderWithInferredContext + : TypeBuilder { + code checkedBody = checkedBodyCode; + let hasInferredContextParam = 1; +} + // Define a new type, named `name`, belonging to `dialect` that inherits from // the given C++ base class. class TypeDef get(MLIRContext *, ); + // ``` + // + // Note that builders should only be provided when a type has parameters. + list builders = ?; + // Use the lowercased name as the keyword for parsing/printing. Specify only // if you want tblgen to generate declarations and/or definitions of // printer/parser for this type. @@ -2488,6 +2567,9 @@ class TypeDef getName() const { return name; } + + /// Return an optional string containing the default value to use for this + /// parameter. + Optional getDefaultValue() const; + + private: + Parameter(Optional name, const llvm::Init *def) + : name(name), def(def) {} + + /// The optional name of the parameter. + Optional name; + + /// The tablegen definition of the parameter. This is either a StringInit, + /// or a CArg DefInit. + const llvm::Init *def; + + // Allow access to the constructor. + friend Builder; + }; + + /// Construct a builder from the given Record instance. + Builder(const llvm::Record *record, ArrayRef loc); + + /// Return a list of parameters used in this build method. + ArrayRef getParameters() const { return parameters; } + + /// Return an optional string containing the body of the builder. + Optional getBody() const; + +protected: + /// The TableGen definition of this builder. + const llvm::Record *def; + +private: + /// A collection of parameters to the builder. + SmallVector parameters; +}; + +} // end namespace tblgen +} // end namespace mlir + +#endif // MLIR_TABLEGEN_BUILDER_H_ diff --git a/mlir/include/mlir/TableGen/Operator.h b/mlir/include/mlir/TableGen/Operator.h index 16d154b3beb0b5..d21b4b213ee41b 100644 --- a/mlir/include/mlir/TableGen/Operator.h +++ b/mlir/include/mlir/TableGen/Operator.h @@ -16,6 +16,7 @@ #include "mlir/Support/LLVM.h" #include "mlir/TableGen/Argument.h" #include "mlir/TableGen/Attribute.h" +#include "mlir/TableGen/Builder.h" #include "mlir/TableGen/Dialect.h" #include "mlir/TableGen/OpTrait.h" #include "mlir/TableGen/Region.h" @@ -287,6 +288,9 @@ class Operator { // Returns the OperandOrAttribute corresponding to the index. OperandOrAttribute getArgToOperandOrAttribute(int index) const; + // Returns the builders of this operation. + ArrayRef getBuilders() const { return builders; } + private: // Populates the vectors containing operands, attributes, results and traits. void populateOpStructure(); @@ -332,6 +336,9 @@ class Operator { // Map from argument to attribute or operand number. SmallVector attrOrOperandMapping; + // The builders of this operator. + SmallVector builders; + // The number of native attributes stored in the leading positions of // `attributes`. int numNativeAttributes; diff --git a/mlir/include/mlir/TableGen/TypeDef.h b/mlir/include/mlir/TableGen/TypeDef.h index 1be5140011f0ee..73a3a1002d0a8f 100644 --- a/mlir/include/mlir/TableGen/TypeDef.h +++ b/mlir/include/mlir/TableGen/TypeDef.h @@ -14,24 +14,45 @@ #define MLIR_TABLEGEN_TYPEDEF_H #include "mlir/Support/LLVM.h" -#include "mlir/TableGen/Dialect.h" +#include "mlir/TableGen/Builder.h" namespace llvm { -class Record; class DagInit; +class Record; class SMLoc; } // namespace llvm namespace mlir { namespace tblgen { - +class Dialect; class TypeParameter; +//===----------------------------------------------------------------------===// +// TypeBuilder +//===----------------------------------------------------------------------===// + +/// Wrapper class that represents a Tablegen TypeBuilder. +class TypeBuilder : public Builder { +public: + using Builder::Builder; + + /// Return an optional code body used for the `getChecked` variant of this + /// builder. + Optional getCheckedBody() const; + + /// Returns true if this builder is able to infer the MLIRContext parameter. + bool hasInferredContextParameter() const; +}; + +//===----------------------------------------------------------------------===// +// TypeDef +//===----------------------------------------------------------------------===// + /// Wrapper class that contains a TableGen TypeDef's record and provides helper /// methods for accessing them. class TypeDef { public: - explicit TypeDef(const llvm::Record *def) : def(def) {} + explicit TypeDef(const llvm::Record *def); // Get the dialect for which this type belongs. Dialect getDialect() const; @@ -95,6 +116,13 @@ class TypeDef { // Get the code location (for error printing). ArrayRef getLoc() const; + // Returns true if the default get/getChecked methods should be skipped during + // generation. + bool skipDefaultBuilders() const; + + // Returns the builders of this type. + ArrayRef getBuilders() const { return builders; } + // Returns whether two TypeDefs are equal by checking the equality of the // underlying record. bool operator==(const TypeDef &other) const; @@ -107,8 +135,15 @@ class TypeDef { private: const llvm::Record *def; + + // The builders of this type definition. + SmallVector builders; }; +//===----------------------------------------------------------------------===// +// TypeParameter +//===----------------------------------------------------------------------===// + // A wrapper class for tblgen TypeParameter, arrays of which belong to TypeDefs // to parameterize them. class TypeParameter { diff --git a/mlir/lib/Bindings/Python/CMakeLists.txt b/mlir/lib/Bindings/Python/CMakeLists.txt index 0c34f5b55415c2..8273489137448e 100644 --- a/mlir/lib/Bindings/Python/CMakeLists.txt +++ b/mlir/lib/Bindings/Python/CMakeLists.txt @@ -35,11 +35,27 @@ endforeach() # Generate dialect-specific bindings. ################################################################################ +add_mlir_dialect_python_bindings(MLIRBindingsPythonLinalgOps + TD_FILE LinalgOps.td + DIALECT_NAME linalg + DEPENDS LinalgOdsGen) +add_dependencies(MLIRBindingsPythonSources MLIRBindingsPythonLinalgOps) + +add_mlir_dialect_python_bindings(MLIRBindingsPythonShapeOps + TD_FILE ShapeOps.td + DIALECT_NAME shape) +add_dependencies(MLIRBindingsPythonSources MLIRBindingsPythonShapeOps) + add_mlir_dialect_python_bindings(MLIRBindingsPythonStandardOps - StandardOps.td - std) + TD_FILE StandardOps.td + DIALECT_NAME std) add_dependencies(MLIRBindingsPythonSources MLIRBindingsPythonStandardOps) +add_mlir_dialect_python_bindings(MLIRBindingsPythonTensorOps + TD_FILE TensorOps.td + DIALECT_NAME tensor) +add_dependencies(MLIRBindingsPythonSources MLIRBindingsPythonTensorOps) + ################################################################################ # Build core python extension ################################################################################ diff --git a/mlir/lib/Bindings/Python/IRModules.cpp b/mlir/lib/Bindings/Python/IRModules.cpp index 2dcee494715d40..218099bedc6f01 100644 --- a/mlir/lib/Bindings/Python/IRModules.cpp +++ b/mlir/lib/Bindings/Python/IRModules.cpp @@ -11,6 +11,7 @@ #include "Globals.h" #include "PybindUtils.h" +#include "mlir-c/AffineMap.h" #include "mlir-c/Bindings/Python/Interop.h" #include "mlir-c/BuiltinAttributes.h" #include "mlir-c/BuiltinTypes.h" @@ -2534,6 +2535,8 @@ class PyUnrankedTensorType } }; +class PyMemRefLayoutMapList; + /// Ranked MemRef Type subclass - MemRefType. class PyMemRefType : public PyConcreteType { public: @@ -2541,16 +2544,22 @@ class PyMemRefType : public PyConcreteType { static constexpr const char *pyClassName = "MemRefType"; using PyConcreteType::PyConcreteType; + PyMemRefLayoutMapList getLayout(); + static void bindDerived(ClassTy &c) { - // TODO: Add mlirMemRefTypeGet and mlirMemRefTypeGetAffineMap binding - // once the affine map binding is completed. c.def_static( - "get_contiguous_memref", - // TODO: Make the location optional and create a default location. + "get", [](PyType &elementType, std::vector shape, - unsigned memorySpace, DefaultingPyLocation loc) { - MlirType t = mlirMemRefTypeContiguousGetChecked( - elementType, shape.size(), shape.data(), memorySpace, loc); + std::vector layout, unsigned memorySpace, + DefaultingPyLocation loc) { + SmallVector maps; + maps.reserve(layout.size()); + for (PyAffineMap &map : layout) + maps.push_back(map); + + MlirType t = mlirMemRefTypeGetChecked(elementType, shape.size(), + shape.data(), maps.size(), + maps.data(), memorySpace, loc); // TODO: Rework error reporting once diagnostic engine is exposed // in C API. if (mlirTypeIsNull(t)) { @@ -2564,15 +2573,11 @@ class PyMemRefType : public PyConcreteType { } return PyMemRefType(elementType.getContext(), t); }, - py::arg("element_type"), py::arg("shape"), py::arg("memory_space"), + py::arg("element_type"), py::arg("shape"), + py::arg("layout") = py::list(), py::arg("memory_space") = 0, py::arg("loc") = py::none(), "Create a memref type") - .def_property_readonly( - "num_affine_maps", - [](PyMemRefType &self) -> intptr_t { - return mlirMemRefTypeGetNumAffineMaps(self); - }, - "Returns the number of affine layout maps in the given MemRef " - "type.") + .def_property_readonly("layout", &PyMemRefType::getLayout, + "The list of layout maps of the MemRef type.") .def_property_readonly( "memory_space", [](PyMemRefType &self) -> unsigned { @@ -2582,6 +2587,41 @@ class PyMemRefType : public PyConcreteType { } }; +/// A list of affine layout maps in a memref type. Internally, these are stored +/// as consecutive elements, random access is cheap. Both the type and the maps +/// are owned by the context, no need to worry about lifetime extension. +class PyMemRefLayoutMapList + : public Sliceable { +public: + static constexpr const char *pyClassName = "MemRefLayoutMapList"; + + PyMemRefLayoutMapList(PyMemRefType type, intptr_t startIndex = 0, + intptr_t length = -1, intptr_t step = 1) + : Sliceable(startIndex, + length == -1 ? mlirMemRefTypeGetNumAffineMaps(type) : length, + step), + memref(type) {} + + intptr_t getNumElements() { return mlirMemRefTypeGetNumAffineMaps(memref); } + + PyAffineMap getElement(intptr_t index) { + return PyAffineMap(memref.getContext(), + mlirMemRefTypeGetAffineMap(memref, index)); + } + + PyMemRefLayoutMapList slice(intptr_t startIndex, intptr_t length, + intptr_t step) { + return PyMemRefLayoutMapList(memref, startIndex, length, step); + } + +private: + PyMemRefType memref; +}; + +PyMemRefLayoutMapList PyMemRefType::getLayout() { + return PyMemRefLayoutMapList(*this); +} + /// Unranked MemRef Type subclass - UnrankedMemRefType. class PyUnrankedMemRefType : public PyConcreteType { @@ -2711,9 +2751,275 @@ class PyFunctionType : public PyConcreteType { } // namespace //------------------------------------------------------------------------------ -// PyAffineMap. +// PyAffineExpr and subclasses. +//------------------------------------------------------------------------------ + +namespace { +/// CRTP base class for Python MLIR affine expressions that subclass AffineExpr +/// and should be castable from it. Intermediate hierarchy classes can be +/// modeled by specifying BaseTy. +template +class PyConcreteAffineExpr : public BaseTy { +public: + // Derived classes must define statics for: + // IsAFunctionTy isaFunction + // const char *pyClassName + // and redefine bindDerived. + using ClassTy = py::class_; + using IsAFunctionTy = bool (*)(MlirAffineExpr); + + PyConcreteAffineExpr() = default; + PyConcreteAffineExpr(PyMlirContextRef contextRef, MlirAffineExpr affineExpr) + : BaseTy(std::move(contextRef), affineExpr) {} + PyConcreteAffineExpr(PyAffineExpr &orig) + : PyConcreteAffineExpr(orig.getContext(), castFrom(orig)) {} + + static MlirAffineExpr castFrom(PyAffineExpr &orig) { + if (!DerivedTy::isaFunction(orig)) { + auto origRepr = py::repr(py::cast(orig)).cast(); + throw SetPyError(PyExc_ValueError, + Twine("Cannot cast affine expression to ") + + DerivedTy::pyClassName + " (from " + origRepr + ")"); + } + return orig; + } + + static void bind(py::module &m) { + auto cls = ClassTy(m, DerivedTy::pyClassName); + cls.def(py::init()); + DerivedTy::bindDerived(cls); + } + + /// Implemented by derived classes to add methods to the Python subclass. + static void bindDerived(ClassTy &m) {} +}; + +class PyAffineConstantExpr : public PyConcreteAffineExpr { +public: + static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsAConstant; + static constexpr const char *pyClassName = "AffineConstantExpr"; + using PyConcreteAffineExpr::PyConcreteAffineExpr; + + static PyAffineConstantExpr get(intptr_t value, + DefaultingPyMlirContext context) { + MlirAffineExpr affineExpr = + mlirAffineConstantExprGet(context->get(), static_cast(value)); + return PyAffineConstantExpr(context->getRef(), affineExpr); + } + + static void bindDerived(ClassTy &c) { + c.def_static("get", &PyAffineConstantExpr::get, py::arg("value"), + py::arg("context") = py::none()); + c.def_property_readonly("value", [](PyAffineConstantExpr &self) { + return mlirAffineConstantExprGetValue(self); + }); + } +}; + +class PyAffineDimExpr : public PyConcreteAffineExpr { +public: + static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsADim; + static constexpr const char *pyClassName = "AffineDimExpr"; + using PyConcreteAffineExpr::PyConcreteAffineExpr; + + static PyAffineDimExpr get(intptr_t pos, DefaultingPyMlirContext context) { + MlirAffineExpr affineExpr = mlirAffineDimExprGet(context->get(), pos); + return PyAffineDimExpr(context->getRef(), affineExpr); + } + + static void bindDerived(ClassTy &c) { + c.def_static("get", &PyAffineDimExpr::get, py::arg("position"), + py::arg("context") = py::none()); + c.def_property_readonly("position", [](PyAffineDimExpr &self) { + return mlirAffineDimExprGetPosition(self); + }); + } +}; + +class PyAffineSymbolExpr : public PyConcreteAffineExpr { +public: + static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsASymbol; + static constexpr const char *pyClassName = "AffineSymbolExpr"; + using PyConcreteAffineExpr::PyConcreteAffineExpr; + + static PyAffineSymbolExpr get(intptr_t pos, DefaultingPyMlirContext context) { + MlirAffineExpr affineExpr = mlirAffineSymbolExprGet(context->get(), pos); + return PyAffineSymbolExpr(context->getRef(), affineExpr); + } + + static void bindDerived(ClassTy &c) { + c.def_static("get", &PyAffineSymbolExpr::get, py::arg("position"), + py::arg("context") = py::none()); + c.def_property_readonly("position", [](PyAffineSymbolExpr &self) { + return mlirAffineSymbolExprGetPosition(self); + }); + } +}; + +class PyAffineBinaryExpr : public PyConcreteAffineExpr { +public: + static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsABinary; + static constexpr const char *pyClassName = "AffineBinaryExpr"; + using PyConcreteAffineExpr::PyConcreteAffineExpr; + + PyAffineExpr lhs() { + MlirAffineExpr lhsExpr = mlirAffineBinaryOpExprGetLHS(get()); + return PyAffineExpr(getContext(), lhsExpr); + } + + PyAffineExpr rhs() { + MlirAffineExpr rhsExpr = mlirAffineBinaryOpExprGetRHS(get()); + return PyAffineExpr(getContext(), rhsExpr); + } + + static void bindDerived(ClassTy &c) { + c.def_property_readonly("lhs", &PyAffineBinaryExpr::lhs); + c.def_property_readonly("rhs", &PyAffineBinaryExpr::rhs); + } +}; + +class PyAffineAddExpr + : public PyConcreteAffineExpr { +public: + static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsAAdd; + static constexpr const char *pyClassName = "AffineAddExpr"; + using PyConcreteAffineExpr::PyConcreteAffineExpr; + + static PyAffineAddExpr get(PyAffineExpr lhs, PyAffineExpr rhs) { + MlirAffineExpr expr = mlirAffineAddExprGet(lhs, rhs); + return PyAffineAddExpr(lhs.getContext(), expr); + } + + static void bindDerived(ClassTy &c) { + c.def_static("get", &PyAffineAddExpr::get); + } +}; + +class PyAffineMulExpr + : public PyConcreteAffineExpr { +public: + static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsAMul; + static constexpr const char *pyClassName = "AffineMulExpr"; + using PyConcreteAffineExpr::PyConcreteAffineExpr; + + static PyAffineMulExpr get(PyAffineExpr lhs, PyAffineExpr rhs) { + MlirAffineExpr expr = mlirAffineMulExprGet(lhs, rhs); + return PyAffineMulExpr(lhs.getContext(), expr); + } + + static void bindDerived(ClassTy &c) { + c.def_static("get", &PyAffineMulExpr::get); + } +}; + +class PyAffineModExpr + : public PyConcreteAffineExpr { +public: + static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsAMod; + static constexpr const char *pyClassName = "AffineModExpr"; + using PyConcreteAffineExpr::PyConcreteAffineExpr; + + static PyAffineModExpr get(PyAffineExpr lhs, PyAffineExpr rhs) { + MlirAffineExpr expr = mlirAffineModExprGet(lhs, rhs); + return PyAffineModExpr(lhs.getContext(), expr); + } + + static void bindDerived(ClassTy &c) { + c.def_static("get", &PyAffineModExpr::get); + } +}; + +class PyAffineFloorDivExpr + : public PyConcreteAffineExpr { +public: + static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsAFloorDiv; + static constexpr const char *pyClassName = "AffineFloorDivExpr"; + using PyConcreteAffineExpr::PyConcreteAffineExpr; + + static PyAffineFloorDivExpr get(PyAffineExpr lhs, PyAffineExpr rhs) { + MlirAffineExpr expr = mlirAffineFloorDivExprGet(lhs, rhs); + return PyAffineFloorDivExpr(lhs.getContext(), expr); + } + + static void bindDerived(ClassTy &c) { + c.def_static("get", &PyAffineFloorDivExpr::get); + } +}; + +class PyAffineCeilDivExpr + : public PyConcreteAffineExpr { +public: + static constexpr IsAFunctionTy isaFunction = mlirAffineExprIsACeilDiv; + static constexpr const char *pyClassName = "AffineCeilDivExpr"; + using PyConcreteAffineExpr::PyConcreteAffineExpr; + + static PyAffineCeilDivExpr get(PyAffineExpr lhs, PyAffineExpr rhs) { + MlirAffineExpr expr = mlirAffineCeilDivExprGet(lhs, rhs); + return PyAffineCeilDivExpr(lhs.getContext(), expr); + } + + static void bindDerived(ClassTy &c) { + c.def_static("get", &PyAffineCeilDivExpr::get); + } +}; +} // namespace + +bool PyAffineExpr::operator==(const PyAffineExpr &other) { + return mlirAffineExprEqual(affineExpr, other.affineExpr); +} + +py::object PyAffineExpr::getCapsule() { + return py::reinterpret_steal( + mlirPythonAffineExprToCapsule(*this)); +} + +PyAffineExpr PyAffineExpr::createFromCapsule(py::object capsule) { + MlirAffineExpr rawAffineExpr = mlirPythonCapsuleToAffineExpr(capsule.ptr()); + if (mlirAffineExprIsNull(rawAffineExpr)) + throw py::error_already_set(); + return PyAffineExpr( + PyMlirContext::forContext(mlirAffineExprGetContext(rawAffineExpr)), + rawAffineExpr); +} + +//------------------------------------------------------------------------------ +// PyAffineMap and utilities. //------------------------------------------------------------------------------ +namespace { +/// A list of expressions contained in an affine map. Internally these are +/// stored as a consecutive array leading to inexpensive random access. Both +/// the map and the expression are owned by the context so we need not bother +/// with lifetime extension. +class PyAffineMapExprList + : public Sliceable { +public: + static constexpr const char *pyClassName = "AffineExprList"; + + PyAffineMapExprList(PyAffineMap map, intptr_t startIndex = 0, + intptr_t length = -1, intptr_t step = 1) + : Sliceable(startIndex, + length == -1 ? mlirAffineMapGetNumResults(map) : length, + step), + affineMap(map) {} + + intptr_t getNumElements() { return mlirAffineMapGetNumResults(affineMap); } + + PyAffineExpr getElement(intptr_t pos) { + return PyAffineExpr(affineMap.getContext(), + mlirAffineMapGetResult(affineMap, pos)); + } + + PyAffineMapExprList slice(intptr_t startIndex, intptr_t length, + intptr_t step) { + return PyAffineMapExprList(affineMap, startIndex, length, step); + } + +private: + PyAffineMap affineMap; +}; +} // end namespace + bool PyAffineMap::operator==(const PyAffineMap &other) { return mlirAffineMapEqual(affineMap, other.affineMap); } @@ -3364,6 +3670,7 @@ void mlir::python::populateIRSubmodule(py::module &m) { PyRankedTensorType::bind(m); PyUnrankedTensorType::bind(m); PyMemRefType::bind(m); + PyMemRefLayoutMapList::bind(m); PyUnrankedMemRefType::bind(m); PyTupleType::bind(m); PyFunctionType::bind(m); @@ -3414,6 +3721,94 @@ void mlir::python::populateIRSubmodule(py::module &m) { PyRegionIterator::bind(m); PyRegionList::bind(m); + //---------------------------------------------------------------------------- + // Mapping of PyAffineExpr and derived classes. + //---------------------------------------------------------------------------- + py::class_(m, "AffineExpr") + .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, + &PyAffineExpr::getCapsule) + .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyAffineExpr::createFromCapsule) + .def("__add__", + [](PyAffineExpr &self, PyAffineExpr &other) { + return PyAffineAddExpr::get(self, other); + }) + .def("__mul__", + [](PyAffineExpr &self, PyAffineExpr &other) { + return PyAffineMulExpr::get(self, other); + }) + .def("__mod__", + [](PyAffineExpr &self, PyAffineExpr &other) { + return PyAffineModExpr::get(self, other); + }) + .def("__sub__", + [](PyAffineExpr &self, PyAffineExpr &other) { + auto negOne = + PyAffineConstantExpr::get(-1, *self.getContext().get()); + return PyAffineAddExpr::get(self, + PyAffineMulExpr::get(negOne, other)); + }) + .def("__eq__", [](PyAffineExpr &self, + PyAffineExpr &other) { return self == other; }) + .def("__eq__", + [](PyAffineExpr &self, py::object &other) { return false; }) + .def("__str__", + [](PyAffineExpr &self) { + PyPrintAccumulator printAccum; + mlirAffineExprPrint(self, printAccum.getCallback(), + printAccum.getUserData()); + return printAccum.join(); + }) + .def("__repr__", + [](PyAffineExpr &self) { + PyPrintAccumulator printAccum; + printAccum.parts.append("AffineExpr("); + mlirAffineExprPrint(self, printAccum.getCallback(), + printAccum.getUserData()); + printAccum.parts.append(")"); + return printAccum.join(); + }) + .def_property_readonly( + "context", + [](PyAffineExpr &self) { return self.getContext().getObject(); }) + .def_static( + "get_add", &PyAffineAddExpr::get, + "Gets an affine expression containing a sum of two expressions.") + .def_static( + "get_mul", &PyAffineMulExpr::get, + "Gets an affine expression containing a product of two expressions.") + .def_static("get_mod", &PyAffineModExpr::get, + "Gets an affine expression containing the modulo of dividing " + "one expression by another.") + .def_static("get_floor_div", &PyAffineFloorDivExpr::get, + "Gets an affine expression containing the rounded-down " + "result of dividing one expression by another.") + .def_static("get_ceil_div", &PyAffineCeilDivExpr::get, + "Gets an affine expression containing the rounded-up result " + "of dividing one expression by another.") + .def_static("get_constant", &PyAffineConstantExpr::get, py::arg("value"), + py::arg("context") = py::none(), + "Gets a constant affine expression with the given value.") + .def_static( + "get_dim", &PyAffineDimExpr::get, py::arg("position"), + py::arg("context") = py::none(), + "Gets an affine expression of a dimension at the given position.") + .def_static( + "get_symbol", &PyAffineSymbolExpr::get, py::arg("position"), + py::arg("context") = py::none(), + "Gets an affine expression of a symbol at the given position.") + .def( + "dump", [](PyAffineExpr &self) { mlirAffineExprDump(self); }, + kDumpDocstring); + PyAffineConstantExpr::bind(m); + PyAffineDimExpr::bind(m); + PyAffineSymbolExpr::bind(m); + PyAffineBinaryExpr::bind(m); + PyAffineAddExpr::bind(m); + PyAffineMulExpr::bind(m); + PyAffineModExpr::bind(m); + PyAffineFloorDivExpr::bind(m); + PyAffineCeilDivExpr::bind(m); + //---------------------------------------------------------------------------- // Mapping of PyAffineMap. //---------------------------------------------------------------------------- @@ -3421,6 +3816,72 @@ void mlir::python::populateIRSubmodule(py::module &m) { .def_property_readonly(MLIR_PYTHON_CAPI_PTR_ATTR, &PyAffineMap::getCapsule) .def(MLIR_PYTHON_CAPI_FACTORY_ATTR, &PyAffineMap::createFromCapsule) + .def("__eq__", + [](PyAffineMap &self, PyAffineMap &other) { return self == other; }) + .def("__eq__", [](PyAffineMap &self, py::object &other) { return false; }) + .def("__str__", + [](PyAffineMap &self) { + PyPrintAccumulator printAccum; + mlirAffineMapPrint(self, printAccum.getCallback(), + printAccum.getUserData()); + return printAccum.join(); + }) + .def("__repr__", + [](PyAffineMap &self) { + PyPrintAccumulator printAccum; + printAccum.parts.append("AffineMap("); + mlirAffineMapPrint(self, printAccum.getCallback(), + printAccum.getUserData()); + printAccum.parts.append(")"); + return printAccum.join(); + }) + .def_property_readonly( + "context", + [](PyAffineMap &self) { return self.getContext().getObject(); }, + "Context that owns the Affine Map") + .def( + "dump", [](PyAffineMap &self) { mlirAffineMapDump(self); }, + kDumpDocstring) + .def_static( + "get", + [](intptr_t dimCount, intptr_t symbolCount, py::list exprs, + DefaultingPyMlirContext context) { + SmallVector affineExprs; + affineExprs.reserve(py::len(exprs)); + for (py::handle expr : exprs) { + try { + affineExprs.push_back(expr.cast()); + } catch (py::cast_error &err) { + std::string msg = + std::string("Invalid expression when attempting to create " + "an AffineMap (") + + err.what() + ")"; + throw py::cast_error(msg); + } catch (py::reference_cast_error &err) { + std::string msg = + std::string("Invalid expression (None?) when attempting to " + "create an AffineMap (") + + err.what() + ")"; + throw py::cast_error(msg); + } + } + MlirAffineMap map = + mlirAffineMapGet(context->get(), dimCount, symbolCount, + affineExprs.size(), affineExprs.data()); + return PyAffineMap(context->getRef(), map); + }, + py::arg("dim_count"), py::arg("symbol_count"), py::arg("exprs"), + py::arg("context") = py::none(), + "Gets a map with the given expressions as results.") + .def_static( + "get_constant", + [](intptr_t value, DefaultingPyMlirContext context) { + MlirAffineMap affineMap = + mlirAffineMapConstantGet(context->get(), value); + return PyAffineMap(context->getRef(), affineMap); + }, + py::arg("value"), py::arg("context") = py::none(), + "Gets an affine map with a single constant result") .def_static( "get_empty", [](DefaultingPyMlirContext context) { @@ -3428,14 +3889,82 @@ void mlir::python::populateIRSubmodule(py::module &m) { return PyAffineMap(context->getRef(), affineMap); }, py::arg("context") = py::none(), "Gets an empty affine map.") + .def_static( + "get_identity", + [](intptr_t nDims, DefaultingPyMlirContext context) { + MlirAffineMap affineMap = + mlirAffineMapMultiDimIdentityGet(context->get(), nDims); + return PyAffineMap(context->getRef(), affineMap); + }, + py::arg("n_dims"), py::arg("context") = py::none(), + "Gets an identity map with the given number of dimensions.") + .def_static( + "get_minor_identity", + [](intptr_t nDims, intptr_t nResults, + DefaultingPyMlirContext context) { + MlirAffineMap affineMap = + mlirAffineMapMinorIdentityGet(context->get(), nDims, nResults); + return PyAffineMap(context->getRef(), affineMap); + }, + py::arg("n_dims"), py::arg("n_results"), + py::arg("context") = py::none(), + "Gets a minor identity map with the given number of dimensions and " + "results.") + .def_static( + "get_permutation", + [](std::vector permutation, + DefaultingPyMlirContext context) { + MlirAffineMap affineMap = mlirAffineMapPermutationGet( + context->get(), permutation.size(), permutation.data()); + return PyAffineMap(context->getRef(), affineMap); + }, + py::arg("permutation"), py::arg("context") = py::none(), + "Gets an affine map that permutes its inputs.") + .def("get_submap", + [](PyAffineMap &self, std::vector &resultPos) { + intptr_t numResults = mlirAffineMapGetNumResults(self); + for (intptr_t pos : resultPos) { + if (pos < 0 || pos >= numResults) + throw py::value_error("result position out of bounds"); + } + MlirAffineMap affineMap = mlirAffineMapGetSubMap( + self, resultPos.size(), resultPos.data()); + return PyAffineMap(self.getContext(), affineMap); + }) + .def("get_major_submap", + [](PyAffineMap &self, intptr_t nResults) { + if (nResults >= mlirAffineMapGetNumResults(self)) + throw py::value_error("number of results out of bounds"); + MlirAffineMap affineMap = + mlirAffineMapGetMajorSubMap(self, nResults); + return PyAffineMap(self.getContext(), affineMap); + }) + .def("get_minor_submap", + [](PyAffineMap &self, intptr_t nResults) { + if (nResults >= mlirAffineMapGetNumResults(self)) + throw py::value_error("number of results out of bounds"); + MlirAffineMap affineMap = + mlirAffineMapGetMinorSubMap(self, nResults); + return PyAffineMap(self.getContext(), affineMap); + }) .def_property_readonly( - "context", - [](PyAffineMap &self) { return self.getContext().getObject(); }, - "Context that owns the Affine Map") - .def("__eq__", - [](PyAffineMap &self, PyAffineMap &other) { return self == other; }) - .def("__eq__", [](PyAffineMap &self, py::object &other) { return false; }) - .def( - "dump", [](PyAffineMap &self) { mlirAffineMapDump(self); }, - kDumpDocstring); + "is_permutation", + [](PyAffineMap &self) { return mlirAffineMapIsPermutation(self); }) + .def_property_readonly("is_projected_permutation", + [](PyAffineMap &self) { + return mlirAffineMapIsProjectedPermutation(self); + }) + .def_property_readonly( + "n_dims", + [](PyAffineMap &self) { return mlirAffineMapGetNumDims(self); }) + .def_property_readonly( + "n_inputs", + [](PyAffineMap &self) { return mlirAffineMapGetNumInputs(self); }) + .def_property_readonly( + "n_symbols", + [](PyAffineMap &self) { return mlirAffineMapGetNumSymbols(self); }) + .def_property_readonly("results", [](PyAffineMap &self) { + return PyAffineMapExprList(self); + }); + PyAffineMapExprList::bind(m); } diff --git a/mlir/lib/Bindings/Python/IRModules.h b/mlir/lib/Bindings/Python/IRModules.h index 3438dd8c0270e3..e789f536a82947 100644 --- a/mlir/lib/Bindings/Python/IRModules.h +++ b/mlir/lib/Bindings/Python/IRModules.h @@ -13,6 +13,7 @@ #include "PybindUtils.h" +#include "mlir-c/AffineExpr.h" #include "mlir-c/AffineMap.h" #include "mlir-c/IR.h" #include "llvm/ADT/DenseMap.h" @@ -668,6 +669,34 @@ class PyValue { MlirValue value; }; +/// Wrapper around MlirAffineExpr. Affine expressions are owned by the context. +class PyAffineExpr : public BaseContextObject { +public: + PyAffineExpr(PyMlirContextRef contextRef, MlirAffineExpr affineExpr) + : BaseContextObject(std::move(contextRef)), affineExpr(affineExpr) {} + bool operator==(const PyAffineExpr &other); + operator MlirAffineExpr() const { return affineExpr; } + MlirAffineExpr get() const { return affineExpr; } + + /// Gets a capsule wrapping the void* within the MlirAffineExpr. + pybind11::object getCapsule(); + + /// Creates a PyAffineExpr from the MlirAffineExpr wrapped by a capsule. + /// Note that PyAffineExpr instances are uniqued, so the returned object + /// may be a pre-existing object. Ownership of the underlying MlirAffineExpr + /// is taken by calling this function. + static PyAffineExpr createFromCapsule(pybind11::object capsule); + + PyAffineExpr add(const PyAffineExpr &other) const; + PyAffineExpr mul(const PyAffineExpr &other) const; + PyAffineExpr floorDiv(const PyAffineExpr &other) const; + PyAffineExpr ceilDiv(const PyAffineExpr &other) const; + PyAffineExpr mod(const PyAffineExpr &other) const; + +private: + MlirAffineExpr affineExpr; +}; + class PyAffineMap : public BaseContextObject { public: PyAffineMap(PyMlirContextRef contextRef, MlirAffineMap affineMap) diff --git a/mlir/lib/Bindings/Python/LinalgOps.td b/mlir/lib/Bindings/Python/LinalgOps.td new file mode 100644 index 00000000000000..7650e954d59eee --- /dev/null +++ b/mlir/lib/Bindings/Python/LinalgOps.td @@ -0,0 +1,16 @@ +//===-- LinalgOps.td - Entry point for linalg bind ---------*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef PYTHON_BINDINGS_LINALG_OPS +#define PYTHON_BINDINGS_LINALG_OPS + +include "mlir/Bindings/Python/Attributes.td" +include "mlir/Dialect/Linalg/IR/LinalgOps.td" +include "mlir/Dialect/Linalg/IR/LinalgStructuredOps.td" + +#endif diff --git a/mlir/lib/Bindings/Python/ShapeOps.td b/mlir/lib/Bindings/Python/ShapeOps.td new file mode 100644 index 00000000000000..c469a586bb27e5 --- /dev/null +++ b/mlir/lib/Bindings/Python/ShapeOps.td @@ -0,0 +1,15 @@ +//===-- ShapeOps.td - Entry point for TensorOps bind -------*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef PYTHON_BINDINGS_SHAPE_OPS +#define PYTHON_BINDINGS_SHAPE_OPS + +include "mlir/Bindings/Python/Attributes.td" +include "mlir/Dialect/Shape/IR/ShapeOps.td" + +#endif diff --git a/mlir/lib/Bindings/Python/TensorOps.td b/mlir/lib/Bindings/Python/TensorOps.td new file mode 100644 index 00000000000000..40ecea7bfe8a17 --- /dev/null +++ b/mlir/lib/Bindings/Python/TensorOps.td @@ -0,0 +1,15 @@ +//===-- TensorOps.td - Entry point for TensorOps bind ------*- tablegen -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef PYTHON_BINDINGS_TENSOR_OPS +#define PYTHON_BINDINGS_TENSOR_OPS + +include "mlir/Bindings/Python/Attributes.td" +include "mlir/Dialect/Tensor/IR/TensorOps.td" + +#endif diff --git a/mlir/lib/CAPI/CMakeLists.txt b/mlir/lib/CAPI/CMakeLists.txt index 8bbee6a74c08f7..1ccf46204f9e9d 100644 --- a/mlir/lib/CAPI/CMakeLists.txt +++ b/mlir/lib/CAPI/CMakeLists.txt @@ -1,6 +1,6 @@ add_subdirectory(IR) add_subdirectory(Registration) -add_subdirectory(Standard) +add_subdirectory(Dialect) add_subdirectory(Transforms) diff --git a/mlir/lib/CAPI/Dialect/CMakeLists.txt b/mlir/lib/CAPI/Dialect/CMakeLists.txt new file mode 100644 index 00000000000000..d256309bf8f08f --- /dev/null +++ b/mlir/lib/CAPI/Dialect/CMakeLists.txt @@ -0,0 +1,48 @@ +# TODO: Make the check source feature optional as an argument on *_add_library. +set(LLVM_OPTIONAL_SOURCES + Linalg.cpp + SCF.cpp + Shape.cpp + Standard.cpp + Tensor.cpp +) + +add_mlir_public_c_api_library(MLIRCAPILinalg + Linalg.cpp + + LINK_LIBS PUBLIC + MLIRCAPIIR + MLIRLinalg +) + +add_mlir_public_c_api_library(MLIRCAPISCF + SCF.cpp + + LINK_LIBS PUBLIC + MLIRCAPIIR + MLIRSCF +) + +add_mlir_public_c_api_library(MLIRCAPIShape + Shape.cpp + + LINK_LIBS PUBLIC + MLIRCAPIIR + MLIRShape +) + +add_mlir_public_c_api_library(MLIRCAPIStandard + Standard.cpp + + LINK_LIBS PUBLIC + MLIRCAPIIR + MLIRStandard +) + +add_mlir_public_c_api_library(MLIRCAPITensor + Tensor.cpp + + LINK_LIBS PUBLIC + MLIRCAPIIR + MLIRTensor +) diff --git a/mlir/lib/CAPI/Dialect/Linalg.cpp b/mlir/lib/CAPI/Dialect/Linalg.cpp new file mode 100644 index 00000000000000..3e45c41adc72c7 --- /dev/null +++ b/mlir/lib/CAPI/Dialect/Linalg.cpp @@ -0,0 +1,14 @@ +//===- Linalg.cpp - C Interface for Linalg dialect ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "mlir-c/Dialect/Linalg.h" +#include "mlir/CAPI/Registration.h" +#include "mlir/Dialect/Linalg/IR/LinalgOps.h" + +MLIR_DEFINE_CAPI_DIALECT_REGISTRATION(Linalg, linalg, + mlir::linalg::LinalgDialect); diff --git a/mlir/lib/CAPI/Dialect/SCF.cpp b/mlir/lib/CAPI/Dialect/SCF.cpp new file mode 100644 index 00000000000000..f81b010b04e21f --- /dev/null +++ b/mlir/lib/CAPI/Dialect/SCF.cpp @@ -0,0 +1,13 @@ +//===- SCF.cpp - C Interface for SCF dialect ------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "mlir/Dialect/SCF/SCF.h" +#include "mlir-c/Dialect/SCF.h" +#include "mlir/CAPI/Registration.h" + +MLIR_DEFINE_CAPI_DIALECT_REGISTRATION(SCF, scf, mlir::scf::SCFDialect); diff --git a/mlir/lib/CAPI/Dialect/Shape.cpp b/mlir/lib/CAPI/Dialect/Shape.cpp new file mode 100644 index 00000000000000..22e20ad8eaaac3 --- /dev/null +++ b/mlir/lib/CAPI/Dialect/Shape.cpp @@ -0,0 +1,13 @@ +//===- Shape.cpp - C Interface for Shape dialect --------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "mlir/Dialect/Shape/IR/Shape.h" +#include "mlir-c/Dialect/Shape.h" +#include "mlir/CAPI/Registration.h" + +MLIR_DEFINE_CAPI_DIALECT_REGISTRATION(Shape, shape, mlir::shape::ShapeDialect); diff --git a/mlir/lib/CAPI/Dialect/Standard.cpp b/mlir/lib/CAPI/Dialect/Standard.cpp new file mode 100644 index 00000000000000..b611cb85f6f62b --- /dev/null +++ b/mlir/lib/CAPI/Dialect/Standard.cpp @@ -0,0 +1,13 @@ +//===- Standard.cpp - C Interface for Standard dialect --------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "mlir-c/Dialect/Standard.h" +#include "mlir/CAPI/Registration.h" +#include "mlir/Dialect/StandardOps/IR/Ops.h" + +MLIR_DEFINE_CAPI_DIALECT_REGISTRATION(Standard, std, mlir::StandardOpsDialect); diff --git a/mlir/lib/CAPI/Dialect/Tensor.cpp b/mlir/lib/CAPI/Dialect/Tensor.cpp new file mode 100644 index 00000000000000..8f336c0bf3c4dc --- /dev/null +++ b/mlir/lib/CAPI/Dialect/Tensor.cpp @@ -0,0 +1,14 @@ +//===- Tensor.cpp - C Interface for Tensor dialect ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "mlir/Dialect/Tensor/IR/Tensor.h" +#include "mlir-c/Dialect/Tensor.h" +#include "mlir/CAPI/Registration.h" + +MLIR_DEFINE_CAPI_DIALECT_REGISTRATION(Tensor, tensor, + mlir::tensor::TensorDialect); diff --git a/mlir/lib/CAPI/IR/AffineExpr.cpp b/mlir/lib/CAPI/IR/AffineExpr.cpp index 01793192b05c98..2d8bc3ce569afd 100644 --- a/mlir/lib/CAPI/IR/AffineExpr.cpp +++ b/mlir/lib/CAPI/IR/AffineExpr.cpp @@ -21,6 +21,10 @@ MlirContext mlirAffineExprGetContext(MlirAffineExpr affineExpr) { return wrap(unwrap(affineExpr).getContext()); } +bool mlirAffineExprEqual(MlirAffineExpr lhs, MlirAffineExpr rhs) { + return unwrap(lhs) == unwrap(rhs); +} + void mlirAffineExprPrint(MlirAffineExpr affineExpr, MlirStringCallback callback, void *userData) { mlir::detail::CallbackOstream stream(callback, userData); @@ -56,6 +60,10 @@ bool mlirAffineExprIsFunctionOfDim(MlirAffineExpr affineExpr, // Affine Dimension Expression. //===----------------------------------------------------------------------===// +bool mlirAffineExprIsADim(MlirAffineExpr affineExpr) { + return unwrap(affineExpr).isa(); +} + MlirAffineExpr mlirAffineDimExprGet(MlirContext ctx, intptr_t position) { return wrap(getAffineDimExpr(position, unwrap(ctx))); } @@ -68,6 +76,10 @@ intptr_t mlirAffineDimExprGetPosition(MlirAffineExpr affineExpr) { // Affine Symbol Expression. //===----------------------------------------------------------------------===// +bool mlirAffineExprIsASymbol(MlirAffineExpr affineExpr) { + return unwrap(affineExpr).isa(); +} + MlirAffineExpr mlirAffineSymbolExprGet(MlirContext ctx, intptr_t position) { return wrap(getAffineSymbolExpr(position, unwrap(ctx))); } @@ -80,6 +92,10 @@ intptr_t mlirAffineSymbolExprGetPosition(MlirAffineExpr affineExpr) { // Affine Constant Expression. //===----------------------------------------------------------------------===// +bool mlirAffineExprIsAConstant(MlirAffineExpr affineExpr) { + return unwrap(affineExpr).isa(); +} + MlirAffineExpr mlirAffineConstantExprGet(MlirContext ctx, int64_t constant) { return wrap(getAffineConstantExpr(constant, unwrap(ctx))); } @@ -159,6 +175,10 @@ MlirAffineExpr mlirAffineCeilDivExprGet(MlirAffineExpr lhs, // Affine Binary Operation Expression. //===----------------------------------------------------------------------===// +bool mlirAffineExprIsABinary(MlirAffineExpr affineExpr) { + return unwrap(affineExpr).isa(); +} + MlirAffineExpr mlirAffineBinaryOpExprGetLHS(MlirAffineExpr affineExpr) { return wrap(unwrap(affineExpr).cast().getLHS()); } diff --git a/mlir/lib/CAPI/IR/AffineMap.cpp b/mlir/lib/CAPI/IR/AffineMap.cpp index ac81586144f553..f532d5dae72e0c 100644 --- a/mlir/lib/CAPI/IR/AffineMap.cpp +++ b/mlir/lib/CAPI/IR/AffineMap.cpp @@ -8,6 +8,7 @@ #include "mlir-c/AffineMap.h" #include "mlir-c/IR.h" +#include "mlir/CAPI/AffineExpr.h" #include "mlir/CAPI/AffineMap.h" #include "mlir/CAPI/IR.h" #include "mlir/CAPI/Utils.h" @@ -37,11 +38,19 @@ MlirAffineMap mlirAffineMapEmptyGet(MlirContext ctx) { return wrap(AffineMap::get(unwrap(ctx))); } -MlirAffineMap mlirAffineMapGet(MlirContext ctx, intptr_t dimCount, - intptr_t symbolCount) { +MlirAffineMap mlirAffineMapZeroResultGet(MlirContext ctx, intptr_t dimCount, + intptr_t symbolCount) { return wrap(AffineMap::get(dimCount, symbolCount, unwrap(ctx))); } +MlirAffineMap mlirAffineMapGet(MlirContext ctx, intptr_t dimCount, + intptr_t symbolCount, intptr_t nAffineExprs, + MlirAffineExpr *affineExprs) { + SmallVector exprs; + ArrayRef exprList = unwrapList(nAffineExprs, affineExprs, exprs); + return wrap(AffineMap::get(dimCount, symbolCount, exprList, unwrap(ctx))); +} + MlirAffineMap mlirAffineMapConstantGet(MlirContext ctx, int64_t val) { return wrap(AffineMap::getConstantMap(val, unwrap(ctx))); } @@ -94,6 +103,10 @@ intptr_t mlirAffineMapGetNumResults(MlirAffineMap affineMap) { return unwrap(affineMap).getNumResults(); } +MlirAffineExpr mlirAffineMapGetResult(MlirAffineMap affineMap, intptr_t pos) { + return wrap(unwrap(affineMap).getResult(static_cast(pos))); +} + intptr_t mlirAffineMapGetNumInputs(MlirAffineMap affineMap) { return unwrap(affineMap).getNumInputs(); } diff --git a/mlir/lib/CAPI/IR/BuiltinTypes.cpp b/mlir/lib/CAPI/IR/BuiltinTypes.cpp index f0c2901f5e100a..2de2fa1afde294 100644 --- a/mlir/lib/CAPI/IR/BuiltinTypes.cpp +++ b/mlir/lib/CAPI/IR/BuiltinTypes.cpp @@ -231,6 +231,17 @@ MlirType mlirMemRefTypeGet(MlirType elementType, intptr_t rank, unwrap(elementType), maps, memorySpace)); } +MlirType mlirMemRefTypeGetChecked(MlirType elementType, intptr_t rank, + const int64_t *shape, intptr_t numMaps, + MlirAffineMap const *affineMaps, + unsigned memorySpace, MlirLocation loc) { + SmallVector maps; + (void)unwrapList(numMaps, affineMaps, maps); + return wrap(MemRefType::getChecked( + unwrap(loc), llvm::makeArrayRef(shape, static_cast(rank)), + unwrap(elementType), maps, memorySpace)); +} + MlirType mlirMemRefTypeContiguousGet(MlirType elementType, intptr_t rank, const int64_t *shape, unsigned memorySpace) { diff --git a/mlir/lib/CAPI/Standard/CMakeLists.txt b/mlir/lib/CAPI/Standard/CMakeLists.txt deleted file mode 100644 index 197fea4ce4b2da..00000000000000 --- a/mlir/lib/CAPI/Standard/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -add_mlir_public_c_api_library(MLIRCAPIStandard - StandardDialect.cpp - - LINK_LIBS PUBLIC - MLIRCAPIIR - MLIRStandard -) diff --git a/mlir/lib/CAPI/Standard/StandardDialect.cpp b/mlir/lib/CAPI/Standard/StandardDialect.cpp deleted file mode 100644 index f78c9c916873e8..00000000000000 --- a/mlir/lib/CAPI/Standard/StandardDialect.cpp +++ /dev/null @@ -1,25 +0,0 @@ -//===- StandardDialect.cpp - C Interface for Standard dialect -------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "mlir-c/StandardDialect.h" -#include "mlir-c/IR.h" -#include "mlir/CAPI/IR.h" -#include "mlir/CAPI/Support.h" -#include "mlir/Dialect/StandardOps/IR/Ops.h" - -void mlirContextRegisterStandardDialect(MlirContext context) { - unwrap(context)->getDialectRegistry().insert(); -} - -MlirDialect mlirContextLoadStandardDialect(MlirContext context) { - return wrap(unwrap(context)->getOrLoadDialect()); -} - -MlirStringRef mlirStandardDialectGetNamespace() { - return wrap(mlir::StandardOpsDialect::getDialectNamespace()); -} diff --git a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp index 48843272295910..587f4975444615 100644 --- a/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp +++ b/mlir/lib/Conversion/AsyncToLLVM/AsyncToLLVM.cpp @@ -1132,6 +1132,71 @@ void ConvertAsyncToLLVMPass::runOnOperation() { } } // namespace +namespace { +class ConvertExecuteOpTypes : public OpConversionPattern { +public: + using OpConversionPattern::OpConversionPattern; + LogicalResult + matchAndRewrite(ExecuteOp op, ArrayRef operands, + ConversionPatternRewriter &rewriter) const override { + ExecuteOp newOp = + cast(rewriter.cloneWithoutRegions(*op.getOperation())); + rewriter.inlineRegionBefore(op.getRegion(), newOp.getRegion(), + newOp.getRegion().end()); + + // Set operands and update block argument and result types. + newOp->setOperands(operands); + if (failed(rewriter.convertRegionTypes(&newOp.getRegion(), *typeConverter))) + return failure(); + for (auto result : newOp.getResults()) + result.setType(typeConverter->convertType(result.getType())); + + rewriter.replaceOp(op, newOp.getResults()); + return success(); + } +}; + +// Dummy pattern to trigger the appropriate type conversion / materialization. +class ConvertAwaitOpTypes : public OpConversionPattern { +public: + using OpConversionPattern::OpConversionPattern; + LogicalResult + matchAndRewrite(AwaitOp op, ArrayRef operands, + ConversionPatternRewriter &rewriter) const override { + rewriter.replaceOpWithNewOp(op, operands.front()); + return success(); + } +}; + +// Dummy pattern to trigger the appropriate type conversion / materialization. +class ConvertYieldOpTypes : public OpConversionPattern { +public: + using OpConversionPattern::OpConversionPattern; + LogicalResult + matchAndRewrite(async::YieldOp op, ArrayRef operands, + ConversionPatternRewriter &rewriter) const override { + rewriter.replaceOpWithNewOp(op, operands); + return success(); + } +}; +} // namespace + std::unique_ptr> mlir::createConvertAsyncToLLVMPass() { return std::make_unique(); } + +void mlir::populateAsyncStructuralTypeConversionsAndLegality( + MLIRContext *context, TypeConverter &typeConverter, + OwningRewritePatternList &patterns, ConversionTarget &target) { + typeConverter.addConversion([&](TokenType type) { return type; }); + typeConverter.addConversion([&](ValueType type) { + return ValueType::get(typeConverter.convertType(type.getValueType())); + }); + + patterns + .insert( + typeConverter, context); + + target.addDynamicallyLegalOp( + [&](Operation *op) { return typeConverter.isLegal(op); }); +} diff --git a/mlir/lib/IR/BuiltinTypes.cpp b/mlir/lib/IR/BuiltinTypes.cpp index b4fc53d9f097d5..af8fdf38144272 100644 --- a/mlir/lib/IR/BuiltinTypes.cpp +++ b/mlir/lib/IR/BuiltinTypes.cpp @@ -31,14 +31,6 @@ using namespace mlir::detail; /// ComplexType //===----------------------------------------------------------------------===// -ComplexType ComplexType::get(Type elementType) { - return Base::get(elementType.getContext(), elementType); -} - -ComplexType ComplexType::getChecked(Location location, Type elementType) { - return Base::getChecked(location, elementType); -} - /// Verify the construction of an integer type. LogicalResult ComplexType::verifyConstructionInvariants(Location loc, Type elementType) { @@ -47,8 +39,6 @@ LogicalResult ComplexType::verifyConstructionInvariants(Location loc, return success(); } -Type ComplexType::getElementType() { return getImpl()->elementType; } - //===----------------------------------------------------------------------===// // Integer Type //===----------------------------------------------------------------------===// @@ -126,11 +116,6 @@ FloatType FloatType::scaleElementBitwidth(unsigned scale) { // FunctionType //===----------------------------------------------------------------------===// -FunctionType FunctionType::get(MLIRContext *context, TypeRange inputs, - TypeRange results) { - return Base::get(context, inputs, results); -} - unsigned FunctionType::getNumInputs() const { return getImpl()->numInputs; } ArrayRef FunctionType::getInputs() const { @@ -189,24 +174,6 @@ FunctionType::getWithoutArgsAndResults(ArrayRef argIndices, // OpaqueType //===----------------------------------------------------------------------===// -OpaqueType OpaqueType::get(MLIRContext *context, Identifier dialect, - StringRef typeData) { - return Base::get(context, dialect, typeData); -} - -OpaqueType OpaqueType::getChecked(Location location, Identifier dialect, - StringRef typeData) { - return Base::getChecked(location, dialect, typeData); -} - -/// Returns the dialect namespace of the opaque type. -Identifier OpaqueType::getDialectNamespace() const { - return getImpl()->dialectNamespace; -} - -/// Returns the raw type data of the opaque type. -StringRef OpaqueType::getTypeData() const { return getImpl()->typeData; } - /// Verify the construction of an opaque type. LogicalResult OpaqueType::verifyConstructionInvariants(Location loc, Identifier dialect, @@ -693,15 +660,6 @@ LogicalResult mlir::getStridesAndOffset(MemRefType t, /// TupleType //===----------------------------------------------------------------------===// -/// Get or create a new TupleType with the provided element types. Assumes the -/// arguments define a well-formed type. -TupleType TupleType::get(MLIRContext *context, TypeRange elementTypes) { - return Base::get(context, elementTypes); -} - -/// Get or create an empty tuple type. -TupleType TupleType::get(MLIRContext *context) { return get(context, {}); } - /// Return the elements types for this tuple. ArrayRef TupleType::getTypes() const { return getImpl()->getTypes(); } @@ -721,6 +679,10 @@ void TupleType::getFlattenedTypes(SmallVectorImpl &types) { /// Return the number of element types. size_t TupleType::size() const { return getImpl()->size(); } +//===----------------------------------------------------------------------===// +// Type Utilities +//===----------------------------------------------------------------------===// + AffineMap mlir::makeStridedLinearLayoutMap(ArrayRef strides, int64_t offset, MLIRContext *context) { diff --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp index 0837a65116691d..3afc10876c73a9 100644 --- a/mlir/lib/IR/MLIRContext.cpp +++ b/mlir/lib/IR/MLIRContext.cpp @@ -772,10 +772,6 @@ getCachedIntegerType(unsigned width, } } -IntegerType IntegerType::get(MLIRContext *context, unsigned width) { - return get(context, width, IntegerType::Signless); -} - IntegerType IntegerType::get(MLIRContext *context, unsigned width, IntegerType::SignednessSemantics signedness) { if (auto cached = getCachedIntegerType(width, signedness, context)) @@ -783,10 +779,6 @@ IntegerType IntegerType::get(MLIRContext *context, unsigned width, return Base::get(context, width, signedness); } -IntegerType IntegerType::getChecked(Location location, unsigned width) { - return getChecked(location, width, IntegerType::Signless); -} - IntegerType IntegerType::getChecked(Location location, unsigned width, SignednessSemantics signedness) { if (auto cached = diff --git a/mlir/lib/IR/TypeDetail.h b/mlir/lib/IR/TypeDetail.h index cd027cde722b79..1973fdd60f0087 100644 --- a/mlir/lib/IR/TypeDetail.h +++ b/mlir/lib/IR/TypeDetail.h @@ -27,31 +27,6 @@ class MLIRContext; namespace detail { -/// Opaque Type Storage and Uniquing. -struct OpaqueTypeStorage : public TypeStorage { - OpaqueTypeStorage(Identifier dialectNamespace, StringRef typeData) - : dialectNamespace(dialectNamespace), typeData(typeData) {} - - /// The hash key used for uniquing. - using KeyTy = std::pair; - bool operator==(const KeyTy &key) const { - return key == KeyTy(dialectNamespace, typeData); - } - - static OpaqueTypeStorage *construct(TypeStorageAllocator &allocator, - const KeyTy &key) { - StringRef tyData = allocator.copyInto(key.second); - return new (allocator.allocate()) - OpaqueTypeStorage(key.first, tyData); - } - - // The dialect namespace. - Identifier dialectNamespace; - - // The parser type data for this opaque type. - StringRef typeData; -}; - /// Integer Type Storage and Uniquing. struct IntegerTypeStorage : public TypeStorage { IntegerTypeStorage(unsigned width, @@ -290,24 +265,6 @@ struct UnrankedMemRefTypeStorage : public BaseMemRefTypeStorage { } }; -/// Complex Type Storage. -struct ComplexTypeStorage : public TypeStorage { - ComplexTypeStorage(Type elementType) : elementType(elementType) {} - - /// The hash key used for uniquing. - using KeyTy = Type; - bool operator==(const KeyTy &key) const { return key == elementType; } - - /// Construction. - static ComplexTypeStorage *construct(TypeStorageAllocator &allocator, - Type elementType) { - return new (allocator.allocate()) - ComplexTypeStorage(elementType); - } - - Type elementType; -}; - /// A type representing a collection of other types. struct TupleTypeStorage final : public TypeStorage, diff --git a/mlir/lib/TableGen/Builder.cpp b/mlir/lib/TableGen/Builder.cpp new file mode 100644 index 00000000000000..8210e8fe1a126e --- /dev/null +++ b/mlir/lib/TableGen/Builder.cpp @@ -0,0 +1,74 @@ +//===- Builder.cpp - Builder definitions ----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "mlir/TableGen/Builder.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" + +using namespace mlir; +using namespace mlir::tblgen; + +//===----------------------------------------------------------------------===// +// Builder::Parameter +//===----------------------------------------------------------------------===// + +/// Return a string containing the C++ type of this parameter. +StringRef Builder::Parameter::getCppType() const { + if (const auto *stringInit = dyn_cast(def)) + return stringInit->getValue(); + const llvm::Record *record = cast(def)->getDef(); + return record->getValueAsString("type"); +} + +/// Return an optional string containing the default value to use for this +/// parameter. +Optional Builder::Parameter::getDefaultValue() const { + if (isa(def)) + return llvm::None; + const llvm::Record *record = cast(def)->getDef(); + Optional value = record->getValueAsOptionalString("defaultValue"); + return value && !value->empty() ? value : llvm::None; +} + +//===----------------------------------------------------------------------===// +// Builder +//===----------------------------------------------------------------------===// + +Builder::Builder(const llvm::Record *record, ArrayRef loc) + : def(record) { + // Initialize the parameters of the builder. + const llvm::DagInit *dag = def->getValueAsDag("dagParams"); + auto *defInit = dyn_cast(dag->getOperator()); + if (!defInit || !defInit->getDef()->getName().equals("ins")) + PrintFatalError(def->getLoc(), "expected 'ins' in builders"); + + bool seenDefaultValue = false; + for (unsigned i = 0, e = dag->getNumArgs(); i < e; ++i) { + const llvm::StringInit *paramName = dag->getArgName(i); + const llvm::Init *paramValue = dag->getArg(i); + Parameter param(paramName ? paramName->getValue() : Optional(), + paramValue); + + // Similarly to C++, once an argument with a default value is detected, the + // following arguments must have default values as well. + if (param.getDefaultValue()) { + seenDefaultValue = true; + } else if (seenDefaultValue) { + PrintFatalError(loc, + "expected an argument with default value after other " + "arguments with default values"); + } + parameters.emplace_back(param); + } +} + +/// Return an optional string containing the body of the builder. +Optional Builder::getBody() const { + Optional body = def->getValueAsOptionalString("body"); + return body && !body->empty() ? body : llvm::None; +} diff --git a/mlir/lib/TableGen/CMakeLists.txt b/mlir/lib/TableGen/CMakeLists.txt index a11473b9370c2c..fa52dde27a4019 100644 --- a/mlir/lib/TableGen/CMakeLists.txt +++ b/mlir/lib/TableGen/CMakeLists.txt @@ -11,6 +11,7 @@ llvm_add_library(MLIRTableGen STATIC Argument.cpp Attribute.cpp + Builder.cpp Constraint.cpp Dialect.cpp Format.cpp diff --git a/mlir/lib/TableGen/Operator.cpp b/mlir/lib/TableGen/Operator.cpp index ca1442f547d56b..209c1ec0d94a79 100644 --- a/mlir/lib/TableGen/Operator.cpp +++ b/mlir/lib/TableGen/Operator.cpp @@ -521,6 +521,18 @@ void Operator::populateOpStructure() { regions.push_back({name, region}); } + // Populate the builders. + auto *builderList = + dyn_cast_or_null(def.getValueInit("builders")); + if (builderList && !builderList->empty()) { + for (llvm::Init *init : builderList->getValues()) + builders.emplace_back(cast(init)->getDef(), def.getLoc()); + } else if (skipDefaultBuilders()) { + PrintFatalError( + def.getLoc(), + "default builders are skipped and no custom builders provided"); + } + LLVM_DEBUG(print(llvm::dbgs())); } diff --git a/mlir/lib/TableGen/TypeDef.cpp b/mlir/lib/TableGen/TypeDef.cpp index 5c4f5348d1b3bf..d6adbc20ef7607 100644 --- a/mlir/lib/TableGen/TypeDef.cpp +++ b/mlir/lib/TableGen/TypeDef.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "mlir/TableGen/TypeDef.h" +#include "mlir/TableGen/Dialect.h" #include "llvm/ADT/StringExtras.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" @@ -18,6 +19,26 @@ using namespace mlir; using namespace mlir::tblgen; +//===----------------------------------------------------------------------===// +// TypeBuilder +//===----------------------------------------------------------------------===// + +/// Return an optional code body used for the `getChecked` variant of this +/// builder. +Optional TypeBuilder::getCheckedBody() const { + Optional body = def->getValueAsOptionalString("checkedBody"); + return body && !body->empty() ? body : llvm::None; +} + +/// Returns true if this builder is able to infer the MLIRContext parameter. +bool TypeBuilder::hasInferredContextParameter() const { + return def->getValueAsBit("hasInferredContextParam"); +} + +//===----------------------------------------------------------------------===// +// TypeDef +//===----------------------------------------------------------------------===// + Dialect TypeDef::getDialect() const { auto *dialectDef = dyn_cast(def->getValue("dialect")->getValue()); @@ -98,6 +119,11 @@ llvm::Optional TypeDef::getExtraDecls() const { return value.empty() ? llvm::Optional() : value; } llvm::ArrayRef TypeDef::getLoc() const { return def->getLoc(); } + +bool TypeDef::skipDefaultBuilders() const { + return def->getValueAsBit("skipDefaultBuilders"); +} + bool TypeDef::operator==(const TypeDef &other) const { return def == other.def; } @@ -106,6 +132,33 @@ bool TypeDef::operator<(const TypeDef &other) const { return getName() < other.getName(); } +//===----------------------------------------------------------------------===// +// TypeParameter +//===----------------------------------------------------------------------===// + +TypeDef::TypeDef(const llvm::Record *def) : def(def) { + // Populate the builders. + auto *builderList = + dyn_cast_or_null(def->getValueInit("builders")); + if (builderList && !builderList->empty()) { + for (llvm::Init *init : builderList->getValues()) { + TypeBuilder builder(cast(init)->getDef(), def->getLoc()); + + // Ensure that all parameters have names. + for (const TypeBuilder::Parameter ¶m : builder.getParameters()) { + if (!param.getName()) + PrintFatalError(def->getLoc(), + "type builder parameters must have a name"); + } + builders.emplace_back(builder); + } + } else if (skipDefaultBuilders()) { + PrintFatalError( + def->getLoc(), + "default builders are skipped and no custom builders provided"); + } +} + StringRef TypeParameter::getName() const { return def->getArgName(num)->getValue(); } diff --git a/mlir/test/Bindings/Python/CMakeLists.txt b/mlir/test/Bindings/Python/CMakeLists.txt index 619f4e317c9638..666bd9fd1cec38 100644 --- a/mlir/test/Bindings/Python/CMakeLists.txt +++ b/mlir/test/Bindings/Python/CMakeLists.txt @@ -1,4 +1,4 @@ include(AddMLIRPythonExtension) add_mlir_dialect_python_bindings(MLIRBindingsPythonTestOps - python_test_ops.td - python_test) + TD_FILE python_test_ops.td + DIALECT_NAME python_test) diff --git a/mlir/test/Bindings/Python/ir_affine_expr.py b/mlir/test/Bindings/Python/ir_affine_expr.py new file mode 100644 index 00000000000000..eb58579448cae1 --- /dev/null +++ b/mlir/test/Bindings/Python/ir_affine_expr.py @@ -0,0 +1,275 @@ +# RUN: %PYTHON %s | FileCheck %s + +import gc +from mlir.ir import * + +def run(f): + print("\nTEST:", f.__name__) + f() + gc.collect() + assert Context._get_live_count() == 0 + + +# CHECK-LABEL: TEST: testAffineExprCapsule +def testAffineExprCapsule(): + with Context() as ctx: + affine_expr = AffineExpr.get_constant(42) + + affine_expr_capsule = affine_expr._CAPIPtr + # CHECK: capsule object + # CHECK: mlir.ir.AffineExpr._CAPIPtr + print(affine_expr_capsule) + + affine_expr_2 = AffineExpr._CAPICreate(affine_expr_capsule) + assert affine_expr == affine_expr_2 + assert affine_expr_2.context == ctx + +run(testAffineExprCapsule) + + +# CHECK-LABEL: TEST: testAffineExprEq +def testAffineExprEq(): + with Context(): + a1 = AffineExpr.get_constant(42) + a2 = AffineExpr.get_constant(42) + a3 = AffineExpr.get_constant(43) + # CHECK: True + print(a1 == a1) + # CHECK: True + print(a1 == a2) + # CHECK: False + print(a1 == a3) + # CHECK: False + print(a1 == None) + # CHECK: False + print(a1 == "foo") + +run(testAffineExprEq) + + +# CHECK-LABEL: TEST: testAffineExprContext +def testAffineExprContext(): + with Context(): + a1 = AffineExpr.get_constant(42) + with Context(): + a2 = AffineExpr.get_constant(42) + + # CHECK: False + print(a1 == a2) + +run(testAffineExprContext) + + +# CHECK-LABEL: TEST: testAffineExprConstant +def testAffineExprConstant(): + with Context(): + a1 = AffineExpr.get_constant(42) + # CHECK: 42 + print(a1.value) + # CHECK: 42 + print(a1) + + a2 = AffineConstantExpr.get(42) + # CHECK: 42 + print(a2.value) + # CHECK: 42 + print(a2) + + assert a1 == a2 + +run(testAffineExprConstant) + + +# CHECK-LABEL: TEST: testAffineExprDim +def testAffineExprDim(): + with Context(): + d1 = AffineExpr.get_dim(1) + d11 = AffineDimExpr.get(1) + d2 = AffineDimExpr.get(2) + + # CHECK: 1 + print(d1.position) + # CHECK: d1 + print(d1) + + # CHECK: 2 + print(d2.position) + # CHECK: d2 + print(d2) + + assert d1 == d11 + assert d1 != d2 + +run(testAffineExprDim) + + +# CHECK-LABEL: TEST: testAffineExprSymbol +def testAffineExprSymbol(): + with Context(): + s1 = AffineExpr.get_symbol(1) + s11 = AffineSymbolExpr.get(1) + s2 = AffineSymbolExpr.get(2) + + # CHECK: 1 + print(s1.position) + # CHECK: s1 + print(s1) + + # CHECK: 2 + print(s2.position) + # CHEKC: s2 + print(s2) + + assert s1 == s11 + assert s1 != s2 + +run(testAffineExprSymbol) + + +# CHECK-LABEL: TEST: testAffineAddExpr +def testAffineAddExpr(): + with Context(): + d1 = AffineDimExpr.get(1) + d2 = AffineDimExpr.get(2) + d12 = AffineExpr.get_add(d1, d2) + # CHECK: d1 + d2 + print(d12) + + d12op = d1 + d2 + # CHECK: d1 + d2 + print(d12op) + + assert d12 == d12op + assert d12.lhs == d1 + assert d12.rhs == d2 + +run(testAffineAddExpr) + + +# CHECK-LABEL: TEST: testAffineMulExpr +def testAffineMulExpr(): + with Context(): + d1 = AffineDimExpr.get(1) + c2 = AffineConstantExpr.get(2) + expr = AffineExpr.get_mul(d1, c2) + # CHECK: d1 * 2 + print(expr) + + # CHECK: d1 * 2 + op = d1 * c2 + print(op) + + assert expr == op + assert expr.lhs == d1 + assert expr.rhs == c2 + +run(testAffineMulExpr) + + +# CHECK-LABEL: TEST: testAffineModExpr +def testAffineModExpr(): + with Context(): + d1 = AffineDimExpr.get(1) + c2 = AffineConstantExpr.get(2) + expr = AffineExpr.get_mod(d1, c2) + # CHECK: d1 mod 2 + print(expr) + + # CHECK: d1 mod 2 + op = d1 % c2 + print(op) + + assert expr == op + assert expr.lhs == d1 + assert expr.rhs == c2 + +run(testAffineModExpr) + + +# CHECK-LABEL: TEST: testAffineFloorDivExpr +def testAffineFloorDivExpr(): + with Context(): + d1 = AffineDimExpr.get(1) + c2 = AffineConstantExpr.get(2) + expr = AffineExpr.get_floor_div(d1, c2) + # CHECK: d1 floordiv 2 + print(expr) + + assert expr.lhs == d1 + assert expr.rhs == c2 + +run(testAffineFloorDivExpr) + + +# CHECK-LABEL: TEST: testAffineCeilDivExpr +def testAffineCeilDivExpr(): + with Context(): + d1 = AffineDimExpr.get(1) + c2 = AffineConstantExpr.get(2) + expr = AffineExpr.get_ceil_div(d1, c2) + # CHECK: d1 ceildiv 2 + print(expr) + + assert expr.lhs == d1 + assert expr.rhs == c2 + +run(testAffineCeilDivExpr) + + +# CHECK-LABEL: TEST: testAffineExprSub +def testAffineExprSub(): + with Context(): + d1 = AffineDimExpr.get(1) + d2 = AffineDimExpr.get(2) + expr = d1 - d2 + # CHECK: d1 - d2 + print(expr) + + assert expr.lhs == d1 + rhs = AffineMulExpr(expr.rhs) + # CHECK: d2 + print(rhs.lhs) + # CHECK: -1 + print(rhs.rhs) + +run(testAffineExprSub) + + +def testClassHierarchy(): + with Context(): + d1 = AffineDimExpr.get(1) + c2 = AffineConstantExpr.get(2) + add = AffineAddExpr.get(d1, c2) + mul = AffineMulExpr.get(d1, c2) + mod = AffineModExpr.get(d1, c2) + floor_div = AffineFloorDivExpr.get(d1, c2) + ceil_div = AffineCeilDivExpr.get(d1, c2) + + # CHECK: False + print(isinstance(d1, AffineBinaryExpr)) + # CHECK: False + print(isinstance(c2, AffineBinaryExpr)) + # CHECK: True + print(isinstance(add, AffineBinaryExpr)) + # CHECK: True + print(isinstance(mul, AffineBinaryExpr)) + # CHECK: True + print(isinstance(mod, AffineBinaryExpr)) + # CHECK: True + print(isinstance(floor_div, AffineBinaryExpr)) + # CHECK: True + print(isinstance(ceil_div, AffineBinaryExpr)) + + try: + AffineBinaryExpr(d1) + except ValueError as e: + # CHECK: Cannot cast affine expression to AffineBinaryExpr + print(e) + + try: + AffineBinaryExpr(c2) + except ValueError as e: + # CHECK: Cannot cast affine expression to AffineBinaryExpr + print(e) + +run(testClassHierarchy) diff --git a/mlir/test/Bindings/Python/ir_affine_map.py b/mlir/test/Bindings/Python/ir_affine_map.py index f668266592336f..fe37eb971555ba 100644 --- a/mlir/test/Bindings/Python/ir_affine_map.py +++ b/mlir/test/Bindings/Python/ir_affine_map.py @@ -22,3 +22,151 @@ def testAffineMapCapsule(): assert am2.context is ctx run(testAffineMapCapsule) + + +# CHECK-LABEL: TEST: testAffineMapGet +def testAffineMapGet(): + with Context() as ctx: + d0 = AffineDimExpr.get(0) + d1 = AffineDimExpr.get(1) + c2 = AffineConstantExpr.get(2) + + # CHECK: (d0, d1)[s0, s1, s2] -> () + map0 = AffineMap.get(2, 3, []) + print(map0) + + # CHECK: (d0, d1)[s0, s1, s2] -> (d1, 2) + map1 = AffineMap.get(2, 3, [d1, c2]) + print(map1) + + # CHECK: () -> (2) + map2 = AffineMap.get(0, 0, [c2]) + print(map2) + + # CHECK: (d0, d1) -> (d0, d1) + map3 = AffineMap.get(2, 0, [d0, d1]) + print(map3) + + # CHECK: (d0, d1) -> (d1) + map4 = AffineMap.get(2, 0, [d1]) + print(map4) + + # CHECK: (d0, d1, d2) -> (d2, d0, d1) + map5 = AffineMap.get_permutation([2, 0, 1]) + print(map5) + + assert map1 == AffineMap.get(2, 3, [d1, c2]) + assert AffineMap.get(0, 0, []) == AffineMap.get_empty() + assert map2 == AffineMap.get_constant(2) + assert map3 == AffineMap.get_identity(2) + assert map4 == AffineMap.get_minor_identity(2, 1) + + try: + AffineMap.get(1, 1, [1]) + except RuntimeError as e: + # CHECK: Invalid expression when attempting to create an AffineMap + print(e) + + try: + AffineMap.get(1, 1, [None]) + except RuntimeError as e: + # CHECK: Invalid expression (None?) when attempting to create an AffineMap + print(e) + + try: + map3.get_submap([42]) + except ValueError as e: + # CHECK: result position out of bounds + print(e) + + try: + map3.get_minor_submap(42) + except ValueError as e: + # CHECK: number of results out of bounds + print(e) + + try: + map3.get_major_submap(42) + except ValueError as e: + # CHECK: number of results out of bounds + print(e) + +run(testAffineMapGet) + + +# CHECK-LABEL: TEST: testAffineMapDerive +def testAffineMapDerive(): + with Context() as ctx: + map5 = AffineMap.get_identity(5) + + # CHECK: (d0, d1, d2, d3, d4) -> (d1, d2, d3) + map123 = map5.get_submap([1,2,3]) + print(map123) + + # CHECK: (d0, d1, d2, d3, d4) -> (d0, d1) + map01 = map5.get_major_submap(2) + print(map01) + + # CHECK: (d0, d1, d2, d3, d4) -> (d3, d4) + map34 = map5.get_minor_submap(2) + print(map34) + +run(testAffineMapDerive) + + +# CHECK-LABEL: TEST: testAffineMapProperties +def testAffineMapProperties(): + with Context(): + d0 = AffineDimExpr.get(0) + d1 = AffineDimExpr.get(1) + d2 = AffineDimExpr.get(2) + map1 = AffineMap.get(3, 0, [d2, d0]) + map2 = AffineMap.get(3, 0, [d2, d0, d1]) + map3 = AffineMap.get(3, 1, [d2, d0, d1]) + # CHECK: False + print(map1.is_permutation) + # CHECK: True + print(map1.is_projected_permutation) + # CHECK: True + print(map2.is_permutation) + # CHECK: True + print(map2.is_projected_permutation) + # CHECK: False + print(map3.is_permutation) + # CHECK: False + print(map3.is_projected_permutation) + +run(testAffineMapProperties) + + +# CHECK-LABEL: TEST: testAffineMapExprs +def testAffineMapExprs(): + with Context(): + d0 = AffineDimExpr.get(0) + d1 = AffineDimExpr.get(1) + d2 = AffineDimExpr.get(2) + map3 = AffineMap.get(3, 1, [d2, d0, d1]) + + # CHECK: 3 + print(map3.n_dims) + # CHECK: 4 + print(map3.n_inputs) + # CHECK: 1 + print(map3.n_symbols) + assert map3.n_inputs == map3.n_dims + map3.n_symbols + + # CHECK: 3 + print(len(map3.results)) + for expr in map3.results: + # CHECK: d2 + # CHECK: d0 + # CHECK: d1 + print(expr) + for expr in map3.results[-1:-4:-1]: + # CHECK: d1 + # CHECK: d0 + # CHECK: d2 + print(expr) + assert list(map3.results) == [d2, d0, d1] + +run(testAffineMapExprs) diff --git a/mlir/test/Bindings/Python/ir_types.py b/mlir/test/Bindings/Python/ir_types.py index a65095c4289e5f..64b684ee99e925 100644 --- a/mlir/test/Bindings/Python/ir_types.py +++ b/mlir/test/Bindings/Python/ir_types.py @@ -326,17 +326,27 @@ def testMemRefType(): f32 = F32Type.get() shape = [2, 3] loc = Location.unknown() - memref = MemRefType.get_contiguous_memref(f32, shape, 2) + memref = MemRefType.get(f32, shape, memory_space=2) # CHECK: memref type: memref<2x3xf32, 2> print("memref type:", memref) # CHECK: number of affine layout maps: 0 - print("number of affine layout maps:", memref.num_affine_maps) + print("number of affine layout maps:", len(memref.layout)) # CHECK: memory space: 2 print("memory space:", memref.memory_space) + layout = AffineMap.get_permutation([1, 0]) + memref_layout = MemRefType.get(f32, shape, [layout]) + # CHECK: memref type: memref<2x3xf32, affine_map<(d0, d1) -> (d1, d0)>> + print("memref type:", memref_layout) + assert len(memref_layout.layout) == 1 + # CHECK: memref layout: (d0, d1) -> (d1, d0) + print("memref layout:", memref_layout.layout[0]) + # CHECK: memory space: 0 + print("memory space:", memref_layout.memory_space) + none = NoneType.get() try: - memref_invalid = MemRefType.get_contiguous_memref(none, shape, 2) + memref_invalid = MemRefType.get(none, shape) except ValueError as e: # CHECK: invalid 'Type(none)' and expected floating point, integer, vector # CHECK: or complex type. diff --git a/mlir/test/CAPI/ir.c b/mlir/test/CAPI/ir.c index 434f272de059c2..5a222cef0bacc5 100644 --- a/mlir/test/CAPI/ir.c +++ b/mlir/test/CAPI/ir.c @@ -16,8 +16,8 @@ #include "mlir-c/BuiltinAttributes.h" #include "mlir-c/BuiltinTypes.h" #include "mlir-c/Diagnostics.h" +#include "mlir-c/Dialect/Standard.h" #include "mlir-c/Registration.h" -#include "mlir-c/StandardDialect.h" #include #include @@ -1007,7 +1007,7 @@ int printBuiltinAttributes(MlirContext ctx) { int printAffineMap(MlirContext ctx) { MlirAffineMap emptyAffineMap = mlirAffineMapEmptyGet(ctx); - MlirAffineMap affineMap = mlirAffineMapGet(ctx, 3, 2); + MlirAffineMap affineMap = mlirAffineMapZeroResultGet(ctx, 3, 2); MlirAffineMap constAffineMap = mlirAffineMapConstantGet(ctx, 2); MlirAffineMap multiDimIdentityAffineMap = mlirAffineMapMultiDimIdentityGet(ctx, 3); @@ -1251,6 +1251,50 @@ int printAffineExpr(MlirContext ctx) { if (!mlirAffineExprIsACeilDiv(affineCeilDivExpr)) return 13; + if (!mlirAffineExprIsABinary(affineAddExpr)) + return 14; + + // Test other 'IsA' method on affine expressions. + if (!mlirAffineExprIsAConstant(affineConstantExpr)) + return 15; + + if (!mlirAffineExprIsADim(affineDimExpr)) + return 16; + + if (!mlirAffineExprIsASymbol(affineSymbolExpr)) + return 17; + + // Test equality and nullity. + MlirAffineExpr otherDimExpr = mlirAffineDimExprGet(ctx, 5); + if (!mlirAffineExprEqual(affineDimExpr, otherDimExpr)) + return 18; + + if (mlirAffineExprIsNull(affineDimExpr)) + return 19; + + return 0; +} + +int affineMapFromExprs(MlirContext ctx) { + MlirAffineExpr affineDimExpr = mlirAffineDimExprGet(ctx, 0); + MlirAffineExpr affineSymbolExpr = mlirAffineSymbolExprGet(ctx, 1); + MlirAffineExpr exprs[] = {affineDimExpr, affineSymbolExpr}; + MlirAffineMap map = mlirAffineMapGet(ctx, 3, 3, 2, exprs); + + // CHECK-LABEL: @affineMapFromExprs + fprintf(stderr, "@affineMapFromExprs"); + // CHECK: (d0, d1, d2)[s0, s1, s2] -> (d0, s1) + mlirAffineMapDump(map); + + if (mlirAffineMapGetNumResults(map) != 2) + return 1; + + if (!mlirAffineExprEqual(mlirAffineMapGetResult(map, 0), affineDimExpr)) + return 2; + + if (!mlirAffineExprEqual(mlirAffineMapGetResult(map, 1), affineSymbolExpr)) + return 3; + return 0; } @@ -1354,8 +1398,10 @@ int main() { return 4; if (printAffineExpr(ctx)) return 5; - if (registerOnlyStd()) + if (affineMapFromExprs(ctx)) return 6; + if (registerOnlyStd()) + return 7; mlirContextDestroy(ctx); diff --git a/mlir/test/Dialect/Vector/canonicalize.mlir b/mlir/test/Dialect/Vector/canonicalize.mlir index cf4473f15f492b..0ff85da85bcb93 100644 --- a/mlir/test/Dialect/Vector/canonicalize.mlir +++ b/mlir/test/Dialect/Vector/canonicalize.mlir @@ -677,3 +677,22 @@ func @dead_transfer_op(%arg0 : tensor<4x4xf32>, %arg1 : memref<4x4xf32>, vector<1x4xf32>, tensor<4x4xf32> return } + +// ----- + +// CHECK-LABEL: func @dead_load +// CHECK-NOT: vector.maskedload +// CHECK-NOT: vector.gather +// CHECK-NOT: vector.expandload +// CHECK: return +func @dead_load(%base: memref, %indices: vector<16xi32>, + %mask: vector<16xi1>, %passthru: vector<16xf32>) { + %c0 = constant 0 : index + %0 = vector.maskedload %base[%c0], %mask, %passthru : + memref, vector<16xi1>, vector<16xf32> into vector<16xf32> + %1 = vector.gather %base[%indices], %mask, %passthru : + memref, vector<16xi32>, vector<16xi1>, vector<16xf32> into vector<16xf32> + %2 = vector.expandload %base[%c0], %mask, %passthru : + memref, vector<16xi1>, vector<16xf32> into vector<16xf32> + return +} diff --git a/mlir/test/lib/Dialect/Test/TestTypeDefs.td b/mlir/test/lib/Dialect/Test/TestTypeDefs.td index 80927dff62c2e0..0e2c11a2ecb070 100644 --- a/mlir/test/lib/Dialect/Test/TestTypeDefs.td +++ b/mlir/test/lib/Dialect/Test/TestTypeDefs.td @@ -51,9 +51,9 @@ def IntegerType : Test_Type<"TestInteger"> { let genVerifyInvariantsDecl = 1; let parameters = ( ins + "unsigned":$width, // SignednessSemantics is defined below. - "::mlir::test::TestIntegerType::SignednessSemantics":$signedness, - "unsigned":$width + "::mlir::test::TestIntegerType::SignednessSemantics":$signedness ); // We define the printer inline. @@ -63,6 +63,17 @@ def IntegerType : Test_Type<"TestInteger"> { $_printer << ", " << getImpl()->width << ">"; }]; + // Define custom builder methods. + let builders = [ + TypeBuilder<(ins "unsigned":$width, + CArg<"SignednessSemantics", "Signless">:$signedness), [{ + return Base::get($_ctxt, width, signedness); + }], [{ + return Base::getChecked($_loc, width, signedness); + }]> + ]; + let skipDefaultBuilders = 1; + // The parser is defined here also. let parser = [{ if (parser.parseLess()) return Type(); @@ -73,7 +84,7 @@ def IntegerType : Test_Type<"TestInteger"> { if ($_parser.parseInteger(width)) return Type(); if ($_parser.parseGreater()) return Type(); Location loc = $_parser.getEncodedSourceLoc($_parser.getNameLoc()); - return getChecked(loc, signedness, width); + return getChecked(loc, width, signedness); }]; // Any extra code one wants in the type's class declaration. @@ -85,9 +96,6 @@ def IntegerType : Test_Type<"TestInteger"> { Unsigned, /// Unsigned integer }; - /// This extra function is necessary since it doesn't include signedness - static IntegerType getChecked(unsigned width, Location location); - /// Return true if this is a signless integer type. bool isSignless() const { return getSignedness() == Signless; } /// Return true if this is a signed integer type. diff --git a/mlir/test/lib/Dialect/Test/TestTypes.cpp b/mlir/test/lib/Dialect/Test/TestTypes.cpp index 14a3e862d85c35..094e5c9fc631ac 100644 --- a/mlir/test/lib/Dialect/Test/TestTypes.cpp +++ b/mlir/test/lib/Dialect/Test/TestTypes.cpp @@ -113,7 +113,7 @@ static llvm::hash_code mlir::test::hash_value(const FieldInfo &fi) { // NOLINT // Example type validity checker. LogicalResult TestIntegerType::verifyConstructionInvariants( - Location loc, TestIntegerType::SignednessSemantics ss, unsigned int width) { + Location loc, unsigned width, TestIntegerType::SignednessSemantics ss) { if (width > 8) return failure(); return success(); diff --git a/mlir/test/mlir-linalg-ods-gen/test-linalg-ods-gen.tc b/mlir/test/mlir-linalg-ods-gen/test-linalg-ods-gen.tc index 1ef12876063778..f81380f02bb382 100644 --- a/mlir/test/mlir-linalg-ods-gen/test-linalg-ods-gen.tc +++ b/mlir/test/mlir-linalg-ods-gen/test-linalg-ods-gen.tc @@ -72,25 +72,3 @@ ods_def : def test3(A: f32(Batch, M, K), B: f32(K, N)) -> (C: f32(Batch, M, N)) { C(b, m, n) = std_addf(std_mulf(A(b, m, k), B(k, n))); } - -// Test attribute definitions -// ODS-LABEL: def Test4Op -// ODS: F32ArrayAttr:$array_attr, -// ODS: F32:$f32_attr, -// ODS: RankedF32ElementsAttr<[4]>:$fvec_attr, -// ODS: I32:$i32_attr, -// ODS: RankedI32ElementsAttr<[5, 6]>:$ivec_attr, -// ODS: OptionalAttr:$optional_attr -// -ods_def : -def test4(A: f32(Batch, M, K), B: f32(K, N)) -> (C: f32(Batch, M, N)) -attr( - f32_attr: f32, - i32_attr: i32, - fvec_attr: 4xf32, - ivec_attr: 5x6xi32, - array_attr : f32[], - optional_attr? : f32 -) { - C(b, m, n) = std_addf(std_mulf(A(b, m, k), B(k, n))); -} diff --git a/mlir/test/mlir-tblgen/typedefs.td b/mlir/test/mlir-tblgen/typedefs.td index 6e6e1c04643a03..5471519ab60a90 100644 --- a/mlir/test/mlir-tblgen/typedefs.td +++ b/mlir/test/mlir-tblgen/typedefs.td @@ -19,8 +19,8 @@ include "mlir/IR/OpBase.td" // DEF: ::mlir::test::SingleParameterType, // DEF: ::mlir::test::IntegerType -// DEF-LABEL: ::mlir::Type generatedTypeParser(::mlir::MLIRContext* ctxt, ::mlir::DialectAsmParser& parser, ::llvm::StringRef mnemonic) -// DEF: if (mnemonic == ::mlir::test::CompoundAType::getMnemonic()) return ::mlir::test::CompoundAType::parse(ctxt, parser); +// DEF-LABEL: ::mlir::Type generatedTypeParser(::mlir::MLIRContext *context, ::mlir::DialectAsmParser &parser, ::llvm::StringRef mnemonic) +// DEF: if (mnemonic == ::mlir::test::CompoundAType::getMnemonic()) return ::mlir::test::CompoundAType::parse(context, parser); // DEF return ::mlir::Type(); def Test_Dialect: Dialect { @@ -33,7 +33,7 @@ def Test_Dialect: Dialect { class TestType : TypeDef { } def A_SimpleTypeA : TestType<"SimpleA"> { -// DECL: class SimpleAType: public ::mlir::Type +// DECL: class SimpleAType : public ::mlir::Type } def RTLValueType : Type, "Type"> { @@ -56,12 +56,13 @@ def B_CompoundTypeA : TestType<"CompoundA"> { let genVerifyInvariantsDecl = 1; -// DECL-LABEL: class CompoundAType: public ::mlir::Type +// DECL-LABEL: class CompoundAType : public ::mlir::Type +// DECL: static CompoundAType getChecked(::mlir::Location loc, int widthOfSomething, ::mlir::test::SimpleTypeA exampleTdType, SomeCppStruct exampleCppType, ::llvm::ArrayRef dims, ::mlir::Type inner); // DECL: static ::mlir::LogicalResult verifyConstructionInvariants(::mlir::Location loc, int widthOfSomething, ::mlir::test::SimpleTypeA exampleTdType, SomeCppStruct exampleCppType, ::llvm::ArrayRef dims, ::mlir::Type inner); -// DECL: static ::mlir::Type getChecked(::mlir::Location loc, int widthOfSomething, ::mlir::test::SimpleTypeA exampleTdType, SomeCppStruct exampleCppType, ::llvm::ArrayRef dims, ::mlir::Type inner); // DECL: static ::llvm::StringRef getMnemonic() { return "cmpnd_a"; } -// DECL: static ::mlir::Type parse(::mlir::MLIRContext* ctxt, ::mlir::DialectAsmParser& parser); -// DECL: void print(::mlir::DialectAsmPrinter& printer) const; +// DECL: static ::mlir::Type parse(::mlir::MLIRContext *context, +// DECL-NEXT: ::mlir::DialectAsmParser &parser); +// DECL: void print(::mlir::DialectAsmPrinter &printer) const; // DECL: int getWidthOfSomething() const; // DECL: ::mlir::test::SimpleTypeA getExampleTdType() const; // DECL: SomeCppStruct getExampleCppType() const; @@ -75,10 +76,11 @@ def C_IndexType : TestType<"Index"> { StringRefParameter<"Label for index">:$label ); -// DECL-LABEL: class IndexType: public ::mlir::Type +// DECL-LABEL: class IndexType : public ::mlir::Type // DECL: static ::llvm::StringRef getMnemonic() { return "index"; } -// DECL: static ::mlir::Type parse(::mlir::MLIRContext* ctxt, ::mlir::DialectAsmParser& parser); -// DECL: void print(::mlir::DialectAsmPrinter& printer) const; +// DECL: static ::mlir::Type parse(::mlir::MLIRContext *context, +// DECL-NEXT: ::mlir::DialectAsmParser &parser); +// DECL: void print(::mlir::DialectAsmPrinter &printer) const; } def D_SingleParameterType : TestType<"SingleParameter"> { @@ -100,7 +102,7 @@ def E_IntegerType : TestType<"Integer"> { TypeParameter<"unsigned", "Bitwidth of integer">:$width ); -// DECL-LABEL: IntegerType: public ::mlir::Type +// DECL-LABEL: IntegerType : public ::mlir::Type let extraClassDeclaration = [{ /// Signedness semantics. diff --git a/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-gen.cpp b/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-gen.cpp index e7ab5edc1118b6..592e6cb774fbf6 100644 --- a/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-gen.cpp +++ b/mlir/tools/mlir-linalg-ods-gen/mlir-linalg-ods-gen.cpp @@ -20,17 +20,11 @@ #include "mlir/Support/LLVM.h" #include "mlir/Support/LogicalResult.h" #include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSwitch.h" -#include "llvm/ADT/Twine.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/ToolOutputFile.h" -#include - #define DEBUG_TYPE "linalg-ods-gen" static llvm::cl::OptionCategory ODSGenCat("Linalg ODS Gen"); @@ -85,14 +79,11 @@ class Token { gt, l_brace, l_paren, - l_square, lt, minus, plus, - question, r_brace, r_paren, - r_square, semicolon, star, @@ -100,7 +91,6 @@ class Token { kw_def, FIRST_KEYWORD = kw_def, kw_ods_def, - kw_attr_def, kw_floordiv, kw_ceildiv, kw_mod, @@ -161,10 +151,6 @@ class Lexer { Token emitError(llvm::SMLoc loc, const Twine &msg); Token emitError(const char *loc, const Twine &msg); - /// Change the position of the lexer cursor. The next token we lex will start - /// at the designated point in the input. - void resetPointer(const char *newPtr) { curPtr = newPtr; } - private: Token formToken(Token::Kind kind, const char *tokStart) { return Token(kind, StringRef(tokStart, curPtr - tokStart)); @@ -261,14 +247,10 @@ Token Lexer::lexToken() { return formToken(Token::Kind::l_brace, tokStart); case '(': return formToken(Token::Kind::l_paren, tokStart); - case '[': - return formToken(Token::Kind::l_square, tokStart); case '}': return formToken(Token::Kind::r_brace, tokStart); case ')': return formToken(Token::Kind::r_paren, tokStart); - case ']': - return formToken(Token::Kind::r_square, tokStart); case '<': return formToken(Token::Kind::lt, tokStart); case '>': @@ -281,8 +263,6 @@ Token Lexer::lexToken() { return formToken(Token::Kind::semicolon, tokStart); case '*': return formToken(Token::Kind::star, tokStart); - case '?': - return formToken(Token::Kind::question, tokStart); case '/': if (*curPtr == '/') { skipComment(); @@ -309,7 +289,6 @@ Token Lexer::lexIdentifier(const char *tokStart) { // Check to see if this identifier is a keyword. StringRef str(tokStart, curPtr - tokStart); Token::Kind kind = StringSwitch(str) - .Case("attr", Token::Kind::kw_attr_def) .Case("def", Token::Kind::kw_def) .Case("ods_def", Token::Kind::kw_ods_def) .Case("floordiv", Token::Kind::kw_floordiv) @@ -373,40 +352,29 @@ class Parser { "shouldn't advance past EOF or errors"); curToken = lexer.lexToken(); } - void consumeToken(Token::Kind kind) { assert(curToken.getKind() == kind && "unexpected token"); curToken = lexer.lexToken(); } - LogicalResult parseToken(Token::Kind kind, const Twine &msg) { if (curToken.getKind() != kind) return emitError(curToken.getLoc(), msg); consumeToken(); return success(); } - - /// Parses an optional token and returns failure if failed to parse. - LogicalResult parseOptionalToken(Token::Kind kind) { - return success(consumeIf(kind)); - } - LogicalResult emitError(llvm::SMLoc loc, const Twine &msg) { lexer.emitError(loc, msg); return failure(); } - LogicalResult emitError(const Twine &msg) { return emitError(curToken.getLoc(), msg); } - bool consumeIf(Token::Kind kind) { if (curToken.isNot(kind)) return false; consumeToken(kind); return true; } - LogicalResult parseCommaSeparatedList(llvm::function_ref parseElement) { // Non-empty case starts with an element. @@ -420,7 +388,6 @@ class Parser { } return success(); } - LogicalResult parseCommaSeparatedListUntil(Token::Kind rightToken, llvm::function_ref parseElement, @@ -994,8 +961,6 @@ class TCParser { LogicalResult parseTensorUse(TensorUse &result, ComprehensionParsingState &state); - LogicalResult parseAttrDef(); - /// Parses a tensor expression. LogicalResult parseExpression(TensorUse currentDefinition, std::unique_ptr &result, @@ -1045,29 +1010,15 @@ class TCParser { unsigned index; }; - //===--------------------------------------------------------------------===// - // Internal bookkeeping of attributes. - //===--------------------------------------------------------------------===// - struct RegisteredAttr { - StringRef elementType; - SmallVector vectorDims; - bool isArray; - bool isOptional; - }; - //===--------------------------------------------------------------------===// // Per-TC def state. //===--------------------------------------------------------------------===// /// Symbols are per TC def. AffineSymbolList symbols; - /// Tensors are per TC def. llvm::StringMap registeredTensors; unsigned nextRegisteredTensorIndex; - /// Attributes are per TC def. - std::map registeredAttrs; - Parser &parser; }; } // namespace @@ -1219,72 +1170,6 @@ LogicalResult TCParser::parseTensorUse(TensorUse &result, return success(); } -/// Parse the information for an attribute def of the form: -/// -/// affine-expr-list ::= affine-expr (`,` affine-expr )* -/// attr-id ::= bare-id (`?`)? -/// dim-list ::= (integer-literal 'x')+ -/// attr-typedef ::= dim-list? type (`[` `]`)? -/// attr-def ::= attr-id `:` attr-typedef -LogicalResult TCParser::parseAttrDef() { - auto attrLoc = parser.curToken.getLoc(); - StringRef attrName = parser.curToken.getSpelling(); - if (failed(parser.parseToken(Token::Kind::id, "expected an id"))) - return failure(); - bool isOptional = succeeded(parser.parseOptionalToken(Token::Kind::question)); - if (failed(parser.parseToken(Token::Kind::colon, "expected colon"))) - return failure(); - - // Parse the attribute's type. We don't expect the type to be arbitrary - // complex, so just use this ad-hoc handling here. - - // Parse potential dimension list - SmallVector vectorDims; - while (parser.curToken.is(Token::Kind::integer)) { - vectorDims.push_back(parser.curToken.getUInt64IntegerValue().getValue()); - parser.consumeToken(); - - StringRef spelling = parser.curToken.getSpelling(); - if (spelling[0] != 'x') - return parser.emitError(parser.curToken.getLoc(), - "expected 'x' in dimension list"); - - // If we had a prefix of 'x', lex the next token immediately after the 'x'. - if (spelling.size() != 1) - parser.lexer.resetPointer(spelling.data() + 1); - - parser.consumeToken(); - } - - StringRef elementType = parser.curToken.getSpelling(); - if (failed(parser.parseToken(Token::Kind::id, "expected an id"))) - return failure(); - - bool isArray = false; - auto arrayLoc = parser.curToken.getLoc(); - if (succeeded(parser.parseOptionalToken(Token::Kind::l_square))) { - isArray = true; - if (failed(parser.parseToken(Token::Kind::r_square, "expected ']'"))) - return failure(); - } - - if (!vectorDims.empty() && isArray) - return parser.emitError(arrayLoc, "unsupported vector array attribute"); - - auto iterBoolPair = registeredAttrs.emplace( - attrName, RegisteredAttr{elementType, vectorDims, isArray, isOptional}); - if (!iterBoolPair.second) - return parser.emitError(attrLoc, - "Failed to register attribute '" + attrName + "'"); - - LLVM_DEBUG(llvm::dbgs() << "Recorded: " << (isOptional ? "[optional]" : "") - << " " << attrName << " " - << "with type: " << elementType - << (isArray ? "[]" : "") << "\n"); - - return success(); -} - /// Parses a tensor expression of the form: /// /// op-spec ::= bare-id `<` reduction-dims-list `>` @@ -1456,13 +1341,10 @@ TCParser::parseOneComprehension(StringRef cppOpName, StringRef linalgOpName, /// Parse and print the information for a ODS def. /// /// tensor-def-list ::= tensor-def (`,` tensor-def )* -/// attr-def-list ::= attr-def (`,` attr-def )* /// /// comprehension-list ::= comprehension comprehension* /// -/// tc-attr-def ::= `attr` `(` attr-def-list `)` /// tc-def ::= `def` bare-id `(`tensor-def-list`)` `->` `(` tensor-def-list`)` -/// (tc-attr-def)? /// `{` comprehension-list `}` /// /// ods-def ::= `ods_def` `<` bare-id `>` `:` tc-def @@ -1471,7 +1353,6 @@ TCParser::parseOneComprehension(StringRef cppOpName, StringRef linalgOpName, /// contain only expressions involving symbols and constants), but can /// otherwise contain arbitrary affine expressions. LogicalResult TCParser::parseAndEmitODSDef(llvm::raw_ostream &os) { - // Parse def header (including C++ op name) if (failed(parser.parseToken(Token::Kind::kw_ods_def, "expected 'ods_def' to define a TC ODS")) || failed(parser.parseToken(Token::Kind::lt, "expected '<'"))) @@ -1483,15 +1364,12 @@ LogicalResult TCParser::parseAndEmitODSDef(llvm::raw_ostream &os) { failed(parser.parseToken(Token::Kind::gt, "expected '>'")) || failed(parser.parseToken(Token::Kind::colon, "expected ':'"))) return failure(); - if (failed(parser.parseToken(Token::Kind::kw_def, "expected 'def' to define a TC"))) return failure(); StringRef tcName = parser.curToken.getSpelling(); LLVM_DEBUG(llvm::dbgs() << "\n\nStart parsing TC: " << tcName << "\n"); - - // Parse input/output tensor definitions if (failed(parser.parseToken(Token::Kind::id, "expected id")) || failed(parser.parseToken(Token::Kind::l_paren, "expected '('"))) return failure(); @@ -1514,16 +1392,6 @@ LogicalResult TCParser::parseAndEmitODSDef(llvm::raw_ostream &os) { Token::Kind::r_paren, parseOutputDef, /*allowEmptyList=*/false))) return failure(); - // Parse optional attribute definitions - if (succeeded(parser.parseOptionalToken(Token::Kind::kw_attr_def))) { - if (failed(parser.parseToken(Token::Kind::l_paren, "expected '('"))) - return failure(); - if (failed(parser.parseCommaSeparatedListUntil( - Token::Kind::r_paren, std::bind(&TCParser::parseAttrDef, this), - /*allowEmptyList=*/false))) - return failure(); - } - // Since we don't declare symbols separately, we discover them eagerly: each // newly encountered id in a tensor shape expression is treated as a new // symbolic. At this point, all tensors have been parsed and all the symbols @@ -1582,52 +1450,12 @@ LogicalResult TCParser::parseAndEmitODSDef(llvm::raw_ostream &os) { void TCParser::printODS(llvm::raw_ostream &os, StringRef cppOpName, StringRef linalgOpName, ComprehensionParsingState &state) { - SmallVector attributes; - for (const auto &attr : registeredAttrs) { - llvm::StringRef name = attr.first; - - llvm::StringRef elementType = attr.second.elementType; - std::string odsType = llvm::StringSwitch(elementType) - .Case("f32", "F32") - .Case("i32", "I32") - .Default(""); - if (odsType.empty()) { - parser.emitError("unimplemented support for attribute element type: " + - elementType); - return; - } - - const auto &dims = attr.second.vectorDims; - if (!dims.empty()) { - SmallVector dimStrs; - for (uint64_t dim : dims) - dimStrs.push_back(std::to_string(dim)); - odsType = llvm::formatv("Ranked{0}ElementsAttr<[{1}]>", odsType, - llvm::join(dimStrs, ", ")); - } - - assert(dims.empty() || !attr.second.isArray); - if (attr.second.isArray) - odsType = llvm::formatv("{0}ArrayAttr", odsType); - - if (attr.second.isOptional) - odsType = llvm::formatv("OptionalAttr<{0}>", odsType); - - attributes.push_back(llvm::formatv("{0}:${1}", odsType, name)); - } - - std::string attrList = llvm::join(attributes, ",\n"); - if (!attrList.empty()) - attrList = ",\n" + attrList; - const char *header = R"FMT( def {0} : LinalgStructuredBase_Op<"{1}", [ AttrSizedOperandSegments, DeclareOpInterfaceMethods, SingleBlockImplicitTerminator<"YieldOp">]> { - let arguments = (ins - Variadic:$inputs, - Variadic:$outputs{4} - ); + let arguments = (ins Variadic:$inputs, + Variadic:$outputs); let results = (outs Variadic:$result_tensors); let regions = (region AnyRegion:$region); @@ -1687,7 +1515,7 @@ void TCParser::printODS(llvm::raw_ostream &os, StringRef cppOpName, static std::function getRegionBuilder() {{ return regionBuilder; } // Generic methods. - static unsigned getNumRegionArgs() {{ return {5}; } + static unsigned getNumRegionArgs() {{ return {4}; } std::string getLibraryCallName() {{ return generateLibraryCallName(getOperation()); } @@ -1703,7 +1531,7 @@ void TCParser::printODS(llvm::raw_ostream &os, StringRef cppOpName, } os << llvm::formatv(header, cppOpName, linalgOpName, nInputs, nOutputs, - attrList, state.orderedTensorArgs.size()); + state.orderedTensorArgs.size()); } /// Print the C++ StructuredOpsInterface impl of `iterator_types`. diff --git a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp index ed04bd07fc4c7b..69c6b022054e00 100644 --- a/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp +++ b/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp @@ -48,7 +48,7 @@ static cl::opt opExcFilter( static const char *const tblgenNamePrefix = "tblgen_"; static const char *const generatedArgName = "odsArg"; -static const char *const builder = "odsBuilder"; +static const char *const odsBuilder = "odsBuilder"; static const char *const builderOpState = "odsState"; // The logic to calculate the actual value range for a declared operand/result @@ -1326,54 +1326,31 @@ void OpEmitter::genUseAttrAsResultTypeBuilder() { body << " }\n"; } -/// Returns a signature of the builder as defined by a dag-typed initializer. -/// Updates the context `fctx` to enable replacement of $_builder and $_state -/// in the body. Reports errors at `loc`. -static std::string builderSignatureFromDAG(const DagInit *init, - ArrayRef loc) { - auto *defInit = dyn_cast(init->getOperator()); - if (!defInit || !defInit->getDef()->getName().equals("ins")) - PrintFatalError(loc, "expected 'ins' in builders"); +/// Returns a signature of the builder. Updates the context `fctx` to enable +/// replacement of $_builder and $_state in the body. +static std::string getBuilderSignature(const Builder &builder) { + ArrayRef params(builder.getParameters()); // Inject builder and state arguments. llvm::SmallVector arguments; - arguments.reserve(init->getNumArgs() + 2); - arguments.push_back(llvm::formatv("::mlir::OpBuilder &{0}", builder).str()); + arguments.reserve(params.size() + 2); + arguments.push_back( + llvm::formatv("::mlir::OpBuilder &{0}", odsBuilder).str()); arguments.push_back( llvm::formatv("::mlir::OperationState &{0}", builderOpState).str()); - // Accept either a StringInit or a DefInit with two string values as dag - // arguments. The former corresponds to the type, the latter to the type and - // the default value. Similarly to C++, once an argument with a default value - // is detected, the following arguments must have default values as well. - bool seenDefaultValue = false; - for (unsigned i = 0, e = init->getNumArgs(); i < e; ++i) { + for (unsigned i = 0, e = params.size(); i < e; ++i) { // If no name is provided, generate one. - StringInit *argName = init->getArgName(i); + Optional paramName = params[i].getName(); std::string name = - argName ? argName->getValue().str() : "odsArg" + std::to_string(i); + paramName ? paramName->str() : "odsArg" + std::to_string(i); - Init *argInit = init->getArg(i); - StringRef type; std::string defaultValue; - if (StringInit *strType = dyn_cast(argInit)) { - type = strType->getValue(); - } else { - const Record *typeAndDefaultValue = cast(argInit)->getDef(); - type = typeAndDefaultValue->getValueAsString("type"); - StringRef defaultValueRef = - typeAndDefaultValue->getValueAsString("defaultValue"); - if (!defaultValueRef.empty()) { - seenDefaultValue = true; - defaultValue = llvm::formatv(" = {0}", defaultValueRef).str(); - } - } - if (seenDefaultValue && defaultValue.empty()) - PrintFatalError(loc, - "expected an argument with default value after other " - "arguments with default values"); + if (Optional defaultParamValue = params[i].getDefaultValue()) + defaultValue = llvm::formatv(" = {0}", *defaultParamValue).str(); arguments.push_back( - llvm::formatv("{0} {1}{2}", type, name, defaultValue).str()); + llvm::formatv("{0} {1}{2}", params[i].getCppType(), name, defaultValue) + .str()); } return llvm::join(arguments, ", "); @@ -1381,41 +1358,26 @@ static std::string builderSignatureFromDAG(const DagInit *init, void OpEmitter::genBuilder() { // Handle custom builders if provided. - // TODO: Create wrapper class for OpBuilder to hide the native - // TableGen API calls here. - { - auto *listInit = dyn_cast_or_null(def.getValueInit("builders")); - if (listInit) { - for (Init *init : listInit->getValues()) { - Record *builderDef = cast(init)->getDef(); - std::string paramStr = builderSignatureFromDAG( - builderDef->getValueAsDag("dagParams"), op.getLoc()); - - StringRef body = builderDef->getValueAsString("body"); - bool hasBody = !body.empty(); - OpMethod::Property properties = - hasBody ? OpMethod::MP_Static : OpMethod::MP_StaticDeclaration; - auto *method = - opClass.addMethodAndPrune("void", "build", properties, paramStr); + for (const Builder &builder : op.getBuilders()) { + std::string paramStr = getBuilderSignature(builder); - FmtContext fctx; - fctx.withBuilder(builder); - fctx.addSubst("_state", builderOpState); - if (hasBody) - method->body() << tgfmt(body, &fctx); - } - } - if (op.skipDefaultBuilders()) { - if (!listInit || listInit->empty()) - PrintFatalError( - op.getLoc(), - "default builders are skipped and no custom builders provided"); - return; - } + Optional body = builder.getBody(); + OpMethod::Property properties = + body ? OpMethod::MP_Static : OpMethod::MP_StaticDeclaration; + auto *method = + opClass.addMethodAndPrune("void", "build", properties, paramStr); + + FmtContext fctx; + fctx.withBuilder(odsBuilder); + fctx.addSubst("_state", builderOpState); + if (body) + method->body() << tgfmt(*body, &fctx); } // Generate default builders that requires all result type, operands, and // attributes as parameters. + if (op.skipDefaultBuilders()) + return; // We generate three classes of builders here: // 1. one having a stand-alone parameter for each operand / attribute, and diff --git a/mlir/tools/mlir-tblgen/TypeDefGen.cpp b/mlir/tools/mlir-tblgen/TypeDefGen.cpp index 20168168bc8d6a..9cbd53270983b1 100644 --- a/mlir/tools/mlir-tblgen/TypeDefGen.cpp +++ b/mlir/tools/mlir-tblgen/TypeDefGen.cpp @@ -148,7 +148,7 @@ class DialectAsmPrinter; /// {0}: The name of the typeDef class. /// {1}: The name of the type base class. static const char *const typeDefDeclSingletonBeginStr = R"( - class {0}: public ::mlir::Type::TypeBase<{0}, {1}, ::mlir::TypeStorage> {{ + class {0} : public ::mlir::Type::TypeBase<{0}, {1}, ::mlir::TypeStorage> {{ public: /// Inherit some necessary constructors from 'TypeBase'. using Base::Base; @@ -166,9 +166,9 @@ static const char *const typeDefDeclSingletonBeginStr = R"( static const char *const typeDefDeclParametricBeginStr = R"( namespace {2} { struct {3}; - } - class {0}: public ::mlir::Type::TypeBase<{0}, {1}, - {2}::{3}> {{ + } // end namespace {2} + class {0} : public ::mlir::Type::TypeBase<{0}, {1}, + {2}::{3}> {{ public: /// Inherit some necessary constructors from 'TypeBase'. using Base::Base; @@ -177,18 +177,68 @@ static const char *const typeDefDeclParametricBeginStr = R"( /// The snippet for print/parse. static const char *const typeDefParsePrint = R"( - static ::mlir::Type parse(::mlir::MLIRContext* ctxt, ::mlir::DialectAsmParser& parser); - void print(::mlir::DialectAsmPrinter& printer) const; + static ::mlir::Type parse(::mlir::MLIRContext *context, + ::mlir::DialectAsmParser &parser); + void print(::mlir::DialectAsmPrinter &printer) const; )"; /// The code block for the verifyConstructionInvariants and getChecked. /// -/// {0}: List of parameters, parameters style. +/// {0}: The name of the typeDef class. +/// {1}: List of parameters, parameters style. static const char *const typeDefDeclVerifyStr = R"( - static ::mlir::LogicalResult verifyConstructionInvariants(::mlir::Location loc{0}); - static ::mlir::Type getChecked(::mlir::Location loc{0}); + static ::mlir::LogicalResult verifyConstructionInvariants(::mlir::Location loc{1}); )"; +/// Emit the builders for the given type. +static void emitTypeBuilderDecls(const TypeDef &typeDef, raw_ostream &os, + TypeParamCommaFormatter ¶mTypes) { + StringRef typeClass = typeDef.getCppClassName(); + bool genCheckedMethods = typeDef.genVerifyInvariantsDecl(); + if (!typeDef.skipDefaultBuilders()) { + os << llvm::formatv( + " static {0} get(::mlir::MLIRContext *context{1});\n", typeClass, + paramTypes); + if (genCheckedMethods) { + os << llvm::formatv( + " static {0} getChecked(::mlir::Location loc{1});\n", typeClass, + paramTypes); + } + } + + // Generate the builders specified by the user. + for (const TypeBuilder &builder : typeDef.getBuilders()) { + std::string paramStr; + llvm::raw_string_ostream paramOS(paramStr); + llvm::interleaveComma( + builder.getParameters(), paramOS, + [&](const TypeBuilder::Parameter ¶m) { + // Note: TypeBuilder parameters are guaranteed to have names. + paramOS << param.getCppType() << " " << *param.getName(); + if (Optional defaultParamValue = param.getDefaultValue()) + paramOS << " = " << *defaultParamValue; + }); + paramOS.flush(); + + // Generate the `get` variant of the builder. + os << " static " << typeClass << " get("; + if (!builder.hasInferredContextParameter()) { + os << "::mlir::MLIRContext *context"; + if (!paramStr.empty()) + os << ", "; + } + os << paramStr << ");\n"; + + // Generate the `getChecked` variant of the builder. + if (genCheckedMethods) { + os << " static " << typeClass << " getChecked(::mlir::Location loc"; + if (!paramStr.empty()) + os << ", " << paramStr; + os << ");\n"; + } + } +} + /// Generate the declaration for the given typeDef class. static void emitTypeDefDecl(const TypeDef &typeDef, raw_ostream &os) { SmallVector params; @@ -212,13 +262,13 @@ static void emitTypeDefDecl(const TypeDef &typeDef, raw_ostream &os) { TypeParamCommaFormatter emitTypeNamePairsAfterComma( TypeParamCommaFormatter::EmitFormat::TypeNamePairs, params); if (!params.empty()) { - os << llvm::formatv(" static {0} get(::mlir::MLIRContext* ctxt{1});\n", - typeDef.getCppClassName(), emitTypeNamePairsAfterComma); - } + emitTypeBuilderDecls(typeDef, os, emitTypeNamePairsAfterComma); - // Emit the verify invariants declaration. - if (typeDef.genVerifyInvariantsDecl()) - os << llvm::formatv(typeDefDeclVerifyStr, emitTypeNamePairsAfterComma); + // Emit the verify invariants declaration. + if (typeDef.genVerifyInvariantsDecl()) + os << llvm::formatv(typeDefDeclVerifyStr, typeDef.getCppClassName(), + emitTypeNamePairsAfterComma); + } // Emit the mnenomic, if specified. if (auto mnenomic = typeDef.getMnemonic()) { @@ -226,7 +276,8 @@ static void emitTypeDefDecl(const TypeDef &typeDef, raw_ostream &os) { << "\"; }\n"; // If mnemonic specified, emit print/parse declarations. - os << typeDefParsePrint; + if (typeDef.getParserCode() || typeDef.getPrinterCode() || !params.empty()) + os << typeDefParsePrint; } if (typeDef.genAccessors()) { @@ -330,17 +381,6 @@ static const char *const typeDefStorageClassConstructorReturn = R"( } )"; -/// The code block for the getChecked definition. -/// -/// {0}: List of parameters, parameters style. -/// {1}: C++ type class name. -/// {2}: Comma separated list of parameter names. -static const char *const typeDefDefGetCheckeStr = R"( - ::mlir::Type {1}::getChecked(Location loc{0}) {{ - return Base::getChecked(loc{2}); - } -)"; - /// Use tgfmt to emit custom allocation code for each parameter, if necessary. static void emitParameterAllocationCode(TypeDef &typeDef, raw_ostream &os) { SmallVector parameters; @@ -403,13 +443,13 @@ static void emitStorageClass(TypeDef typeDef, raw_ostream &os) { parameters, /* prependComma */ false)); // 3) Emit the construct method. - if (typeDef.hasStorageCustomConstructor()) + if (typeDef.hasStorageCustomConstructor()) { // If user wants to build the storage constructor themselves, declare it // here and then they can write the definition elsewhere. os << " static " << typeDef.getStorageClassName() << " *construct(::mlir::TypeStorageAllocator &allocator, const KeyTy " "&key);\n"; - else { + } else { // If not, autogenerate one. // First, unbox the parameters. @@ -445,7 +485,7 @@ void emitParserPrinter(TypeDef typeDef, raw_ostream &os) { // Both the mnenomic and printerCode must be defined (for parity with // parserCode). os << "void " << typeDef.getCppClassName() - << "::print(::mlir::DialectAsmPrinter& printer) const {\n"; + << "::print(::mlir::DialectAsmPrinter &printer) const {\n"; if (*printerCode == "") { // If no code specified, emit error. PrintFatalError(typeDef.getLoc(), @@ -460,7 +500,7 @@ void emitParserPrinter(TypeDef typeDef, raw_ostream &os) { if (auto parserCode = typeDef.getParserCode()) { // The mnenomic must be defined so the dispatcher knows how to dispatch. os << "::mlir::Type " << typeDef.getCppClassName() - << "::parse(::mlir::MLIRContext* ctxt, ::mlir::DialectAsmParser& " + << "::parse(::mlir::MLIRContext *context, ::mlir::DialectAsmParser &" "parser) " "{\n"; if (*parserCode == "") { @@ -470,51 +510,112 @@ void emitParserPrinter(TypeDef typeDef, raw_ostream &os) { ": parser (if specified) must have non-empty code"); } auto fmtCtxt = - FmtContext().addSubst("_parser", "parser").addSubst("_ctxt", "ctxt"); + FmtContext().addSubst("_parser", "parser").addSubst("_ctxt", "context"); os << tgfmt(*parserCode, &fmtCtxt) << "\n}\n"; } } -/// Print all the typedef-specific definition code. -static void emitTypeDefDef(TypeDef typeDef, raw_ostream &os) { - NamespaceEmitter ns(os, typeDef.getDialect()); - SmallVector parameters; - typeDef.getParameters(parameters); - - // Emit the storage class, if requested and necessary. - if (typeDef.genStorageClass() && typeDef.getNumParameters() > 0) - emitStorageClass(typeDef, os); - - if (!parameters.empty()) { +/// Emit the builders for the given type. +static void emitTypeBuilderDefs(const TypeDef &typeDef, raw_ostream &os, + ArrayRef typeDefParams) { + bool genCheckedMethods = typeDef.genVerifyInvariantsDecl(); + StringRef typeClass = typeDef.getCppClassName(); + if (!typeDef.skipDefaultBuilders()) { os << llvm::formatv( - "{0} {0}::get(::mlir::MLIRContext* ctxt{1}) {{\n" - " return Base::get(ctxt{2});\n}\n", - typeDef.getCppClassName(), + "{0} {0}::get(::mlir::MLIRContext *context{1}) {{\n" + " return Base::get(context{2});\n}\n", + typeClass, TypeParamCommaFormatter( - TypeParamCommaFormatter::EmitFormat::TypeNamePairs, parameters), + TypeParamCommaFormatter::EmitFormat::TypeNamePairs, typeDefParams), TypeParamCommaFormatter(TypeParamCommaFormatter::EmitFormat::JustParams, - parameters)); + typeDefParams)); + if (genCheckedMethods) { + os << llvm::formatv( + "{0} {0}::getChecked(::mlir::Location loc{1}) {{\n" + " return Base::getChecked(loc{2});\n}\n", + typeClass, + TypeParamCommaFormatter( + TypeParamCommaFormatter::EmitFormat::TypeNamePairs, + typeDefParams), + TypeParamCommaFormatter( + TypeParamCommaFormatter::EmitFormat::JustParams, typeDefParams)); + } } - // Emit the parameter accessors. - if (typeDef.genAccessors()) - for (const TypeParameter ¶meter : parameters) { - SmallString<16> name = parameter.getName(); - name[0] = llvm::toUpper(name[0]); - os << formatv("{0} {3}::get{1}() const { return getImpl()->{2}; }\n", - parameter.getCppType(), name, parameter.getName(), - typeDef.getCppClassName()); + // Generate the builders specified by the user. + auto builderFmtCtx = FmtContext().addSubst("_ctxt", "context"); + auto checkedBuilderFmtCtx = FmtContext() + .addSubst("_loc", "loc") + .addSubst("_ctxt", "loc.getContext()"); + for (const TypeBuilder &builder : typeDef.getBuilders()) { + Optional body = builder.getBody(); + Optional checkedBody = + genCheckedMethods ? builder.getCheckedBody() : llvm::None; + if (!body && !checkedBody) + continue; + std::string paramStr; + llvm::raw_string_ostream paramOS(paramStr); + llvm::interleaveComma(builder.getParameters(), paramOS, + [&](const TypeBuilder::Parameter ¶m) { + // Note: TypeBuilder parameters are guaranteed to + // have names. + paramOS << param.getCppType() << " " + << *param.getName(); + }); + paramOS.flush(); + + // Emit the `get` variant of the builder. + if (body) { + os << llvm::formatv("{0} {0}::get(", typeClass); + if (!builder.hasInferredContextParameter()) { + os << "::mlir::MLIRContext *context"; + if (!paramStr.empty()) + os << ", "; + os << llvm::formatv("{0}) {{\n {1};\n}\n", paramStr, + tgfmt(*body, &builderFmtCtx).str()); + } else { + os << llvm::formatv("{0}) {{\n {1};\n}\n", paramStr, *body); + } } - // Generate getChecked() method. - if (typeDef.genVerifyInvariantsDecl()) { - os << llvm::formatv( - typeDefDefGetCheckeStr, - TypeParamCommaFormatter( - TypeParamCommaFormatter::EmitFormat::TypeNamePairs, parameters), - typeDef.getCppClassName(), - TypeParamCommaFormatter(TypeParamCommaFormatter::EmitFormat::JustParams, - parameters)); + // Emit the `getChecked` variant of the builder. + if (checkedBody) { + os << llvm::formatv("{0} {0}::getChecked(::mlir::Location loc", + typeClass); + if (!paramStr.empty()) + os << ", " << paramStr; + os << llvm::formatv(") {{\n {0};\n}\n", + tgfmt(*checkedBody, &checkedBuilderFmtCtx)); + } + } +} + +/// Print all the typedef-specific definition code. +static void emitTypeDefDef(const TypeDef &typeDef, raw_ostream &os) { + NamespaceEmitter ns(os, typeDef.getDialect()); + + SmallVector parameters; + typeDef.getParameters(parameters); + if (!parameters.empty()) { + // Emit the storage class, if requested and necessary. + if (typeDef.genStorageClass()) + emitStorageClass(typeDef, os); + + // Emit the builders for this type. + emitTypeBuilderDefs(typeDef, os, parameters); + + // Generate accessor definitions only if we also generate the storage class. + // Otherwise, let the user define the exact accessor definition. + if (typeDef.genAccessors() && typeDef.genStorageClass()) { + // Emit the parameter accessors. + for (const TypeParameter ¶meter : parameters) { + SmallString<16> name = parameter.getName(); + name[0] = llvm::toUpper(name[0]); + os << formatv("{0} {3}::get{1}() const { return getImpl()->{2}; }\n", + parameter.getCppType(), name, parameter.getName(), + typeDef.getCppClassName()); + } + } } // If mnemonic is specified maybe print definitions for the parser and printer @@ -534,9 +635,9 @@ static void emitParsePrintDispatch(ArrayRef types, raw_ostream &os) { // The parser dispatch is just a list of if-elses, matching on the // mnemonic and calling the class's parse function. - os << "static ::mlir::Type generatedTypeParser(::mlir::MLIRContext* " - "ctxt, " - "::mlir::DialectAsmParser& parser, ::llvm::StringRef mnemonic) {\n"; + os << "static ::mlir::Type generatedTypeParser(::mlir::MLIRContext *" + "context, ::mlir::DialectAsmParser &parser, " + "::llvm::StringRef mnemonic) {\n"; for (const TypeDef &type : types) { if (type.getMnemonic()) { os << formatv(" if (mnemonic == {0}::{1}::getMnemonic()) return " @@ -547,9 +648,9 @@ static void emitParsePrintDispatch(ArrayRef types, raw_ostream &os) { // If the type has no parameters and no parser code, just invoke a normal // `get`. if (type.getNumParameters() == 0 && !type.getParserCode()) - os << "get(ctxt);\n"; + os << "get(context);\n"; else - os << "parse(ctxt, parser);\n"; + os << "parse(context, parser);\n"; } } os << " return ::mlir::Type();\n"; @@ -559,7 +660,7 @@ static void emitParsePrintDispatch(ArrayRef types, raw_ostream &os) { // printer. os << "static ::mlir::LogicalResult generatedTypePrinter(::mlir::Type " "type, " - "::mlir::DialectAsmPrinter& printer) {\n" + "::mlir::DialectAsmPrinter &printer) {\n" << " return ::llvm::TypeSwitch<::mlir::Type, " "::mlir::LogicalResult>(type)\n"; for (const TypeDef &type : types) { @@ -594,7 +695,7 @@ static bool emitTypeDefDefs(const llvm::RecordKeeper &recordKeeper, IfDefScope scope("GET_TYPEDEF_CLASSES", os); emitParsePrintDispatch(typeDefs, os); - for (auto typeDef : typeDefs) + for (const TypeDef &typeDef : typeDefs) emitTypeDefDef(typeDef, os); return false;