Skip to content

Commit f597367

Browse files
authored
[flang][HLFIR] add skip_rebox option to hlfir.declare (#162305)
hlfir.declare with a fir.box input always lead to a fir.rebox being created to ensure the lower bounds and attributes are set correctly in the local descriptor for the entity. This is really needed for hlfir.declare using fir.box function argument that do not come with any guarantees with regards to the lower bounds. Sometimes however, this fir.rebox just adds a lot of noise in the SSA chain, especially at the LLVM level and it is known that the input descriptor is already correct. I am making this patch in the context of OpenACC where I want to remap the variables inside the compute region, creating a fir.rebox on the way. This fir.rebox cannot be optimized away by FIR because of the OpenACC ops in the SSA chain. This patch adds a flag to indicate the the fir.box is known to have the correct lower bounds and attributes so that it can have a simpler code generation to FIR.
1 parent 1ab69d7 commit f597367

File tree

5 files changed

+37
-5
lines changed

5 files changed

+37
-5
lines changed

flang/include/flang/Optimizer/HLFIR/HLFIROps.td

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ def hlfir_DeclareOp
7373
local lower bound values. It is intended to be used when generating FIR
7474
from HLFIR in order to avoid descriptor creation for simple entities.
7575

76+
The attribute skip_rebox can be set to indicate that the second and first
77+
result are known to be the same descriptors (the input descriptor is known
78+
to already have the correct attributes and lower bounds).
79+
7680
Example:
7781

7882
CHARACTER(n) :: c(10:n, 20:n)
@@ -98,14 +102,16 @@ def hlfir_DeclareOp
98102
DefaultValuedAttr<UI64Attr, "0">:$storage_offset,
99103
Builtin_StringAttr:$uniq_name,
100104
OptionalAttr<fir_FortranVariableFlagsAttr>:$fortran_attrs,
101-
OptionalAttr<cuf_DataAttributeAttr>:$data_attr);
105+
OptionalAttr<cuf_DataAttributeAttr>:$data_attr,
106+
OptionalAttr<UnitAttr>:$skip_rebox);
102107

103108
let results = (outs AnyFortranVariable, AnyRefOrBoxLike);
104109

105110
let assemblyFormat = [{
106111
$memref (`(` $shape^ `)`)? (`typeparams` $typeparams^)?
107112
(`dummy_scope` $dummy_scope^)?
108113
(`storage` `(` $storage^ `[` $storage_offset `]` `)`)?
114+
(`skip_rebox` $skip_rebox^)?
109115
attr-dict `:` functional-type(operands, results)
110116
}];
111117

flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ void hlfir::DeclareOp::build(mlir::OpBuilder &builder,
281281
getDeclareOutputTypes(inputType, hasExplicitLbs);
282282
build(builder, result, {hlfirVariableType, firVarType}, memref, shape,
283283
typeparams, dummy_scope, storage, storage_offset, nameAttr,
284-
fortran_attrs, data_attr);
284+
fortran_attrs, data_attr, /*skip_rebox=*/mlir::UnitAttr{});
285285
}
286286

