Skip to content

Commit

Permalink
[flang] add hlfir.null to implement NULL()
Browse files Browse the repository at this point in the history
In HLFIR, the address of a Fortran entity in lowering must be defined
by an operation that has the FortranVariableOpInterface (it is a sanity
requirement to ensure that the mlir::Value propagated in certain places
of lowering can be reasoned about).
fir.zero_bits does not have this interface and it makes little sense to
add it since it can "zero initialize" more types than just addresses.

Creating an hlfir.declare for null addresses is a bit too much (what
would be the name), and it would be noisy in the IR.

Instead add a small hlfir.null operation whose codegen is simply a
replacement by fir.zero_bits.

It may also later help dealing with the NULL(MOLD) cases in a nicer
way (the current lowering of this uses special handling it).

Differential Revision: https://reviews.llvm.org/D141040
  • Loading branch information
jeanPerier committed Jan 6, 2023
1 parent 543db09 commit 241cb29
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 2 deletions.
25 changes: 25 additions & 0 deletions flang/include/flang/Optimizer/HLFIR/HLFIROps.td
Expand Up @@ -457,4 +457,29 @@ def hlfir_ApplyOp : hlfir_Op<"apply", [NoMemoryEffect, AttrSizedOperandSegments]
];
}

def hlfir_NullOp : hlfir_Op<"null", [NoMemoryEffect, fir_FortranVariableOpInterface]> {
let summary = "create a NULL() address";

let description = [{
Create a NULL() address.
So far is not intended to represent NULL(MOLD).
}];

let results = (outs AnyFortranVariable);
let builders = [OpBuilder<(ins)>];

let assemblyFormat = "type(results) attr-dict";
let extraClassDeclaration = [{
// Implement FortranVariableInterface interface.
std::optional<fir::FortranVariableFlagsEnum> getFortranAttrs() const {
return std::nullopt;
}
mlir::Value getShape() const {return mlir::Value{};}
mlir::OperandRange getExplicitTypeParams() const {
// Return an empty range.
return {(*this)->getOperands().begin(), (*this)->getOperands().begin()};
}
}];
}

#endif // FORTRAN_DIALECT_HLFIR_OPS
10 changes: 10 additions & 0 deletions flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
Expand Up @@ -503,5 +503,15 @@ void hlfir::ApplyOp::build(mlir::OpBuilder &builder,
build(builder, odsState, resultType, expr, indices, typeparams);
}

//===----------------------------------------------------------------------===//
// NullOp
//===----------------------------------------------------------------------===//

void hlfir::NullOp::build(mlir::OpBuilder &builder,
mlir::OperationState &odsState) {
return build(builder, odsState,
fir::ReferenceType::get(builder.getNoneType()));
}

#define GET_OP_CLASSES
#include "flang/Optimizer/HLFIR/HLFIROps.cpp.inc"
17 changes: 15 additions & 2 deletions flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp
Expand Up @@ -291,6 +291,18 @@ class NoReassocOpConversion
}
};

class NullOpConversion : public mlir::OpRewritePattern<hlfir::NullOp> {
public:
explicit NullOpConversion(mlir::MLIRContext *ctx) : OpRewritePattern{ctx} {}

mlir::LogicalResult
matchAndRewrite(hlfir::NullOp nullop,
mlir::PatternRewriter &rewriter) const override {
rewriter.replaceOpWithNewOp<fir::ZeroOp>(nullop, nullop.getType());
return mlir::success();
}
};

class ConvertHLFIRtoFIR
: public hlfir::impl::ConvertHLFIRtoFIRBase<ConvertHLFIRtoFIR> {
public:
Expand All @@ -302,8 +314,9 @@ class ConvertHLFIRtoFIR
auto module = this->getOperation();
auto *context = &getContext();
mlir::RewritePatternSet patterns(context);
patterns.insert<AssignOpConversion, DeclareOpConversion,
DesignateOpConversion, NoReassocOpConversion>(context);
patterns
.insert<AssignOpConversion, DeclareOpConversion, DesignateOpConversion,
NoReassocOpConversion, NullOpConversion>(context);
mlir::ConversionTarget target(*context);
target.addIllegalDialect<hlfir::hlfirDialect>();
target.markUnknownOpDynamicallyLegal(
Expand Down
9 changes: 9 additions & 0 deletions flang/test/HLFIR/null-codegen.fir
@@ -0,0 +1,9 @@
// Test hlfir.null code generation to FIR

// RUN: fir-opt %s -convert-hlfir-to-fir | FileCheck %s

func.func @test() {
// CHECK: fir.zero_bits !fir.ref<none>
%0 = hlfir.null !fir.ref<none>
return
}
9 changes: 9 additions & 0 deletions flang/test/HLFIR/null.fir
@@ -0,0 +1,9 @@
// Test hlfir.null operation parse, verify (no errors), and unparse.

// RUN: fir-opt %s | fir-opt | FileCheck %s

func.func @test() {
// CHECK: hlfir.null !fir.ref<none>
%0 = hlfir.null !fir.ref<none>
return
}

0 comments on commit 241cb29

Please sign in to comment.