|
54 | 54 | using namespace mlir; |
55 | 55 |
|
56 | 56 | static ParseResult parseApplyRegisteredPassOptions( |
57 | | - OpAsmParser &parser, |
58 | | - std::optional<OpAsmParser::UnresolvedOperand> &dynamicOptions, |
59 | | - StringAttr &staticOptions); |
| 57 | + OpAsmParser &parser, ArrayAttr &options, |
| 58 | + SmallVectorImpl<OpAsmParser::UnresolvedOperand> &dynamicOptions); |
60 | 59 | static void printApplyRegisteredPassOptions(OpAsmPrinter &printer, |
61 | | - Operation *op, Value dynamicOptions, |
62 | | - StringAttr staticOptions); |
| 60 | + Operation *op, ArrayAttr options, |
| 61 | + ValueRange dynamicOptions); |
63 | 62 | static ParseResult parseSequenceOpOperands( |
64 | 63 | OpAsmParser &parser, std::optional<OpAsmParser::UnresolvedOperand> &root, |
65 | 64 | Type &rootType, |
@@ -785,25 +784,40 @@ DiagnosedSilenceableFailure |
785 | 784 | transform::ApplyRegisteredPassOp::apply(transform::TransformRewriter &rewriter, |
786 | 785 | transform::TransformResults &results, |
787 | 786 | transform::TransformState &state) { |
788 | | - // Check whether pass options are specified, either as a dynamic param or |
789 | | - // a static attribute. In either case, options are passed as a single string. |
790 | | - StringRef options; |
791 | | - if (auto dynamicOptions = getDynamicOptions()) { |
792 | | - ArrayRef<Attribute> dynamicOptionsParam = state.getParams(dynamicOptions); |
793 | | - if (dynamicOptionsParam.size() != 1) { |
794 | | - return emitSilenceableError() |
795 | | - << "options passed as a param must be a single value, got " |
796 | | - << dynamicOptionsParam.size(); |
797 | | - } |
798 | | - if (auto optionsStrAttr = dyn_cast<StringAttr>(dynamicOptionsParam[0])) { |
799 | | - options = optionsStrAttr.getValue(); |
| 787 | + // Obtain a single options-string from options passed statically as |
| 788 | + // string attributes as well as "dynamically" through params. |
| 789 | + std::string options; |
| 790 | + OperandRange dynamicOptions = getDynamicOptions(); |
| 791 | + size_t dynamicOptionsIdx = 0; |
| 792 | + for (auto [idx, optionAttr] : llvm::enumerate(getOptions())) { |
| 793 | + if (idx > 0) |
| 794 | + options += " "; // Interleave options seperator. |
| 795 | + |
| 796 | + if (auto strAttr = dyn_cast<StringAttr>(optionAttr)) { |
| 797 | + options += strAttr.getValue(); |
| 798 | + } else if (isa<UnitAttr>(optionAttr)) { |
| 799 | + assert(dynamicOptionsIdx < dynamicOptions.size() && |
| 800 | + "number of dynamic option markers (UnitAttr) in options ArrayAttr " |
| 801 | + "should be the same as the number of options passed as params"); |
| 802 | + ArrayRef<Attribute> dynamicOption = |
| 803 | + state.getParams(dynamicOptions[dynamicOptionsIdx++]); |
| 804 | + if (dynamicOption.size() != 1) |
| 805 | + return emitSilenceableError() << "options passed as a param must have " |
| 806 | + "a single value associated, param " |
| 807 | + << dynamicOptionsIdx - 1 << " associates " |
| 808 | + << dynamicOption.size(); |
| 809 | + |
| 810 | + if (auto dynamicOptionStr = dyn_cast<StringAttr>(dynamicOption[0])) { |
| 811 | + options += dynamicOptionStr.getValue(); |
| 812 | + } else { |
| 813 | + return emitSilenceableError() |
| 814 | + << "options passed as a param must be a string, got " |
| 815 | + << dynamicOption[0]; |
| 816 | + } |
800 | 817 | } else { |
801 | | - return emitSilenceableError() |
802 | | - << "options passed as a param must be a string, got " |
803 | | - << dynamicOptionsParam[0]; |
| 818 | + assert(false && |
| 819 | + "expected options element to be either StringAttr or UnitAttr"); |
804 | 820 | } |
805 | | - } else { |
806 | | - options = getStaticOptions(); |
807 | 821 | } |
808 | 822 |
|
809 | 823 | // Get pass or pass pipeline from registry. |
@@ -850,43 +864,88 @@ transform::ApplyRegisteredPassOp::apply(transform::TransformRewriter &rewriter, |
850 | 864 | } |
851 | 865 |
|
852 | 866 | static ParseResult parseApplyRegisteredPassOptions( |
853 | | - OpAsmParser &parser, |
854 | | - std::optional<OpAsmParser::UnresolvedOperand> &dynamicOptions, |
855 | | - StringAttr &staticOptions) { |
856 | | - dynamicOptions = std::nullopt; |
857 | | - OpAsmParser::UnresolvedOperand dynamicOptionsOperand; |
858 | | - OptionalParseResult hasDynamicOptions = |
859 | | - parser.parseOptionalOperand(dynamicOptionsOperand); |
860 | | - |
861 | | - if (hasDynamicOptions.has_value()) { |
862 | | - if (failed(hasDynamicOptions.value())) |
863 | | - return failure(); |
| 867 | + OpAsmParser &parser, ArrayAttr &options, |
| 868 | + SmallVectorImpl<OpAsmParser::UnresolvedOperand> &dynamicOptions) { |
| 869 | + auto dynamicOptionMarker = UnitAttr::get(parser.getContext()); |
| 870 | + SmallVector<Attribute> optionsArray; |
| 871 | + |
| 872 | + auto parseOperandOrString = [&]() -> OptionalParseResult { |
| 873 | + OpAsmParser::UnresolvedOperand operand; |
| 874 | + OptionalParseResult parsedOperand = parser.parseOptionalOperand(operand); |
| 875 | + if (parsedOperand.has_value()) { |
| 876 | + if (failed(parsedOperand.value())) |
| 877 | + return failure(); |
864 | 878 |
|
865 | | - dynamicOptions = dynamicOptionsOperand; |
866 | | - return success(); |
867 | | - } |
| 879 | + dynamicOptions.push_back(operand); |
| 880 | + optionsArray.push_back( |
| 881 | + dynamicOptionMarker); // Placeholder for knowing where to |
| 882 | + // inject the dynamic option-as-param. |
| 883 | + return success(); |
| 884 | + } |
868 | 885 |
|
869 | | - OptionalParseResult hasStaticOptions = |
870 | | - parser.parseOptionalAttribute(staticOptions); |
871 | | - if (hasStaticOptions.has_value()) { |
872 | | - if (failed(hasStaticOptions.value())) |
| 886 | + StringAttr stringAttr; |
| 887 | + OptionalParseResult parsedStringAttr = |
| 888 | + parser.parseOptionalAttribute(stringAttr); |
| 889 | + if (parsedStringAttr.has_value()) { |
| 890 | + if (failed(parsedStringAttr.value())) |
| 891 | + return failure(); |
| 892 | + optionsArray.push_back(stringAttr); |
| 893 | + return success(); |
| 894 | + } |
| 895 | + |
| 896 | + return std::nullopt; |
| 897 | + }; |
| 898 | + |
| 899 | + OptionalParseResult parsedOptionsElement = parseOperandOrString(); |
| 900 | + while (parsedOptionsElement.has_value()) { |
| 901 | + if (failed(parsedOptionsElement.value())) |
873 | 902 | return failure(); |
874 | | - return success(); |
| 903 | + parsedOptionsElement = parseOperandOrString(); |
875 | 904 | } |
876 | 905 |
|
| 906 | + if (optionsArray.empty()) { |
| 907 | + return parser.emitError(parser.getCurrentLocation()) |
| 908 | + << "expected at least one option (either a string or a param)"; |
| 909 | + } |
| 910 | + options = parser.getBuilder().getArrayAttr(optionsArray); |
877 | 911 | return success(); |
878 | 912 | } |
879 | 913 |
|
880 | 914 | static void printApplyRegisteredPassOptions(OpAsmPrinter &printer, |
881 | | - Operation *op, Value dynamicOptions, |
882 | | - StringAttr staticOptions) { |
883 | | - if (dynamicOptions) { |
884 | | - printer.printOperand(dynamicOptions); |
885 | | - } else if (!staticOptions.getValue().empty()) { |
886 | | - printer.printAttribute(staticOptions); |
| 915 | + Operation *op, ArrayAttr options, |
| 916 | + ValueRange dynamicOptions) { |
| 917 | + size_t currentDynamicOptionIdx = 0; |
| 918 | + for (Attribute optionAttr : options) { |
| 919 | + if (currentDynamicOptionIdx > 0) |
| 920 | + printer << " "; // Interleave options separator. |
| 921 | + |
| 922 | + if (isa<UnitAttr>(optionAttr)) |
| 923 | + printer.printOperand(dynamicOptions[currentDynamicOptionIdx++]); |
| 924 | + else if (auto strAttr = dyn_cast<StringAttr>(optionAttr)) |
| 925 | + printer.printAttribute(strAttr); |
| 926 | + else |
| 927 | + assert(false && "each option should be either a StringAttr or UnitAttr"); |
887 | 928 | } |
888 | 929 | } |
889 | 930 |
|
| 931 | +LogicalResult transform::ApplyRegisteredPassOp::verify() { |
| 932 | + size_t numUnitsInOptions = 0; |
| 933 | + for (Attribute optionsElement : getOptions()) { |
| 934 | + if (isa<UnitAttr>(optionsElement)) |
| 935 | + numUnitsInOptions++; |
| 936 | + else if (!isa<StringAttr>(optionsElement)) |
| 937 | + return emitOpError() << "expected each option to be either a StringAttr " |
| 938 | + << "or a UnitAttr, got " << optionsElement; |
| 939 | + } |
| 940 | + |
| 941 | + if (getDynamicOptions().size() != numUnitsInOptions) |
| 942 | + return emitOpError() |
| 943 | + << "expected the same number of options passed as params as " |
| 944 | + << "UnitAttr elements in options ArrayAttr"; |
| 945 | + |
| 946 | + return success(); |
| 947 | +} |
| 948 | + |
890 | 949 | //===----------------------------------------------------------------------===// |
891 | 950 | // CastOp |
892 | 951 | //===----------------------------------------------------------------------===// |
|
0 commit comments