287287
llvm::LogicalResult hlfir::DeclareOp::verify() {
@@ -294,6 +294,9 @@ llvm::LogicalResult hlfir::DeclareOp::verify() {
294294
return emitOpError("first result type is inconsistent with variable "
295295
"properties: expected ")
296296
<< hlfirVariableType;
297+
if (getSkipRebox() && !llvm::isa<fir::BaseBoxType>(getMemref().getType()))
298+
return emitOpError(
299+
"skip_rebox attribute must only be set when the input is a box");
297300
// The rest of the argument verification is done by the
298301
// FortranVariableInterface verifier.
299302
auto fortranVar =

flang/lib/Optimizer/HLFIR/Transforms/ConvertToFIR.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "flang/Optimizer/HLFIR/HLFIROps.h"
2424
#include "flang/Optimizer/HLFIR/Passes.h"
2525
#include "mlir/Transforms/DialectConversion.h"
26+
#include "llvm/ADT/SmallSet.h"
2627

2728
namespace hlfir {
2829
#define GEN_PASS_DEF_CONVERTHLFIRTOFIR
@@ -312,10 +313,12 @@ class DeclareOpConversion : public mlir::OpRewritePattern<hlfir::DeclareOp> {
312313
// Propagate other attributes from hlfir.declare to fir.declare.
313314
// OpenACC's acc.declare is one example. Right now, the propagation
314315
// is verbatim.
315-
mlir::NamedAttrList elidedAttrs =
316-
mlir::NamedAttrList{firDeclareOp->getAttrs()};
316+
llvm::SmallSet<llvm::StringRef, 8> elidedAttrs;
317+
for (const mlir::NamedAttribute &firAttr : firDeclareOp->getAttrs())
318+
elidedAttrs.insert(firAttr.getName());
319+
elidedAttrs.insert(declareOp.getSkipReboxAttrName());
317320
for (const mlir::NamedAttribute &attr : declareOp->getAttrs())
318-
if (!elidedAttrs.get(attr.getName()))
321+
if (!elidedAttrs.contains(attr.getName()))
319322
firDeclareOp->setAttr(attr.getName(), attr.getValue());
320323

321324
auto firBase = firDeclareOp.getResult();
@@ -328,6 +331,8 @@ class DeclareOpConversion : public mlir::OpRewritePattern<hlfir::DeclareOp> {
328331
auto genHlfirBox = [&]() -> mlir::Value {
329332
if (auto baseBoxType =
330333
mlir::dyn_cast<fir::BaseBoxType>(firBase.getType())) {
334+
if (declareOp.getSkipRebox())
335+
return firBase;
331336
// Rebox so that lower bounds and attributes are correct.
332337
if (baseBoxType.isAssumedRank())
333338
return fir::ReboxAssumedRankOp::create(

flang/test/HLFIR/declare-codegen.fir

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,15 @@ func.func @array_declare_box_2(%arg0: !fir.box<!fir.array<?x?xf32>>) {
124124
// CHECK: %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {uniq_name = "x"} : (!fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>>
125125
// CHECK: %[[VAL_2:.*]] = fir.rebox %[[VAL_1]] : (!fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>>
126126

127+
func.func @array_declare_box_3(%arg0: !fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>> {
128+
%0:2 = hlfir.declare %arg0 skip_rebox {uniq_name = "x"} : (!fir.box<!fir.array<?x?xf32>>) -> (!fir.box<!fir.array<?x?xf32>>, !fir.box<!fir.array<?x?xf32>>)
129+
return %0#0 : !fir.box<!fir.array<?x?xf32>>
130+
}
131+
// CHECK-LABEL: func.func @array_declare_box_3(
132+
// CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>> {
133+
// CHECK: %[[VAL_1:.*]] = fir.declare %[[VAL_0]] {uniq_name = "x"} : (!fir.box<!fir.array<?x?xf32>>) -> !fir.box<!fir.array<?x?xf32>>
134+
// CHECK: return %[[VAL_1]]
135+
127136
func.func @array_declare_char_box(%arg0: !fir.box<!fir.array<?x?x!fir.char<1,?>>>) {
128137
%0:2 = hlfir.declare %arg0 {uniq_name = "x"} : (!fir.box<!fir.array<?x?x!fir.char<1,?>>>) -> (!fir.box<!fir.array<?x?x!fir.char<1,?>>>, !fir.box<!fir.array<?x?x!fir.char<1,?>>>)
129138
return

flang/test/HLFIR/invalid.fir

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ func.func @bad_array_declare(%arg0: !fir.ref<!fir.array<?x?xf32>>) {
3636
return
3737
}
3838

39+
// -----
40+
func.func @bad_declare_skip_rebox(%arg0: !fir.ref<f32>) {
41+
// expected-error@+1 {{'hlfir.declare' op skip_rebox attribute must only be set when the input is a box}}
42+
%0:2 = hlfir.declare %arg0 skip_rebox {uniq_name = "x"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
43+
return
44+
}
45+
46+
// -----
47+
3948
// -----
4049
func.func @bad_assign_scalar_character(%arg0: !fir.boxchar<1>, %arg1: !fir.char<1,?>) {
4150
// expected-error@+1 {{'hlfir.assign' op operand #0 must be any Fortran value or variable type, but got '!fir.char<1,?>'}}

0 commit comments

Comments
 (0)