diff --git a/flang/include/flang/Optimizer/CodeGen/CGPasses.td b/flang/include/flang/Optimizer/CodeGen/CGPasses.td index 5e47119582776a..0d20a669a15a1f 100644 --- a/flang/include/flang/Optimizer/CodeGen/CGPasses.td +++ b/flang/include/flang/Optimizer/CodeGen/CGPasses.td @@ -63,7 +63,10 @@ def TargetRewritePass : Pass<"target-rewrite", "mlir::ModuleOp"> { "Disable target-specific conversion of CHARACTER.">, Option<"noComplexConversion", "no-complex-conversion", "bool", /*default=*/"false", - "Disable target-specific conversion of COMPLEX."> + "Disable target-specific conversion of COMPLEX.">, + Option<"noStructConversion", "no-struct-conversion", + "bool", /*default=*/"false", + "Disable target-specific conversion of derived type value."> ]; } diff --git a/flang/include/flang/Optimizer/CodeGen/CodeGen.h b/flang/include/flang/Optimizer/CodeGen/CodeGen.h index 7d8e548d89a18b..5ea96c900bc630 100644 --- a/flang/include/flang/Optimizer/CodeGen/CodeGen.h +++ b/flang/include/flang/Optimizer/CodeGen/CodeGen.h @@ -34,6 +34,7 @@ std::unique_ptr createFirCodeGenRewritePass(); struct TargetRewriteOptions { bool noCharacterConversion{}; bool noComplexConversion{}; + bool noStructConversion{}; }; /// Prerequiste pass for code gen. Perform intermediate rewrites to tailor the diff --git a/flang/lib/Optimizer/CodeGen/TargetRewrite.cpp b/flang/lib/Optimizer/CodeGen/TargetRewrite.cpp index 277f3e447ed164..2f5c8cc0071ae1 100644 --- a/flang/lib/Optimizer/CodeGen/TargetRewrite.cpp +++ b/flang/lib/Optimizer/CodeGen/TargetRewrite.cpp @@ -79,6 +79,7 @@ class TargetRewrite : public fir::impl::TargetRewritePassBase { TargetRewrite(const fir::TargetRewriteOptions &options) { noCharacterConversion = options.noCharacterConversion; noComplexConversion = options.noComplexConversion; + noStructConversion = options.noStructConversion; } void runOnOperation() override final { @@ -252,6 +253,11 @@ class TargetRewrite : public fir::impl::TargetRewritePassBase { fir::CodeGenSpecifics::Marshalling &newInTyAndAttrs, llvm::SmallVectorImpl &newOpers, mlir::Value &savedStackPtr) { + if (noStructConversion) { + newInTyAndAttrs.push_back(fir::CodeGenSpecifics::getTypeAndAttr(recTy)); + newOpers.push_back(oper); + return; + } auto structArgs = specifics->structArgumentType(loc, recTy, newInTyAndAttrs); if (structArgs.size() != 1) @@ -522,6 +528,10 @@ class TargetRewrite : public fir::impl::TargetRewritePassBase { void lowerStructSignatureArg(mlir::Location loc, fir::RecordType recTy, fir::CodeGenSpecifics::Marshalling &newInTyAndAttrs) { + if (noStructConversion) { + newInTyAndAttrs.push_back(fir::CodeGenSpecifics::getTypeAndAttr(recTy)); + return; + } auto structArgs = specifics->structArgumentType(loc, recTy, newInTyAndAttrs); newInTyAndAttrs.insert(newInTyAndAttrs.end(), structArgs.begin(), @@ -645,7 +655,7 @@ class TargetRewrite : public fir::impl::TargetRewritePassBase { !noCharacterConversion) || (fir::isa_complex(ty) && !noComplexConversion) || (ty.isa() && hasCCallingConv) || - ty.isa()) { + (ty.isa() && !noStructConversion)) { LLVM_DEBUG(llvm::dbgs() << "rewrite " << signature << " for target\n"); return false; } @@ -1128,6 +1138,10 @@ class TargetRewrite : public fir::impl::TargetRewritePassBase { void doStructArg(mlir::func::FuncOp func, fir::RecordType recTy, fir::CodeGenSpecifics::Marshalling &newInTyAndAttrs, FIXUPS &fixups) { + if (noStructConversion) { + newInTyAndAttrs.push_back(fir::CodeGenSpecifics::getTypeAndAttr(recTy)); + return; + } auto structArgs = specifics->structArgumentType(func.getLoc(), recTy, newInTyAndAttrs); createFuncOpArgFixups(func, newInTyAndAttrs, structArgs, fixups); diff --git a/flang/test/Fir/target-rewrite-selective-no-struct.fir b/flang/test/Fir/target-rewrite-selective-no-struct.fir new file mode 100644 index 00000000000000..ea3fa3319caabd --- /dev/null +++ b/flang/test/Fir/target-rewrite-selective-no-struct.fir @@ -0,0 +1,25 @@ +// Test no-struct-conversion of target-rewrite pass. +// RUN: fir-opt -target-rewrite="no-struct-conversion" %s | FileCheck %s + +func.func @test(%arg0: !fir.type) { + return +} + +func.func @test_call(%arg0: !fir.type) { + fir.call @test(%arg0) : (!fir.type) -> () + return +} + +func.func @test_addr_off() { + %0 = fir.address_of(@test) : (!fir.type) -> () + return +} + +// CHECK-LABEL: func.func @test(%{{.*}}: !fir.type) { + +// CHECK-LABEL: func.func @test_call( +// CHECK-SAME: %[[ARG0:.*]]: !fir.type) { +// CHECK: fir.call @test(%[[ARG0]]) : (!fir.type) -> () + +// CHECK-LABEL: func.func @test_addr_off() { +// CHECK: fir.address_of(@test) : (!fir.type) -> ()