[Flow] Fix TensorSliceOp::fold for parameter attributes (#24762)

[Flow] Fix tensor folding for parameter attributes
    
TensorSliceOp::fold and TensorUpdateOp::fold assume that fully folded
tensor operands are ElementsAttr values. However, #flow.parameter.named
    folds to a parameter attribute instead, resulting in invalid casts.
    
Skip folding when the required operands are not ElementsAttr values and
add regression coverage for slicing and updating parameter-backed tensors.
    
Fixes #24751

Signed-off-by: zhangpan <98025960+zhangpan2001@users.noreply.github.com>
diff --git a/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOpFolders.cpp b/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOpFolders.cpp
index 311120f..bea682a 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOpFolders.cpp
+++ b/compiler/src/iree/compiler/Dialect/Flow/IR/FlowOpFolders.cpp
@@ -1023,7 +1023,10 @@
       return {};
     }
     // Fully constant arguments so we can perform the slice here.
-    auto tensor = cast<ElementsAttr>(operands.getSource());
+    auto tensor = dyn_cast<ElementsAttr>(operands.getSource());
+    if (!tensor) {
+      return {};
+    }
     int64_t rank = cast<ShapedType>(getSource().getType()).getRank();
     auto start =
         llvm::map_to_vector(operands.getStartIndices(), [](Attribute value) {
@@ -1153,9 +1156,12 @@
       llvm::count(operands.getStartIndices(), nullptr) == 0;
   if (operands.getUpdate() && operands.getTarget() && allIndicesConstant) {
     // Fully constant arguments so we can perform the update here.
-    return tensorUpdate(cast<ElementsAttr>(operands.getUpdate()),
-                        cast<ElementsAttr>(operands.getTarget()),
-                        operands.getStartIndices());
+    auto update = dyn_cast<ElementsAttr>(operands.getUpdate());
+    auto target = dyn_cast<ElementsAttr>(operands.getTarget());
+    if (!update || !target) {
+      return {};
+    }
+    return tensorUpdate(update, target, operands.getStartIndices());
   } else {
     // Replace the entire tensor when the sizes match.
     auto updateType = cast<ShapedType>(getUpdate().getType());
diff --git a/compiler/src/iree/compiler/Dialect/Flow/IR/test/tensor_folding.mlir b/compiler/src/iree/compiler/Dialect/Flow/IR/test/tensor_folding.mlir
index af7731f..aa69163 100644
--- a/compiler/src/iree/compiler/Dialect/Flow/IR/test/tensor_folding.mlir
+++ b/compiler/src/iree/compiler/Dialect/Flow/IR/test/tensor_folding.mlir
@@ -690,6 +690,21 @@
 
 // -----
 
+// CHECK-LABEL: @noFoldSliceParameterAttr
+util.func public @noFoldSliceParameterAttr() -> tensor<16xf32> {
+  // CHECK: %[[C:.+]] = flow.tensor.constant #flow.parameter.named<"m"::"w"> : tensor<20xf32>
+  %0 = flow.tensor.constant #flow.parameter.named<"m"::"w"> : tensor<20xf32>
+  %c0 = arith.constant 0 : index
+  %c16 = arith.constant 16 : index
+  // CHECK: %[[S:.+]] = flow.tensor.slice %[[C]]
+  // CHECK-SAME:             : tensor<20xf32> -> tensor<16xf32>
+  %1 = flow.tensor.slice %0[%c0 for %c16] : tensor<20xf32> -> tensor<16xf32>
+  // CHECK-NEXT: util.return %[[S]]
+  util.return %1 : tensor<16xf32>
+}
+
+// -----
+
 // CHECK-LABEL: @sliceOfSliceStatic2D
 util.func public @sliceOfSliceStatic2D(%src: tensor<3x3xf32>) -> tensor<1x1xf32> {
   %c0 = arith.constant 0 : index
@@ -857,6 +872,21 @@
 
 // -----
 
+// CHECK-LABEL: @noFoldUpdateParameterAttr
+util.func public @noFoldUpdateParameterAttr() -> tensor<4xf32> {
+  // CHECK: %[[UPDATE:.+]] = flow.tensor.constant dense<1.000000e+00> : tensor<1xf32>
+  %0 = flow.tensor.constant dense<1.0> : tensor<1xf32>
+  // CHECK: %[[TARGET:.+]] = flow.tensor.constant #flow.parameter.named<"m"::"w"> : tensor<4xf32>
+  %1 = flow.tensor.constant #flow.parameter.named<"m"::"w"> : tensor<4xf32>
+  %c0 = arith.constant 0 : index
+  // CHECK: %[[RESULT:.+]] = flow.tensor.update %[[UPDATE]], %[[TARGET]]
+  %2 = flow.tensor.update %0, %1[%c0] : tensor<1xf32> -> tensor<4xf32>
+  // CHECK-NEXT: util.return %[[RESULT]]
+  util.return %2 : tensor<4xf32>
+}
+
+// -----
+
 // CHECK-LABEL: @updateReplace
 util.func public @updateReplace(%arg0 : tensor<4xi32>, %arg1 : tensor<4xi32>) -> tensor<4xi32> {
   %c0 = arith.constant 0 : index