Skip to content

Commit 0f495ae

Browse files
committed
updating enums
1 parent 723de7f commit 0f495ae

29 files changed

+262
-239
lines changed

mlir/include/mlir/Dialect/Tosa/IR/TosaOpBase.td

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ def Tosa_VariableOpBuilder : OpBuilder<
207207
}]>;
208208

209209

210-
// Wrapper over base I32EnumAttr to set common fields.
210+
// Wrapper over base I32EnumAttr to set common fields.
211211
class Tosa_I32Enum<string name, string description, list<I32EnumAttrCase> cases>
212212
: I32EnumAttr<name, description, cases> {
213213
let genSpecializedAttr = 0;
@@ -276,6 +276,7 @@ def Tosa_ProfileAttr
276276
def Tosa_ProfileArrayAttr
277277
: TypedArrayAttrBase<Tosa_ProfileAttr, "TOSA profile array attribute">;
278278

279+
279280
// The base class for defining op availability dimensions.
280281
class Availability {
281282
// The following are fields for controlling the generated C++ OpInterface.
@@ -381,6 +382,34 @@ class Extension<list<I32EnumAttrCase> extensions> : Availability {
381382
let instance = "ref";
382383
}
383384

385+
//===----------------------------------------------------------------------===//
386+
// Iterable attributes.
387+
//===----------------------------------------------------------------------===//
388+
// Defined in `section 3. Enumerations` of the TOSA specification.
389+
390+
def Tosa_RESIZE_BILINEAR : I32EnumAttrCase<"BILINEAR", 1>;
391+
def Tosa_RESIZE_NEAREST_NEIGHBOR : I32EnumAttrCase<"NEAREST_NEIGHBOR", 2>;
392+
393+
def Tosa_ResizeTypeAttr
394+
: Tosa_I32EnumAttr<"ResizeType", "Supported resize/upsampling strategies", "resize_type",
395+
[Tosa_RESIZE_BILINEAR, Tosa_RESIZE_NEAREST_NEIGHBOR]>;
396+
397+
def Tosa_NANPROPAGATION_PROPAGATE : I32EnumAttrCase<"PROPAGATE", 1>;
398+
def Tosa_NANPROPAGATION_IGNORE : I32EnumAttrCase<"IGNORE", 2>;
399+
400+
def Tosa_NanPropagationAttr
401+
: Tosa_I32EnumAttr<"NanPropagation", "Supported NaN propagation strategies", "nan",
402+
[Tosa_NANPROPAGATION_PROPAGATE, Tosa_NANPROPAGATION_IGNORE]>;
403+
404+
def Tosa_ROUNDING_SINGLE_ROUND : I32EnumAttrCase<"SINGLE_ROUND", 1>;
405+
def Tosa_ROUNDING_INEXACT_ROUND : I32EnumAttrCase<"INEXACT_ROUND", 2>;
406+
def Tosa_ROUNDING_DOUBLE_ROUND : I32EnumAttrCase<"DOUBLE_ROUND", 3>;
407+
408+
def Tosa_RoundingTypeAttr
409+
: Tosa_I32EnumAttr<"RoundingType", "Supported rounding modes", "rounding_type",
410+
[Tosa_ROUNDING_SINGLE_ROUND, Tosa_ROUNDING_INEXACT_ROUND, Tosa_ROUNDING_DOUBLE_ROUND]>;
411+
412+
384413
//===----------------------------------------------------------------------===//
385414
// TOSA Interfaces.
386415
//===----------------------------------------------------------------------===//

mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def Tosa_ArgMaxOp : Tosa_InferShapedTypeOp<"argmax"> {
4343
let arguments = (ins
4444
Tosa_TensorAtLeast1D: $input,
4545
I32Attr: $axis,
46-
DefaultValuedAttr<Tosa_NanPropagationAttr, "\"PROPAGATE\"">:$nan_mode
46+
DefaultValuedAttr<Tosa_NanPropagationAttr, "::mlir::tosa::NanPropagation::PROPAGATE">:$nan_mode
4747
);
4848

4949
let results = (outs
@@ -357,7 +357,7 @@ def Tosa_MaxPool2dOp : Tosa_InferShapedTypeOp<"max_pool2d"> {
357357
Tosa_IntArrayAttr2:$kernel,
358358
Tosa_IntArrayAttr2:$stride,
359359
Tosa_IntArrayAttr4:$pad,
360-
DefaultValuedAttr<Tosa_NanPropagationAttr, "\"PROPAGATE\"">:$nan_mode
360+
DefaultValuedAttr<Tosa_NanPropagationAttr, "::mlir::tosa::NanPropagation::PROPAGATE">:$nan_mode
361361
);
362362

363363
let results = (outs
@@ -487,7 +487,7 @@ def Tosa_ClampOp : Tosa_ElementwiseUnaryOp<"clamp"> {
487487
Tosa_Tensor:$input,
488488
Tosa_IntOrFloatAttr:$min_val,
489489
Tosa_IntOrFloatAttr:$max_val,
490-
DefaultValuedAttr<Tosa_NanPropagationAttr, "\"PROPAGATE\"">:$nan_mode
490+
DefaultValuedAttr<Tosa_NanPropagationAttr, "::mlir::tosa::NanPropagation::PROPAGATE">:$nan_mode
491491
);
492492

493493
let results = (outs
@@ -935,7 +935,7 @@ def Tosa_MaximumOp : Tosa_ElementwiseOp<"maximum", [
935935
let arguments = (ins
936936
Tosa_Tensor:$input1,
937937
Tosa_Tensor:$input2,
938-
DefaultValuedAttr<Tosa_NanPropagationAttr, "\"PROPAGATE\"">:$nan_mode
938+
DefaultValuedAttr<Tosa_NanPropagationAttr, "::mlir::tosa::NanPropagation::PROPAGATE">:$nan_mode
939939
);
940940

941941
let results = (outs
@@ -964,7 +964,7 @@ def Tosa_MinimumOp : Tosa_ElementwiseOp<"minimum", [
964964
let arguments = (ins
965965
Tosa_Tensor:$input1,
966966
Tosa_Tensor:$input2,
967-
DefaultValuedAttr<Tosa_NanPropagationAttr, "\"PROPAGATE\"">:$nan_mode
967+
DefaultValuedAttr<Tosa_NanPropagationAttr, "::mlir::tosa::NanPropagation::PROPAGATE">:$nan_mode
968968
);
969969

970970
let results = (outs
@@ -1711,7 +1711,7 @@ def Tosa_ReduceMaxOp : Tosa_InferTensorTypeOp<"reduce_max"> {
17111711
let arguments = (ins
17121712
Tosa_TensorAtLeast1D:$input,
17131713
I32Attr:$axis,
1714-
DefaultValuedAttr<Tosa_NanPropagationAttr, "\"PROPAGATE\"">:$nan_mode
1714+
DefaultValuedAttr<Tosa_NanPropagationAttr, "::mlir::tosa::NanPropagation::PROPAGATE">:$nan_mode
17151715
);
17161716

17171717
let results = (outs
@@ -1751,7 +1751,7 @@ def Tosa_ReduceMinOp : Tosa_InferTensorTypeOp<"reduce_min"> {
17511751
let arguments = (ins
17521752
Tosa_TensorAtLeast1D:$input,
17531753
I32Attr:$axis,
1754-
DefaultValuedAttr<Tosa_NanPropagationAttr, "\"PROPAGATE\"">:$nan_mode
1754+
DefaultValuedAttr<Tosa_NanPropagationAttr, "::mlir::tosa::NanPropagation::PROPAGATE">:$nan_mode
17551755
);
17561756

17571757
let results = (outs

mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313
#ifndef TOSA_TYPES_BASE
1414
#define TOSA_TYPES_BASE
1515

16+
1617
include "mlir/IR/AttrTypeBase.td"
1718
include "mlir/IR/OpBase.td"
1819

1920
include "mlir/Dialect/Tosa/IR/TosaOpBase.td"
2021

22+
2123
//===----------------------------------------------------------------------===//
2224
// Tosa Type Definitions.
2325
//===----------------------------------------------------------------------===//
@@ -234,29 +236,6 @@ def Tosa_IntegerAttr : Attr<CPred<"::llvm::isa<::mlir::IntegerAttr>($_self)">,
234236

235237
def Tosa_IntOrFloatAttr : AnyAttrOf<[Tosa_IntegerAttr, Tosa_FloatAttr]>;
236238

237-
//===----------------------------------------------------------------------===//
238-
// Iterable attributes.
239-
//===----------------------------------------------------------------------===//
240-
// Defined in `section 3. Enumerations` of the TOSA specification.
241-
242-
// Supported regimes for tosa.resize.
243-
def Tosa_ResizeTypeAttr : StringBasedAttr<
244-
CPred<"::llvm::cast<StringAttr>($_self).getValue() == \"BILINEAR\" || " #
245-
"::llvm::cast<StringAttr>($_self).getValue() == \"NEAREST_NEIGHBOR\"">,
246-
"Supported resize/upsampling strategies">;
247-
248-
// Supported NaN propagation strategies.
249-
def Tosa_NanPropagationAttr : StringBasedAttr<
250-
CPred<"::llvm::cast<StringAttr>($_self).getValue() == \"PROPAGATE\" || " #
251-
"::llvm::cast<StringAttr>($_self).getValue() == \"IGNORE\"">,
252-
"Supported NaN propagation strategies">;
253-
254-
// Rounding mode for tosa.rescale
255-
def Tosa_RoundingTypeAttr : StringBasedAttr<
256-
CPred<"::llvm::cast<StringAttr>($_self).getValue() == \"SINGLE_ROUND\" || " #
257-
"::llvm::cast<StringAttr>($_self).getValue() == \"INEXACT_ROUND\" || " #
258-
"::llvm::cast<StringAttr>($_self).getValue() == \"DOUBLE_ROUND\"">,
259-
"Supported rounding modes">;
260239

261240
def Tosa_TensorTypeAttr : TypeAttrBase<"TensorType", "Tensor type attribute">;
262241

mlir/lib/Conversion/TosaToArith/TosaToArith.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,9 @@ class ApplyScaleGenericOpConverter
6464

6565
LogicalResult matchAndRewrite(tosa::ApplyScaleOp op,
6666
PatternRewriter &rewriter) const final {
67-
StringRef roundingMode = op.getRoundingMode();
68-
if (roundingMode != "DOUBLE_ROUND" && roundingMode != "SINGLE_ROUND") {
67+
RoundingType roundingMode = op.getRoundingMode();
68+
if (roundingMode != RoundingType::DOUBLE_ROUND &&
69+
roundingMode != RoundingType::SINGLE_ROUND) {
6970
return failure();
7071
}
7172

@@ -100,7 +101,7 @@ class ApplyScaleGenericOpConverter
100101
multiply64 = arith::AddIOp::create(rewriter, loc, multiply64, round);
101102

102103
// Apply double rounding if necessary.
103-
if (op.getRoundingMode() == "DOUBLE_ROUND") {
104+
if (op.getRoundingMode() == RoundingType::DOUBLE_ROUND) {
104105
int64_t roundInt = 1 << 30;
105106
Value roundUp = getConstantValue(loc, i64Ty, roundInt, rewriter);
106107
Value roundDown = getConstantValue(loc, i64Ty, -roundInt, rewriter);
@@ -129,8 +130,9 @@ class ApplyScale32BitOpConverter : public OpRewritePattern<tosa::ApplyScaleOp> {
129130

130131
LogicalResult matchAndRewrite(tosa::ApplyScaleOp op,
131132
PatternRewriter &rewriter) const final {
132-
StringRef roundingMode = op.getRoundingMode();
133-
if (roundingMode != "DOUBLE_ROUND" && roundingMode != "SINGLE_ROUND") {
133+
RoundingType roundingMode = op.getRoundingMode();
134+
if (roundingMode != RoundingType::DOUBLE_ROUND &&
135+
roundingMode != RoundingType::SINGLE_ROUND) {
134136
return failure();
135137
}
136138

@@ -179,7 +181,7 @@ class ApplyScale32BitOpConverter : public OpRewritePattern<tosa::ApplyScaleOp> {
179181
arith::SelectOp::create(rewriter, loc, shiftOver32, shiftHighR, zero32);
180182

181183
// Conditionally perform our double round.
182-
if (op.getRoundingMode() == "DOUBLE_ROUND") {
184+
if (op.getRoundingMode() == RoundingType::DOUBLE_ROUND) {
183185
Value negOne32 = getConstantValue(loc, i32Ty, -1, rewriter);
184186
Value valuePositive = arith::CmpIOp::create(
185187
rewriter, loc, arith::CmpIPredicate::sge, value32, zero32);

mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ materializeBinaryNanCheckIfRequired(OpTy op, PatternRewriter &rewriter,
6565
return result;
6666

6767
auto nanMode = op.getNanMode();
68-
if (nanMode == "PROPAGATE")
68+
if (nanMode == NanPropagation::PROPAGATE)
6969
return result;
7070

7171
// Unordered comparison of NaN against itself will always return true.
@@ -156,9 +156,11 @@ static Value createLinalgBodyCalculationForElementwiseOp(
156156
if (!b.getType().isInteger(32))
157157
b = arith::ExtSIOp::create(rewriter, loc, rewriter.getI32Type(), b);
158158

159-
auto result = tosa::ApplyScaleOp::create(
160-
rewriter, loc, rewriter.getI32Type(), a, b, shiftConst,
161-
rewriter.getStringAttr("SINGLE_ROUND"));
159+
auto roundingAttr = RoundingTypeAttr::get(rewriter.getContext(),
160+
RoundingType::SINGLE_ROUND);
161+
auto result =
162+
tosa::ApplyScaleOp::create(rewriter, loc, rewriter.getI32Type(), a,
163+
b, shiftConst, roundingAttr);
162164

163165
if (elementTy.isInteger(32))
164166
return result;
@@ -464,7 +466,7 @@ static Value createLinalgBodyCalculationForElementwiseOp(
464466

465467
// In the case of "PROPAGATE" semantics no compare and selection is
466468
// required.
467-
if (nanMode == "PROPAGATE")
469+
if (nanMode == NanPropagation::PROPAGATE)
468470
return result;
469471

470472
// In the case of "IGNORE" semantics materialize a comparison
@@ -1173,7 +1175,8 @@ static LogicalResult reduceMatchAndRewriteHelper(OpTy op, uint64_t axis,
11731175
if constexpr (std::is_same_v<OpTy, tosa::ReduceMinOp> ||
11741176
std::is_same_v<OpTy, tosa::ReduceMaxOp>) {
11751177
// NaN propagation has no meaning for non floating point types.
1176-
if (isa<FloatType>(elementTy) && op.getNanMode() == "IGNORE") {
1178+
if (isa<FloatType>(elementTy) &&
1179+
op.getNanMode() == NanPropagation::IGNORE) {
11771180
isNanIgnoreMode = true;
11781181
// Because the TOSA spec requires the result be NaN iff all elements in
11791182
// the reduction are NaN we can't simply perform a compare and select.
@@ -1336,11 +1339,11 @@ class RescaleConverter : public OpRewritePattern<tosa::RescaleOp> {
13361339
unsigned rank = inputTy.getRank();
13371340

13381341
// This is an illegal configuration. terminate and log an error
1339-
if (op.getRoundingMode() == "INEXACT_ROUND")
1342+
if (op.getRoundingMode() == RoundingType::INEXACT_ROUND)
13401343
return rewriter.notifyMatchFailure(
13411344
op, "tosa.rescale with rounding mode = 'INEXACT_ROUND' is not "
13421345
"currently supported");
1343-
if (op.getRoundingMode() == "DOUBLE_ROUND" && !op.getScale32())
1346+
if (op.getRoundingMode() == RoundingType::DOUBLE_ROUND && !op.getScale32())
13441347
return rewriter.notifyMatchFailure(
13451348
op, "tosa.rescale requires scale32 for double_round to be true");
13461349

@@ -1386,11 +1389,10 @@ class RescaleConverter : public OpRewritePattern<tosa::RescaleOp> {
13861389
// is ever true.
13871390

13881391
bool doubleRound =
1389-
op.getRoundingMode() == "DOUBLE_ROUND" &&
1392+
op.getRoundingMode() == RoundingType::DOUBLE_ROUND &&
13901393
llvm::any_of(shiftValues, [](int32_t v) { return v > 31; });
1391-
StringAttr roundingMode = doubleRound
1392-
? rewriter.getStringAttr("DOUBLE_ROUND")
1393-
: rewriter.getStringAttr("SINGLE_ROUND");
1394+
RoundingType roundingMode =
1395+
doubleRound ? RoundingType::DOUBLE_ROUND : RoundingType::SINGLE_ROUND;
13941396

13951397
SmallVector<AffineMap> indexingMaps = {
13961398
rewriter.getMultiDimIdentityMap(rank)};
@@ -1573,7 +1575,7 @@ class ResizeUnaryConverter : public OpRewritePattern<tosa::ResizeOp> {
15731575
auto input = op.getInput();
15741576
auto inputTy = cast<RankedTensorType>(input.getType());
15751577
auto resultTy = cast<RankedTensorType>(op.getType());
1576-
const bool isBilinear = op.getMode() == "BILINEAR";
1578+
const bool isBilinear = op.getMode() == ResizeType::BILINEAR;
15771579

15781580
auto inputH = inputTy.getDimSize(1);
15791581
auto inputW = inputTy.getDimSize(2);
@@ -1585,7 +1587,8 @@ class ResizeUnaryConverter : public OpRewritePattern<tosa::ResizeOp> {
15851587
op, "tosa.resize is not a pure 1x1->1x1 image operation");
15861588

15871589
// TODO(suderman): These string values should be declared the TOSA dialect.
1588-
if (op.getMode() != "NEAREST_NEIGHBOR" && op.getMode() != "BILINEAR")
1590+
if (op.getMode() != ResizeType::NEAREST_NEIGHBOR &&
1591+
op.getMode() != ResizeType::BILINEAR)
15891592
return rewriter.notifyMatchFailure(
15901593
op, "tosa.resize mode should be NEAREST_NEIGHBOR or BILINEAR");
15911594

@@ -1785,7 +1788,8 @@ class GenericResizeConverter : public OpRewritePattern<tosa::ResizeOp> {
17851788
return rewriter.notifyMatchFailure(
17861789
op, "unable to get dynamic dimensions of tosa.resize");
17871790

1788-
if (op.getMode() != "NEAREST_NEIGHBOR" && op.getMode() != "BILINEAR")
1791+
if (op.getMode() != ResizeType::NEAREST_NEIGHBOR &&
1792+
op.getMode() != ResizeType::BILINEAR)
17891793
return rewriter.notifyMatchFailure(
17901794
op, "tosa.resize mode should be NEAREST_NEIGHBOR or BILINEAR");
17911795

@@ -1890,7 +1894,7 @@ class GenericResizeConverter : public OpRewritePattern<tosa::ResizeOp> {
18901894
getIndexAndDeltaInt(ix, dx, inX, xScaleN, xScaleD, xOffset, imageW, b);
18911895
}
18921896

1893-
if (op.getMode() == "NEAREST_NEIGHBOR") {
1897+
if (op.getMode() == ResizeType::NEAREST_NEIGHBOR) {
18941898
auto one = arith::ConstantOp::create(b, b.getI32IntegerAttr(1));
18951899

18961900
auto getNearestIndexAndClamp = [&](Value val, Value dval, Value scale,
@@ -1926,7 +1930,7 @@ class GenericResizeConverter : public OpRewritePattern<tosa::ResizeOp> {
19261930
linalg::YieldOp::create(b, result);
19271931
} else {
19281932
// The mode here must be BILINEAR.
1929-
assert(op.getMode() == "BILINEAR");
1933+
assert(op.getMode() == ResizeType::BILINEAR);
19301934

19311935
auto oneVal = arith::ConstantOp::create(b, b.getI32IntegerAttr(1));
19321936

@@ -2291,7 +2295,7 @@ class ArgMaxConverter : public OpRewritePattern<tosa::ArgMaxOp> {
22912295

22922296
Value predicate;
22932297
if (isa<FloatType>(inElementTy)) {
2294-
if (argmaxOp.getNanMode() == "IGNORE") {
2298+
if (argmaxOp.getNanMode() == NanPropagation::IGNORE) {
22952299
// Only update index & max value for non NaN values. If all
22962300
// values are NaNs, the initial index will be return which is 0.
22972301
predicate = arith::CmpFOp::create(rewriter, nestedLoc,

mlir/lib/Conversion/TosaToLinalg/TosaToLinalgNamed.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,7 @@ class MaxPool2dConverter : public OpConversionPattern<tosa::MaxPool2dOp> {
803803
dilationAttr);
804804

805805
rewriter.setInsertionPointAfter(op);
806-
StringRef nanMode = op.getNanMode();
806+
NanPropagation nanMode = op.getNanMode();
807807
rewriter.replaceOp(op, resultOp);
808808

809809
// NaN propagation has no meaning for non floating point types.
@@ -817,7 +817,7 @@ class MaxPool2dConverter : public OpConversionPattern<tosa::MaxPool2dOp> {
817817
// we've already produced a named op we will just take its body and modify
818818
// it to include the appropriate checks. If the current value is NaN the
819819
// old value of pool will be taken otherwise we use the result.
820-
if (nanMode == "IGNORE") {
820+
if (nanMode == NanPropagation::IGNORE) {
821821
auto genericOp = linalg::GenericOp::create(
822822
rewriter, loc, resultOp.getType(0), resultOp.getInputs(),
823823
resultOp.getOutputs(), resultOp.getIndexingMapsArray(),
@@ -1040,11 +1040,13 @@ class AvgPool2dConverter : public OpRewritePattern<tosa::AvgPool2dOp> {
10401040
rewriter, loc, rewriter.getI8IntegerAttr(30));
10411041
Value shift = arith::AddIOp::create(rewriter, loc, k8, thirty8);
10421042

1043-
auto scaled =
1044-
tosa::ApplyScaleOp::create(
1045-
rewriter, loc, rewriter.getI32Type(), poolVal, multiplier,
1046-
shift, rewriter.getStringAttr("SINGLE_ROUND"))
1047-
.getResult();
1043+
auto roundingAttr = RoundingTypeAttr::get(
1044+
rewriter.getContext(), RoundingType::SINGLE_ROUND);
1045+
1046+
auto scaled = tosa::ApplyScaleOp::create(
1047+
rewriter, loc, rewriter.getI32Type(), poolVal,
1048+
multiplier, shift, roundingAttr)
1049+
.getResult();
10481050

10491051
// If we have quantization information we need to apply output
10501052
// zeropoint.

mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,8 @@ struct ClampClampOptimization : public OpRewritePattern<tosa::ClampOp> {
555555
// Check we have a valid NaN propagation combination.
556556
const auto opNanMode = op.getNanMode();
557557
const auto clampNanMode = clampOp.getNanMode();
558-
if (opNanMode == "IGNORE" && clampNanMode == "PROPAGATE")
558+
if (opNanMode == NanPropagation::IGNORE &&
559+
clampNanMode == NanPropagation::PROPAGATE)
559560
return failure();
560561

561562
auto maxValAttr = op.getMaxValAttr();
@@ -636,10 +637,14 @@ struct ClampClampOptimization : public OpRewritePattern<tosa::ClampOp> {
636637
}
637638
}
638639

640+
auto newMode =
641+
(opNanMode != clampNanMode) ? tosa::NanPropagation::IGNORE : opNanMode;
642+
643+
auto newModeAttr = NanPropagationAttr::get(rewriter.getContext(), newMode);
644+
639645
rewriter.replaceOpWithNewOp<tosa::ClampOp>(
640646
op, op.getType(), clampOp.getInput(), newMinValAttr, newMaxValAttr,
641-
rewriter.getStringAttr((opNanMode != clampNanMode) ? "IGNORE"
642-
: opNanMode));
647+
newModeAttr);
643648
return success();
644649
}
645650
};

0 commit comments

Comments
 (0)