parent
							
								
									4a18aa41ee
								
							
						
					
					
						commit
						7a983ea389
					
				|  | @ -1201,6 +1201,8 @@ def HLO_PadOp: HLO_Op<"pad", | |||
| 
 | ||||
|   // TODO(b/129422361): PadOp has a custom constructor for HLO. | ||||
|   let hasCustomHLOConverter = 1; | ||||
| 
 | ||||
|   let hasFolder = 1; | ||||
| } | ||||
| 
 | ||||
| def HLO_TraceOp: HLO_Op<"trace", []>, BASE_HLO_TraceOp { | ||||
|  |  | |||
|  | @ -1787,6 +1787,61 @@ static LogicalResult Verify(PadOp op) { | |||
|   return success(); | ||||
| } | ||||
| 
 | ||||
| OpFoldResult PadOp::fold(ArrayRef<Attribute> operands) { | ||||
|   // If all padding is zero then it is an identity pad.
 | ||||
|   auto is_zero = [](const APInt& i) { return i == 0; }; | ||||
|   if (llvm::all_of(edge_padding_low().getIntValues(), is_zero) && | ||||
|       llvm::all_of(edge_padding_high().getIntValues(), is_zero) && | ||||
|       llvm::all_of(interior_padding().getIntValues(), is_zero)) | ||||
|     return operand(); | ||||
| 
 | ||||
|   // If any padding is negative then it isn't supported by the folder (yet).
 | ||||
|   auto is_negative = [](const APInt& i) { return i.slt(0); }; | ||||
|   if (llvm::all_of(edge_padding_low().getIntValues(), is_negative) && | ||||
|       llvm::all_of(edge_padding_high().getIntValues(), is_negative) && | ||||
|       llvm::all_of(interior_padding().getIntValues(), is_negative)) | ||||
|     return {}; | ||||
| 
 | ||||
|   DenseElementsAttr input = operands[0].dyn_cast_or_null<DenseElementsAttr>(); | ||||
|   DenseElementsAttr padding = operands[1].dyn_cast_or_null<DenseElementsAttr>(); | ||||
|   RankedTensorType return_type = getType().dyn_cast_or_null<RankedTensorType>(); | ||||
|   if (!input || !input.getType().hasRank() || !padding || !return_type || | ||||
|       !return_type.hasStaticShape()) | ||||
|     return {}; | ||||
| 
 | ||||
|   // Fill the full result tensor with the padding value.
 | ||||
|   llvm::SmallVector<Attribute, 4> result(return_type.getNumElements(), | ||||
|                                          padding.getValue({})); | ||||
| 
 | ||||
|   auto next_index = [](llvm::SmallVector<uint64_t, 8>& index, | ||||
|                        llvm::ArrayRef<int64_t> shape) { | ||||
|     for (int64_t i = index.size() - 1; i >= 0; --i) { | ||||
|       ++index[i]; | ||||
|       if (index[i] < shape[i]) return true; | ||||
|       index[i] = 0; | ||||
|     } | ||||
|     return false; | ||||
|   }; | ||||
| 
 | ||||
|   // Iterate over all elements of the input tensor and copy it to the correct
 | ||||
|   // location in the output tensor.
 | ||||
|   llvm::SmallVector<uint64_t, 8> index(input.getType().getRank(), 0); | ||||
|   do { | ||||
|     uint64_t linear_index = 0; | ||||
|     uint64_t linear_index_multiplyer = 1; | ||||
|     for (int64_t i = index.size() - 1; i >= 0; --i) { | ||||
|       linear_index += | ||||
|           (edge_padding_low().getValue<int64_t>({uint64_t(i)}) + | ||||
|            index[i] * | ||||
|                (interior_padding().getValue<int64_t>({uint64_t(i)}) + 1)) * | ||||
|           linear_index_multiplyer; | ||||
|       linear_index_multiplyer *= return_type.getShape()[i]; | ||||
|     } | ||||
|     result[linear_index] = input.getValue(index); | ||||
|   } while (next_index(index, input.getType().getShape())); | ||||
|   return DenseElementsAttr::get(return_type, result); | ||||
| } | ||||
| 
 | ||||
| //===----------------------------------------------------------------------===//
 | ||||
| // ReshapeOp
 | ||||
| //===----------------------------------------------------------------------===//
 | ||||
|  |  | |||
|  | @ -1437,3 +1437,29 @@ func @scatter_out_of_bound() -> tensor<3x3xi32> { | |||
|   // CHECK: "mhlo.scatter" | ||||
| } | ||||
| 
 | ||||
| // CHECK-LABEL: @pad_identity_fold | ||||
| func @pad_identity_fold(%arg0: tensor<5x7xf32>) -> tensor<5x7xf32> { | ||||
|   %0 = constant dense<0.0> : tensor<f32> | ||||
|   %1 = "mhlo.pad"(%arg0, %0) { | ||||
|     edge_padding_low = dense<0> : tensor<2xi64>, | ||||
|     edge_padding_high = dense<0> : tensor<2xi64>, | ||||
|     interior_padding = dense<0> : tensor<2xi64> | ||||
|   } : (tensor<5x7xf32>, tensor<f32>) -> tensor<5x7xf32> | ||||
|   return %1 : tensor<5x7xf32> | ||||
|   // CHECK: return %arg0 : tensor<5x7xf32> | ||||
| } | ||||
| 
 | ||||
| // CHECK-LABEL: @pad_fold | ||||
| func @pad_fold() -> tensor<4x5xi32> { | ||||
|   %0 = constant dense<[[2, 3], [4, 5]]> : tensor<2x2xi32> | ||||
|   %1 = constant dense<1> : tensor<i32> | ||||
|   %3 = "mhlo.pad"(%0, %1) { | ||||
|     edge_padding_low = dense<[1, 0]> : tensor<2xi64>, | ||||
|     edge_padding_high = dense<[1, 2]> : tensor<2xi64>, | ||||
|     interior_padding = dense<[0, 1]> : tensor<2xi64> | ||||
|   } : (tensor<2x2xi32>, tensor<i32>) -> tensor<4x5xi32> | ||||
|   return %3 : tensor<4x5xi32> | ||||
|   // CHECK: constant dense<[ | ||||
|   // CHECK-SAME: [1, 1, 1, 1, 1], [2, 1, 3, 1, 1], [4, 1, 5, 1, 1], [1, 1, 1, 1, 1] | ||||
|   // CHECK-SAME: ]> : tensor<4x5xi32> | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue