diff --git a/flang/include/flang/Optimizer/CodeGen/CGOps.td b/flang/include/flang/Optimizer/CodeGen/CGOps.td --- a/flang/include/flang/Optimizer/CodeGen/CGOps.td +++ b/flang/include/flang/Optimizer/CodeGen/CGOps.td @@ -42,6 +42,7 @@ The default is a vector of the value 1. - slice: A vector of triples that describe an array slice. - subcomponent: A vector of indices for subobject slicing. + - substring: A substring operator (offset, length) for CHARACTER. - LEN type parameters: A vector of runtime LEN type parameters that describe an correspond to the elemental derived type. @@ -54,14 +55,15 @@ Variadic:$shift, Variadic:$slice, Variadic:$subcomponent, + Variadic:$substr, Variadic:$lenParams ); let results = (outs fir_BoxType); let assemblyFormat = [{ $memref (`(`$shape^`)`)? (`origin` $shift^)? (`[`$slice^`]`)? - (`path` $subcomponent^)? (`typeparams` $lenParams^)? attr-dict - `:` functional-type(operands, results) + (`path` $subcomponent^)? (`substr` $substr^)? (`typeparams` $lenParams^)? + attr-dict `:` functional-type(operands, results) }]; let extraClassDeclaration = [{ @@ -76,9 +78,10 @@ unsigned shiftOffset() { return shapeOffset() + shape().size(); } unsigned sliceOffset() { return shiftOffset() + shift().size(); } unsigned subcomponentOffset() { return sliceOffset() + slice().size(); } - unsigned lenParamOffset() { - return subcomponentOffset() + subcomponent().size(); + unsigned substrOffset() { + return subcomponentOffset() + subcomponent().size(); } + unsigned lenParamOffset() { return substrOffset() + substr().size(); } }]; } @@ -97,6 +100,7 @@ The default is a vector of the value 1. - slice: A vector of triples that describe an array slice. - subcomponent: A vector of indices for subobject slicing. + - substring: A substring operator (offset, length) for CHARACTER. The box argument is mandatory, the other arguments are optional. There must not both be a shape and slice/subcomponent arguments @@ -107,14 +111,15 @@ Variadic:$shape, Variadic:$shift, Variadic:$slice, - Variadic:$subcomponent + Variadic:$subcomponent, + Variadic:$substr ); let results = (outs fir_BoxType); let assemblyFormat = [{ $box (`(`$shape^`)`)? (`origin` $shift^)? (`[`$slice^`]`)? - (`path` $subcomponent^) ? attr-dict - `:` functional-type(operands, results) + (`path` $subcomponent^)? (`substr` $substr^)? attr-dict `:` + functional-type(operands, results) }]; let extraClassDeclaration = [{ diff --git a/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp b/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp --- a/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp +++ b/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp @@ -102,7 +102,7 @@ } auto xbox = rewriter.create( loc, embox.getType(), embox.memref(), shapeOpers, llvm::None, - llvm::None, llvm::None, embox.typeparams()); + llvm::None, llvm::None, llvm::None, embox.typeparams()); LLVM_DEBUG(llvm::dbgs() << "rewriting " << embox << " to " << xbox << '\n'); rewriter.replaceOp(embox, xbox.getOperation()->getResults()); return mlir::success(); @@ -124,14 +124,16 @@ } llvm::SmallVector sliceOpers; llvm::SmallVector subcompOpers; + llvm::SmallVector substrOpers; if (auto s = embox.getSlice()) if (auto sliceOp = dyn_cast_or_null(s.getDefiningOp())) { - sliceOpers.append(sliceOp.triples().begin(), sliceOp.triples().end()); - subcompOpers.append(sliceOp.fields().begin(), sliceOp.fields().end()); + sliceOpers.assign(sliceOp.triples().begin(), sliceOp.triples().end()); + subcompOpers.assign(sliceOp.fields().begin(), sliceOp.fields().end()); + substrOpers.assign(sliceOp.substr().begin(), sliceOp.substr().end()); } auto xbox = rewriter.create( loc, embox.getType(), embox.memref(), shapeOpers, shiftOpers, - sliceOpers, subcompOpers, embox.typeparams()); + sliceOpers, subcompOpers, substrOpers, embox.typeparams()); LLVM_DEBUG(llvm::dbgs() << "rewriting " << embox << " to " << xbox << '\n'); rewriter.replaceOp(embox, xbox.getOperation()->getResults()); return mlir::success(); @@ -172,15 +174,17 @@ } llvm::SmallVector sliceOpers; llvm::SmallVector subcompOpers; + llvm::SmallVector substrOpers; if (auto s = rebox.slice()) if (auto sliceOp = dyn_cast_or_null(s.getDefiningOp())) { sliceOpers.append(sliceOp.triples().begin(), sliceOp.triples().end()); subcompOpers.append(sliceOp.fields().begin(), sliceOp.fields().end()); + substrOpers.append(sliceOp.substr().begin(), sliceOp.substr().end()); } auto xRebox = rewriter.create( loc, rebox.getType(), rebox.box(), shapeOpers, shiftOpers, sliceOpers, - subcompOpers); + subcompOpers, substrOpers); LLVM_DEBUG(llvm::dbgs() << "rewriting " << rebox << " to " << xRebox << '\n'); rewriter.replaceOp(rebox, xRebox.getOperation()->getResults()); @@ -227,6 +231,9 @@ if (auto sliceOp = dyn_cast_or_null(s.getDefiningOp())) { sliceOpers.append(sliceOp.triples().begin(), sliceOp.triples().end()); subcompOpers.append(sliceOp.fields().begin(), sliceOp.fields().end()); + assert(sliceOp.substr().empty() && + "Don't allow substring operations on array_coor. This " + "restriction may be lifted in the future."); } auto xArrCoor = rewriter.create( loc, arrCoor.getType(), arrCoor.memref(), shapeOpers, shiftOpers, diff --git a/flang/test/Fir/cg-ops.fir b/flang/test/Fir/cg-ops.fir --- a/flang/test/Fir/cg-ops.fir +++ b/flang/test/Fir/cg-ops.fir @@ -1,4 +1,4 @@ -// RUN: fir-opt --pass-pipeline="builtin.func(cg-rewrite),fir.global(cg-rewrite),cse" %s | FileCheck %s +// RUN: fir-opt --split-input-file --pass-pipeline="cg-rewrite,cse" %s | FileCheck %s // CHECK-LABEL: func @codegen( // CHECK-SAME: %[[arg:.*]]: !fir @@ -16,6 +16,8 @@ return } +// ----- + // CHECK-LABEL: fir.global @box_global fir.global @box_global : !fir.box> { // CHECK: %[[arr:.*]] = fir.zero_bits !fir.ref @@ -28,3 +30,37 @@ %3 = fir.embox %arr (%1) [%2] : (!fir.ref>, !fir.shapeshift<1>, !fir.slice<1>) -> !fir.box> fir.has_value %3 : !fir.box> } + +// ----- + +// fir.embox with slice with substr + +// CHECK-LABEL: func @codegen( +// CHECK-SAME: %[[arg:.*]]: !fir +func @codegen(%addr : !fir.ref>) { + // CHECK: %[[zero:.*]] = arith.constant 0 : index + %0 = arith.constant 0 : index + %1 = fir.shape_shift %0, %0 : (index, index) -> !fir.shapeshift<1> + %2 = fir.slice %0, %0, %0 substr %0, %0: (index, index, index, index, index) -> !fir.slice<1> + // CHECK: %[[box:.*]] = fircg.ext_embox %[[arg]](%[[zero]]) origin %[[zero]][%[[zero]], %[[zero]], %[[zero]]] substr %[[zero]], %[[zero]] : (!fir.ref>, index, index, index, index, index, index, index) -> !fir.box> + %3 = fir.embox %addr (%1) [%2] : (!fir.ref>, !fir.shapeshift<1>, !fir.slice<1>) -> !fir.box> + return +} + +// ----- + +// fir.rebox with slice with substr + +// CHECK-LABEL: func @codegen( +// CHECK-SAME: %[[arg:.*]]: !fir +func @codegen(%addr : !fir.box>) { + %c0 = arith.constant 0 : index + %c1 = arith.constant 1 : index + %c10 = arith.constant 10 : index + %0 = fir.slice %c10, %c1, %c1 substr %c1, %c1: (index, index, index, index, index) -> !fir.slice<1> + %1 = fir.shift %c0 : (index) -> !fir.shift<1> + %2 = fir.rebox %addr(%1) [%0] : (!fir.box>, !fir.shift<1>, !fir.slice<1>) -> !fir.box> + return +} + +// CHECK: %{{.*}} = fircg.ext_rebox %[[arg]] origin %{{.*}}[%{{.*}}, %{{.*}}, %{{.*}}] substr %{{.*}}, %{{.*}} : (!fir.box>, index, index, index, index, index, index) -> !fir.box>