From ab93bd6959d6d2df1b44c1654938452dc30898b0 Mon Sep 17 00:00:00 2001 From: Hsiangkai Wang Date: Tue, 11 Feb 2025 16:02:52 +0000 Subject: [PATCH 01/17] [mlir][tosa] Change ClampOp's min/max attributes (#125197) This changes Tosa ClampOp attributes to min_val and max_val which are either integer attributes or float attributes, and adds verify checks that these attribute element types must match element types of input and output Co-authored-by: Tai Ly --- mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td | 6 +- .../mlir/Dialect/Tosa/IR/TosaTypesBase.td | 8 ++ .../Conversion/TosaToLinalg/TosaToLinalg.cpp | 8 +- .../Dialect/Tosa/IR/TosaCanonicalizations.cpp | 129 +++++++++++++----- mlir/lib/Dialect/Tosa/IR/TosaOps.cpp | 36 +++-- .../TosaToLinalg/tosa-to-linalg.mlir | 41 +----- mlir/test/Dialect/Tosa/canonicalize.mlir | 65 ++++----- mlir/test/Dialect/Tosa/invalid.mlir | 4 +- mlir/test/Dialect/Tosa/ops.mlir | 12 +- mlir/test/Dialect/Tosa/tosa-infer-shapes.mlir | 4 +- .../Dialect/Tosa/tosa-reduce-transposes.mlir | 45 +++--- 11 files changed, 199 insertions(+), 159 deletions(-) diff --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td b/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td index 840558a81493..7a65417db0ea 100644 --- a/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td +++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaOps.td @@ -394,10 +394,8 @@ def Tosa_ClampOp : Tosa_ElementwiseUnaryOp<"clamp"> { let arguments = (ins Tosa_Tensor:$input, - I64Attr:$min_int, - I64Attr:$max_int, - Tosa_FloatAttr:$min_fp, - Tosa_FloatAttr:$max_fp, + Tosa_IntOrFloatAttr:$min_val, + Tosa_IntOrFloatAttr:$max_val, DefaultValuedAttr:$nan_mode ); diff --git a/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td b/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td index 7aa1f72ec6e1..120adf82249e 100644 --- a/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td +++ b/mlir/include/mlir/Dialect/Tosa/IR/TosaTypesBase.td @@ -202,6 +202,14 @@ def Tosa_FloatAttr : Attr($_self)">, let returnType = [{ ::mlir::APFloat }]; } +def Tosa_IntegerAttr : Attr($_self)">, + "arbitrary integer attribute"> { + let storageType = [{ ::mlir::IntegerAttr }]; + let returnType = [{ ::llvm::APInt }]; +} + +def Tosa_IntOrFloatAttr : AnyAttrOf<[Tosa_IntegerAttr, Tosa_FloatAttr]>; + //===----------------------------------------------------------------------===// // Iterable attributes. //===----------------------------------------------------------------------===// diff --git a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp index 0246d9019368..28bc8732b797 100644 --- a/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp +++ b/mlir/lib/Conversion/TosaToLinalg/TosaToLinalg.cpp @@ -389,8 +389,8 @@ static Value createLinalgBodyCalculationForElementwiseOp( // tosa::ClampOp if (isa(op) && isa(elementTy)) { bool losesInfo = false; - APFloat minApf = cast(op->getAttr("min_fp")).getValue(); - APFloat maxApf = cast(op->getAttr("max_fp")).getValue(); + APFloat minApf = cast(op->getAttr("min_val")).getValue(); + APFloat maxApf = cast(op->getAttr("max_val")).getValue(); minApf.convert(cast(elementTy).getFloatSemantics(), APFloat::rmNearestTiesToEven, &losesInfo); maxApf.convert(cast(elementTy).getFloatSemantics(), @@ -405,9 +405,9 @@ static Value createLinalgBodyCalculationForElementwiseOp( if (isa(op) && isa(elementTy)) { auto intTy = cast(elementTy); int64_t min = - cast(op->getAttr("min_int")).getValue().getSExtValue(); + cast(op->getAttr("min_val")).getValue().getSExtValue(); int64_t max = - cast(op->getAttr("max_int")).getValue().getSExtValue(); + cast(op->getAttr("max_val")).getValue().getSExtValue(); int64_t minRepresentable = std::numeric_limits::min(); int64_t maxRepresentable = std::numeric_limits::max(); diff --git a/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp b/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp index a9a65ac271b3..69b3f6d67416 100644 --- a/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp +++ b/mlir/lib/Dialect/Tosa/IR/TosaCanonicalizations.cpp @@ -287,10 +287,12 @@ struct ClampIsNoOp : public OpRewritePattern { if (isa(inputElementType)) { // Unlike integer types, floating point types can represent infinity. - auto minClamp = op.getMinFp(); - auto maxClamp = op.getMaxFp(); - bool isMin = minClamp.isInfinity() && minClamp.isNegative(); - bool isMax = maxClamp.isInfinity() && !maxClamp.isNegative(); + auto minClamp = + llvm::cast(op.getMinValAttr()).getValue(); + auto maxClamp = + llvm::cast(op.getMaxValAttr()).getValue(); + bool isMin = minClamp.isNegInfinity(); + bool isMax = maxClamp.isInfinity(); if (isMin && isMax) { rewriter.replaceOp(op, input); @@ -300,8 +302,10 @@ struct ClampIsNoOp : public OpRewritePattern { } if (inputElementType.isUnsignedInteger()) { - int64_t minClamp = op.getMinInt(); - int64_t maxClamp = op.getMaxInt(); + int64_t minClamp = + llvm::cast(op.getMinValAttr()).getUInt(); + int64_t maxClamp = + llvm::cast(op.getMaxValAttr()).getUInt(); int64_t intMin = APInt::getMinValue(inputElementType.getIntOrFloatBitWidth()) @@ -318,8 +322,10 @@ struct ClampIsNoOp : public OpRewritePattern { } if (llvm::isa(inputElementType)) { - int64_t minClamp = op.getMinInt(); - int64_t maxClamp = op.getMaxInt(); + int64_t minClamp = + llvm::cast(op.getMinValAttr()).getInt(); + int64_t maxClamp = + llvm::cast(op.getMaxValAttr()).getInt(); int64_t intMin = APInt::getSignedMinValue(inputElementType.getIntOrFloatBitWidth()) @@ -374,9 +380,10 @@ struct ClampClampOptimization : public OpRewritePattern { LogicalResult matchAndRewrite(tosa::ClampOp op, PatternRewriter &rewriter) const override { + Value input = op.getInput(); + // Check the input to the CLAMP op is itself a CLAMP. - auto clampOp = - dyn_cast_if_present(op.getInput().getDefiningOp()); + auto clampOp = dyn_cast_if_present(input.getDefiningOp()); if (!clampOp) return failure(); @@ -386,34 +393,86 @@ struct ClampClampOptimization : public OpRewritePattern { if (opNanMode == "IGNORE" && clampNanMode == "PROPAGATE") return failure(); - // Check we have intersecting ranges. - const auto opMinInt = op.getMinInt(); - const auto opMaxInt = op.getMaxInt(); - const auto clampOpMinInt = clampOp.getMinInt(); - const auto clampOpMaxInt = clampOp.getMaxInt(); - ClampRange opRangeIntRange(opMinInt, opMaxInt); - ClampRange clampRangeIntRange(clampOpMinInt, clampOpMaxInt); - if (!opRangeIntRange.intersects(clampRangeIntRange)) - return failure(); + auto maxValAttr = op.getMaxValAttr(); + auto minValAttr = op.getMinValAttr(); + auto clampOpMaxValAttr = clampOp.getMaxValAttr(); + auto clampOpMinValAttr = clampOp.getMinValAttr(); - const auto opMinFloat = op.getMinFp(); - const auto opMaxFloat = op.getMaxFp(); - const auto clampOpMinFloat = clampOp.getMinFp(); - const auto clampOpMaxFloat = clampOp.getMaxFp(); - ClampRange opRangeFloatRange(opMinFloat, opMaxFloat); - ClampRange clampRangeFloatRange(clampOpMinFloat, clampOpMaxFloat); - if (!opRangeFloatRange.intersects(clampRangeFloatRange)) - return failure(); + auto inputEType = llvm::cast(input.getType()).getElementType(); + if (auto quantType = + llvm::dyn_cast(inputEType)) { + inputEType = quantType.getStorageType(); + } + + Attribute newMinValAttr, newMaxValAttr; + if (mlir::isa(inputEType)) { + auto floatMaxValAttr = cast(maxValAttr); + auto floatMinValAttr = cast(minValAttr); + auto clampOpFloatMaxValAttr = cast(clampOpMaxValAttr); + auto clampOpFloatMinValAttr = cast(clampOpMinValAttr); + + // Check we have intersecting ranges. + const auto opMinFloat = floatMinValAttr.getValue(); + const auto opMaxFloat = floatMaxValAttr.getValue(); + const auto clampOpMinFloat = clampOpFloatMinValAttr.getValue(); + const auto clampOpMaxFloat = clampOpFloatMaxValAttr.getValue(); + ClampRange opRangeFloatRange(opMinFloat, opMaxFloat); + ClampRange clampRangeFloatRange(clampOpMinFloat, + clampOpMaxFloat); + if (!opRangeFloatRange.intersects(clampRangeFloatRange)) + return failure(); + + // Run the transformation. + auto newMinVal = std::max(opMinFloat, clampOpMinFloat); + auto newMaxVal = std::min(opMaxFloat, clampOpMaxFloat); + newMinValAttr = rewriter.getFloatAttr(inputEType, newMinVal); + newMaxValAttr = rewriter.getFloatAttr(inputEType, newMaxVal); + } else { + assert(mlir::isa(inputEType)); + auto intMaxValAttr = cast(maxValAttr); + auto intMinValAttr = cast(minValAttr); + auto clampOpIntMaxValAttr = cast(clampOpMaxValAttr); + auto clampOpIntMinValAttr = cast(clampOpMinValAttr); + + if (inputEType.isUnsignedInteger()) { + // Check we have intersecting ranges. + const auto opMinInt = intMinValAttr.getUInt(); + const auto opMaxInt = intMaxValAttr.getUInt(); + const auto clampOpMinInt = clampOpIntMinValAttr.getUInt(); + const auto clampOpMaxInt = clampOpIntMaxValAttr.getUInt(); + ClampRange opRangeIntRange(opMinInt, opMaxInt); + ClampRange clampRangeIntRange(clampOpMinInt, + clampOpMaxInt); + if (!opRangeIntRange.intersects(clampRangeIntRange)) + return failure(); + + // Run the transformation. + auto newMinVal = std::max(opMinInt, clampOpMinInt); + auto newMaxVal = std::min(opMaxInt, clampOpMaxInt); + newMinValAttr = rewriter.getIntegerAttr(inputEType, newMinVal); + newMaxValAttr = rewriter.getIntegerAttr(inputEType, newMaxVal); + } else { + // Check we have intersecting ranges. + const auto opMinInt = intMinValAttr.getInt(); + const auto opMaxInt = intMaxValAttr.getInt(); + const auto clampOpMinInt = clampOpIntMinValAttr.getInt(); + const auto clampOpMaxInt = clampOpIntMaxValAttr.getInt(); + ClampRange opRangeIntRange(opMinInt, opMaxInt); + ClampRange clampRangeIntRange(clampOpMinInt, + clampOpMaxInt); + if (!opRangeIntRange.intersects(clampRangeIntRange)) + return failure(); + + // Run the transformation. + auto newMinVal = std::max(opMinInt, clampOpMinInt); + auto newMaxVal = std::min(opMaxInt, clampOpMaxInt); + newMinValAttr = rewriter.getIntegerAttr(inputEType, newMinVal); + newMaxValAttr = rewriter.getIntegerAttr(inputEType, newMaxVal); + } + } - // Run the transformation. - const auto minFp = std::max(opMinFloat, clampOpMinFloat).convertToFloat(); - const auto maxFp = std::min(opMaxFloat, clampOpMaxFloat).convertToFloat(); - const auto minInt = std::max(opMinInt, clampOpMinInt); - const auto maxInt = std::min(opMaxInt, clampOpMaxInt); rewriter.replaceOpWithNewOp( - op, op.getType(), clampOp.getInput(), - rewriter.getI64IntegerAttr(minInt), rewriter.getI64IntegerAttr(maxInt), - rewriter.getF32FloatAttr(minFp), rewriter.getF32FloatAttr(maxFp), + op, op.getType(), clampOp.getInput(), newMinValAttr, newMaxValAttr, rewriter.getStringAttr((opNanMode != clampNanMode) ? "IGNORE" : opNanMode)); return success(); diff --git a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp index af4a5dc96265..cff24d825d3f 100644 --- a/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp +++ b/mlir/lib/Dialect/Tosa/IR/TosaOps.cpp @@ -476,26 +476,40 @@ LogicalResult tosa::ClampOp::verify() { llvm::dyn_cast(inputETy)) { inputETy = quantType.getStorageType(); } - mlir::Type maxFpType = getMaxFpAttr().getType(); - mlir::Type minFpType = getMinFpAttr().getType(); mlir::Type outputETy = llvm::cast(getOutput().getType()).getElementType(); if (auto quantType = llvm::dyn_cast(outputETy)) { outputETy = quantType.getStorageType(); } - unsigned dataTypeBitWidth = inputETy.getIntOrFloatBitWidth(); - if (inputETy != outputETy) return emitOpError("input/output element types are incompatible."); - // If input datatype is float, check that the two min/max_fp attributes - // share the same type and that their type is either the same of the input's - // datatype, or a float type whose bitwidth > input datatype bitwidth. - if (!inputETy.isInteger(dataTypeBitWidth)) { - if (((maxFpType != minFpType) || - (maxFpType != inputETy && maxFpType.getIntOrFloatBitWidth() <= - inputETy.getIntOrFloatBitWidth()))) + auto maxValAttr = getMaxValAttr(); + auto minValAttr = getMinValAttr(); + + unsigned dataTypeBitWidth = inputETy.getIntOrFloatBitWidth(); + + if (inputETy.isInteger(dataTypeBitWidth)) { + // if input datatype is integer, check that the min_val/max_val attributes + // are integer attributes, and that their type is the same as the input's + // datatype + auto intMaxValAttr = mlir::dyn_cast(maxValAttr); + auto intMinValAttr = mlir::dyn_cast(minValAttr); + if (!intMaxValAttr || !intMinValAttr || + (intMaxValAttr.getType() != intMinValAttr.getType()) || + (intMaxValAttr.getType() != inputETy)) + return emitOpError("min/max attributes types are incompatible with " + "input/output element types."); + } else { + // otherwise, input datatype is float, check that the min_val/max_val + // attributes share the same type and that their type is the same as the + // input's datatype + auto floatMaxValAttr = mlir::dyn_cast(maxValAttr); + auto floatMinValAttr = mlir::dyn_cast(minValAttr); + if (!floatMaxValAttr || !floatMinValAttr || + (floatMaxValAttr.getType() != floatMinValAttr.getType()) || + (floatMaxValAttr.getType() != inputETy)) return emitOpError("min/max attributes types are incompatible with " "input/output element types."); } diff --git a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg.mlir b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg.mlir index d8ba28a3ce88..56521fb67ef0 100644 --- a/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg.mlir +++ b/mlir/test/Conversion/TosaToLinalg/tosa-to-linalg.mlir @@ -529,7 +529,7 @@ func.func @test_simple_f32(%arg0: tensor<1xf32>) -> () { // CHECK: linalg.generic // CHECK: arith.minimumf // CHECK: arith.maximumf - %18 = tosa.clamp %0 {min_int = 1 : i64, max_int = 5 : i64, min_fp = 1.0 : f32, max_fp = 5.0 : f32} : (tensor<1xf32>) -> tensor<1xf32> + %18 = tosa.clamp %0 {min_val = 1.0 : f32, max_val = 5.0 : f32} : (tensor<1xf32>) -> tensor<1xf32> // CHECK: linalg.generic // CHECK: arith.negf @@ -729,35 +729,14 @@ func.func @test_simple_i32(%arg0: tensor<1xi32>, %unsigned: tensor<1xui32>, %uns // CHECK: linalg.generic // CHECK-DAG: arith.maxsi // CHECK-DAG: arith.minsi - %19 = tosa.clamp %0 {min_int = 1 : i64, max_int = 5 : i64, min_fp = 1.0 : f32, max_fp = 5.0 : f32} : (tensor<1xi32>) -> tensor<1xi32> + %19 = tosa.clamp %0 {min_val = 1 : i32, max_val = 5 : i32} : (tensor<1xi32>) -> tensor<1xi32> // CHECK: linalg.generic // CHECK-DAG: %[[LB:.*]] = arith.constant 4 : i32 // CHECK-DAG: %[[UB:.*]] = arith.constant 32 : i32 // CHECK-DAG: arith.maxui %[[LB]], // CHECK-DAG: arith.minui %[[UB]], - %u0 = tosa.clamp %unsigned {min_int = 4 : i64, max_int = 32 : i64, min_fp = 1.0 : f32, max_fp = 5.0 : f32} : (tensor<1xui32>) -> tensor<1xui32> - - // CHECK: linalg.generic - // CHECK-DAG: %[[LB:.*]] = arith.constant -1 : i32 - // CHECK-DAG: %[[UB:.*]] = arith.constant -1 : i32 - // CHECK-DAG: arith.maxui %[[LB]], - // CHECK-DAG: arith.minui %[[UB]], - %u1 = tosa.clamp %unsigned {min_int = 9223372036854775807 : i64, max_int = 9223372036854775807 : i64, min_fp = 1.0 : f32, max_fp = 5.0 : f32} : (tensor<1xui32>) -> tensor<1xui32> - - // CHECK: linalg.generic - // CHECK-DAG: %[[LB:.*]] = arith.constant 0 : i32 - // CHECK-DAG: %[[UB:.*]] = arith.constant 0 : i32 - // CHECK-DAG: arith.maxui %[[LB]], - // CHECK-DAG: arith.minui %[[UB]], - %u2 = tosa.clamp %unsigned {min_int = -3 : i64, max_int = -2 : i64, min_fp = 1.0 : f32, max_fp = 5.0 : f32} : (tensor<1xui32>) -> tensor<1xui32> - - // CHECK: linalg.generic - // CHECK-DAG: %[[LB:.*]] = arith.constant 0 : i64 - // CHECK-DAG: %[[UB:.*]] = arith.constant 9223372036854775807 : i64 - // CHECK-DAG: arith.maxui %[[LB]], - // CHECK-DAG: arith.minui %[[UB]], - %u3 = tosa.clamp %unsigned64 {min_int = -3 : i64, max_int = 9223372036854775807 : i64, min_fp = 1.0 : f32, max_fp = 5.0 : f32} : (tensor<1xui64>) -> tensor<1xui64> + %u0 = tosa.clamp %unsigned {min_val = 4 : ui32, max_val = 32 : ui32} : (tensor<1xui32>) -> tensor<1xui32> // CHECK: linalg.generic // CHECK: arith.trunci @@ -807,15 +786,7 @@ func.func @test_i8(%arg0: tensor<1xi8>) -> () { // CHECK-DAG: %[[C126:.+]] = arith.constant 126 // CHECK-DAG: %[[LOWER:.+]] = arith.maxsi %[[C127]], %[[ARG1]] // CHECK-DAG: %[[CLAMPED:.+]] = arith.minsi %[[C126]], %[[LOWER]] - %0 = tosa.clamp %arg0 {min_int = -127 : i64, max_int = 126 : i64, min_fp = 0.0 : f32, max_fp = 0.0 : f32} : (tensor<1xi8>) -> tensor<1xi8> - - // CHECK: linalg.generic - // CHECK: ^bb0(%[[ARG1:.+]]: i8, - // CHECK-DAG: %[[C128:.+]] = arith.constant -128 - // CHECK-DAG: %[[C127:.+]] = arith.constant 127 - // CHECK-DAG: %[[LOWER:.+]] = arith.maxsi %[[C128]], %[[ARG1]] - // CHECK-DAG: %[[CLAMPED:.+]] = arith.minsi %[[C127]], %[[LOWER]] - %1 = tosa.clamp %arg0 {min_int = -130 : i64, max_int = 130 : i64, min_fp = 0.0 : f32, max_fp = 0.0 : f32} : (tensor<1xi8>) -> tensor<1xi8> + %0 = tosa.clamp %arg0 {min_val = -127 : i8, max_val = 126 : i8} : (tensor<1xi8>) -> tensor<1xi8> return } @@ -830,7 +801,7 @@ func.func @test_i64(%arg0: tensor<1xi64>) -> () { // CHECK-DAG: %[[C126:.+]] = arith.constant 9223372036854775807 // CHECK-DAG: %[[LOWER:.+]] = arith.maxsi %[[C127]], %[[ARG1]] // CHECK-DAG: %[[CLAMPED:.+]] = arith.minsi %[[C126]], %[[LOWER]] - %0 = tosa.clamp %arg0 {min_int = -9223372036854775808 : i64, max_int = 9223372036854775807 : i64, min_fp = 0.0 : f32, max_fp = 0.0 : f32} : (tensor<1xi64>) -> tensor<1xi64> + %0 = tosa.clamp %arg0 {min_val = -9223372036854775808 : i64, max_val = 9223372036854775807 : i64} : (tensor<1xi64>) -> tensor<1xi64> return } @@ -845,7 +816,7 @@ func.func @test_clamp_f16(%arg0: tensor<1xf16>) -> () { // CHECK-DAG: %[[C6:.+]] = arith.constant 6.0 // CHECK-DAG: %[[MIN:.+]] = arith.minimumf %[[ARG1]], %[[C6]] // CHECK-DAG: %[[MAX:.+]] = arith.maximumf %[[MIN]], %[[C0]] - %0 = tosa.clamp %arg0 {min_int = 0 : i64, max_int = 0 : i64, min_fp = 0.0 : f32, max_fp = 6.0 : f32} : (tensor<1xf16>) -> tensor<1xf16> + %0 = tosa.clamp %arg0 {min_val = 0.0 : f16, max_val = 6.0 : f16} : (tensor<1xf16>) -> tensor<1xf16> return } diff --git a/mlir/test/Dialect/Tosa/canonicalize.mlir b/mlir/test/Dialect/Tosa/canonicalize.mlir index 582fd77cd7bc..58a70fb03a09 100644 --- a/mlir/test/Dialect/Tosa/canonicalize.mlir +++ b/mlir/test/Dialect/Tosa/canonicalize.mlir @@ -52,25 +52,16 @@ func.func @cast_nofold(%arg0: tensor) -> tensor { // CHECK-LABEL: @clamp_i32_not_noop func.func @clamp_i32_not_noop(%arg0: tensor<4xi32>) -> tensor<4xi32> { // CHECK: tosa.clamp - %0 = tosa.clamp %arg0 {min_int = 1 : i64, max_int = 4 : i64, min_fp = 1.0 : f32, max_fp = 4.0 : f32} : (tensor<4xi32>) -> tensor<4xi32> + %0 = tosa.clamp %arg0 {min_val = 1 : i32, max_val = 4 : i32} : (tensor<4xi32>) -> tensor<4xi32> return %0 : tensor<4xi32> } // ----- -// CHECK-LABEL: @clamp_f16_not_noop -func.func @clamp_f16_not_noop(%arg0: tensor<4xf16>) -> tensor<4xf16> { - // CHECK: tosa.clamp - %0 = tosa.clamp %arg0 {min_int = -128 : i64, max_int = 127 : i64, min_fp = -3.40282347E+38 : f32, max_fp = 3.40282347E+38 : f32} : (tensor<4xf16>) -> tensor<4xf16> - return %0 : tensor<4xf16> -} - -// ----- - // CHECK-LABEL: @clamp_f32_not_noop func.func @clamp_f32_not_noop(%arg0: tensor<4xf32>) -> tensor<4xf32> { // CHECK: tosa.clamp - %0 = tosa.clamp %arg0 {min_int = -128 : i64, max_int = 127 : i64, min_fp = -3.40282347E+38 : f32, max_fp = 3.40282347E+38 : f32} : (tensor<4xf32>) -> tensor<4xf32> + %0 = tosa.clamp %arg0 {min_val = -3.40282347E+38 : f32, max_val = 3.40282347E+38 : f32} : (tensor<4xf32>) -> tensor<4xf32> return %0 : tensor<4xf32> } @@ -80,8 +71,8 @@ func.func @clamp_f32_not_noop(%arg0: tensor<4xf32>) -> tensor<4xf32> { func.func @clamp_f16_is_noop(%arg0: tensor<4xf16>) -> tensor<4xf16> { // CHECK: return %arg0 // CHECK-NOT: "tosa.clamp" - // 0xFF800000 and 0x7F800000 are respectively negative and positive F32 infinity. - %0 = tosa.clamp %arg0 {min_int = -128 : i64, max_int = 127 : i64, min_fp = 0xFF800000 : f32, max_fp = 0x7F800000 : f32} : (tensor<4xf16>) -> tensor<4xf16> + // 0x7C00 and 0xFC00 are respectively positive and negative F32 infinity. + %0 = tosa.clamp %arg0 {max_val = 0x7C00 : f16, min_val = 0xFC00 : f16} : (tensor<4xf16>) -> tensor<4xf16> return %0 : tensor<4xf16> } @@ -92,7 +83,7 @@ func.func @clamp_f32_is_noop(%arg0: tensor<4xf32>) -> tensor<4xf32> { // CHECK: return %arg0 // CHECK-NOT: "tosa.clamp" // 0xFF800000 and 0x7F800000 are respectively negative and positive F32 infinity. - %0 = tosa.clamp %arg0 {min_int = -128 : i64, max_int = 127 : i64, min_fp = 0xFF800000 : f32, max_fp = 0x7F800000 : f32} : (tensor<4xf32>) -> tensor<4xf32> + %0 = tosa.clamp %arg0 {min_val = 0xFF800000 : f32, max_val = 0x7F800000 : f32} : (tensor<4xf32>) -> tensor<4xf32> return %0 : tensor<4xf32> } @@ -102,7 +93,7 @@ func.func @clamp_f32_is_noop(%arg0: tensor<4xf32>) -> tensor<4xf32> { func.func @clamp_int8_is_noop(%arg0: tensor<4xi8>) -> tensor<4xi8> { // CHECK: return %arg0 // CHECK-NOT: tosa.clamp - %0 = tosa.clamp %arg0 {min_int = -128 : i64, max_int = 127 : i64, min_fp = -3.40282347E+38 : f32, max_fp = 3.40282347E+38 : f32} : (tensor<4xi8>) -> tensor<4xi8> + %0 = tosa.clamp %arg0 {min_val = -128 : i8, max_val = 127 : i8} : (tensor<4xi8>) -> tensor<4xi8> return %0 : tensor<4xi8> } @@ -112,7 +103,7 @@ func.func @clamp_int8_is_noop(%arg0: tensor<4xi8>) -> tensor<4xi8> { func.func @clamp_int16_is_noop(%arg0: tensor<4xi16>) -> tensor<4xi16> { // CHECK: return %arg0 // CHECK-NOT: tosa.clamp - %0 = tosa.clamp %arg0 {min_int = -32768 : i64, max_int = 32767 : i64, min_fp = -3.40282347E+38 : f32, max_fp = 3.40282347E+38 : f32} : (tensor<4xi16>) -> tensor<4xi16> + %0 = tosa.clamp %arg0 {min_val = -32768 : i16, max_val = 32767 : i16} : (tensor<4xi16>) -> tensor<4xi16> return %0 : tensor<4xi16> } @@ -122,7 +113,7 @@ func.func @clamp_int16_is_noop(%arg0: tensor<4xi16>) -> tensor<4xi16> { func.func @clamp_uint8_is_noop(%arg0: tensor<4xui8>) -> tensor<4xui8> { // CHECK: return %arg0 // CHECK-NOT: tosa.clamp - %0 = tosa.clamp %arg0 {min_int = 0 : i64, max_int = 255 : i64, min_fp = -3.40282347E+38 : f32, max_fp = 3.40282347E+38 : f32} : (tensor<4xui8>) -> tensor<4xui8> + %0 = tosa.clamp %arg0 {min_val = 0 : ui8, max_val = 255 : ui8} : (tensor<4xui8>) -> tensor<4xui8> return %0 : tensor<4xui8> } @@ -130,9 +121,9 @@ func.func @clamp_uint8_is_noop(%arg0: tensor<4xui8>) -> tensor<4xui8> { // CHECK-LABEL: @clamp_twice_is_single_clamp func.func @clamp_twice_is_single_clamp(%arg0: tensor<4xi8>) -> tensor<4xi8> { - // CHECK: tosa.clamp %arg0 {max_fp = 3.000000e+00 : f32, max_int = 2 : i64, min_fp = -3.000000e+00 : f32, min_int = -2 : i64} - %0 = tosa.clamp %arg0 {max_fp = 3.0 : f32, max_int = 4 : i64, min_fp = -5.0 : f32, min_int = -2 : i64} : (tensor<4xi8>) -> tensor<4xi8> - %1 = tosa.clamp %0 {max_fp = 5.0 : f32, max_int = 2 : i64, min_fp = -3.0 : f32, min_int = -4 : i64} : (tensor<4xi8>) -> tensor<4xi8> + // CHECK: tosa.clamp %arg0 {max_val = 2 : i8, min_val = -2 : i8} + %0 = tosa.clamp %arg0 {max_val = 4 : i8, min_val = -2 : i8} : (tensor<4xi8>) -> tensor<4xi8> + %1 = tosa.clamp %0 {max_val = 2 : i8, min_val = -4 : i8} : (tensor<4xi8>) -> tensor<4xi8> return %1 : tensor<4xi8> } @@ -140,10 +131,10 @@ func.func @clamp_twice_is_single_clamp(%arg0: tensor<4xi8>) -> tensor<4xi8> { // CHECK: @disjoint_clamp_twice_is_not_single_clamp(%[[INPUT:.*]]: tensor<4xi8>) func.func @disjoint_clamp_twice_is_not_single_clamp(%arg0: tensor<4xi8>) -> tensor<4xi8> { - // CHECK: %[[CLAMP_1:.*]] = tosa.clamp %[[INPUT]] {max_fp = -5.000000e+00 : f32, max_int = -5 : i64, min_fp = -1.000000e+00 : f32, min_int = -10 : i64} : (tensor<4xi8>) -> tensor<4xi8> - // CHECK-NEXT: tosa.clamp %[[CLAMP_1]] {max_fp = 5.000000e+00 : f32, max_int = 5 : i64, min_fp = 1.000000e+00 : f32, min_int = 1 : i64} : (tensor<4xi8>) -> tensor<4xi8> - %0 = tosa.clamp %arg0 {max_fp = -5.0 : f32, max_int = -5 : i64, min_fp = -1.0 : f32, min_int = -10 : i64} : (tensor<4xi8>) -> tensor<4xi8> - %1 = tosa.clamp %0 {max_fp = 5.0 : f32, max_int = 5 : i64, min_fp = 1.0 : f32, min_int = 1 : i64} : (tensor<4xi8>) -> tensor<4xi8> + // CHECK: %[[CLAMP_1:.*]] = tosa.clamp %[[INPUT]] {max_val = -5 : i8, min_val = -10 : i8} : (tensor<4xi8>) -> tensor<4xi8> + // CHECK-NEXT: tosa.clamp %[[CLAMP_1]] {max_val = 5 : i8, min_val = 1 : i8} : (tensor<4xi8>) -> tensor<4xi8> + %0 = tosa.clamp %arg0 {max_val = -5 : i8, min_val = -10 : i8} : (tensor<4xi8>) -> tensor<4xi8> + %1 = tosa.clamp %0 {max_val = 5 : i8, min_val = 1 : i8} : (tensor<4xi8>) -> tensor<4xi8> return %1 : tensor<4xi8> } @@ -151,9 +142,9 @@ func.func @disjoint_clamp_twice_is_not_single_clamp(%arg0: tensor<4xi8>) -> tens // CHECK-LABEL: @clamp_twice_with_nan_propagate_is_single_clamp func.func @clamp_twice_with_nan_propagate_is_single_clamp(%arg0: tensor<4xi8>) -> tensor<4xi8> { - // CHECK: tosa.clamp %arg0 {max_fp = 3.000000e+00 : f32, max_int = 2 : i64, min_fp = -3.000000e+00 : f32, min_int = -2 : i64} - %0 = tosa.clamp %arg0 {max_fp = 3.0 : f32, max_int = 4 : i64, min_fp = -5.0 : f32, min_int = -2 : i64, nan_mode = "PROPAGATE"} : (tensor<4xi8>) -> tensor<4xi8> - %1 = tosa.clamp %0 {max_fp = 5.0 : f32, max_int = 2 : i64, min_fp = -3.0 : f32, min_int = -4 : i64, nan_mode = "PROPAGATE"} : (tensor<4xi8>) -> tensor<4xi8> + // CHECK: tosa.clamp %arg0 {max_val = 2 : i8, min_val = -2 : i8} + %0 = tosa.clamp %arg0 {max_val = 4 : i8, min_val = -2 : i8, nan_mode = "PROPAGATE"} : (tensor<4xi8>) -> tensor<4xi8> + %1 = tosa.clamp %0 {max_val = 2 : i8, min_val = -4 : i8, nan_mode = "PROPAGATE"} : (tensor<4xi8>) -> tensor<4xi8> return %1 : tensor<4xi8> } @@ -161,9 +152,9 @@ func.func @clamp_twice_with_nan_propagate_is_single_clamp(%arg0: tensor<4xi8>) - // CHECK-LABEL: @clamp_twice_with_nan_ignore_is_single_clamp func.func @clamp_twice_with_nan_ignore_is_single_clamp(%arg0: tensor<4xi8>) -> tensor<4xi8> { - // CHECK: tosa.clamp %arg0 {max_fp = 3.000000e+00 : f32, max_int = 2 : i64, min_fp = -3.000000e+00 : f32, min_int = -2 : i64, nan_mode = "IGNORE"} - %0 = tosa.clamp %arg0 {max_fp = 3.0 : f32, max_int = 4 : i64, min_fp = -5.0 : f32, min_int = -2 : i64, nan_mode = "IGNORE"} : (tensor<4xi8>) -> tensor<4xi8> - %1 = tosa.clamp %0 {max_fp = 5.0 : f32, max_int = 2 : i64, min_fp = -3.0 : f32, min_int = -4 : i64, nan_mode = "IGNORE"} : (tensor<4xi8>) -> tensor<4xi8> + // CHECK: tosa.clamp %arg0 {max_val = 2 : i8, min_val = -2 : i8, nan_mode = "IGNORE"} + %0 = tosa.clamp %arg0 {max_val = 4 : i8, min_val = -2 : i8, nan_mode = "IGNORE"} : (tensor<4xi8>) -> tensor<4xi8> + %1 = tosa.clamp %0 {max_val = 2 : i8, min_val = -4 : i8, nan_mode = "IGNORE"} : (tensor<4xi8>) -> tensor<4xi8> return %1 : tensor<4xi8> } @@ -171,9 +162,9 @@ func.func @clamp_twice_with_nan_ignore_is_single_clamp(%arg0: tensor<4xi8>) -> t // CHECK-LABEL: @clamp_twice_with_nan_ignore_propagate_is_single_clamp func.func @clamp_twice_with_nan_ignore_propagate_is_single_clamp(%arg0: tensor<4xi8>) -> tensor<4xi8> { - // CHECK: tosa.clamp %arg0 {max_fp = 3.000000e+00 : f32, max_int = 2 : i64, min_fp = -3.000000e+00 : f32, min_int = -2 : i64, nan_mode = "IGNORE"} - %0 = tosa.clamp %arg0 {max_fp = 3.0 : f32, max_int = 4 : i64, min_fp = -5.0 : f32, min_int = -2 : i64, nan_mode = "IGNORE"} : (tensor<4xi8>) -> tensor<4xi8> - %1 = tosa.clamp %0 {max_fp = 5.0 : f32, max_int = 2 : i64, min_fp = -3.0 : f32, min_int = -4 : i64, nan_mode = "PROPAGATE"} : (tensor<4xi8>) -> tensor<4xi8> + // CHECK: tosa.clamp %arg0 {max_val = 2 : i8, min_val = -2 : i8, nan_mode = "IGNORE"} + %0 = tosa.clamp %arg0 {max_val = 4 : i8, min_val = -2 : i8, nan_mode = "IGNORE"} : (tensor<4xi8>) -> tensor<4xi8> + %1 = tosa.clamp %0 {max_val = 2 : i8, min_val = -4 : i8, nan_mode = "PROPAGATE"} : (tensor<4xi8>) -> tensor<4xi8> return %1 : tensor<4xi8> } @@ -181,10 +172,10 @@ func.func @clamp_twice_with_nan_ignore_propagate_is_single_clamp(%arg0: tensor<4 // CHECK: @clamp_twice_with_nan_propagate_ignore_is_not_single_clamp(%[[INPUT:.*]]: tensor<4xi8>) func.func @clamp_twice_with_nan_propagate_ignore_is_not_single_clamp(%arg0: tensor<4xi8>) -> tensor<4xi8> { - // CHECK: %[[CLAMP_1:.*]] = tosa.clamp %[[INPUT]] {max_fp = 3.000000e+00 : f32, max_int = 4 : i64, min_fp = -5.000000e+00 : f32, min_int = -2 : i64} : (tensor<4xi8>) -> tensor<4xi8> - // CHECK-NEXT: tosa.clamp %[[CLAMP_1]] {max_fp = 5.000000e+00 : f32, max_int = 2 : i64, min_fp = -3.000000e+00 : f32, min_int = -4 : i64, nan_mode = "IGNORE"} : (tensor<4xi8>) -> tensor<4xi8> - %0 = tosa.clamp %arg0 {max_fp = 3.0 : f32, max_int = 4 : i64, min_fp = -5.0 : f32, min_int = -2 : i64, nan_mode = "PROPAGATE"} : (tensor<4xi8>) -> tensor<4xi8> - %1 = tosa.clamp %0 {max_fp = 5.0 : f32, max_int = 2 : i64, min_fp = -3.0 : f32, min_int = -4 : i64, nan_mode = "IGNORE"} : (tensor<4xi8>) -> tensor<4xi8> + // CHECK: %[[CLAMP_1:.*]] = tosa.clamp %[[INPUT]] {max_val = 4 : i8, min_val = -2 : i8} : (tensor<4xi8>) -> tensor<4xi8> + // CHECK-NEXT: tosa.clamp %[[CLAMP_1]] {max_val = 2 : i8, min_val = -4 : i8, nan_mode = "IGNORE"} : (tensor<4xi8>) -> tensor<4xi8> + %0 = tosa.clamp %arg0 {max_val = 4 : i8, min_val = -2 : i8, nan_mode = "PROPAGATE"} : (tensor<4xi8>) -> tensor<4xi8> + %1 = tosa.clamp %0 {max_val = 2 : i8, min_val = -4 : i8, nan_mode = "IGNORE"} : (tensor<4xi8>) -> tensor<4xi8> return %1 : tensor<4xi8> } diff --git a/mlir/test/Dialect/Tosa/invalid.mlir b/mlir/test/Dialect/Tosa/invalid.mlir index 20fc10d77d0e..e77078161d06 100644 --- a/mlir/test/Dialect/Tosa/invalid.mlir +++ b/mlir/test/Dialect/Tosa/invalid.mlir @@ -806,7 +806,7 @@ func.func @test_unsupported_int64_data_type(%arg0: tensor<1x13x13x5xf32>) -> ten // CHECK-LABEL: test_mismatch_in_out_data_type_clamp func.func @test_mismatch_in_out_data_type_clamp(%arg0: tensor<13x21x3xf32>) -> tensor<13x21x3xf16> { // expected-error@+1 {{'tosa.clamp' op requires the same element type for all operands and results}} - %0 = tosa.clamp %arg0 {min_fp = 0.0 : f32, max_fp = 1.0: f32, min_int = 0 : i64, max_int = 1 : i64} : (tensor<13x21x3xf32>) -> tensor<13x21x3xf16> + %0 = tosa.clamp %arg0 {min_val = 0.0 : f32, max_val = 1.0: f32} : (tensor<13x21x3xf32>) -> tensor<13x21x3xf16> return %0 : tensor<13x21x3xf16> } @@ -815,7 +815,7 @@ func.func @test_mismatch_in_out_data_type_clamp(%arg0: tensor<13x21x3xf32>) -> t // CHECK-LABEL: test_mismatch_in_out_shape_clamp func.func @test_mismatch_in_out_shape_clamp(%arg0: tensor<13x21x3xf32>) -> tensor<13x21x1xf32> { // expected-error@+1 {{'tosa.clamp' op requires the same shape for all operands and results}} - %0 = tosa.clamp %arg0 {min_fp = 0.0 : f32, max_fp = 1.0: f32, min_int = 0 : i64, max_int = 1 : i64} : (tensor<13x21x3xf32>) -> tensor<13x21x1xf32> + %0 = tosa.clamp %arg0 {min_val = 0.0 : f32, max_val = 1.0: f32} : (tensor<13x21x3xf32>) -> tensor<13x21x1xf32> return %0 : tensor<13x21x1xf32> } diff --git a/mlir/test/Dialect/Tosa/ops.mlir b/mlir/test/Dialect/Tosa/ops.mlir index d7e4f682c28b..0d3dfead4a7a 100644 --- a/mlir/test/Dialect/Tosa/ops.mlir +++ b/mlir/test/Dialect/Tosa/ops.mlir @@ -193,42 +193,42 @@ func.func @test_transpose_conv2d_with_local_bound(%arg0: tensor<1x32x32x8xf32>, // ----- // CHECK-LABEL: clamp func.func @test_clamp(%arg0: tensor<13x21x3xf32>) -> tensor<13x21x3xf32> { - %0 = tosa.clamp %arg0 {min_fp = 0.0 : f32, max_fp = 1.0: f32, min_int = 0 : i64, max_int = 1 : i64} : (tensor<13x21x3xf32>) -> tensor<13x21x3xf32> + %0 = tosa.clamp %arg0 {min_val = 0.0 : f32, max_val = 1.0: f32} : (tensor<13x21x3xf32>) -> tensor<13x21x3xf32> return %0 : tensor<13x21x3xf32> } // ----- // CHECK-LABEL: clamp_propagate func.func @test_clamp_propagate(%arg0: tensor<13x21x3xf32>) -> tensor<13x21x3xf32> { - %0 = tosa.clamp %arg0 {min_fp = 0.0 : f32, max_fp = 1.0: f32, min_int = 0 : i64, max_int = 1 : i64, nan_mode = "PROPAGATE"} : (tensor<13x21x3xf32>) -> tensor<13x21x3xf32> + %0 = tosa.clamp %arg0 {min_val = 0.0 : f32, max_val = 1.0: f32, nan_mode = "PROPAGATE"} : (tensor<13x21x3xf32>) -> tensor<13x21x3xf32> return %0 : tensor<13x21x3xf32> } // ----- // CHECK-LABEL: clamp_ignore func.func @test_clamp_ignore(%arg0: tensor<13x21x3xf32>) -> tensor<13x21x3xf32> { - %0 = tosa.clamp %arg0 {min_fp = 0.0 : f32, max_fp = 1.0: f32, min_int = 0 : i64, max_int = 1 : i64, nan_mode = "IGNORE"} : (tensor<13x21x3xf32>) -> tensor<13x21x3xf32> + %0 = tosa.clamp %arg0 {min_val = 0.0 : f32, max_val = 1.0: f32, nan_mode = "IGNORE"} : (tensor<13x21x3xf32>) -> tensor<13x21x3xf32> return %0 : tensor<13x21x3xf32> } // ----- // CHECK-LABEL: clamp_f16 func.func @test_clamp_f16(%arg0: tensor<13x21x3xf16>) -> tensor<13x21x3xf16> { - %0 = tosa.clamp %arg0 {min_fp = 0.0 : f16, max_fp = 1.0: f16, min_int = 0 : i64, max_int = 1 : i64} : (tensor<13x21x3xf16>) -> tensor<13x21x3xf16> + %0 = tosa.clamp %arg0 {min_val = 0.0 : f16, max_val = 1.0: f16} : (tensor<13x21x3xf16>) -> tensor<13x21x3xf16> return %0 : tensor<13x21x3xf16> } // ----- // CHECK-LABEL: clamp_bf16 func.func @test_clamp_bf16(%arg0: tensor<13x21x3xbf16>) -> tensor<13x21x3xbf16> { - %0 = tosa.clamp %arg0 {min_fp = 0.0 : bf16, max_fp = 1.0: bf16, min_int = 0 : i64, max_int = 1 : i64} : (tensor<13x21x3xbf16>) -> tensor<13x21x3xbf16> + %0 = tosa.clamp %arg0 {min_val = 0.0 : bf16, max_val = 1.0: bf16} : (tensor<13x21x3xbf16>) -> tensor<13x21x3xbf16> return %0 : tensor<13x21x3xbf16> } // ----- // CHECK-LABEL: clamp_quantized func.func @test_clamp_quantized(%arg0: tensor<13x21x3x!quant.uniform>) -> tensor<13x21x3x!quant.uniform> { - %0 = tosa.clamp %arg0 {min_fp = 0.0 : f32, max_fp = 1.0: f32, min_int = 0 : i64, max_int = 1 : i64} : (tensor<13x21x3x!quant.uniform>) -> tensor<13x21x3x!quant.uniform> + %0 = tosa.clamp %arg0 {min_val = 0 : i8, max_val = 1 : i8} : (tensor<13x21x3x!quant.uniform>) -> tensor<13x21x3x!quant.uniform> return %0 : tensor<13x21x3x!quant.uniform> } diff --git a/mlir/test/Dialect/Tosa/tosa-infer-shapes.mlir b/mlir/test/Dialect/Tosa/tosa-infer-shapes.mlir index bdd403567a4e..a0a7e5dec6ed 100644 --- a/mlir/test/Dialect/Tosa/tosa-infer-shapes.mlir +++ b/mlir/test/Dialect/Tosa/tosa-infer-shapes.mlir @@ -34,7 +34,7 @@ func.func @test_unary_f32(%arg0 : tensor<4xf32>) -> () { %1 = tosa.ceil %arg0 : (tensor<4xf32>) -> tensor<*xf32> // CHECK: tosa.clamp %arg0 {{.+}} : (tensor<4xf32>) -> tensor<4xf32> - %2 = tosa.clamp %arg0 { max_int = 10 : i64, min_int = 0 : i64, min_fp = 0.0 : f32, max_fp = 10.0 : f32 } : (tensor<4xf32>) -> tensor<*xf32> + %2 = tosa.clamp %arg0 { min_val = 0.0 : f32, max_val = 10.0 : f32 } : (tensor<4xf32>) -> tensor<*xf32> // CHECK: tosa.exp %arg0 : (tensor<4xf32>) -> tensor<4xf32> %3 = tosa.exp %arg0 : (tensor<4xf32>) -> tensor<*xf32> @@ -82,7 +82,7 @@ func.func @test_unary_i32(%arg0 : tensor<4xi32>) -> () { %1 = tosa.bitwise_not %arg0 : (tensor<4xi32>) -> tensor<*xi32> // CHECK: tosa.clamp %arg0 {{.+}} : (tensor<4xi32>) -> tensor<4xi32> - %2 = tosa.clamp %arg0 { max_int = 10 : i64, min_int = 0 : i64, min_fp = 0.0 : f32, max_fp = 10.0 : f32 } : (tensor<4xi32>) -> tensor<*xi32> + %2 = tosa.clamp %arg0 { max_val = 10 : i32, min_val = 0 : i32} : (tensor<4xi32>) -> tensor<*xi32> // CHECK: tosa.clz %arg0 : (tensor<4xi32>) -> tensor<4xi32> %3 = tosa.clz %arg0 : (tensor<4xi32>) -> tensor<*xi32> diff --git a/mlir/test/Dialect/Tosa/tosa-reduce-transposes.mlir b/mlir/test/Dialect/Tosa/tosa-reduce-transposes.mlir index 947335e45a9d..e70f3644da64 100644 --- a/mlir/test/Dialect/Tosa/tosa-reduce-transposes.mlir +++ b/mlir/test/Dialect/Tosa/tosa-reduce-transposes.mlir @@ -22,7 +22,7 @@ func.func @test_transpose_tracks_to_nullifying_single_step(%arg0: tensor<1x2x3x4 func.func @test_transpose_tracks_to_nullifying_multi_unary_step(%arg0: tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32> { %perms0 = "tosa.const"() {value = dense<[0, 2, 3, 1]> : tensor<4xi32>} : () -> tensor<4xi32> %0 = tosa.transpose %arg0, %perms0 : (tensor<1x2x3x4xi32>, tensor<4xi32>) -> tensor<1x3x4x2xi32> - %clamp = tosa.clamp %0 {max_fp = 1.0 : f32, min_fp = 0.0 : f32, max_int = 1 : i64, min_int = 0 : i64} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> + %clamp = tosa.clamp %0 {max_val = 1 : i32, min_val = 0 : i32} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> %abs = tosa.abs %clamp : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> %bitwise_not = tosa.bitwise_not %abs : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> %perms1 = "tosa.const"() {value = dense<[0, 3, 1, 2]> : tensor<4xi32>} : () -> tensor<4xi32> @@ -41,7 +41,7 @@ func.func @test_transpose_tracks_to_nullifying_diverging_binary(%arg0: tensor<1x %perms0 = "tosa.const"() {value = dense<[0, 2, 3, 1]> : tensor<4xi32>} : () -> tensor<4xi32> %transpose0 = tosa.transpose %arg0, %perms0 : (tensor<1x2x3x4xi32>, tensor<4xi32>) -> tensor<1x3x4x2xi32> %transpose1 = tosa.transpose %arg1, %perms0 : (tensor<1x2x3x4xi32>, tensor<4xi32>) -> tensor<1x3x4x2xi32> - %clamp = tosa.clamp %transpose0 {max_fp = 1.0 : f32, min_fp = 0.0 : f32, max_int = 1 : i64, min_int = 0 : i64} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> + %clamp = tosa.clamp %transpose0 {max_val = 1 : i32, min_val = 0 : i32} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> %abs = tosa.abs %transpose1 : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> %add = tosa.add %clamp, %abs : (tensor<1x3x4x2xi32>, tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> %perms1 = "tosa.const"() {value = dense<[0, 3, 1, 2]> : tensor<4xi32>} : () -> tensor<4xi32> @@ -61,7 +61,7 @@ func.func @test_transpose_tracks_to_nullifying_diverging_binary_with_broadcastin %perms0 = "tosa.const"() {value = dense<[0, 2, 3, 1]> : tensor<4xi32>} : () -> tensor<4xi32> %transpose0 = tosa.transpose %arg0, %perms0 : (tensor<1x2x3x4xi32>, tensor<4xi32>) -> tensor<1x3x4x2xi32> %transpose1 = tosa.transpose %arg1, %perms0 : (tensor<1x2x1x4xi32>, tensor<4xi32>) -> tensor<1x1x4x2xi32> - %clamp = tosa.clamp %transpose0 {max_fp = 1.0 : f32, min_fp = 0.0 : f32, max_int = 1 : i64, min_int = 0 : i64} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> + %clamp = tosa.clamp %transpose0 {max_val = 1 : i32, min_val = 0 : i32} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> %abs = tosa.abs %transpose1 : (tensor<1x1x4x2xi32>) -> tensor<1x1x4x2xi32> %add = tosa.add %clamp, %abs : (tensor<1x3x4x2xi32>, tensor<1x1x4x2xi32>) -> tensor<1x3x4x2xi32> %perms1 = "tosa.const"() {value = dense<[0, 3, 1, 2]> : tensor<4xi32>} : () -> tensor<4xi32> @@ -212,7 +212,7 @@ func.func @test_reshape_for_broadcast(%arg0: tensor<4x3x2xi32>) -> tensor<4x3x2x // CHECK-DAG: %[[VAL_19:.*]] = tosa.const_shape {value = dense<[1, 1, 1, 64]> : tensor<4xindex>} : () -> !tosa.shape<4> // CHECK-DAG: %[[VAL_20:.*]] = tosa.reshape %[[VAL_3]], %[[VAL_19]] : (tensor<64xf32>, !tosa.shape<4>) -> tensor<1x1x1x64xf32> // CHECK-DAG: %[[VAL_21:.*]] = tosa.add %[[VAL_18]], %[[VAL_20]] : (tensor<1x112x112x64xf32>, tensor<1x1x1x64xf32>) -> tensor<1x112x112x64xf32> -// CHECK-DAG: %[[VAL_22:.*]] = tosa.clamp %[[VAL_21]] {max_fp = 3.40282347E+38 : f32, max_int = 2147483647 : i64, min_fp = 0.000000e+00 : f32, min_int = 0 : i64} : (tensor<1x112x112x64xf32>) -> tensor<1x112x112x64xf32> +// CHECK-DAG: %[[VAL_22:.*]] = tosa.clamp %[[VAL_21]] {max_val = 3.40282347E+38 : f32, min_val = 0.000000e+00 : f32} : (tensor<1x112x112x64xf32>) -> tensor<1x112x112x64xf32> func.func @test_resnet18_common_case(%arg0: tensor<64xf32>, %arg1: tensor<64xf32>, %74: tensor<1x112x112x64xf32>) -> tensor<1x112x112x64xf32> { %58 = tosa.const_shape {value = dense<[1, 64, 1, 1]> : tensor<4xindex>} : () -> !tosa.shape<4> %59 = "tosa.const"() <{value = dense_resource : tensor<64xf32>}> : () -> tensor<64xf32> @@ -233,12 +233,11 @@ func.func @test_resnet18_common_case(%arg0: tensor<64xf32>, %arg1: tensor<64xf32 %84 = tosa.mul %82, %83 : (tensor<1x64x112x112xf32>, tensor<1x64x1x1xf32>) -> tensor<1x64x112x112xf32> %85 = tosa.reshape %59, %58 : (tensor<64xf32>, !tosa.shape<4>) -> tensor<1x64x1x1xf32> %86 = tosa.add %84, %85 : (tensor<1x64x112x112xf32>, tensor<1x64x1x1xf32>) -> tensor<1x64x112x112xf32> - %87 = tosa.clamp %86 {max_fp = 3.40282347E+38 : f32, max_int = 2147483647 : i64, min_fp = 0.000000e+00 : f32, min_int = 0 : i64} : (tensor<1x64x112x112xf32>) -> tensor<1x64x112x112xf32> + %87 = tosa.clamp %86 {max_val = 3.40282347E+38 : f32, min_val = 0.000000e+00 : f32} : (tensor<1x64x112x112xf32>) -> tensor<1x64x112x112xf32> %88 = tosa.transpose %87, %63 : (tensor<1x64x112x112xf32>, tensor<4xi32>) -> tensor<1x112x112x64xf32> return %88 : tensor<1x112x112x64xf32> } - // ----- // CHECK-LABEL: @test_back_to_back_nullifiers @@ -280,7 +279,7 @@ func.func @test_back_to_back_nullifiers_different_transposes(%arg0: tensor<2x3x4 func.func @test_no_transform_if_outside_fan_in_cone(%arg0: tensor<3x3x3x3xi32>) -> (tensor<3x3x3x3xi32>, tensor<3x3x3x3xi32>) { %perms0 = "tosa.const"() {value = dense<[0, 2, 3, 1]> : tensor<4xi32>} : () -> tensor<4xi32> %0 = tosa.transpose %arg0, %perms0 : (tensor<3x3x3x3xi32>, tensor<4xi32>) -> tensor<3x3x3x3xi32> - %clamp = tosa.clamp %0 {max_fp = 3.40282347E+38 : f32, max_int = 2147483647 : i64, min_fp = 0.000000e+00 : f32, min_int = 0 : i64} : (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32> + %clamp = tosa.clamp %0 {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32> %perms1 = "tosa.const"() {value = dense<[0, 3, 1, 2]> : tensor<4xi32>} : () -> tensor<4xi32> %1 = tosa.transpose %clamp, %perms1 : (tensor<3x3x3x3xi32>, tensor<4xi32>) -> tensor<3x3x3x3xi32> return %1, %clamp : tensor<3x3x3x3xi32>, tensor<3x3x3x3xi32> @@ -296,7 +295,7 @@ func.func @test_two_different_downstream_converge_to_reshape_same_perms(%arg0: t %0 = "tosa.const"() <{value = dense<[0, 2, 1]> : tensor<3xi32>}> : () -> tensor<3xi32> %shape = tosa.const_shape {value = dense<[1, 64, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> %1 = tosa.reshape %arg0, %shape : (tensor<64xf32>, !tosa.shape<3>) -> tensor<1x64x1xf32> - %2 = tosa.clamp %1 {max_fp = 3.40282347E+38 : f32, max_int = 2147483647 : i64, min_fp = 0.000000e+00 : f32, min_int = 0 : i64} : (tensor<1x64x1xf32>) -> tensor<1x64x1xf32> + %2 = tosa.clamp %1 {max_val = 3.40282347E+38 : f32, min_val = 0.000000e+00 : f32} : (tensor<1x64x1xf32>) -> tensor<1x64x1xf32> %3 = tosa.transpose %1, %0 : (tensor<1x64x1xf32>, tensor<3xi32>) -> tensor<1x1x64xf32> %4 = tosa.transpose %2, %0 : (tensor<1x64x1xf32>, tensor<3xi32>) -> tensor<1x1x64xf32> return %3, %4 : tensor<1x1x64xf32>, tensor<1x1x64xf32> @@ -317,7 +316,7 @@ func.func @test_two_different_downstream_converge_to_reshape_different_perms(%ar %1 = "tosa.const"() <{value = dense<[0, 2, 1]> : tensor<3xi32>}> : () -> tensor<3xi32> %shape = tosa.const_shape {value = dense<[1, 64, 1]> : tensor<3xindex>} : () -> !tosa.shape<3> %2 = tosa.reshape %arg0, %shape : (tensor<64xf32>, !tosa.shape<3>) -> tensor<1x64x1xf32> - %3 = tosa.clamp %2 {max_fp = 3.40282347E+38 : f32, max_int = 2147483647 : i64, min_fp = 0.000000e+00 : f32, min_int = 0 : i64} : (tensor<1x64x1xf32>) -> tensor<1x64x1xf32> + %3 = tosa.clamp %2 {max_val = 3.40282347E+38 : f32, min_val = 0.000000e+00 : f32} : (tensor<1x64x1xf32>) -> tensor<1x64x1xf32> %4 = tosa.transpose %2, %1 : (tensor<1x64x1xf32>, tensor<3xi32>) -> tensor<1x1x64xf32> %5 = tosa.transpose %3, %0 : (tensor<1x64x1xf32>, tensor<3xi32>) -> tensor<64x1x1xf32> return %4, %5 : tensor<1x1x64xf32>, tensor<64x1x1xf32> @@ -335,7 +334,7 @@ func.func @test_two_different_downstream_converge_to_reshape_different_perms(%ar // CHECK: return %[[RES1]], %[[RES2]] func.func @test_outside_perms_usage_of_fan_in(%arg0: tensor<2x3xf32>, %arg1: tensor<3x2xf32>) -> (tensor<2x3xf32>, tensor<3x2xf32>) { %0 = "tosa.const"() <{value = dense<[1, 0]> : tensor<2xi32>}> : () -> tensor<2xi32> %1 = tosa.transpose %arg0, %0 : (tensor<2x3xf32>, tensor<2xi32>) -> tensor<3x2xf32> - %2 = tosa.clamp %1 {max_fp = 3.40282347E+38 : f32, max_int = 2147483647 : i64, min_fp = 0.000000e+00 : f32, min_int = 0 : i64} : (tensor<3x2xf32>) -> tensor<3x2xf32> + %2 = tosa.clamp %1 {max_val = 3.40282347E+38 : f32, min_val = 0.000000e+00 : f32} : (tensor<3x2xf32>) -> tensor<3x2xf32> %3 = tosa.transpose %2, %0 : (tensor<3x2xf32>, tensor<2xi32>) -> tensor<2x3xf32> %4 = tosa.add %arg1, %2 : (tensor<3x2xf32>, tensor<3x2xf32>) -> tensor<3x2xf32> return %3, %4: tensor<2x3xf32>, tensor<3x2xf32> @@ -352,7 +351,7 @@ func.func @test_outside_perms_usage_of_fan_in(%arg0: tensor<2x3xf32>, %arg1: ten func.func @test_use_present_in_another_valid_perms_fan_in(%arg0: tensor<2x3xf32>, %arg1: tensor<2x3xf32>) -> (tensor<2x3xf32>, tensor<2x3xf32>) { %0 = "tosa.const"() <{value = dense<[1, 0]> : tensor<2xi32>}> : () -> tensor<2xi32> %1 = tosa.transpose %arg0, %0 : (tensor<2x3xf32>, tensor<2xi32>) -> tensor<3x2xf32> - %2 = tosa.clamp %1 {max_fp = 3.40282347E+38 : f32, max_int = 2147483647 : i64, min_fp = 0.000000e+00 : f32, min_int = 0 : i64} : (tensor<3x2xf32>) -> tensor<3x2xf32> + %2 = tosa.clamp %1 {max_val = 3.40282347E+38 : f32, min_val = 0.000000e+00 : f32} : (tensor<3x2xf32>) -> tensor<3x2xf32> %3 = tosa.transpose %2, %0 : (tensor<3x2xf32>, tensor<2xi32>) -> tensor<2x3xf32> %4 = tosa.transpose %arg1, %0 : (tensor<2x3xf32>, tensor<2xi32>) -> tensor<3x2xf32> %5 = tosa.add %4, %2 : (tensor<3x2xf32>, tensor<3x2xf32>) -> tensor<3x2xf32> @@ -389,7 +388,7 @@ func.func @test_two_same_perms_fan_in_but_one_doesnt_convert_dependents(%arg0: t func.func @test_direct_use_in_other_transpose_with_same_perms(%arg0: tensor<3x3x3x3xi32>) -> (tensor<3x3x3x3xi32>, tensor<3x3x3x3xi32>) { %perms0 = "tosa.const"() {value = dense<[0, 2, 3, 1]> : tensor<4xi32>} : () -> tensor<4xi32> %0 = tosa.transpose %arg0, %perms0 : (tensor<3x3x3x3xi32>, tensor<4xi32>) -> tensor<3x3x3x3xi32> - %clamp = tosa.clamp %0 {max_fp = 3.40282347E+38 : f32, max_int = 2147483647 : i64, min_fp = 0.000000e+00 : f32, min_int = 0 : i64} : (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32> + %clamp = tosa.clamp %0 {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32> %perms1 = "tosa.const"() {value = dense<[0, 3, 1, 2]> : tensor<4xi32>} : () -> tensor<4xi32> %1 = tosa.transpose %clamp, %perms1 : (tensor<3x3x3x3xi32>, tensor<4xi32>) -> tensor<3x3x3x3xi32> %2 = tosa.transpose %clamp, %perms1 : (tensor<3x3x3x3xi32>, tensor<4xi32>) -> tensor<3x3x3x3xi32> @@ -413,12 +412,12 @@ func.func @test_const_transpose() -> tensor<2x3xi32> { // CHECK-LABEL: @test_transpose_tracks_to_const_single_step // CHECK: %[[NEW_CONST:.*]] = "tosa.const"() <{value = dense<0> : tensor<1x2x3x4xi32>}> : () -> tensor<1x2x3x4xi32> -// CHECK: %[[NEW_CLAMP:.*]] = tosa.clamp %[[NEW_CONST]] {max_fp = 3.40282347E+38 : f32, max_int = 2147483647 : i64, min_fp = 0.000000e+00 : f32, min_int = 0 : i64} : (tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32> +// CHECK: %[[NEW_CLAMP:.*]] = tosa.clamp %[[NEW_CONST]] {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32> // CHECK-NOT: tosa.transpose // CHECK: return %[[NEW_CLAMP]] func.func @test_transpose_tracks_to_const_single_step() -> tensor<1x2x3x4xi32> { %0 = "tosa.const"() {value = dense<0> : tensor<1x3x4x2xi32>} : () -> tensor<1x3x4x2xi32> - %clamp = tosa.clamp %0 {max_fp = 3.40282347E+38 : f32, max_int = 2147483647 : i64, min_fp = 0.000000e+00 : f32, min_int = 0 : i64} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> + %clamp = tosa.clamp %0 {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> %perms1 = "tosa.const"() {value = dense<[0, 3, 1, 2]> : tensor<4xi32>} : () -> tensor<4xi32> %1 = tosa.transpose %clamp, %perms1 : (tensor<1x3x4x2xi32>, tensor<4xi32>) -> tensor<1x2x3x4xi32> return %1 : tensor<1x2x3x4xi32> @@ -428,14 +427,14 @@ func.func @test_transpose_tracks_to_const_single_step() -> tensor<1x2x3x4xi32> { // CHECK-LABEL: @test_static_unary_path_to_const // CHECK: %[[NEW_CONST:.*]] = "tosa.const"() <{value = dense<1> : tensor<1x2x3x4xi32>}> : () -> tensor<1x2x3x4xi32> -// CHECK: %[[NEW_CLAMP:.*]] = tosa.clamp %[[NEW_CONST]] {max_fp = 3.40282347E+38 : f32, max_int = 2147483647 : i64, min_fp = 0.000000e+00 : f32, min_int = 0 : i64} : (tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32> +// CHECK: %[[NEW_CLAMP:.*]] = tosa.clamp %[[NEW_CONST]] {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32> // CHECK: %[[NEW_ABS:.*]] = tosa.abs %[[NEW_CLAMP]] : (tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32> // CHECK: %[[NEW_NOT:.*]] = tosa.bitwise_not %[[NEW_ABS]] : (tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32> // CHECK: return %[[NEW_NOT]] func.func @test_static_unary_path_to_const() -> tensor<1x2x3x4xi32> { %perms0 = "tosa.const"() {value = dense<[0, 2, 3, 1]> : tensor<4xi32>} : () -> tensor<4xi32> %0 = "tosa.const"() {value = dense<1> : tensor<1x3x4x2xi32>} : () -> tensor<1x3x4x2xi32> - %clamp = tosa.clamp %0 {max_fp = 3.40282347E+38 : f32, max_int = 2147483647 : i64, min_fp = 0.000000e+00 : f32, min_int = 0 : i64} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> + %clamp = tosa.clamp %0 {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> %abs = tosa.abs %clamp : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> %bitwise_not = tosa.bitwise_not %abs : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> %perms1 = "tosa.const"() {value = dense<[0, 3, 1, 2]> : tensor<4xi32>} : () -> tensor<4xi32> @@ -449,7 +448,7 @@ func.func @test_static_unary_path_to_const() -> tensor<1x2x3x4xi32> { // CHECK: %[[NEW_CONST:.*]] = "tosa.const"() // CHECK-SAME{LITERAL}: dense<[[[[1, 3, 5, 7], [9, 11, 13, 15], [17, 19, 21, 23]], [[2, 4, 6, 8], [10, 12, 14, 16], [18, 20, 22, 24]]]]> // CHECK: tensor<1x2x3x4xi32>}> : () -> tensor<1x2x3x4xi32> -// CHECK: %[[NEW_CLAMP:.*]] = tosa.clamp %arg0 {max_fp = 3.40282347E+38 : f32, max_int = 2147483647 : i64, min_fp = 0.000000e+00 : f32, min_int = 0 : i64} : (tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32> +// CHECK: %[[NEW_CLAMP:.*]] = tosa.clamp %arg0 {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32> // CHECK: %[[NEW_ABS:.*]] = tosa.abs %[[NEW_CONST]] : (tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32> // CHECK: %[[NEW_ADD:.*]] = tosa.add %[[NEW_ABS]], %[[NEW_CLAMP]] : (tensor<1x2x3x4xi32>, tensor<1x2x3x4xi32>) -> tensor<1x2x3x4xi32> // CHECK: return %[[NEW_ADD]] @@ -459,7 +458,7 @@ func.func @test_static_diverges_to_non_splat_const_and_nullifying(%arg0: tensor< %const = "tosa.const"() {value = dense<[[[[1, 2], [3, 4], [5, 6], [7, 8]], [[9, 10], [11, 12], [13, 14], [15, 16]], [[17, 18], [19, 20], [21, 22], [23, 24]]]]> : tensor<1x3x4x2xi32>} : () -> tensor<1x3x4x2xi32> - %clamp = tosa.clamp %transpose0 {max_fp = 3.40282347E+38 : f32, max_int = 2147483647 : i64, min_fp = 0.000000e+00 : f32, min_int = 0 : i64} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> + %clamp = tosa.clamp %transpose0 {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> %abs = tosa.abs %const : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> %add = tosa.add %abs, %clamp : (tensor<1x3x4x2xi32>, tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> %perms2 = "tosa.const"() {value = dense<[0, 3, 1, 2]> : tensor<4xi32>} : () -> tensor<4xi32> @@ -475,7 +474,7 @@ func.func @test_static_diverges_to_non_splat_const_and_nullifying(%arg0: tensor< func.func @test_multi_downstream_both_nullify(%arg0: tensor<3x3x3x3xi32>) -> (tensor<3x3x3x3xi32>, tensor<3x3x3x3xi32>) { %perms0 = "tosa.const"() {value = dense<[0, 2, 3, 1]> : tensor<4xi32>} : () -> tensor<4xi32> %0 = tosa.transpose %arg0, %perms0 : (tensor<3x3x3x3xi32>, tensor<4xi32>) -> tensor<3x3x3x3xi32> - %clamp = tosa.clamp %0 {max_fp = 3.40282347E+38 : f32, max_int = 2147483647 : i64, min_fp = 0.000000e+00 : f32, min_int = 0 : i64} : (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32> + %clamp = tosa.clamp %0 {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32> %perms1 = "tosa.const"() {value = dense<[0, 3, 1, 2]> : tensor<4xi32>} : () -> tensor<4xi32> %1 = tosa.transpose %clamp, %perms1 : (tensor<3x3x3x3xi32>, tensor<4xi32>) -> tensor<3x3x3x3xi32> %2 = tosa.transpose %clamp, %perms1 : (tensor<3x3x3x3xi32>, tensor<4xi32>) -> tensor<3x3x3x3xi32> @@ -495,7 +494,7 @@ func.func @test_multi_downstream_both_nullify(%arg0: tensor<3x3x3x3xi32>) -> (te func.func @test_multi_downstream_one_nullifies_upstream_other_does_not(%arg0: tensor<3x3x3x3xi32>) -> (tensor<3x3x3x3xi32>, tensor<3x3x3x3xi32>) { %perms0 = "tosa.const"() {value = dense<[0, 2, 3, 1]> : tensor<4xi32>} : () -> tensor<4xi32> %0 = tosa.transpose %arg0, %perms0 : (tensor<3x3x3x3xi32>, tensor<4xi32>) -> tensor<3x3x3x3xi32> - %clamp = tosa.clamp %0 {max_fp = 3.40282347E+38 : f32, max_int = 2147483647 : i64, min_fp = 0.000000e+00 : f32, min_int = 0 : i64} : (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32> + %clamp = tosa.clamp %0 {max_val = 2147483647 : i32, min_val = 0 : i32} : (tensor<3x3x3x3xi32>) -> tensor<3x3x3x3xi32> %perms1 = "tosa.const"() {value = dense<[0, 3, 1, 2]> : tensor<4xi32>} : () -> tensor<4xi32> %1 = tosa.transpose %clamp, %perms1 : (tensor<3x3x3x3xi32>, tensor<4xi32>) -> tensor<3x3x3x3xi32> %2 = tosa.transpose %clamp, %perms0 : (tensor<3x3x3x3xi32>, tensor<4xi32>) -> tensor<3x3x3x3xi32> @@ -536,7 +535,7 @@ func.func @test_transpose_tracks_to_nullifying_diverging_binary_unknown_dim_repl %perms0 = "tosa.const"() {value = dense<[0, 2, 3, 1]> : tensor<4xi32>} : () -> tensor<4xi32> %transpose0 = tosa.transpose %arg0, %perms0 : (tensor<1x?x3x4xi32>, tensor<4xi32>) -> tensor %transpose1 = tosa.transpose %arg1, %perms0 : (tensor<1x2x?x4xi32>, tensor<4xi32>) -> tensor<1x?x?x2xi32> - %clamp = tosa.clamp %transpose0 {min_int = 0 : i64, max_int = 1 : i64, min_fp = 0.0 : f64, max_fp = 1.0 : f64} : (tensor) -> tensor + %clamp = tosa.clamp %transpose0 {min_val = 0 : i32, max_val = 1 : i32} : (tensor) -> tensor %abs = tosa.abs %transpose1 : (tensor<1x?x?x2xi32>) -> tensor<1x?x?x2xi32> %add = tosa.add %clamp, %abs : (tensor, tensor<1x?x?x2xi32>) -> tensor<1x3x4x2xi32> %perms1 = "tosa.const"() {value = dense<[0, 3, 1, 2]> : tensor<4xi32>} : () -> tensor<4xi32> @@ -571,7 +570,7 @@ func.func @test_unimplemented_non_const_perms(%perms: tensor<2xi32>) -> tensor) -> tensor<1x2x4x3xi32> { %perms0 = "tosa.const"() {value = dense<[0, 3, 2, 1]> : tensor<4xi32>} : () -> tensor<4xi32> %0 = tosa.transpose %arg0, %perms0 : (tensor<1x2x3x4xi32>, tensor<4xi32>) -> tensor<1x4x3x2xi32> - %clamp = tosa.clamp %0 {min_int = 0 : i64, max_int = 1 : i64, min_fp = 0.0 : f64, max_fp = 1.0 : f64} : (tensor<1x4x3x2xi32>) -> tensor<1x4x3x2xi32> + %clamp = tosa.clamp %0 {min_val = 0 : i32, max_val = 1 : i32} : (tensor<1x4x3x2xi32>) -> tensor<1x4x3x2xi32> %perms1 = "tosa.const"() {value = dense<[0, 3, 1, 2]> : tensor<4xi32>} : () -> tensor<4xi32> %1 = tosa.transpose %clamp, %perms1 : (tensor<1x4x3x2xi32>, tensor<4xi32>) -> tensor<1x2x4x3xi32> return %1 : tensor<1x2x4x3xi32> @@ -653,7 +652,7 @@ func.func @test_unimplemented_static_diverges_to_one_nullifying_one_non_nullifyi %perms1 = "tosa.const"() {value = dense<[0, 3, 2, 1]> : tensor<4xi32>} : () -> tensor<4xi32> %transpose0 = tosa.transpose %arg0, %perms0 : (tensor<1x2x3x4xi32>, tensor<4xi32>) -> tensor<1x3x4x2xi32> %transpose1 = tosa.transpose %arg1, %perms1 : (tensor<1x2x4x3xi32>, tensor<4xi32>) -> tensor<1x3x4x2xi32> - %clamp = tosa.clamp %transpose0 {min_int = 0 : i64, max_int = 1 : i64, min_fp = 0.0 : f64, max_fp = 1.0 : f64} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> + %clamp = tosa.clamp %transpose0 {min_val = 0 : i32, max_val = 1 : i32} : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> %abs = tosa.abs %transpose1 : (tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> %add = tosa.add %clamp, %abs : (tensor<1x3x4x2xi32>, tensor<1x3x4x2xi32>) -> tensor<1x3x4x2xi32> %perms2 = "tosa.const"() {value = dense<[0, 3, 1, 2]> : tensor<4xi32>} : () -> tensor<4xi32> From 5bf42d3e2e83344db14fc0e33623840c53cebfc4 Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Tue, 11 Feb 2025 08:04:51 -0800 Subject: [PATCH 02/17] [lldb] Fix ubsan violation with plugin loading (#126652) This typedef doesn't match the signature below, specifically the signature takes a `lldb:SBDebugger` vs this was defined as `lldb:SBDebugger&`. ``` lldb/source/API/SBDebugger.cpp:199:13: runtime error: call to function lldb::PluginInitialize(lldb::SBDebugger) through pointer to incorrect function type 'bool (*)(lldb::SBDebugger &)' .../CustomPlugin.cpp:134: note: lldb::PluginInitialize(lldb::SBDebugger) defined here ``` --- lldb/source/API/SBDebugger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp index 4e6b22492a0d..bdb8e538b99f 100644 --- a/lldb/source/API/SBDebugger.cpp +++ b/lldb/source/API/SBDebugger.cpp @@ -185,7 +185,7 @@ lldb::SBError SBDebugger::InitializeWithErrorHandling() { llvm::sys::DynamicLibrary dynlib = llvm::sys::DynamicLibrary::getPermanentLibrary(spec.GetPath().c_str()); if (dynlib.isValid()) { - typedef bool (*LLDBCommandPluginInit)(lldb::SBDebugger & debugger); + typedef bool (*LLDBCommandPluginInit)(lldb::SBDebugger debugger); lldb::SBDebugger debugger_sb(debugger_sp); // This calls the bool lldb::PluginInitialize(lldb::SBDebugger debugger) From b7188f6313fef2d5a248e71ba6028460b2ac0558 Mon Sep 17 00:00:00 2001 From: Ivan Kosarev Date: Tue, 11 Feb 2025 16:10:49 +0000 Subject: [PATCH 03/17] [AMDGPU][NFC] Remove an unneeded return value. (#126739) And rename the function to disassociate it from the one where generating loading of the input value may actually fail. --- llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp | 19 ++++++++++--------- .../lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp | 14 +++++++------- llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h | 6 +++--- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp index bb00442342d8..478a4c161fce 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUCallLowering.cpp @@ -816,7 +816,7 @@ bool AMDGPUCallLowering::passSpecialInputs(MachineIRBuilder &MIRBuilder, Register InputReg = MRI.createGenericVirtualRegister(ArgTy); if (IncomingArg) { - LI->loadInputValue(InputReg, MIRBuilder, IncomingArg, ArgRC, ArgTy); + LI->buildLoadInputValue(InputReg, MIRBuilder, IncomingArg, ArgRC, ArgTy); } else if (InputID == AMDGPUFunctionArgInfo::IMPLICIT_ARG_PTR) { LI->getImplicitArgPtr(InputReg, MRI, MIRBuilder); } else if (InputID == AMDGPUFunctionArgInfo::LDS_KERNEL_ID) { @@ -883,8 +883,9 @@ bool AMDGPUCallLowering::passSpecialInputs(MachineIRBuilder &MIRBuilder, NeedWorkItemIDX) { if (ST.getMaxWorkitemID(MF.getFunction(), 0) != 0) { InputReg = MRI.createGenericVirtualRegister(S32); - LI->loadInputValue(InputReg, MIRBuilder, IncomingArgX, - std::get<1>(WorkitemIDX), std::get<2>(WorkitemIDX)); + LI->buildLoadInputValue(InputReg, MIRBuilder, IncomingArgX, + std::get<1>(WorkitemIDX), + std::get<2>(WorkitemIDX)); } else { InputReg = MIRBuilder.buildConstant(S32, 0).getReg(0); } @@ -893,8 +894,8 @@ bool AMDGPUCallLowering::passSpecialInputs(MachineIRBuilder &MIRBuilder, if (IncomingArgY && !IncomingArgY->isMasked() && CalleeArgInfo->WorkItemIDY && NeedWorkItemIDY && ST.getMaxWorkitemID(MF.getFunction(), 1) != 0) { Register Y = MRI.createGenericVirtualRegister(S32); - LI->loadInputValue(Y, MIRBuilder, IncomingArgY, std::get<1>(WorkitemIDY), - std::get<2>(WorkitemIDY)); + LI->buildLoadInputValue(Y, MIRBuilder, IncomingArgY, + std::get<1>(WorkitemIDY), std::get<2>(WorkitemIDY)); Y = MIRBuilder.buildShl(S32, Y, MIRBuilder.buildConstant(S32, 10)).getReg(0); InputReg = InputReg ? MIRBuilder.buildOr(S32, InputReg, Y).getReg(0) : Y; @@ -903,8 +904,8 @@ bool AMDGPUCallLowering::passSpecialInputs(MachineIRBuilder &MIRBuilder, if (IncomingArgZ && !IncomingArgZ->isMasked() && CalleeArgInfo->WorkItemIDZ && NeedWorkItemIDZ && ST.getMaxWorkitemID(MF.getFunction(), 2) != 0) { Register Z = MRI.createGenericVirtualRegister(S32); - LI->loadInputValue(Z, MIRBuilder, IncomingArgZ, std::get<1>(WorkitemIDZ), - std::get<2>(WorkitemIDZ)); + LI->buildLoadInputValue(Z, MIRBuilder, IncomingArgZ, + std::get<1>(WorkitemIDZ), std::get<2>(WorkitemIDZ)); Z = MIRBuilder.buildShl(S32, Z, MIRBuilder.buildConstant(S32, 20)).getReg(0); InputReg = InputReg ? MIRBuilder.buildOr(S32, InputReg, Z).getReg(0) : Z; @@ -925,8 +926,8 @@ bool AMDGPUCallLowering::passSpecialInputs(MachineIRBuilder &MIRBuilder, ArgDescriptor IncomingArg = ArgDescriptor::createArg( IncomingArgX ? *IncomingArgX : IncomingArgY ? *IncomingArgY : *IncomingArgZ, ~0u); - LI->loadInputValue(InputReg, MIRBuilder, &IncomingArg, - &AMDGPU::VGPR_32RegClass, S32); + LI->buildLoadInputValue(InputReg, MIRBuilder, &IncomingArg, + &AMDGPU::VGPR_32RegClass, S32); } } diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp index e9e47eaadd55..908d323c7fec 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -4275,10 +4275,11 @@ verifyCFIntrinsic(MachineInstr &MI, MachineRegisterInfo &MRI, MachineInstr *&Br, return UseMI; } -bool AMDGPULegalizerInfo::loadInputValue(Register DstReg, MachineIRBuilder &B, - const ArgDescriptor *Arg, - const TargetRegisterClass *ArgRC, - LLT ArgTy) const { +void AMDGPULegalizerInfo::buildLoadInputValue(Register DstReg, + MachineIRBuilder &B, + const ArgDescriptor *Arg, + const TargetRegisterClass *ArgRC, + LLT ArgTy) const { MCRegister SrcReg = Arg->getRegister(); assert(SrcReg.isPhysical() && "Physical register expected"); assert(DstReg.isVirtual() && "Virtual register expected"); @@ -4304,8 +4305,6 @@ bool AMDGPULegalizerInfo::loadInputValue(Register DstReg, MachineIRBuilder &B, } else { B.buildCopy(DstReg, LiveIn); } - - return true; } bool AMDGPULegalizerInfo::loadInputValue( @@ -4369,7 +4368,8 @@ bool AMDGPULegalizerInfo::loadInputValue( if (!Arg->isRegister() || !Arg->getRegister().isValid()) return false; // TODO: Handle these - return loadInputValue(DstReg, B, Arg, ArgRC, ArgTy); + buildLoadInputValue(DstReg, B, Arg, ArgRC, ArgTy); + return true; } bool AMDGPULegalizerInfo::legalizePreloadedArgIntrin( diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h index 86c15197805d..03b7c36fc450 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h +++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.h @@ -111,9 +111,9 @@ class AMDGPULegalizerInfo final : public LegalizerInfo { bool legalizeCTLZ_ZERO_UNDEF(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B) const; - bool loadInputValue(Register DstReg, MachineIRBuilder &B, - const ArgDescriptor *Arg, - const TargetRegisterClass *ArgRC, LLT ArgTy) const; + void buildLoadInputValue(Register DstReg, MachineIRBuilder &B, + const ArgDescriptor *Arg, + const TargetRegisterClass *ArgRC, LLT ArgTy) const; bool loadInputValue(Register DstReg, MachineIRBuilder &B, AMDGPUFunctionArgInfo::PreloadedValue ArgType) const; From 2ad9d5f5f01cd4f29788a0cf7b21790df13fca71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Tue, 11 Feb 2025 17:20:23 +0100 Subject: [PATCH 04/17] [llvm] [cmake] Expose `LLVM_BUILD_TELEMETRY` in `LLVMConfig.cmake` (#126710) Add `LLVM_BUILD_TELEMETRY` to the list of flags exposed in `LLVMConfig.cmake`. This fixes telemetry library being misdetected as `OFF` when building LLDB standalone. Fixes bac62ee5b473e70981a6bd9759ec316315fca07d. ------ I guess this also needs a backport to 20.x. --- llvm/cmake/modules/LLVMConfig.cmake.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/llvm/cmake/modules/LLVMConfig.cmake.in b/llvm/cmake/modules/LLVMConfig.cmake.in index c49f10b9343f..28655ee3ab87 100644 --- a/llvm/cmake/modules/LLVMConfig.cmake.in +++ b/llvm/cmake/modules/LLVMConfig.cmake.in @@ -100,6 +100,8 @@ set(LLVM_ENABLE_PIC @LLVM_ENABLE_PIC@) set(LLVM_BUILD_32_BITS @LLVM_BUILD_32_BITS@) +set(LLVM_BUILD_TELEMETRY @LLVM_BUILD_TELEMETRY@) + if (NOT "@LLVM_PTHREAD_LIB@" STREQUAL "") set(LLVM_PTHREAD_LIB "@LLVM_PTHREAD_LIB@") endif() From 76392421553f3b25552970812868f70721971451 Mon Sep 17 00:00:00 2001 From: Stanislav Mekhanoshin Date: Tue, 11 Feb 2025 08:35:45 -0800 Subject: [PATCH 05/17] [AMDGPU] Create new directive .amdhsa_inst_pref_size (#126622) The field INST_PREF_SIZE is available since gfx11. --- llvm/docs/AMDGPUUsage.rst | 3 +++ llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp | 12 ++++++++++++ .../AMDGPU/Disassembler/AMDGPUDisassembler.cpp | 8 ++++---- .../AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp | 10 ++++++++++ llvm/test/MC/AMDGPU/hsa-diag-v4.s | 10 ++++++++++ llvm/test/MC/AMDGPU/hsa-gfx12-v4.s | 4 +++- llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx11.s | 2 ++ llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx12.s | 8 ++++++-- llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-gfx11.s | 11 +++++++---- llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-gfx12.s | 5 +++-- 10 files changed, 60 insertions(+), 13 deletions(-) diff --git a/llvm/docs/AMDGPUUsage.rst b/llvm/docs/AMDGPUUsage.rst index 84980d0c31d4..899b2cf3b490 100644 --- a/llvm/docs/AMDGPUUsage.rst +++ b/llvm/docs/AMDGPUUsage.rst @@ -18213,6 +18213,9 @@ terminated by an ``.end_amdhsa_kernel`` directive. :ref:`amdgpu-amdhsa-compute_pgm_rsrc1-gfx6-gfx12-table`. ``.amdhsa_shared_vgpr_count`` 0 GFX10-GFX11 Controls SHARED_VGPR_COUNT in :ref:`amdgpu-amdhsa-compute_pgm_rsrc3-gfx10-gfx11-table`. + ``.amdhsa_inst_pref_size`` 0 GFX11-GFX12 Controls INST_PREF_SIZE in + :ref:`amdgpu-amdhsa-compute_pgm_rsrc3-gfx10-gfx11-table` or + :ref:`amdgpu-amdhsa-compute_pgm_rsrc3-gfx12-table` ``.amdhsa_exception_fp_ieee_invalid_op`` 0 GFX6-GFX12 Controls ENABLE_EXCEPTION_IEEE_754_FP_INVALID_OPERATION in :ref:`amdgpu-amdhsa-compute_pgm_rsrc2-gfx6-gfx12-table`. ``.amdhsa_exception_fp_denorm_src`` 0 GFX6-GFX12 Controls ENABLE_EXCEPTION_FP_DENORMAL_SOURCE in diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp index 4b6d02fff4ae..4ff9cff09f31 100644 --- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -5876,6 +5876,18 @@ bool AMDGPUAsmParser::ParseDirectiveAMDHSAKernel() { PARSE_BITS_ENTRY(KD.compute_pgm_rsrc3, COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT, ExprVal, ValRange); + } else if (ID == ".amdhsa_inst_pref_size") { + if (IVersion.Major < 11) + return Error(IDRange.Start, "directive requires gfx11+", IDRange); + if (IVersion.Major == 11) { + PARSE_BITS_ENTRY(KD.compute_pgm_rsrc3, + COMPUTE_PGM_RSRC3_GFX11_INST_PREF_SIZE, ExprVal, + ValRange); + } else { + PARSE_BITS_ENTRY(KD.compute_pgm_rsrc3, + COMPUTE_PGM_RSRC3_GFX12_PLUS_INST_PREF_SIZE, ExprVal, + ValRange); + } } else if (ID == ".amdhsa_exception_fp_ieee_invalid_op") { PARSE_BITS_ENTRY( KD.compute_pgm_rsrc2, diff --git a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp index 58cdbe6cf373..02ad08740049 100644 --- a/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp +++ b/llvm/lib/Target/AMDGPU/Disassembler/AMDGPUDisassembler.cpp @@ -2233,15 +2233,15 @@ Expected AMDGPUDisassembler::decodeCOMPUTE_PGM_RSRC3( // Bits [4-11]. if (isGFX11()) { - PRINT_PSEUDO_DIRECTIVE_COMMENT("INST_PREF_SIZE", - COMPUTE_PGM_RSRC3_GFX11_INST_PREF_SIZE); + PRINT_DIRECTIVE(".amdhsa_inst_pref_size", + COMPUTE_PGM_RSRC3_GFX11_INST_PREF_SIZE); PRINT_PSEUDO_DIRECTIVE_COMMENT("TRAP_ON_START", COMPUTE_PGM_RSRC3_GFX11_TRAP_ON_START); PRINT_PSEUDO_DIRECTIVE_COMMENT("TRAP_ON_END", COMPUTE_PGM_RSRC3_GFX11_TRAP_ON_END); } else if (isGFX12Plus()) { - PRINT_PSEUDO_DIRECTIVE_COMMENT( - "INST_PREF_SIZE", COMPUTE_PGM_RSRC3_GFX12_PLUS_INST_PREF_SIZE); + PRINT_DIRECTIVE(".amdhsa_inst_pref_size", + COMPUTE_PGM_RSRC3_GFX12_PLUS_INST_PREF_SIZE); } else { CHECK_RESERVED_BITS_DESC_MSG(COMPUTE_PGM_RSRC3_GFX10_RESERVED1, "COMPUTE_PGM_RSRC3", diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp index eccd77d6c00f..059bab583852 100644 --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp @@ -579,7 +579,17 @@ void AMDGPUTargetAsmStreamer::EmitAmdhsaKernelDescriptor( amdhsa::COMPUTE_PGM_RSRC3_GFX10_GFX11_SHARED_VGPR_COUNT, ".amdhsa_shared_vgpr_count"); } + if (IVersion.Major == 11) { + PrintField(KD.compute_pgm_rsrc3, + amdhsa::COMPUTE_PGM_RSRC3_GFX11_INST_PREF_SIZE_SHIFT, + amdhsa::COMPUTE_PGM_RSRC3_GFX11_INST_PREF_SIZE, + ".amdhsa_inst_pref_size"); + } if (IVersion.Major >= 12) { + PrintField(KD.compute_pgm_rsrc3, + amdhsa::COMPUTE_PGM_RSRC3_GFX12_PLUS_INST_PREF_SIZE_SHIFT, + amdhsa::COMPUTE_PGM_RSRC3_GFX12_PLUS_INST_PREF_SIZE, + ".amdhsa_inst_pref_size"); PrintField(KD.compute_pgm_rsrc1, amdhsa::COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN_SHIFT, amdhsa::COMPUTE_PGM_RSRC1_GFX12_PLUS_ENABLE_WG_RR_EN, diff --git a/llvm/test/MC/AMDGPU/hsa-diag-v4.s b/llvm/test/MC/AMDGPU/hsa-diag-v4.s index 3733b162edcf..9ab177cf2b12 100644 --- a/llvm/test/MC/AMDGPU/hsa-diag-v4.s +++ b/llvm/test/MC/AMDGPU/hsa-diag-v4.s @@ -280,6 +280,16 @@ .amdhsa_shared_vgpr_count 15 .end_amdhsa_kernel +// GCN-LABEL: warning: test_amdhsa_inst_pref_size_invalid +// PREGFX10: error: directive requires gfx11+ +// NONAMDHSA: error: unknown directive +.warning "test_amdhsa_inst_pref_size_invalid" +.amdhsa_kernel test_amdhsa_inst_pref_size_invalid + .amdhsa_next_free_vgpr 273 + .amdhsa_next_free_sgpr 0 + .amdhsa_inst_pref_size 15 +.end_amdhsa_kernel + // GCN-LABEL: warning: test_next_free_vgpr_invalid // AMDHSA: error: .amdgcn.next_free_{v,s}gpr symbols must be absolute expressions // NONAMDHSA-NOT: error: diff --git a/llvm/test/MC/AMDGPU/hsa-gfx12-v4.s b/llvm/test/MC/AMDGPU/hsa-gfx12-v4.s index ea649bc76116..e90a97600822 100644 --- a/llvm/test/MC/AMDGPU/hsa-gfx12-v4.s +++ b/llvm/test/MC/AMDGPU/hsa-gfx12-v4.s @@ -33,7 +33,7 @@ // complete // OBJDUMP-NEXT: 0040 01000000 01000000 08000000 00000000 // OBJDUMP-NEXT: 0050 00000000 00000000 00000000 00000000 -// OBJDUMP-NEXT: 0060 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0060 00000000 00000000 00000000 f00f0000 // OBJDUMP-NEXT: 0070 015021e4 1f0f007f 5e040000 00000000 // special_sgpr // OBJDUMP-NEXT: 0080 00000000 00000000 00000000 00000000 @@ -120,6 +120,7 @@ disabled_user_sgpr: .amdhsa_workgroup_processor_mode 1 .amdhsa_memory_ordered 1 .amdhsa_forward_progress 1 + .amdhsa_inst_pref_size 255 .amdhsa_round_robin_scheduling 1 .amdhsa_exception_fp_ieee_invalid_op 1 .amdhsa_exception_fp_denorm_src 1 @@ -158,6 +159,7 @@ disabled_user_sgpr: // ASM-NEXT: .amdhsa_workgroup_processor_mode 1 // ASM-NEXT: .amdhsa_memory_ordered 1 // ASM-NEXT: .amdhsa_forward_progress 1 +// ASM-NEXT: .amdhsa_inst_pref_size 255 // ASM-NEXT: .amdhsa_round_robin_scheduling 1 // ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op 1 // ASM-NEXT: .amdhsa_exception_fp_denorm_src 1 diff --git a/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx11.s b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx11.s index 85a7ad05b00f..68cf28f2ac49 100644 --- a/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx11.s +++ b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx11.s @@ -133,6 +133,7 @@ expr_defined: // ASM-NEXT: .amdhsa_memory_ordered (((((((((((((((((((1621884928|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(((alignto(max(defined_value+4, 1), 8))/8)-1))&(~960))&1073741824)>>30 // ASM-NEXT: .amdhsa_forward_progress (((((((((((((((((((1621884928|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~63))|(((alignto(max(defined_value+4, 1), 8))/8)-1))&(~960))&2147483648)>>31 // ASM-NEXT: .amdhsa_shared_vgpr_count 0 +// ASM-NEXT: .amdhsa_inst_pref_size 0 // ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op (((((((((((((((((((((((((((128|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|defined_boolean)&(~62))&16777216)>>24 // ASM-NEXT: .amdhsa_exception_fp_denorm_src (((((((((((((((((((((((((((128|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|defined_boolean)&(~62))&33554432)>>25 // ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero (((((((((((((((((((((((((((128|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|defined_boolean)&(~62))&67108864)>>26 @@ -180,6 +181,7 @@ expr_defined: // ASM-NEXT: .amdhsa_memory_ordered 1 // ASM-NEXT: .amdhsa_forward_progress 1 // ASM-NEXT: .amdhsa_shared_vgpr_count 0 +// ASM-NEXT: .amdhsa_inst_pref_size 0 // ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op 1 // ASM-NEXT: .amdhsa_exception_fp_denorm_src 1 // ASM-NEXT: .amdhsa_exception_fp_ieee_div_zero 1 diff --git a/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx12.s b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx12.s index 51d0fb30b320..6f7a9a260568 100644 --- a/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx12.s +++ b/llvm/test/MC/AMDGPU/hsa-sym-exprs-gfx12.s @@ -9,12 +9,12 @@ // expr_defined_later // OBJDUMP-NEXT: 0000 2b000000 2c000000 00000000 00000000 // OBJDUMP-NEXT: 0010 00000000 00000000 00000000 00000000 -// OBJDUMP-NEXT: 0020 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0020 00000000 00000000 00000000 f0020000 // OBJDUMP-NEXT: 0030 05f02fe4 811f007f 000c0000 00000000 // expr_defined // OBJDUMP-NEXT: 0040 2a000000 2b000000 00000000 00000000 // OBJDUMP-NEXT: 0050 00000000 00000000 00000000 00000000 -// OBJDUMP-NEXT: 0060 00000000 00000000 00000000 00000000 +// OBJDUMP-NEXT: 0060 00000000 00000000 00000000 f0020000 // OBJDUMP-NEXT: 0070 05f02fe4 811f007f 000c0000 00000000 .text @@ -53,6 +53,7 @@ expr_defined: .amdhsa_workgroup_processor_mode defined_boolean .amdhsa_memory_ordered defined_boolean .amdhsa_forward_progress defined_boolean + .amdhsa_inst_pref_size defined_value+6 .amdhsa_exception_fp_ieee_invalid_op defined_boolean .amdhsa_exception_fp_denorm_src defined_boolean .amdhsa_exception_fp_ieee_div_zero defined_boolean @@ -89,6 +90,7 @@ expr_defined: .amdhsa_workgroup_processor_mode defined_boolean .amdhsa_memory_ordered defined_boolean .amdhsa_forward_progress defined_boolean + .amdhsa_inst_pref_size defined_value+6 .amdhsa_exception_fp_ieee_invalid_op defined_boolean .amdhsa_exception_fp_denorm_src defined_boolean .amdhsa_exception_fp_ieee_div_zero defined_boolean @@ -132,6 +134,7 @@ expr_defined: // ASM-NEXT: .amdhsa_workgroup_processor_mode (((((((((((((((((((((1611399168|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(((alignto(max(defined_value+4, 1), 8))/8)-1))&(~960))&536870912)>>29 // ASM-NEXT: .amdhsa_memory_ordered (((((((((((((((((((((1611399168|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(((alignto(max(defined_value+4, 1), 8))/8)-1))&(~960))&1073741824)>>30 // ASM-NEXT: .amdhsa_forward_progress (((((((((((((((((((((1611399168|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(((alignto(max(defined_value+4, 1), 8))/8)-1))&(~960))&2147483648)>>31 +// ASM-NEXT: .amdhsa_inst_pref_size (((defined_value+6)<<4)&4080)>>4 // ASM-NEXT: .amdhsa_round_robin_scheduling (((((((((((((((((((((1611399168|(defined_2_bits<<12))&(~49152))|(defined_2_bits<<14))&(~196608))|(defined_2_bits<<16))&(~786432))|(defined_2_bits<<18))&(~67108864))|(defined_boolean<<26))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~2147483648))|(defined_boolean<<31))&(~2097152))|(defined_boolean<<21))&(~63))|(((alignto(max(defined_value+4, 1), 8))/8)-1))&(~960))&2097152)>>21 // ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op (((((((((((((((((((((((((((128|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|defined_boolean)&(~62))&16777216)>>24 // ASM-NEXT: .amdhsa_exception_fp_denorm_src (((((((((((((((((((((((((((128|(defined_2_bits<<11))&(~128))|(defined_boolean<<7))&(~256))|(defined_boolean<<8))&(~512))|(defined_boolean<<9))&(~1024))|(defined_boolean<<10))&(~16777216))|(defined_boolean<<24))&(~33554432))|(defined_boolean<<25))&(~67108864))|(defined_boolean<<26))&(~134217728))|(defined_boolean<<27))&(~268435456))|(defined_boolean<<28))&(~536870912))|(defined_boolean<<29))&(~1073741824))|(defined_boolean<<30))&(~1))|defined_boolean)&(~62))&33554432)>>25 @@ -177,6 +180,7 @@ expr_defined: // ASM-NEXT: .amdhsa_workgroup_processor_mode 1 // ASM-NEXT: .amdhsa_memory_ordered 1 // ASM-NEXT: .amdhsa_forward_progress 1 +// ASM-NEXT: .amdhsa_inst_pref_size 47 // ASM-NEXT: .amdhsa_round_robin_scheduling 1 // ASM-NEXT: .amdhsa_exception_fp_ieee_invalid_op 1 // ASM-NEXT: .amdhsa_exception_fp_denorm_src 1 diff --git a/llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-gfx11.s b/llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-gfx11.s index 750809128189..3cd7a0503e30 100644 --- a/llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-gfx11.s +++ b/llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-gfx11.s @@ -13,7 +13,7 @@ ; CHECK-NEXT: .amdhsa_private_segment_fixed_size 0 ; CHECK-NEXT: .amdhsa_kernarg_size 0 ; CHECK-NEXT: ; SHARED_VGPR_COUNT 0 -; CHECK-NEXT: ; INST_PREF_SIZE 0 +; CHECK-NEXT: .amdhsa_inst_pref_size 0 ; CHECK-NEXT: ; TRAP_ON_START 0 ; CHECK-NEXT: ; TRAP_ON_END 0 ; CHECK-NEXT: ; IMAGE_OP 0 @@ -70,7 +70,7 @@ ; CHECK-NEXT: .amdhsa_private_segment_fixed_size 0 ; CHECK-NEXT: .amdhsa_kernarg_size 0 ; CHECK-NEXT: .amdhsa_shared_vgpr_count 0 -; CHECK-NEXT: ; INST_PREF_SIZE 0 +; CHECK-NEXT: .amdhsa_inst_pref_size 0 ; CHECK-NEXT: ; TRAP_ON_START 0 ; CHECK-NEXT: ; TRAP_ON_END 0 ; CHECK-NEXT: ; IMAGE_OP 0 @@ -114,6 +114,7 @@ .amdhsa_next_free_vgpr 32 .amdhsa_next_free_sgpr 32 .amdhsa_shared_vgpr_count 0 + .amdhsa_inst_pref_size 0 .end_amdhsa_kernel ;--- 3.s @@ -127,7 +128,7 @@ ; CHECK-NEXT: .amdhsa_private_segment_fixed_size 0 ; CHECK-NEXT: .amdhsa_kernarg_size 0 ; CHECK-NEXT: .amdhsa_shared_vgpr_count 1 -; CHECK-NEXT: ; INST_PREF_SIZE 0 +; CHECK-NEXT: .amdhsa_inst_pref_size 63 ; CHECK-NEXT: ; TRAP_ON_START 0 ; CHECK-NEXT: ; TRAP_ON_END 0 ; CHECK-NEXT: ; IMAGE_OP 0 @@ -171,6 +172,7 @@ .amdhsa_next_free_vgpr 32 .amdhsa_next_free_sgpr 32 .amdhsa_shared_vgpr_count 1 + .amdhsa_inst_pref_size 63 .end_amdhsa_kernel ;--- 4.s @@ -184,7 +186,7 @@ ; CHECK-NEXT: .amdhsa_private_segment_fixed_size 0 ; CHECK-NEXT: .amdhsa_kernarg_size 0 ; CHECK-NEXT: .amdhsa_shared_vgpr_count 1 -; CHECK-NEXT: ; INST_PREF_SIZE 0 +; CHECK-NEXT: .amdhsa_inst_pref_size 63 ; CHECK-NEXT: ; TRAP_ON_START 0 ; CHECK-NEXT: ; TRAP_ON_END 0 ; CHECK-NEXT: ; IMAGE_OP 0 @@ -228,5 +230,6 @@ .amdhsa_next_free_vgpr 32 .amdhsa_next_free_sgpr 32 .amdhsa_shared_vgpr_count 1 + .amdhsa_inst_pref_size 63 .amdhsa_wavefront_size32 0 .end_amdhsa_kernel diff --git a/llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-gfx12.s b/llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-gfx12.s index c644e15efc8d..ed2b87d9885c 100644 --- a/llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-gfx12.s +++ b/llvm/test/tools/llvm-objdump/ELF/AMDGPU/kd-gfx12.s @@ -12,7 +12,7 @@ ; CHECK-NEXT: .amdhsa_group_segment_fixed_size 0 ; CHECK-NEXT: .amdhsa_private_segment_fixed_size 0 ; CHECK-NEXT: .amdhsa_kernarg_size 0 -; CHECK-NEXT: ; INST_PREF_SIZE 0 +; CHECK-NEXT: .amdhsa_inst_pref_size 0 ; CHECK-NEXT: ; GLG_EN 0 ; CHECK-NEXT: ; IMAGE_OP 0 ; CHECK-NEXT: .amdhsa_next_free_vgpr 32 @@ -66,7 +66,7 @@ ; CHECK-NEXT: .amdhsa_group_segment_fixed_size 0 ; CHECK-NEXT: .amdhsa_private_segment_fixed_size 0 ; CHECK-NEXT: .amdhsa_kernarg_size 0 -; CHECK-NEXT: ; INST_PREF_SIZE 0 +; CHECK-NEXT: .amdhsa_inst_pref_size 255 ; CHECK-NEXT: ; GLG_EN 0 ; CHECK-NEXT: ; IMAGE_OP 0 ; CHECK-NEXT: .amdhsa_next_free_vgpr 32 @@ -108,4 +108,5 @@ .amdhsa_next_free_vgpr 32 .amdhsa_next_free_sgpr 32 .amdhsa_wavefront_size32 0 + .amdhsa_inst_pref_size 255 .end_amdhsa_kernel From 2f54223247e8f9f0fc006b944de8351f376814af Mon Sep 17 00:00:00 2001 From: sitrin Date: Tue, 11 Feb 2025 11:58:56 -0500 Subject: [PATCH 06/17] [Docs] Fix typo in TypeSanitizer.rst "tale" -> "table" (NFC) (#126721) The word `table` is now in place of the word `tale`. Fixes #126719. Co-authored-by: sitrin --- clang/docs/TypeSanitizer.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/docs/TypeSanitizer.rst b/clang/docs/TypeSanitizer.rst index 4d1dfc23a6c5..3c683a6c24bb 100644 --- a/clang/docs/TypeSanitizer.rst +++ b/clang/docs/TypeSanitizer.rst @@ -27,7 +27,7 @@ reduce these impacts. The TypeSanitizer Algorithm =========================== For each TBAA type-access descriptor, encoded in LLVM IR using TBAA Metadata, the instrumentation -pass generates descriptor tales. Thus there is a unique pointer to each type (and access descriptor). +pass generates descriptor tables. Thus there is a unique pointer to each type (and access descriptor). These tables are comdat (except for anonymous-namespace types), so the pointer values are unique across the program. From b3510a88b3c19645fbde09cb58af6dead68ebd36 Mon Sep 17 00:00:00 2001 From: Florian Mayer Date: Tue, 11 Feb 2025 09:05:35 -0800 Subject: [PATCH 07/17] [NFC] [clang] simplify isDesignatorAtObjectEnd (#126658) IsLastOrInvalidFieldDecl would always return true if `Invalid=true`, so we know that !IsLastOrInvalidFieldDecl(...) means !Invalid. --- clang/lib/AST/ExprConstant.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 192b679b4c99..5c6ca4c9ee4d 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -12536,10 +12536,9 @@ static const Expr *ignorePointerCastsAndParens(const Expr *E) { static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) { assert(!LVal.Designator.Invalid); - auto IsLastOrInvalidFieldDecl = [&Ctx](const FieldDecl *FD, bool &Invalid) { + auto IsLastOrInvalidFieldDecl = [&Ctx](const FieldDecl *FD) { const RecordDecl *Parent = FD->getParent(); - Invalid = Parent->isInvalidDecl(); - if (Invalid || Parent->isUnion()) + if (Parent->isInvalidDecl() || Parent->isUnion()) return true; const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(Parent); return FD->getFieldIndex() + 1 == Layout.getFieldCount(); @@ -12548,14 +12547,12 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) { auto &Base = LVal.getLValueBase(); if (auto *ME = dyn_cast_or_null(Base.dyn_cast())) { if (auto *FD = dyn_cast(ME->getMemberDecl())) { - bool Invalid; - if (!IsLastOrInvalidFieldDecl(FD, Invalid)) - return Invalid; + if (!IsLastOrInvalidFieldDecl(FD)) + return false; } else if (auto *IFD = dyn_cast(ME->getMemberDecl())) { for (auto *FD : IFD->chain()) { - bool Invalid; - if (!IsLastOrInvalidFieldDecl(cast(FD), Invalid)) - return Invalid; + if (!IsLastOrInvalidFieldDecl(cast(FD))) + return false; } } } @@ -12591,9 +12588,8 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) { return false; BaseType = CT->getElementType(); } else if (auto *FD = getAsField(Entry)) { - bool Invalid; - if (!IsLastOrInvalidFieldDecl(FD, Invalid)) - return Invalid; + if (!IsLastOrInvalidFieldDecl(FD)) + return false; BaseType = FD->getType(); } else { assert(getAsBaseClass(Entry) && "Expecting cast to a base class"); From 8e4e1449318de0e73192edf0b3c6a0d5b6ec7a31 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Tue, 11 Feb 2025 09:06:40 -0800 Subject: [PATCH 08/17] [CodeGen] Avoid repeated hash lookups (NFC) (#126672) --- clang/lib/CodeGen/CGOpenMPRuntime.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index cafaaa364cb7..b679d63874b3 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -1457,14 +1457,13 @@ void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { clearLocThreadIdInsertPt(CGF); OpenMPLocThreadIDMap.erase(CGF.CurFn); } - if (FunctionUDRMap.count(CGF.CurFn) > 0) { - for(const auto *D : FunctionUDRMap[CGF.CurFn]) + if (auto I = FunctionUDRMap.find(CGF.CurFn); I != FunctionUDRMap.end()) { + for (const auto *D : I->second) UDRMap.erase(D); - FunctionUDRMap.erase(CGF.CurFn); + FunctionUDRMap.erase(I); } - auto I = FunctionUDMMap.find(CGF.CurFn); - if (I != FunctionUDMMap.end()) { - for(const auto *D : I->second) + if (auto I = FunctionUDMMap.find(CGF.CurFn); I != FunctionUDMMap.end()) { + for (const auto *D : I->second) UDMMap.erase(D); FunctionUDMMap.erase(I); } From c50f924aeae2d2eded772a7a80b20d46e1c9b41e Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Tue, 11 Feb 2025 09:07:15 -0800 Subject: [PATCH 09/17] [Sema] Avoid repeated hash lookups (NFC) (#126674) --- clang/lib/Sema/SemaOpenMP.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 376995d624e2..39ce65381a98 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -5078,7 +5078,8 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, // At most one if clause without a directive-name-modifier can appear on // the directive. OpenMPDirectiveKind CurNM = IC->getNameModifier(); - if (FoundNameModifiers[CurNM]) { + auto &FNM = FoundNameModifiers[CurNM]; + if (FNM) { S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause) << getOpenMPDirectiveName(Kind) << getOpenMPClauseName(OMPC_if) << (CurNM != OMPD_unknown) << getOpenMPDirectiveName(CurNM); @@ -5087,7 +5088,7 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind, NameModifierLoc.push_back(IC->getNameModifierLoc()); ++NamedModifiersNumber; } - FoundNameModifiers[CurNM] = IC; + FNM = IC; if (CurNM == OMPD_unknown) continue; // Check if the specified name modifier is allowed for the current @@ -6759,16 +6760,15 @@ SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareSimdDirective( ->getCanonicalDecl() == CanonPVD) { // OpenMP [2.8.1, simd construct, Restrictions] // A list-item cannot appear in more than one aligned clause. - if (AlignedArgs.count(CanonPVD) > 0) { + auto [It, Inserted] = AlignedArgs.try_emplace(CanonPVD, E); + if (!Inserted) { Diag(E->getExprLoc(), diag::err_omp_used_in_clause_twice) << 1 << getOpenMPClauseName(OMPC_aligned) << E->getSourceRange(); - Diag(AlignedArgs[CanonPVD]->getExprLoc(), - diag::note_omp_explicit_dsa) + Diag(It->second->getExprLoc(), diag::note_omp_explicit_dsa) << getOpenMPClauseName(OMPC_aligned); continue; } - AlignedArgs[CanonPVD] = E; QualType QTy = PVD->getType() .getNonReferenceType() .getUnqualifiedType() From 43c82a8e07819ad0553ef0dffedff3c8b8cecf5e Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Tue, 11 Feb 2025 09:07:46 -0800 Subject: [PATCH 10/17] [clang-installapi] Avoid repeated hash lookups (NFC) (#126677) --- clang/tools/clang-installapi/Options.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/clang/tools/clang-installapi/Options.cpp b/clang/tools/clang-installapi/Options.cpp index 8a2c3463189f..0dddcfce58ca 100644 --- a/clang/tools/clang-installapi/Options.cpp +++ b/clang/tools/clang-installapi/Options.cpp @@ -263,11 +263,12 @@ bool Options::processInstallAPIXOptions(InputArgList &Args) { } const StringRef ASpelling = NextA->getSpelling(); const auto &AValues = NextA->getValues(); + auto &UniqueArgs = FEOpts.UniqueArgs[Label]; if (AValues.empty()) - FEOpts.UniqueArgs[Label].emplace_back(ASpelling.str()); + UniqueArgs.emplace_back(ASpelling.str()); else for (const StringRef Val : AValues) - FEOpts.UniqueArgs[Label].emplace_back((ASpelling + Val).str()); + UniqueArgs.emplace_back((ASpelling + Val).str()); A->claim(); NextA->claim(); @@ -608,32 +609,37 @@ Options::processAndFilterOutInstallAPIOptions(ArrayRef Args) { ParsedArgs.hasArg(OPT_not_for_dyld_shared_cache); for (const Arg *A : ParsedArgs.filtered(OPT_allowable_client)) { + auto It = ArgToArchMap.find(A); LinkerOpts.AllowableClients[A->getValue()] = - ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet(); + It != ArgToArchMap.end() ? It->second : ArchitectureSet(); A->claim(); } for (const Arg *A : ParsedArgs.filtered(OPT_reexport_l)) { + auto It = ArgToArchMap.find(A); LinkerOpts.ReexportedLibraries[A->getValue()] = - ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet(); + It != ArgToArchMap.end() ? It->second : ArchitectureSet(); A->claim(); } for (const Arg *A : ParsedArgs.filtered(OPT_reexport_library)) { + auto It = ArgToArchMap.find(A); LinkerOpts.ReexportedLibraryPaths[A->getValue()] = - ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet(); + It != ArgToArchMap.end() ? It->second : ArchitectureSet(); A->claim(); } for (const Arg *A : ParsedArgs.filtered(OPT_reexport_framework)) { + auto It = ArgToArchMap.find(A); LinkerOpts.ReexportedFrameworks[A->getValue()] = - ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet(); + It != ArgToArchMap.end() ? It->second : ArchitectureSet(); A->claim(); } for (const Arg *A : ParsedArgs.filtered(OPT_rpath)) { + auto It = ArgToArchMap.find(A); LinkerOpts.RPaths[A->getValue()] = - ArgToArchMap.count(A) ? ArgToArchMap[A] : ArchitectureSet(); + It != ArgToArchMap.end() ? It->second : ArchitectureSet(); A->claim(); } From 497506f6f454272e7c4921b3143768c6927738e4 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Tue, 11 Feb 2025 09:08:15 -0800 Subject: [PATCH 11/17] [Analysis] Avoid repeated hash lookups (NFC) (#126678) --- llvm/lib/Analysis/DDG.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Analysis/DDG.cpp b/llvm/lib/Analysis/DDG.cpp index a0774096c512..0907a7fb021f 100644 --- a/llvm/lib/Analysis/DDG.cpp +++ b/llvm/lib/Analysis/DDG.cpp @@ -241,9 +241,10 @@ bool DataDependenceGraph::addNode(DDGNode &N) { } const PiBlockDDGNode *DataDependenceGraph::getPiBlock(const NodeType &N) const { - if (!PiBlockMap.contains(&N)) + auto It = PiBlockMap.find(&N); + if (It == PiBlockMap.end()) return nullptr; - auto *Pi = PiBlockMap.find(&N)->second; + auto *Pi = It->second; assert(!PiBlockMap.contains(Pi) && "Nested pi-blocks detected."); return Pi; } From c9686d6904f24de8c63294dd708c9e0d0b4f7a47 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Tue, 11 Feb 2025 09:09:04 -0800 Subject: [PATCH 12/17] [SystemZ] Avoid repeated hash lookups (NFC) (#126679) --- llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp index d307c73a87fc..589dd8b63412 100644 --- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -688,16 +688,17 @@ void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) { int64_t SrcDisp = MI->getOperand(5).getImm(); SystemZTargetStreamer *TS = getTargetStreamer(); - MCSymbol *DotSym = nullptr; - MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg) - .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp); + MCInst ET = MCInstBuilder(TargetInsOpc) + .addReg(DestReg) + .addImm(DestDisp) + .addImm(1) + .addReg(SrcReg) + .addImm(SrcDisp); SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget()); - SystemZTargetStreamer::EXRLT2SymMap::iterator I = - TS->EXRLTargets2Sym.find(ET_STI); - if (I != TS->EXRLTargets2Sym.end()) - DotSym = I->second; - else - TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol(); + auto [It, Inserted] = TS->EXRLTargets2Sym.try_emplace(ET_STI); + if (Inserted) + It->second = OutContext.createTempSymbol(); + MCSymbol *DotSym = It->second; const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); EmitToStreamer( *OutStreamer, From 042e860a8a3a2e1be384a5de04b90607ce32e294 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Tue, 11 Feb 2025 09:09:43 -0800 Subject: [PATCH 13/17] [Vectorize] Avoid repeated hash lookups (NFC) (#126681) --- llvm/lib/Transforms/Vectorize/VPlan.h | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h index 3816e1b61576..fbbc466f2f7f 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -3709,18 +3709,16 @@ class VPlan { /// yet) for \p V. VPValue *getOrAddLiveIn(Value *V) { assert(V && "Trying to get or add the VPValue of a null Value"); - if (!Value2VPValue.count(V)) { + auto [It, Inserted] = Value2VPValue.try_emplace(V); + if (Inserted) { VPValue *VPV = new VPValue(V); VPLiveInsToFree.push_back(VPV); assert(VPV->isLiveIn() && "VPV must be a live-in."); - assert(!Value2VPValue.count(V) && "Value already exists in VPlan"); - Value2VPValue[V] = VPV; + It->second = VPV; } - assert(Value2VPValue.count(V) && "Value does not exist in VPlan"); - assert(Value2VPValue[V]->isLiveIn() && - "Only live-ins should be in mapping"); - return Value2VPValue[V]; + assert(It->second->isLiveIn() && "Only live-ins should be in mapping"); + return It->second; } /// Return the live-in VPValue for \p V, if there is one or nullptr otherwise. From cf87eb9d9b006ff28296e399dcc73d68bb187e91 Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Tue, 11 Feb 2025 18:11:23 +0100 Subject: [PATCH 14/17] [ValueTracking] Handle trunc to i1 as condition in dominating condition. (#126414) proof: https://alive2.llvm.org/ce/z/gALGmv --- llvm/lib/Analysis/ValueTracking.cpp | 24 ++++++++++++- .../test/Transforms/InstCombine/known-bits.ll | 36 +++++++------------ 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index fb744d61aad6..28d7e1ce401e 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -797,10 +797,28 @@ static void computeKnownBitsFromCond(const Value *V, Value *Cond, else Known2 = Known2.intersectWith(Known3); Known = Known.unionWith(Known2); + return; } - if (auto *Cmp = dyn_cast(Cond)) + if (auto *Cmp = dyn_cast(Cond)) { computeKnownBitsFromICmpCond(V, Cmp, Known, SQ, Invert); + return; + } + + if (match(Cond, m_Trunc(m_Specific(V)))) { + KnownBits DstKnown(1); + if (Invert) { + DstKnown.setAllZero(); + } else { + DstKnown.setAllOnes(); + } + if (cast(Cond)->hasNoUnsignedWrap()) { + Known = Known.unionWith(DstKnown.zext(Known.getBitWidth())); + return; + } + Known = Known.unionWith(DstKnown.anyext(Known.getBitWidth())); + return; + } if (Depth < MaxAnalysisRecursionDepth && match(Cond, m_Not(m_Value(A)))) computeKnownBitsFromCond(V, A, Known, Depth + 1, SQ, !Invert); @@ -10280,6 +10298,10 @@ void llvm::findValuesAffectedByCondition( m_Value()))) { // Handle patterns that computeKnownFPClass() support. AddAffected(A); + } else if (!IsAssume && match(V, m_Trunc(m_Value(X)))) { + // Assume is checked here as X is already added above for assumes in + // addValueAffectedByCondition + AddAffected(X); } else if (!IsAssume && match(V, m_Not(m_Value(X)))) { // Assume is checked here to avoid issues with ephemeral values Worklist.push_back(X); diff --git a/llvm/test/Transforms/InstCombine/known-bits.ll b/llvm/test/Transforms/InstCombine/known-bits.ll index b729cbd971ac..9a9fec694ff0 100644 --- a/llvm/test/Transforms/InstCombine/known-bits.ll +++ b/llvm/test/Transforms/InstCombine/known-bits.ll @@ -2167,11 +2167,9 @@ define i8 @test_trunc_and_1(i8 %a) { ; CHECK-NEXT: [[CAST:%.*]] = trunc i8 [[A:%.*]] to i1 ; CHECK-NEXT: br i1 [[CAST]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; CHECK: if.then: -; CHECK-NEXT: [[B:%.*]] = and i8 [[A]], 1 -; CHECK-NEXT: ret i8 [[B]] +; CHECK-NEXT: ret i8 1 ; CHECK: if.else: -; CHECK-NEXT: [[C:%.*]] = and i8 [[A]], 1 -; CHECK-NEXT: ret i8 [[C]] +; CHECK-NEXT: ret i8 0 ; entry: %cast = trunc i8 %a to i1 @@ -2192,11 +2190,9 @@ define i8 @test_not_trunc_and_1(i8 %a) { ; CHECK-NEXT: [[CAST:%.*]] = trunc i8 [[A:%.*]] to i1 ; CHECK-NEXT: br i1 [[CAST]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]] ; CHECK: if.then: -; CHECK-NEXT: [[B:%.*]] = and i8 [[A]], 1 -; CHECK-NEXT: ret i8 [[B]] +; CHECK-NEXT: ret i8 0 ; CHECK: if.else: -; CHECK-NEXT: [[C:%.*]] = and i8 [[A]], 1 -; CHECK-NEXT: ret i8 [[C]] +; CHECK-NEXT: ret i8 1 ; entry: %cast = trunc i8 %a to i1 @@ -2243,11 +2239,9 @@ define i8 @test_trunc_nuw_and_1(i8 %a) { ; CHECK-NEXT: [[CAST:%.*]] = trunc nuw i8 [[A:%.*]] to i1 ; CHECK-NEXT: br i1 [[CAST]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]] ; CHECK: if.then: -; CHECK-NEXT: [[B:%.*]] = and i8 [[A]], 1 -; CHECK-NEXT: ret i8 [[B]] +; CHECK-NEXT: ret i8 0 ; CHECK: if.else: -; CHECK-NEXT: [[C:%.*]] = and i8 [[A]], 1 -; CHECK-NEXT: ret i8 [[C]] +; CHECK-NEXT: ret i8 1 ; entry: %cast = trunc nuw i8 %a to i1 @@ -2268,11 +2262,9 @@ define i8 @test_trunc_nuw_or_2(i8 %a) { ; CHECK-NEXT: [[CAST:%.*]] = trunc nuw i8 [[A:%.*]] to i1 ; CHECK-NEXT: br i1 [[CAST]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]] ; CHECK: if.then: -; CHECK-NEXT: [[B:%.*]] = or i8 [[A]], 2 -; CHECK-NEXT: ret i8 [[B]] +; CHECK-NEXT: ret i8 2 ; CHECK: if.else: -; CHECK-NEXT: [[C:%.*]] = or i8 [[A]], 2 -; CHECK-NEXT: ret i8 [[C]] +; CHECK-NEXT: ret i8 3 ; entry: %cast = trunc nuw i8 %a to i1 @@ -2293,11 +2285,9 @@ define i8 @test_not_trunc_nuw_and_1(i8 %a) { ; CHECK-NEXT: [[CAST:%.*]] = trunc nuw i8 [[A:%.*]] to i1 ; CHECK-NEXT: br i1 [[CAST]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]] ; CHECK: if.then: -; CHECK-NEXT: [[B:%.*]] = and i8 [[A]], 1 -; CHECK-NEXT: ret i8 [[B]] +; CHECK-NEXT: ret i8 0 ; CHECK: if.else: -; CHECK-NEXT: [[C:%.*]] = and i8 [[A]], 1 -; CHECK-NEXT: ret i8 [[C]] +; CHECK-NEXT: ret i8 1 ; entry: %cast = trunc nuw i8 %a to i1 @@ -2319,8 +2309,7 @@ define i8 @test_trunc_cond_and(i8 %x, i1 %c) { ; CHECK-NEXT: [[COND:%.*]] = and i1 [[C:%.*]], [[CMP]] ; CHECK-NEXT: br i1 [[COND]], label [[IF:%.*]], label [[EXIT:%.*]] ; CHECK: if: -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[X]], -2 -; CHECK-NEXT: ret i8 [[OR1]] +; CHECK-NEXT: ret i8 -1 ; CHECK: exit: ; CHECK-NEXT: [[OR2:%.*]] = or i8 [[X]], -2 ; CHECK-NEXT: ret i8 [[OR2]] @@ -2345,8 +2334,7 @@ define i8 @test_not_trunc_cond_and(i8 %x, i1 %c) { ; CHECK-NEXT: [[COND:%.*]] = and i1 [[C:%.*]], [[NOT]] ; CHECK-NEXT: br i1 [[COND]], label [[IF:%.*]], label [[EXIT:%.*]] ; CHECK: if: -; CHECK-NEXT: [[OR1:%.*]] = or i8 [[X]], -2 -; CHECK-NEXT: ret i8 [[OR1]] +; CHECK-NEXT: ret i8 -2 ; CHECK: exit: ; CHECK-NEXT: [[OR2:%.*]] = or i8 [[X]], -2 ; CHECK-NEXT: ret i8 [[OR2]] From f574d8235371c4f28cad8e800d99bcb7ad579b7d Mon Sep 17 00:00:00 2001 From: Sharjeel Khan Date: Tue, 11 Feb 2025 12:11:40 -0500 Subject: [PATCH 15/17] [Clang][Driver][HIP] Fix test for HIP as it was failing (#126585) This PR #125646 added this test and it was failing in Android's compiler and on my machine locally. I removed the "Build config" check and it passes now. --- .../test/Driver/dep-file-flag-with-multiple-offload-archs.hip | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/test/Driver/dep-file-flag-with-multiple-offload-archs.hip b/clang/test/Driver/dep-file-flag-with-multiple-offload-archs.hip index 79a52f0bc898..f17e56acfb7f 100644 --- a/clang/test/Driver/dep-file-flag-with-multiple-offload-archs.hip +++ b/clang/test/Driver/dep-file-flag-with-multiple-offload-archs.hip @@ -1,6 +1,5 @@ -// RUN: %clang -### -nogpuinc -nogpulib --offload-arch=gfx1030 --offload-arch=gfx1100 --offload-arch=gfx1101 -MD -MF tmp.d %s 2>&1 | FileCheck %s +// RUN: %clang -### -nogpuinc -nogpulib --offload-arch=gfx1030 --offload-arch=gfx1100 --offload-arch=gfx1101 --target=x86_64-linux-gnu -MD -MF tmp.d %s 2>&1 | FileCheck %s -// CHECK: Build config: // CHECK-NOT: {{.*}}clang{{.*}}"-target-cpu" "gfx1030"{{.*}}"-dependency-file" "tmp.d" // CHECK: {{.*}}lld{{.*}}"-plugin-opt=mcpu=gfx1030" // CHECK-NOT: {{.*}}clang{{.*}}"-target-cpu" "gfx1100"{{.*}}"-dependency-file" "tmp.d" From c3d8c625af8ebbf8a9af035c18ec4e1cb1d8d2f3 Mon Sep 17 00:00:00 2001 From: Razvan Lupusoru Date: Tue, 11 Feb 2025 09:16:59 -0800 Subject: [PATCH 16/17] [flang][acc] Fill-in name for privatized loop iv (#126601) When the loop induction variable implicit private clause was being generated, the name was left empty. The intent is that the data clause operation holds the source language variable name. Thus, add the missing name now. --- flang/lib/Lower/OpenACC.cpp | 1 + flang/test/Lower/OpenACC/acc-loop.f90 | 6 +++--- .../test/Lower/OpenACC/acc-private-unwrap-defaultbounds.f90 | 2 +- flang/test/Lower/OpenACC/acc-private.f90 | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index a11a2c824bf9..3dd35ed9ae48 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -1803,6 +1803,7 @@ static void privatizeIv(Fortran::lower::AbstractConverter &converter, builder, recipeName, loc, ivValue.getType()); std::stringstream asFortran; + asFortran << Fortran::lower::mangle::demangleName(toStringRef(sym.name())); auto op = createDataEntryOp( builder, loc, ivValue, asFortran, {}, true, /*implicit=*/true, mlir::acc::DataClause::acc_private, ivValue.getType(), diff --git a/flang/test/Lower/OpenACC/acc-loop.f90 b/flang/test/Lower/OpenACC/acc-loop.f90 index d65ca538bf60..f77aefcc2c31 100644 --- a/flang/test/Lower/OpenACC/acc-loop.f90 +++ b/flang/test/Lower/OpenACC/acc-loop.f90 @@ -321,8 +321,8 @@ subroutine sub1(i, j, k) ! CHECK: %[[DC_K:.*]] = fir.alloca i32 {bindc_name = "k"} ! CHECK: %[[DC_J:.*]] = fir.alloca i32 {bindc_name = "j"} ! CHECK: %[[DC_I:.*]] = fir.alloca i32 {bindc_name = "i"} -! CHECK: %[[P_I:.*]] = acc.private varPtr(%[[DC_I]] : !fir.ref) -> !fir.ref {implicit = true, name = ""} -! CHECK: %[[P_J:.*]] = acc.private varPtr(%[[DC_J]] : !fir.ref) -> !fir.ref {implicit = true, name = ""} -! CHECK: %[[P_K:.*]] = acc.private varPtr(%[[DC_K]] : !fir.ref) -> !fir.ref {implicit = true, name = ""} +! CHECK: %[[P_I:.*]] = acc.private varPtr(%[[DC_I]] : !fir.ref) -> !fir.ref {implicit = true, name = "i"} +! CHECK: %[[P_J:.*]] = acc.private varPtr(%[[DC_J]] : !fir.ref) -> !fir.ref {implicit = true, name = "j"} +! CHECK: %[[P_K:.*]] = acc.private varPtr(%[[DC_K]] : !fir.ref) -> !fir.ref {implicit = true, name = "k"} ! CHECK: acc.loop combined(parallel) private(@privatization_ref_i32 -> %[[P_I]] : !fir.ref, @privatization_ref_i32 -> %[[P_J]] : !fir.ref, @privatization_ref_i32 -> %[[P_K]] : !fir.ref) control(%{{.*}} : i32, %{{.*}} : i32, %{{.*}} : i32) = (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) to (%c10{{.*}}, %c100{{.*}}, %c200{{.*}} : i32, i32, i32) step (%c1{{.*}}, %c1{{.*}}, %c1{{.*}} : i32, i32, i32) ! CHECK: } attributes {inclusiveUpperbound = array} diff --git a/flang/test/Lower/OpenACC/acc-private-unwrap-defaultbounds.f90 b/flang/test/Lower/OpenACC/acc-private-unwrap-defaultbounds.f90 index febb933e9897..d86f82dae8d0 100644 --- a/flang/test/Lower/OpenACC/acc-private-unwrap-defaultbounds.f90 +++ b/flang/test/Lower/OpenACC/acc-private-unwrap-defaultbounds.f90 @@ -396,7 +396,7 @@ subroutine acc_private_use() ! CHECK: %[[I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFacc_private_useEi"} ! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %0 {uniq_name = "_QFacc_private_useEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.parallel -! CHECK: %[[PRIV_I:.*]] = acc.private varPtr(%[[DECL_I]]#1 : !fir.ref) -> !fir.ref {implicit = true, name = ""} +! CHECK: %[[PRIV_I:.*]] = acc.private varPtr(%[[DECL_I]]#1 : !fir.ref) -> !fir.ref {implicit = true, name = "i"} ! CHECK: %[[DECL_PRIV_I:.*]]:2 = hlfir.declare %[[PRIV_I]] {uniq_name = "_QFacc_private_useEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.loop {{.*}} private(@privatization_ref_i32 -> %[[PRIV_I]] : !fir.ref) control(%[[IV0:.*]] : i32) = (%c1{{.*}} : i32) to (%c10{{.*}} : i32) step (%c1{{.*}} : i32) ! CHECK: fir.store %[[IV0]] to %[[DECL_PRIV_I]]#0 : !fir.ref diff --git a/flang/test/Lower/OpenACC/acc-private.f90 b/flang/test/Lower/OpenACC/acc-private.f90 index 99e3b223c857..c86da8c001b5 100644 --- a/flang/test/Lower/OpenACC/acc-private.f90 +++ b/flang/test/Lower/OpenACC/acc-private.f90 @@ -384,7 +384,7 @@ subroutine acc_private_use() ! CHECK: %[[I:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFacc_private_useEi"} ! CHECK: %[[DECL_I:.*]]:2 = hlfir.declare %0 {uniq_name = "_QFacc_private_useEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.parallel -! CHECK: %[[PRIV_I:.*]] = acc.private varPtr(%[[DECL_I]]#1 : !fir.ref) -> !fir.ref {implicit = true, name = ""} +! CHECK: %[[PRIV_I:.*]] = acc.private varPtr(%[[DECL_I]]#1 : !fir.ref) -> !fir.ref {implicit = true, name = "i"} ! CHECK: %[[DECL_PRIV_I:.*]]:2 = hlfir.declare %[[PRIV_I]] {uniq_name = "_QFacc_private_useEi"} : (!fir.ref) -> (!fir.ref, !fir.ref) ! CHECK: acc.loop {{.*}} private(@privatization_ref_i32 -> %[[PRIV_I]] : !fir.ref) control(%[[IV0:.*]] : i32) = (%c1{{.*}} : i32) to (%c10{{.*}} : i32) step (%c1{{.*}} : i32) ! CHECK: fir.store %[[IV0]] to %[[DECL_PRIV_I]]#0 : !fir.ref From 75cb5633844deb4e0c6a5c7bdf84013b563818d3 Mon Sep 17 00:00:00 2001 From: Ilia Kuklin Date: Tue, 11 Feb 2025 22:17:52 +0500 Subject: [PATCH 17/17] [clang][Sema] Move computing enum bits into a separate function (#126096) Move the code that computes `NumNegativeBits` and `NumPositiveBits` for an enum to a separate function in `ASTContext.h`. This function needs to be called from LLDB as well (#115005) --- clang/include/clang/AST/ASTContext.h | 41 +++++++++++++++++++++ clang/lib/AST/ASTContext.cpp | 13 +++++++ clang/lib/Sema/SemaDecl.cpp | 54 +++------------------------- 3 files changed, 59 insertions(+), 49 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 65be782c1ba4..a96b9c0a1704 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -1733,6 +1733,47 @@ class ASTContext : public RefCountedBase { unsigned NumPositiveBits, QualType &BestType, QualType &BestPromotionType); + /// Determine whether the given integral value is representable within + /// the given type T. + bool isRepresentableIntegerValue(llvm::APSInt &Value, QualType T); + + /// Compute NumNegativeBits and NumPositiveBits for an enum based on + /// the constant values of its enumerators. + template + bool computeEnumBits(RangeT EnumConstants, unsigned &NumNegativeBits, + unsigned &NumPositiveBits) { + NumNegativeBits = 0; + NumPositiveBits = 0; + bool MembersRepresentableByInt = true; + for (auto *Elem : EnumConstants) { + EnumConstantDecl *ECD = cast_or_null(Elem); + if (!ECD) + continue; // Already issued a diagnostic. + + llvm::APSInt InitVal = ECD->getInitVal(); + if (InitVal.isUnsigned() || InitVal.isNonNegative()) { + // If the enumerator is zero that should still be counted as a positive + // bit since we need a bit to store the value zero. + unsigned ActiveBits = InitVal.getActiveBits(); + NumPositiveBits = std::max({NumPositiveBits, ActiveBits, 1u}); + } else { + NumNegativeBits = + std::max(NumNegativeBits, (unsigned)InitVal.getSignificantBits()); + } + + MembersRepresentableByInt &= isRepresentableIntegerValue(InitVal, IntTy); + } + + // If we have an empty set of enumerators we still need one bit. + // From [dcl.enum]p8 + // If the enumerator-list is empty, the values of the enumeration are as if + // the enumeration had a single enumerator with value 0 + if (!NumPositiveBits && !NumNegativeBits) + NumPositiveBits = 1; + + return MembersRepresentableByInt; + } + QualType getUnresolvedUsingType(const UnresolvedUsingTypenameDecl *Decl) const; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index e3b44bdbe3dc..b1b9d56ccca9 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -5320,6 +5320,19 @@ bool ASTContext::computeBestEnumTypes(bool IsPacked, unsigned NumNegativeBits, return EnumTooLarge; } +bool ASTContext::isRepresentableIntegerValue(llvm::APSInt &Value, QualType T) { + assert((T->isIntegralType(*this) || T->isEnumeralType()) && + "Integral type required!"); + unsigned BitWidth = getIntWidth(T); + + if (Value.isUnsigned() || Value.isNonNegative()) { + if (T->isSignedIntegerOrEnumerationType()) + --BitWidth; + return Value.getActiveBits() <= BitWidth; + } + return Value.getSignificantBits() <= BitWidth; +} + QualType ASTContext::getUnresolvedUsingType( const UnresolvedUsingTypenameDecl *Decl) const { if (Decl->TypeForDecl) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 74e0fcec2d91..6eedc77ed20a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -19633,23 +19633,6 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, ProcessAPINotes(Record); } -/// Determine whether the given integral value is representable within -/// the given type T. -static bool isRepresentableIntegerValue(ASTContext &Context, - llvm::APSInt &Value, - QualType T) { - assert((T->isIntegralType(Context) || T->isEnumeralType()) && - "Integral type required!"); - unsigned BitWidth = Context.getIntWidth(T); - - if (Value.isUnsigned() || Value.isNonNegative()) { - if (T->isSignedIntegerOrEnumerationType()) - --BitWidth; - return Value.getActiveBits() <= BitWidth; - } - return Value.getSignificantBits() <= BitWidth; -} - // Given an integral type, return the next larger integral type // (or a NULL type of no such type exists). static QualType getNextLargerIntegralType(ASTContext &Context, QualType T) { @@ -19723,7 +19706,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, // representable in the underlying type of the enumeration. In C++11, // we perform a non-narrowing conversion as part of converted constant // expression checking. - if (!isRepresentableIntegerValue(Context, EnumVal, EltTy)) { + if (!Context.isRepresentableIntegerValue(EnumVal, EltTy)) { if (Context.getTargetInfo() .getTriple() .isWindowsMSVCEnvironment()) { @@ -19752,7 +19735,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, // representable as an int. // Complain if the value is not representable in an int. - if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy)) { + if (!Context.isRepresentableIntegerValue(EnumVal, Context.IntTy)) { Diag(IdLoc, getLangOpts().C23 ? diag::warn_c17_compat_enum_value_not_int : diag::ext_c23_enum_value_not_int) @@ -19844,7 +19827,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, : diag::ext_c23_enum_value_not_int) << 1 << toString(EnumVal, 10) << 1; } else if (!getLangOpts().CPlusPlus && !EltTy->isDependentType() && - !isRepresentableIntegerValue(Context, EnumVal, EltTy)) { + !Context.isRepresentableIntegerValue(EnumVal, EltTy)) { // Enforce C99 6.7.2.2p2 even when we compute the next value. Diag(IdLoc, getLangOpts().C23 ? diag::warn_c17_compat_enum_value_not_int : diag::ext_c23_enum_value_not_int) @@ -20171,35 +20154,8 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, // reverse the list. unsigned NumNegativeBits = 0; unsigned NumPositiveBits = 0; - bool MembersRepresentableByInt = true; - - for (unsigned i = 0, e = Elements.size(); i != e; ++i) { - EnumConstantDecl *ECD = - cast_or_null(Elements[i]); - if (!ECD) continue; // Already issued a diagnostic. - - llvm::APSInt InitVal = ECD->getInitVal(); - - // Keep track of the size of positive and negative values. - if (InitVal.isUnsigned() || InitVal.isNonNegative()) { - // If the enumerator is zero that should still be counted as a positive - // bit since we need a bit to store the value zero. - unsigned ActiveBits = InitVal.getActiveBits(); - NumPositiveBits = std::max({NumPositiveBits, ActiveBits, 1u}); - } else { - NumNegativeBits = - std::max(NumNegativeBits, (unsigned)InitVal.getSignificantBits()); - } - MembersRepresentableByInt &= - isRepresentableIntegerValue(Context, InitVal, Context.IntTy); - } - - // If we have an empty set of enumerators we still need one bit. - // From [dcl.enum]p8 - // If the enumerator-list is empty, the values of the enumeration are as if - // the enumeration had a single enumerator with value 0 - if (!NumPositiveBits && !NumNegativeBits) - NumPositiveBits = 1; + bool MembersRepresentableByInt = + Context.computeEnumBits(Elements, NumNegativeBits, NumPositiveBits); // Figure out the type that should be used for this enum. QualType BestType;