diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -534,6 +534,7 @@ let builders = [LLVM_OneResultOpBuilder]; let parser = [{ return parseExtractValueOp(parser, result); }]; let printer = [{ printExtractValueOp(p, *this); }]; + let hasFolder = 1; } def LLVM_InsertElementOp : LLVM_Op<"insertelement", [NoSideEffect]> { let arguments = (ins LLVM_AnyVector:$vector, LLVM_PrimitiveType:$value, diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -1050,6 +1050,16 @@ return success(); } +OpFoldResult LLVM::ExtractValueOp::fold(ArrayRef operands) { + auto insertValueOp = container().getDefiningOp(); + while (insertValueOp) { + if (position() == insertValueOp.position()) + return insertValueOp.value(); + insertValueOp = insertValueOp.container().getDefiningOp(); + } + return {}; +} + //===----------------------------------------------------------------------===// // Printing/parsing for LLVM::InsertElementOp. //===----------------------------------------------------------------------===// diff --git a/mlir/test/Dialect/LLVMIR/canonicalize.mlir b/mlir/test/Dialect/LLVMIR/canonicalize.mlir new file mode 100644 --- /dev/null +++ b/mlir/test/Dialect/LLVMIR/canonicalize.mlir @@ -0,0 +1,23 @@ +// RUN: mlir-opt -canonicalize %s -split-input-file | FileCheck %s + +// CHECK-LABEL: fold_extractvalue +llvm.func @fold_extractvalue() -> i32 { + // CHECK: %[[C0:.*]] = constant 0 : i32 + %c0 = constant 0 : i32 + // CHECK: %[[C1:.*]] = constant 1 : i32 + %c1 = constant 1 : i32 + + %0 = llvm.mlir.undef : !llvm.struct<(i32, i32)> + + // CHECK-NOT: insertvalue + %1 = llvm.insertvalue %c0, %0[0] : !llvm.struct<(i32, i32)> + %2 = llvm.insertvalue %c1, %1[1] : !llvm.struct<(i32, i32)> + + // CHECK-NOT: extractvalue + %3 = llvm.extractvalue %2[0] : !llvm.struct<(i32, i32)> + %4 = llvm.extractvalue %2[1] : !llvm.struct<(i32, i32)> + + // CHECK: llvm.add %[[C0]], %[[C1]] + %5 = llvm.add %3, %4 : i32 + llvm.return %5 : i32 +}