Skip to content

Commit

Permalink
[fir] Add conversion patterns for slice, shape, shapeshift and shift ops
Browse files Browse the repository at this point in the history
The information in these perations is used by other operation.
At this point they should not have anymore uses.

This patch is part of the upstreaming effort from fir-dev branch.

Reviewed By: kiranchandramohan

Differential Revision: https://reviews.llvm.org/D113971

Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
  • Loading branch information
clementval and schweitzpgi committed Nov 17, 2021
1 parent 13744e3 commit 1ed5a90
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 4 deletions.
45 changes: 41 additions & 4 deletions flang/lib/Optimizer/CodeGen/CodeGen.cpp
Expand Up @@ -1469,6 +1469,42 @@ struct NegcOpConversion : public FIROpConversion<fir::NegcOp> {
}
};

/// Conversion pattern for operation that must be dead. The information in these
/// operations is used by other operation. At this point they should not have
/// anymore uses.
/// These operations are normally dead after the pre-codegen pass.
template <typename FromOp>
struct MustBeDeadConversion : public FIROpConversion<FromOp> {
explicit MustBeDeadConversion(fir::LLVMTypeConverter &lowering)
: FIROpConversion<FromOp>(lowering) {}
using OpAdaptor = typename FromOp::Adaptor;

mlir::LogicalResult
matchAndRewrite(FromOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const final {
if (!op->getUses().empty())
return rewriter.notifyMatchFailure(op, "op must be dead");
rewriter.eraseOp(op);
return success();
}
};

struct ShapeOpConversion : public MustBeDeadConversion<fir::ShapeOp> {
using MustBeDeadConversion::MustBeDeadConversion;
};

struct ShapeShiftOpConversion : public MustBeDeadConversion<fir::ShapeShiftOp> {
using MustBeDeadConversion::MustBeDeadConversion;
};

struct ShiftOpConversion : public MustBeDeadConversion<fir::ShiftOp> {
using MustBeDeadConversion::MustBeDeadConversion;
};

struct SliceOpConversion : public MustBeDeadConversion<fir::SliceOp> {
using MustBeDeadConversion::MustBeDeadConversion;
};

/// `fir.is_present` -->
/// ```
/// %0 = llvm.mlir.constant(0 : i64)
Expand Down Expand Up @@ -1635,10 +1671,11 @@ class FIRToLLVMLowering : public fir::FIRToLLVMLoweringBase<FIRToLLVMLowering> {
GlobalOpConversion, InsertOnRangeOpConversion, InsertValueOpConversion,
IsPresentOpConversion, LoadOpConversion, NegcOpConversion,
MulcOpConversion, SelectCaseOpConversion, SelectOpConversion,
SelectRankOpConversion, SelectTypeOpConversion, StoreOpConversion,
StringLitOpConversion, SubcOpConversion, UnboxCharOpConversion,
UndefOpConversion, UnreachableOpConversion, ZeroOpConversion>(
typeConverter);
SelectRankOpConversion, SelectTypeOpConversion, ShapeOpConversion,
ShapeShiftOpConversion, ShiftOpConversion, SliceOpConversion,
StoreOpConversion, StringLitOpConversion, SubcOpConversion,
UnboxCharOpConversion, UndefOpConversion, UnreachableOpConversion,
ZeroOpConversion>(typeConverter);
mlir::populateStdToLLVMConversionPatterns(typeConverter, pattern);
mlir::arith::populateArithmeticToLLVMConversionPatterns(typeConverter,
pattern);
Expand Down
48 changes: 48 additions & 0 deletions flang/test/Fir/convert-to-llvm-invalid.fir
Expand Up @@ -100,3 +100,51 @@ func @gentypedesc() {

// expected-error@+1{{'fir.dt_entry' op expects parent op 'fir.dispatch_table'}}
fir.dt_entry "method", @method_impl

// -----

// Test `fir.shape` conversion failure because the op has uses.

func @shape_not_dead(%arg0: !fir.ref<!fir.array<?x?xf32>>, %i: index, %j: index) {
%c0 = arith.constant 1 : index
// expected-error@+1{{failed to legalize operation 'fir.shape'}}
%0 = fir.shape %c0, %c0 : (index, index) -> !fir.shape<2>
%1 = fir.array_coor %arg0(%0) %i, %j : (!fir.ref<!fir.array<?x?xf32>>, !fir.shape<2>, index, index) -> !fir.ref<f32>
return
}

// -----

// Test `fir.slice` conversion failure because the op has uses.

func @slice_not_dead(%arg0: !fir.ref<!fir.array<?x?xf32>>, %i: index, %j: index) {
%c0 = arith.constant 1 : index
// expected-error@+1{{failed to legalize operation 'fir.slice'}}
%0 = fir.slice %c0, %c0, %c0, %c0, %c0, %c0 : (index, index, index, index, index, index) -> !fir.slice<2>
%1 = fir.array_coor %arg0[%0] %i, %j : (!fir.ref<!fir.array<?x?xf32>>, !fir.slice<2>, index, index) -> !fir.ref<f32>
return
}

// -----

// Test `fir.shift` conversion failure because the op has uses.

func @shift_not_dead(%arg0: !fir.box<!fir.array<?xf32>>, %i: index) {
%c0 = arith.constant 1 : index
// expected-error@+1{{failed to legalize operation 'fir.shift'}}
%0 = fir.shift %c0 : (index) -> !fir.shift<1>
%1 = fir.array_coor %arg0(%0) %i : (!fir.box<!fir.array<?xf32>>, !fir.shift<1>, index) -> !fir.ref<f32>
return
}

// -----

// Test `fir.shape_shift` conversion failure because the op has uses.

func @shape_shift_not_dead(%arg0: !fir.ref<!fir.array<?x?xf32>>, %i: index, %j: index) {
%c0 = arith.constant 1 : index
// expected-error@+1{{failed to legalize operation 'fir.shape_shift'}}
%0 = fir.shape_shift %c0, %c0, %c0, %c0 : (index, index, index, index) -> !fir.shapeshift<2>
%1 = fir.array_coor %arg0(%0) %i, %j : (!fir.ref<!fir.array<?x?xf32>>, !fir.shapeshift<2>, index, index) -> !fir.ref<f32>
return
}
48 changes: 48 additions & 0 deletions flang/test/Fir/convert-to-llvm.fir
Expand Up @@ -1271,3 +1271,51 @@ func @string_lit1() {

// CHECK-LABEL: llvm.func @string_lit1
// %{{.*}} = llvm.mlir.constant(dense<[158, 2345]> : vector<2xi16>) : !llvm.array<2 x i16>

// -----

// Test must be dead conversion.

func @dead_shift() {
%c0 = arith.constant 0 : index
%0 = fir.shift %c0 : (index) -> !fir.shift<1>
return
}

// CHECK-LABEL: llvm.func @dead_shift
// CHECK-NOT: fir.shift
// CHECK: %{{.*}} = llvm.mlir.constant(0 : index) : i{{.*}}
// CHECK-NEXT: llvm.return

func @dead_shape() {
%c0 = arith.constant 0 : index
%0 = fir.shape %c0 : (index) -> !fir.shape<1>
return
}

// CHECK-LABEL: llvm.func @dead_shape
// CHECK-NOT: fir.shape
// CHECK: %{{.*}} = llvm.mlir.constant(0 : index) : i{{.*}}
// CHECK-NEXT: llvm.return

func @dead_shapeshift() {
%c0 = arith.constant 0 : index
%0 = fir.shape_shift %c0, %c0 : (index, index) -> !fir.shapeshift<1>
return
}

// CHECK-LABEL: llvm.func @dead_shapeshift
// CHECK-NOT: fir.shape_shift
// CHECK: %{{.*}} = llvm.mlir.constant(0 : index) : i{{.*}}
// CHECK-NEXT: llvm.return

func @dead_slice() {
%c0 = arith.constant 0 : index
%0 = fir.slice %c0, %c0, %c0 : (index, index, index) -> !fir.slice<1>
return
}

// CHECK-LABEL: llvm.func @dead_slice
// CHECK-NOT: fir.slice
// CHECK: %{{.*}} = llvm.mlir.constant(0 : index) : i{{.*}}
// CHECK-NEXT: llvm.return

0 comments on commit 1ed5a90

Please sign in to comment.