[llvm-branch-commits] [flang] [flang][hlfir] optimize hlfir.eval_in_mem bufferization (PR #118069)

2024-11-29 Thread via llvm-branch-commits

https://github.com/jeanPerier created 
https://github.com/llvm/llvm-project/pull/118069

This patch extends the optimize bufferization to deal with the new 
hlfir.eval_in_mem and move the evaluation contained in its body to operate 
directly over the LHS when it can prove there are no access to the LHS inside 
the region (and that the LHS is contiguous).

This will allow the array function call optimization when lowering is changed 
to produce an hlfir.eval_in_mem in the next patch.

>From 6be998ec6f74937820e350f51796490b41a76d46 Mon Sep 17 00:00:00 2001
From: Jean Perier 
Date: Thu, 28 Nov 2024 08:26:39 -0800
Subject: [PATCH] [flang][hlfir] optimize hlfir.eval_in_mem bufferization

---
 .../lib/Optimizer/Analysis/AliasAnalysis.cpp  |  14 ++-
 .../Transforms/OptimizedBufferization.cpp | 108 ++
 .../HLFIR/opt-bufferization-eval_in_mem.fir   |  67 +++
 3 files changed, 188 insertions(+), 1 deletion(-)
 create mode 100644 flang/test/HLFIR/opt-bufferization-eval_in_mem.fir

diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp 
b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index 2b24791d6c7c52..c561285b9feef5 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -91,6 +91,13 @@ bool AliasAnalysis::Source::isDummyArgument() const {
   return false;
 }
 
+static bool isEvaluateInMemoryBlockArg(mlir::Value v) {
+  if (auto evalInMem = llvm::dyn_cast_or_null(
+  v.getParentRegion()->getParentOp()))
+return evalInMem.getMemory() == v;
+  return false;
+}
+
 bool AliasAnalysis::Source::isData() const { return origin.isData; }
 bool AliasAnalysis::Source::isBoxData() const {
   return mlir::isa(fir::unwrapRefType(valueType)) &&
@@ -698,7 +705,7 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value 
v,
   breakFromLoop = true;
 });
   }
-  if (!defOp && type == SourceKind::Unknown)
+  if (!defOp && type == SourceKind::Unknown) {
 // Check if the memory source is coming through a dummy argument.
 if (isDummyArgument(v)) {
   type = SourceKind::Argument;
@@ -708,7 +715,12 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value 
v,
 
   if (isPointerReference(ty))
 attributes.set(Attribute::Pointer);
+} else if (isEvaluateInMemoryBlockArg(v)) {
+  // hlfir.eval_in_mem block operands is allocated by the operation.
+  type = SourceKind::Allocate;
+  ty = v.getType();
 }
+  }
 
   if (type == SourceKind::Global) {
 return {{global, instantiationPoint, followingData},
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp 
b/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
index a0160b233e3cd1..e8c15a256b9da0 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
@@ -1108,6 +1108,113 @@ class ReductionMaskConversion : public 
mlir::OpRewritePattern {
   }
 };
 
+class EvaluateIntoMemoryAssignBufferization
+: public mlir::OpRewritePattern {
+
+public:
+  using mlir::OpRewritePattern::OpRewritePattern;
+
+  llvm::LogicalResult
+  matchAndRewrite(hlfir::EvaluateInMemoryOp,
+  mlir::PatternRewriter &rewriter) const override;
+};
+
+static bool mayReadOrWrite(mlir::Region ®ion, mlir::Value var) {
+  fir::AliasAnalysis aliasAnalysis;
+  for (mlir::Operation &op : region.getOps()) {
+if (op.hasTrait()) {
+  for (mlir::Region &subRegion : op.getRegions())
+if (mayReadOrWrite(subRegion, var))
+  return true;
+  // In MLIR, RecursiveMemoryEffects can be combined with
+  // MemoryEffectOpInterface to describe extra effects on top of the
+  // effects of the nested operations.  However, the presence of
+  // RecursiveMemoryEffects and the absence of MemoryEffectOpInterface
+  // implies the operation has no other memory effects than the one of its
+  // nested operations.
+  if (!mlir::isa(op))
+continue;
+}
+if (!aliasAnalysis.getModRef(&op, var).isNoModRef())
+  return true;
+  }
+  return false;
+}
+
+static llvm::LogicalResult
+tryUsingAssignLhsDirectly(hlfir::EvaluateInMemoryOp evalInMem,
+  mlir::PatternRewriter &rewriter) {
+  mlir::Location loc = evalInMem.getLoc();
+  hlfir::DestroyOp destroy;
+  hlfir::AssignOp assign;
+  for (auto user : llvm::enumerate(evalInMem->getUsers())) {
+if (user.index() > 2)
+  return mlir::failure();
+mlir::TypeSwitch(user.value())
+.Case([&](hlfir::AssignOp op) { assign = op; })
+.Case([&](hlfir::DestroyOp op) { destroy = op; });
+  }
+  if (!assign || !destroy || destroy.mustFinalizeExpr() ||
+  assign.isAllocatableAssignment())
+return mlir::failure();
+
+  hlfir::Entity lhs{assign.getLhs()};
+  // EvaluateInMemoryOp memory is contiguous, so in general, it can only be
+  // replace by the LHS if the LHS is contiguous.
+  if (!lhs.isS

[llvm-branch-commits] [flang] [flang][hlfir] optimize hlfir.eval_in_mem bufferization (PR #118069)

2024-11-29 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-flang-fir-hlfir

Author: None (jeanPerier)


Changes

This patch extends the optimize bufferization to deal with the new 
hlfir.eval_in_mem and move the evaluation contained in its body to operate 
directly over the LHS when it can prove there are no access to the LHS inside 
the region (and that the LHS is contiguous).

This will allow the array function call optimization when lowering is changed 
to produce an hlfir.eval_in_mem in the next patch.

---
Full diff: https://github.com/llvm/llvm-project/pull/118069.diff


3 Files Affected:

- (modified) flang/lib/Optimizer/Analysis/AliasAnalysis.cpp (+13-1) 
- (modified) flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp 
(+108) 
- (added) flang/test/HLFIR/opt-bufferization-eval_in_mem.fir (+67) 


``diff
diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp 
b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
index 2b24791d6c7c52..c561285b9feef5 100644
--- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
+++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp
@@ -91,6 +91,13 @@ bool AliasAnalysis::Source::isDummyArgument() const {
   return false;
 }
 
+static bool isEvaluateInMemoryBlockArg(mlir::Value v) {
+  if (auto evalInMem = llvm::dyn_cast_or_null(
+  v.getParentRegion()->getParentOp()))
+return evalInMem.getMemory() == v;
+  return false;
+}
+
 bool AliasAnalysis::Source::isData() const { return origin.isData; }
 bool AliasAnalysis::Source::isBoxData() const {
   return mlir::isa(fir::unwrapRefType(valueType)) &&
@@ -698,7 +705,7 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value 
v,
   breakFromLoop = true;
 });
   }
-  if (!defOp && type == SourceKind::Unknown)
+  if (!defOp && type == SourceKind::Unknown) {
 // Check if the memory source is coming through a dummy argument.
 if (isDummyArgument(v)) {
   type = SourceKind::Argument;
@@ -708,7 +715,12 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value 
v,
 
   if (isPointerReference(ty))
 attributes.set(Attribute::Pointer);
+} else if (isEvaluateInMemoryBlockArg(v)) {
+  // hlfir.eval_in_mem block operands is allocated by the operation.
+  type = SourceKind::Allocate;
+  ty = v.getType();
 }
+  }
 
   if (type == SourceKind::Global) {
 return {{global, instantiationPoint, followingData},
diff --git a/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp 
b/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
index a0160b233e3cd1..e8c15a256b9da0 100644
--- a/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
+++ b/flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp
@@ -1108,6 +1108,113 @@ class ReductionMaskConversion : public 
mlir::OpRewritePattern {
   }
 };
 
+class EvaluateIntoMemoryAssignBufferization
+: public mlir::OpRewritePattern {
+
+public:
+  using mlir::OpRewritePattern::OpRewritePattern;
+
+  llvm::LogicalResult
+  matchAndRewrite(hlfir::EvaluateInMemoryOp,
+  mlir::PatternRewriter &rewriter) const override;
+};
+
+static bool mayReadOrWrite(mlir::Region ®ion, mlir::Value var) {
+  fir::AliasAnalysis aliasAnalysis;
+  for (mlir::Operation &op : region.getOps()) {
+if (op.hasTrait()) {
+  for (mlir::Region &subRegion : op.getRegions())
+if (mayReadOrWrite(subRegion, var))
+  return true;
+  // In MLIR, RecursiveMemoryEffects can be combined with
+  // MemoryEffectOpInterface to describe extra effects on top of the
+  // effects of the nested operations.  However, the presence of
+  // RecursiveMemoryEffects and the absence of MemoryEffectOpInterface
+  // implies the operation has no other memory effects than the one of its
+  // nested operations.
+  if (!mlir::isa(op))
+continue;
+}
+if (!aliasAnalysis.getModRef(&op, var).isNoModRef())
+  return true;
+  }
+  return false;
+}
+
+static llvm::LogicalResult
+tryUsingAssignLhsDirectly(hlfir::EvaluateInMemoryOp evalInMem,
+  mlir::PatternRewriter &rewriter) {
+  mlir::Location loc = evalInMem.getLoc();
+  hlfir::DestroyOp destroy;
+  hlfir::AssignOp assign;
+  for (auto user : llvm::enumerate(evalInMem->getUsers())) {
+if (user.index() > 2)
+  return mlir::failure();
+mlir::TypeSwitch(user.value())
+.Case([&](hlfir::AssignOp op) { assign = op; })
+.Case([&](hlfir::DestroyOp op) { destroy = op; });
+  }
+  if (!assign || !destroy || destroy.mustFinalizeExpr() ||
+  assign.isAllocatableAssignment())
+return mlir::failure();
+
+  hlfir::Entity lhs{assign.getLhs()};
+  // EvaluateInMemoryOp memory is contiguous, so in general, it can only be
+  // replace by the LHS if the LHS is contiguous.
+  if (!lhs.isSimplyContiguous())
+return mlir::failure();
+  // Character assignment may involves truncation/padding, so the LHS
+  // cannot be used to evaluate RHS in place without proving the LHS 

[llvm-branch-commits] [flang] [flang] optimize array function calls using hlfir.eval_in_mem (PR #118070)

2024-11-29 Thread via llvm-branch-commits

https://github.com/jeanPerier created 
https://github.com/llvm/llvm-project/pull/118070

This patch encapsulate array function call lowering into hlfir.eval_in_mem and 
allows directly evaluating the call into the LHS when possible.

The conditions are: LHS is contiguous, not accessed inside the function, it is 
not a whole allocatable, and the function results needs not to be finalized. 
All these conditions are tested in the previous [hlfir.eval_in_mem optimization 
patch](https://github.com/llvm/llvm-project/pull/118069) that is leveraging 
[the extension of getModRef to handle function 
calls](https://github.com/llvm/llvm-project/pull/117164)).

This yields a 25% speed-up on polyhedron channel2 benchmark (from 1min to 45s 
measured on an X86-64 Zen 2).



>From 4debf91864773ba805a9439cde9b74fc44315acc Mon Sep 17 00:00:00 2001
From: Jean Perier 
Date: Thu, 28 Nov 2024 08:28:21 -0800
Subject: [PATCH] [flang] optimize array function calls using hlfir.eval_in_mem

---
 flang/include/flang/Lower/ConvertCall.h   |   6 +-
 .../flang/Optimizer/HLFIR/HLFIRDialect.h  |   4 +
 flang/lib/Lower/ConvertCall.cpp   | 102 +-
 flang/lib/Lower/ConvertExpr.cpp   |  13 +-
 flang/lib/Optimizer/HLFIR/IR/HLFIRDialect.cpp |  15 ++
 flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp |  11 +-
 .../order_assignments/where-scheduling.f90|   2 +-
 .../test/Lower/HLFIR/calls-array-results.f90  | 131 ++
 flang/test/Lower/HLFIR/where-nonelemental.f90 |  38 ++---
 .../Lower/explicit-interface-results-2.f90|   2 -
 .../test/Lower/explicit-interface-results.f90 |   8 +-
 flang/test/Lower/forall/array-constructor.f90 |   2 +-
 12 files changed, 260 insertions(+), 74 deletions(-)
 create mode 100644 flang/test/Lower/HLFIR/calls-array-results.f90

diff --git a/flang/include/flang/Lower/ConvertCall.h 
b/flang/include/flang/Lower/ConvertCall.h
index bc082907e61760..2c51a887010c87 100644
--- a/flang/include/flang/Lower/ConvertCall.h
+++ b/flang/include/flang/Lower/ConvertCall.h
@@ -24,6 +24,10 @@
 
 namespace Fortran::lower {
 
+struct LoweredResult {
+  std::variant result;
+};
+
 /// Given a call site for which the arguments were already lowered, generate
 /// the call and return the result. This function deals with explicit result
 /// allocation and lowering if needed. It also deals with passing the host
@@ -32,7 +36,7 @@ namespace Fortran::lower {
 /// It is only used for HLFIR.
 /// The returned boolean indicates if finalization has been emitted in
 /// \p stmtCtx for the result.
-std::pair genCallOpAndResult(
+std::pair genCallOpAndResult(
 mlir::Location loc, Fortran::lower::AbstractConverter &converter,
 Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
 Fortran::lower::CallerInterface &caller, mlir::FunctionType callSiteType,
diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h 
b/flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h
index 3830237f96f3cc..447d5fbab89998 100644
--- a/flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h
+++ b/flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h
@@ -61,6 +61,10 @@ inline mlir::Type getFortranElementOrSequenceType(mlir::Type 
type) {
   return type;
 }
 
+/// Build the hlfir.expr type for the value held in a variable of type \p
+/// variableType.
+mlir::Type getExprType(mlir::Type variableType);
+
 /// Is this a fir.box or fir.class address type?
 inline bool isBoxAddressType(mlir::Type type) {
   type = fir::dyn_cast_ptrEleTy(type);
diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index e84e7afbe82e09..088d8f96caa410 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -284,7 +284,8 @@ static void remapActualToDummyDescriptors(
   }
 }
 
-std::pair Fortran::lower::genCallOpAndResult(
+std::pair
+Fortran::lower::genCallOpAndResult(
 mlir::Location loc, Fortran::lower::AbstractConverter &converter,
 Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
 Fortran::lower::CallerInterface &caller, mlir::FunctionType callSiteType,
@@ -326,6 +327,11 @@ std::pair 
Fortran::lower::genCallOpAndResult(
 }
   }
 
+  const bool isExprCall =
+  converter.getLoweringOptions().getLowerToHighLevelFIR() &&
+  callSiteType.getNumResults() == 1 &&
+  llvm::isa(callSiteType.getResult(0));
+
   mlir::IndexType idxTy = builder.getIndexType();
   auto lowerSpecExpr = [&](const auto &expr) -> mlir::Value {
 mlir::Value convertExpr = builder.createConvert(
@@ -333,6 +339,8 @@ std::pair 
Fortran::lower::genCallOpAndResult(
 return fir::factory::genMaxWithZero(builder, loc, convertExpr);
   };
   llvm::SmallVector resultLengths;
+  mlir::Value arrayResultShape;
+  hlfir::EvaluateInMemoryOp evaluateInMemory;
   auto allocatedResult = [&]() -> std::optional {
 llvm::SmallVector extents;
 llvm::SmallVector lengths;
@@ -366,6 +374,18 @@ std::pair 
Fortran::lower::genCallOpAndResult(
   

[llvm-branch-commits] [flang] [flang] optimize array function calls using hlfir.eval_in_mem (PR #118070)

2024-11-29 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-flang-fir-hlfir

Author: None (jeanPerier)


Changes

This patch encapsulate array function call lowering into hlfir.eval_in_mem and 
allows directly evaluating the call into the LHS when possible.

The conditions are: LHS is contiguous, not accessed inside the function, it is 
not a whole allocatable, and the function results needs not to be finalized. 
All these conditions are tested in the previous [hlfir.eval_in_mem optimization 
patch](https://github.com/llvm/llvm-project/pull/118069) that is leveraging 
[the extension of getModRef to handle function 
calls](https://github.com/llvm/llvm-project/pull/117164)).

This yields a 25% speed-up on polyhedron channel2 benchmark (from 1min to 45s 
measured on an X86-64 Zen 2).



---

Patch is 34.18 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/118070.diff


12 Files Affected:

- (modified) flang/include/flang/Lower/ConvertCall.h (+5-1) 
- (modified) flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h (+4) 
- (modified) flang/lib/Lower/ConvertCall.cpp (+69-33) 
- (modified) flang/lib/Lower/ConvertExpr.cpp (+8-5) 
- (modified) flang/lib/Optimizer/HLFIR/IR/HLFIRDialect.cpp (+15) 
- (modified) flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp (+1-10) 
- (modified) flang/test/HLFIR/order_assignments/where-scheduling.f90 (+1-1) 
- (added) flang/test/Lower/HLFIR/calls-array-results.f90 (+131) 
- (modified) flang/test/Lower/HLFIR/where-nonelemental.f90 (+21-17) 
- (modified) flang/test/Lower/explicit-interface-results-2.f90 (-2) 
- (modified) flang/test/Lower/explicit-interface-results.f90 (+4-4) 
- (modified) flang/test/Lower/forall/array-constructor.f90 (+1-1) 


``diff
diff --git a/flang/include/flang/Lower/ConvertCall.h 
b/flang/include/flang/Lower/ConvertCall.h
index bc082907e61760..2c51a887010c87 100644
--- a/flang/include/flang/Lower/ConvertCall.h
+++ b/flang/include/flang/Lower/ConvertCall.h
@@ -24,6 +24,10 @@
 
 namespace Fortran::lower {
 
+struct LoweredResult {
+  std::variant result;
+};
+
 /// Given a call site for which the arguments were already lowered, generate
 /// the call and return the result. This function deals with explicit result
 /// allocation and lowering if needed. It also deals with passing the host
@@ -32,7 +36,7 @@ namespace Fortran::lower {
 /// It is only used for HLFIR.
 /// The returned boolean indicates if finalization has been emitted in
 /// \p stmtCtx for the result.
-std::pair genCallOpAndResult(
+std::pair genCallOpAndResult(
 mlir::Location loc, Fortran::lower::AbstractConverter &converter,
 Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
 Fortran::lower::CallerInterface &caller, mlir::FunctionType callSiteType,
diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h 
b/flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h
index 3830237f96f3cc..447d5fbab89998 100644
--- a/flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h
+++ b/flang/include/flang/Optimizer/HLFIR/HLFIRDialect.h
@@ -61,6 +61,10 @@ inline mlir::Type getFortranElementOrSequenceType(mlir::Type 
type) {
   return type;
 }
 
+/// Build the hlfir.expr type for the value held in a variable of type \p
+/// variableType.
+mlir::Type getExprType(mlir::Type variableType);
+
 /// Is this a fir.box or fir.class address type?
 inline bool isBoxAddressType(mlir::Type type) {
   type = fir::dyn_cast_ptrEleTy(type);
diff --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index e84e7afbe82e09..088d8f96caa410 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -284,7 +284,8 @@ static void remapActualToDummyDescriptors(
   }
 }
 
-std::pair Fortran::lower::genCallOpAndResult(
+std::pair
+Fortran::lower::genCallOpAndResult(
 mlir::Location loc, Fortran::lower::AbstractConverter &converter,
 Fortran::lower::SymMap &symMap, Fortran::lower::StatementContext &stmtCtx,
 Fortran::lower::CallerInterface &caller, mlir::FunctionType callSiteType,
@@ -326,6 +327,11 @@ std::pair 
Fortran::lower::genCallOpAndResult(
 }
   }
 
+  const bool isExprCall =
+  converter.getLoweringOptions().getLowerToHighLevelFIR() &&
+  callSiteType.getNumResults() == 1 &&
+  llvm::isa(callSiteType.getResult(0));
+
   mlir::IndexType idxTy = builder.getIndexType();
   auto lowerSpecExpr = [&](const auto &expr) -> mlir::Value {
 mlir::Value convertExpr = builder.createConvert(
@@ -333,6 +339,8 @@ std::pair 
Fortran::lower::genCallOpAndResult(
 return fir::factory::genMaxWithZero(builder, loc, convertExpr);
   };
   llvm::SmallVector resultLengths;
+  mlir::Value arrayResultShape;
+  hlfir::EvaluateInMemoryOp evaluateInMemory;
   auto allocatedResult = [&]() -> std::optional {
 llvm::SmallVector extents;
 llvm::SmallVector lengths;
@@ -366,6 +374,18 @@ std::pair 
Fortran::lower::genCallOpAndResult(
   resultLengths = lengths;
 }
 
+if (!extents.empty())
+  arrayResultShap

[llvm-branch-commits] [flang] [flang] optimize array function calls using hlfir.eval_in_mem (PR #118070)

2024-11-29 Thread via llvm-branch-commits

jeanPerier wrote:

Note that this is a "classic" Fortran compiler optimization, you can verify 
that at least all of gfortran, ifx, and nvfortran are doing it on something 
very easy like:

```
subroutine test
interface
 function foo()
real :: foo(100)
 end function
end interface
   real x(100)
   x = foo()
   call bar(x)
end subroutine
```

https://github.com/llvm/llvm-project/pull/118070
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] release/19.x: [clang-repl] Fix generation of wasm binaries while running clang-repl in browser (#117978) (PR #118077)

2024-11-29 Thread via llvm-branch-commits

llvmbot wrote:

@vgvassilev What do you think about merging this PR to the release branch?

https://github.com/llvm/llvm-project/pull/118077
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] release/19.x: [clang-repl] Fix generation of wasm binaries while running clang-repl in browser (#117978) (PR #118077)

2024-11-29 Thread via llvm-branch-commits

https://github.com/llvmbot milestoned 
https://github.com/llvm/llvm-project/pull/118077
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] release/19.x: [clang-repl] Fix generation of wasm binaries while running clang-repl in browser (#117978) (PR #118077)

2024-11-29 Thread via llvm-branch-commits

https://github.com/llvmbot created 
https://github.com/llvm/llvm-project/pull/118077

Backport a174aa1e416c4e27945f5a8c646b119126dc8441

Requested by: @anutosh491

>From d181adec32cf3c5e6dfee26f2b4b5d9aa543ea6a Mon Sep 17 00:00:00 2001
From: Anutosh Bhat 
Date: Fri, 29 Nov 2024 15:31:02 +0530
Subject: [PATCH] [clang-repl] Fix generation of wasm binaries while running
 clang-repl in browser (#117978)

Co-authored-by: Vassil Vassilev 
(cherry picked from commit a174aa1e416c4e27945f5a8c646b119126dc8441)
---
 clang/lib/Interpreter/CMakeLists.txt  |  2 +
 clang/lib/Interpreter/Interpreter.cpp |  1 +
 clang/lib/Interpreter/Wasm.cpp| 57 ---
 3 files changed, 46 insertions(+), 14 deletions(-)

diff --git a/clang/lib/Interpreter/CMakeLists.txt 
b/clang/lib/Interpreter/CMakeLists.txt
index 0a2d60757c216d..85efa4b0f984f4 100644
--- a/clang/lib/Interpreter/CMakeLists.txt
+++ b/clang/lib/Interpreter/CMakeLists.txt
@@ -15,6 +15,7 @@ set(LLVM_LINK_COMPONENTS
 if (EMSCRIPTEN AND "lld" IN_LIST LLVM_ENABLE_PROJECTS)
   set(WASM_SRC Wasm.cpp)
   set(WASM_LINK lldWasm)
+  set(COMMON_LINK lldCommon)
 endif()
 
 add_clang_library(clangInterpreter
@@ -45,6 +46,7 @@ add_clang_library(clangInterpreter
   clangSema
   clangSerialization
   ${WASM_LINK}
+  ${COMMON_LINK}
   )
 
 if ((MINGW OR CYGWIN) AND BUILD_SHARED_LIBS)
diff --git a/clang/lib/Interpreter/Interpreter.cpp 
b/clang/lib/Interpreter/Interpreter.cpp
index c0b8bfebb43437..985d0b7c0ef311 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -193,6 +193,7 @@ IncrementalCompilerBuilder::CreateCpp() {
   Argv.push_back("-target");
   Argv.push_back("wasm32-unknown-emscripten");
   Argv.push_back("-shared");
+  Argv.push_back("-fvisibility=default");
 #endif
   Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
 
diff --git a/clang/lib/Interpreter/Wasm.cpp b/clang/lib/Interpreter/Wasm.cpp
index 79efbaa03982d0..aa10b160ccf847 100644
--- a/clang/lib/Interpreter/Wasm.cpp
+++ b/clang/lib/Interpreter/Wasm.cpp
@@ -23,6 +23,31 @@
 #include 
 
 namespace lld {
+enum Flavor {
+  Invalid,
+  Gnu, // -flavor gnu
+  MinGW,   // -flavor gnu MinGW
+  WinLink, // -flavor link
+  Darwin,  // -flavor darwin
+  Wasm,// -flavor wasm
+};
+
+using Driver = bool (*)(llvm::ArrayRef, llvm::raw_ostream &,
+llvm::raw_ostream &, bool, bool);
+
+struct DriverDef {
+  Flavor f;
+  Driver d;
+};
+
+struct Result {
+  int retCode;
+  bool canRunAgain;
+};
+
+Result lldMain(llvm::ArrayRef args, llvm::raw_ostream &stdoutOS,
+   llvm::raw_ostream &stderrOS, llvm::ArrayRef drivers);
+
 namespace wasm {
 bool link(llvm::ArrayRef args, llvm::raw_ostream &stdoutOS,
   llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
@@ -51,13 +76,14 @@ llvm::Error 
WasmIncrementalExecutor::addModule(PartialTranslationUnit &PTU) {
   llvm::TargetMachine *TargetMachine = Target->createTargetMachine(
   PTU.TheModule->getTargetTriple(), "", "", TO, llvm::Reloc::Model::PIC_);
   PTU.TheModule->setDataLayout(TargetMachine->createDataLayout());
-  std::string OutputFileName = PTU.TheModule->getName().str() + ".wasm";
+  std::string ObjectFileName = PTU.TheModule->getName().str() + ".o";
+  std::string BinaryFileName = PTU.TheModule->getName().str() + ".wasm";
 
   std::error_code Error;
-  llvm::raw_fd_ostream OutputFile(llvm::StringRef(OutputFileName), Error);
+  llvm::raw_fd_ostream ObjectFileOutput(llvm::StringRef(ObjectFileName), 
Error);
 
   llvm::legacy::PassManager PM;
-  if (TargetMachine->addPassesToEmitFile(PM, OutputFile, nullptr,
+  if (TargetMachine->addPassesToEmitFile(PM, ObjectFileOutput, nullptr,
  llvm::CodeGenFileType::ObjectFile)) {
 return llvm::make_error(
 "Wasm backend cannot produce object.", llvm::inconvertibleErrorCode());
@@ -69,27 +95,30 @@ llvm::Error 
WasmIncrementalExecutor::addModule(PartialTranslationUnit &PTU) {
llvm::inconvertibleErrorCode());
   }
 
-  OutputFile.close();
+  ObjectFileOutput.close();
 
   std::vector LinkerArgs = {"wasm-ld",
   "-shared",
   "--import-memory",
-  "--no-entry",
-  "--export-all",
   "--experimental-pic",
   "--stack-first",
   "--allow-undefined",
-  OutputFileName.c_str(),
+  ObjectFileName.c_str(),
   "-o",
-  OutputFileName.c_str()};
-  int Result =
-  lld::wasm::link(LinkerArgs, llvm::outs(), llvm::errs(), false, false);
-  if (!Result)
+   

[llvm-branch-commits] [clang] release/19.x: [clang-repl] Fix generation of wasm binaries while running clang-repl in browser (#117978) (PR #118077)

2024-11-29 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: None (llvmbot)


Changes

Backport a174aa1e416c4e27945f5a8c646b119126dc8441

Requested by: @anutosh491

---
Full diff: https://github.com/llvm/llvm-project/pull/118077.diff


3 Files Affected:

- (modified) clang/lib/Interpreter/CMakeLists.txt (+2) 
- (modified) clang/lib/Interpreter/Interpreter.cpp (+1) 
- (modified) clang/lib/Interpreter/Wasm.cpp (+43-14) 


``diff
diff --git a/clang/lib/Interpreter/CMakeLists.txt 
b/clang/lib/Interpreter/CMakeLists.txt
index 0a2d60757c216d..85efa4b0f984f4 100644
--- a/clang/lib/Interpreter/CMakeLists.txt
+++ b/clang/lib/Interpreter/CMakeLists.txt
@@ -15,6 +15,7 @@ set(LLVM_LINK_COMPONENTS
 if (EMSCRIPTEN AND "lld" IN_LIST LLVM_ENABLE_PROJECTS)
   set(WASM_SRC Wasm.cpp)
   set(WASM_LINK lldWasm)
+  set(COMMON_LINK lldCommon)
 endif()
 
 add_clang_library(clangInterpreter
@@ -45,6 +46,7 @@ add_clang_library(clangInterpreter
   clangSema
   clangSerialization
   ${WASM_LINK}
+  ${COMMON_LINK}
   )
 
 if ((MINGW OR CYGWIN) AND BUILD_SHARED_LIBS)
diff --git a/clang/lib/Interpreter/Interpreter.cpp 
b/clang/lib/Interpreter/Interpreter.cpp
index c0b8bfebb43437..985d0b7c0ef311 100644
--- a/clang/lib/Interpreter/Interpreter.cpp
+++ b/clang/lib/Interpreter/Interpreter.cpp
@@ -193,6 +193,7 @@ IncrementalCompilerBuilder::CreateCpp() {
   Argv.push_back("-target");
   Argv.push_back("wasm32-unknown-emscripten");
   Argv.push_back("-shared");
+  Argv.push_back("-fvisibility=default");
 #endif
   Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
 
diff --git a/clang/lib/Interpreter/Wasm.cpp b/clang/lib/Interpreter/Wasm.cpp
index 79efbaa03982d0..aa10b160ccf847 100644
--- a/clang/lib/Interpreter/Wasm.cpp
+++ b/clang/lib/Interpreter/Wasm.cpp
@@ -23,6 +23,31 @@
 #include 
 
 namespace lld {
+enum Flavor {
+  Invalid,
+  Gnu, // -flavor gnu
+  MinGW,   // -flavor gnu MinGW
+  WinLink, // -flavor link
+  Darwin,  // -flavor darwin
+  Wasm,// -flavor wasm
+};
+
+using Driver = bool (*)(llvm::ArrayRef, llvm::raw_ostream &,
+llvm::raw_ostream &, bool, bool);
+
+struct DriverDef {
+  Flavor f;
+  Driver d;
+};
+
+struct Result {
+  int retCode;
+  bool canRunAgain;
+};
+
+Result lldMain(llvm::ArrayRef args, llvm::raw_ostream &stdoutOS,
+   llvm::raw_ostream &stderrOS, llvm::ArrayRef drivers);
+
 namespace wasm {
 bool link(llvm::ArrayRef args, llvm::raw_ostream &stdoutOS,
   llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
@@ -51,13 +76,14 @@ llvm::Error 
WasmIncrementalExecutor::addModule(PartialTranslationUnit &PTU) {
   llvm::TargetMachine *TargetMachine = Target->createTargetMachine(
   PTU.TheModule->getTargetTriple(), "", "", TO, llvm::Reloc::Model::PIC_);
   PTU.TheModule->setDataLayout(TargetMachine->createDataLayout());
-  std::string OutputFileName = PTU.TheModule->getName().str() + ".wasm";
+  std::string ObjectFileName = PTU.TheModule->getName().str() + ".o";
+  std::string BinaryFileName = PTU.TheModule->getName().str() + ".wasm";
 
   std::error_code Error;
-  llvm::raw_fd_ostream OutputFile(llvm::StringRef(OutputFileName), Error);
+  llvm::raw_fd_ostream ObjectFileOutput(llvm::StringRef(ObjectFileName), 
Error);
 
   llvm::legacy::PassManager PM;
-  if (TargetMachine->addPassesToEmitFile(PM, OutputFile, nullptr,
+  if (TargetMachine->addPassesToEmitFile(PM, ObjectFileOutput, nullptr,
  llvm::CodeGenFileType::ObjectFile)) {
 return llvm::make_error(
 "Wasm backend cannot produce object.", llvm::inconvertibleErrorCode());
@@ -69,27 +95,30 @@ llvm::Error 
WasmIncrementalExecutor::addModule(PartialTranslationUnit &PTU) {
llvm::inconvertibleErrorCode());
   }
 
-  OutputFile.close();
+  ObjectFileOutput.close();
 
   std::vector LinkerArgs = {"wasm-ld",
   "-shared",
   "--import-memory",
-  "--no-entry",
-  "--export-all",
   "--experimental-pic",
   "--stack-first",
   "--allow-undefined",
-  OutputFileName.c_str(),
+  ObjectFileName.c_str(),
   "-o",
-  OutputFileName.c_str()};
-  int Result =
-  lld::wasm::link(LinkerArgs, llvm::outs(), llvm::errs(), false, false);
-  if (!Result)
+  BinaryFileName.c_str()};
+
+  const lld::DriverDef WasmDriver = {lld::Flavor::Wasm, &lld::wasm::link};
+  std::vector WasmDriverArgs;
+  WasmDriverArgs.push_back(WasmDriver);
+  lld::Result Result =
+  lld::lldMain(LinkerArgs, llvm::outs(), llvm::errs(), WasmDriverArgs);
+
+  if (Re

[llvm-branch-commits] [clang] release/19.x: [clang-repl] Fix generation of wasm binaries while running clang-repl in browser (#117978) (PR #118077)

2024-11-29 Thread Vassil Vassilev via llvm-branch-commits

https://github.com/vgvassilev approved this pull request.

This is a low risk feature as it is maintained at a best effort basis at the 
moment. LGTM!

https://github.com/llvm/llvm-project/pull/118077
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] release/19.x: [clang-repl] Fix generation of wasm binaries while running clang-repl in browser (#117978) (PR #118077)

2024-11-29 Thread Anutosh Bhat via llvm-branch-commits

anutosh491 wrote:

Hi @tru 

Just curious as to know when a 19.1.5 release is scheduled ? 

https://github.com/llvm/llvm-project/pull/118077
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [compiler-rt] [TySan] Fix struct access with different bases (PR #108385)

2024-11-29 Thread via llvm-branch-commits

https://github.com/gbMattN updated 
https://github.com/llvm/llvm-project/pull/108385

>From 4f5a7f198988a45fe64b9d1ba88e68a6d7f14e32 Mon Sep 17 00:00:00 2001
From: Matthew Nagy 
Date: Thu, 12 Sep 2024 12:36:57 +
Subject: [PATCH 1/4] [TySan] Fix struct access with different bases

---
 compiler-rt/lib/tysan/tysan.cpp   |  5 +++
 .../tysan/struct-offset-different-base.cpp| 33 +++
 2 files changed, 38 insertions(+)
 create mode 100644 compiler-rt/test/tysan/struct-offset-different-base.cpp

diff --git a/compiler-rt/lib/tysan/tysan.cpp b/compiler-rt/lib/tysan/tysan.cpp
index f1b6bdcf0d8261..c339a0fca11397 100644
--- a/compiler-rt/lib/tysan/tysan.cpp
+++ b/compiler-rt/lib/tysan/tysan.cpp
@@ -129,6 +129,11 @@ static bool isAliasingLegalUp(tysan_type_descriptor *TDA,
   break;
   }
 
+  // This offset can't be negative. Therefore we must be accessing 
something
+  // partially inside the last type
+  if (TDA->Struct.Members[Idx].Offset > OffsetA)
+Idx -= 1;
+
   OffsetA -= TDA->Struct.Members[Idx].Offset;
   TDA = TDA->Struct.Members[Idx].Type;
 } else {
diff --git a/compiler-rt/test/tysan/struct-offset-different-base.cpp 
b/compiler-rt/test/tysan/struct-offset-different-base.cpp
new file mode 100644
index 00..3e1d6f2a6a42f5
--- /dev/null
+++ b/compiler-rt/test/tysan/struct-offset-different-base.cpp
@@ -0,0 +1,33 @@
+// RUN: %clangxx_tysan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+
+// Modified reproducer from https://github.com/llvm/llvm-project/issues/105960
+
+#include 
+
+struct inner {
+   char buffer;
+   int i;
+};
+
+void init_inner(inner *iPtr) {
+   iPtr->i = 0;
+}
+
+struct outer {
+   inner foo;
+char buffer;
+};
+
+int main(void) {
+outer *l = new outer();
+
+init_inner(&l->foo);
+
+int access_offsets_with_different_base = l->foo.i;
+printf("%d\n", access_offsets_with_different_base);
+
+return 0;
+}
+
+// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation

>From 6f795458c4c16522533dbdcb4d8ace299bfda9ff Mon Sep 17 00:00:00 2001
From: gbMattN 
Date: Tue, 12 Nov 2024 17:05:44 +
Subject: [PATCH 2/4] Changed test to check for output

---
 compiler-rt/test/tysan/struct-offset-different-base.cpp | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/compiler-rt/test/tysan/struct-offset-different-base.cpp 
b/compiler-rt/test/tysan/struct-offset-different-base.cpp
index 3e1d6f2a6a42f5..4563f7025bea48 100644
--- a/compiler-rt/test/tysan/struct-offset-different-base.cpp
+++ b/compiler-rt/test/tysan/struct-offset-different-base.cpp
@@ -1,5 +1,5 @@
 // RUN: %clangxx_tysan -O0 %s -o %t && %run %t >%t.out 2>&1
-// RUN: FileCheck %s < %t.out
+// RUN: FileCheck %s --implicit-check-not ERROR < %t.out
 
 // Modified reproducer from https://github.com/llvm/llvm-project/issues/105960
 
@@ -11,7 +11,7 @@ struct inner {
 };
 
 void init_inner(inner *iPtr) {
-   iPtr->i = 0;
+   iPtr->i = 200;
 }
 
 struct outer {
@@ -25,9 +25,9 @@ int main(void) {
 init_inner(&l->foo);
 
 int access_offsets_with_different_base = l->foo.i;
-printf("%d\n", access_offsets_with_different_base);
+printf("Accessed value is %d\n", access_offsets_with_different_base);
 
 return 0;
 }
 
-// CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation
+// CHECK: Accessed value is 200

>From 3e2499197f82a53d8eb44239598d5276638a80f9 Mon Sep 17 00:00:00 2001
From: gbMattN 
Date: Tue, 26 Nov 2024 16:44:43 +
Subject: [PATCH 3/4] More format changes

---
 compiler-rt/lib/tysan/tysan.cpp   |  2 +-
 .../tysan/struct-offset-different-base.cpp| 28 +--
 2 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/compiler-rt/lib/tysan/tysan.cpp b/compiler-rt/lib/tysan/tysan.cpp
index c339a0fca11397..c032bd1c0a5f7c 100644
--- a/compiler-rt/lib/tysan/tysan.cpp
+++ b/compiler-rt/lib/tysan/tysan.cpp
@@ -133,7 +133,7 @@ static bool isAliasingLegalUp(tysan_type_descriptor *TDA,
   // partially inside the last type
   if (TDA->Struct.Members[Idx].Offset > OffsetA)
 Idx -= 1;
-
+
   OffsetA -= TDA->Struct.Members[Idx].Offset;
   TDA = TDA->Struct.Members[Idx].Type;
 } else {
diff --git a/compiler-rt/test/tysan/struct-offset-different-base.cpp 
b/compiler-rt/test/tysan/struct-offset-different-base.cpp
index 4563f7025bea48..da0efd2cb6503c 100644
--- a/compiler-rt/test/tysan/struct-offset-different-base.cpp
+++ b/compiler-rt/test/tysan/struct-offset-different-base.cpp
@@ -6,28 +6,26 @@
 #include 
 
 struct inner {
-   char buffer;
-   int i;
+  char buffer;
+  int i;
 };
 
-void init_inner(inner *iPtr) {
-   iPtr->i = 200;
-}
+void init_inner(inner *iPtr) { iPtr->i = 200; }
 
 struct outer {
-   inner foo;
-char buffer;
+  inner foo;
+  char buffer;
 };
 
 int main(void) {
-outer *l = new outer();
-
-init_inner(&l->foo);
-
-i

[llvm-branch-commits] [compiler-rt] [TySan] Fixed false positive when accessing offset member variables (PR #95387)

2024-11-29 Thread via llvm-branch-commits

https://github.com/gbMattN updated 
https://github.com/llvm/llvm-project/pull/95387

>From 620ee820a39ac1e92ee86f64d290ad32b8d426be Mon Sep 17 00:00:00 2001
From: Matthew Nagy 
Date: Fri, 28 Jun 2024 16:12:31 +
Subject: [PATCH 1/2] [TySan] Fixed false positive when accessing global
 object's member variables

---
 compiler-rt/lib/tysan/tysan.cpp   | 19 +++-
 .../test/tysan/global-struct-members.c| 31 +++
 2 files changed, 49 insertions(+), 1 deletion(-)
 create mode 100644 compiler-rt/test/tysan/global-struct-members.c

diff --git a/compiler-rt/lib/tysan/tysan.cpp b/compiler-rt/lib/tysan/tysan.cpp
index f1b6bdcf0d8261..5ba967c0782e08 100644
--- a/compiler-rt/lib/tysan/tysan.cpp
+++ b/compiler-rt/lib/tysan/tysan.cpp
@@ -226,7 +226,24 @@ __tysan_check(void *addr, int size, tysan_type_descriptor 
*td, int flags) {
 OldTDPtr -= i;
 OldTD = *OldTDPtr;
 
-if (!isAliasingLegal(td, OldTD, i))
+// When shadow memory is set for global objects, the entire object is 
tagged with the struct type
+// This means that when you access a member variable, tysan reads that as 
you accessing a struct midway
+// through, with 'i' being the offset
+// Therefore, if you are accessing a struct, we need to find the member 
type. We can go through the
+// members of the struct type and see if there is a member at the offset 
you are accessing the struct by.
+// If there is indeed a member starting at offset 'i' in the struct, we 
should check aliasing legality
+// with that type. If there isn't, we run alias checking on the struct 
with will give us the correct error.
+tysan_type_descriptor *InternalMember = OldTD;
+if (OldTD->Tag == TYSAN_STRUCT_TD) {
+  for (int j = 0; j < OldTD->Struct.MemberCount; j++) {
+if (OldTD->Struct.Members[j].Offset == i) {
+  InternalMember = OldTD->Struct.Members[j].Type;
+  break;
+}
+  }
+}
+
+if (!isAliasingLegal(td, InternalMember, i))
   reportError(addr, size, td, OldTD, AccessStr,
   "accesses part of an existing object", -i, pc, bp, sp);
 
diff --git a/compiler-rt/test/tysan/global-struct-members.c 
b/compiler-rt/test/tysan/global-struct-members.c
new file mode 100644
index 00..76ea3c431dd7bc
--- /dev/null
+++ b/compiler-rt/test/tysan/global-struct-members.c
@@ -0,0 +1,31 @@
+// RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+
+#include 
+
+struct X {
+  int a, b, c;
+} x;
+
+static struct X xArray[2];
+
+int main() {
+  x.a = 1;
+  x.b = 2;
+  x.c = 3;
+
+  printf("%d %d %d\n", x.a, x.b, x.c);
+  // CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation
+
+  for (size_t i = 0; i < 2; i++) {
+xArray[i].a = 1;
+xArray[i].b = 1;
+xArray[i].c = 1;
+  }
+
+  struct X *xPtr = (struct X *)&(xArray[0].c);
+  xPtr->a = 1;
+  // CHECK: ERROR: TypeSanitizer: type-aliasing-violation
+  // CHECK: WRITE of size 4 at {{.*}} with type int (in X at offset 0) 
accesses an existing object of type int (in X at offset 8)
+  // CHECK: {{#0 0x.* in main .*struct-members.c:}}[[@LINE-3]]
+}

>From 9a2c70c7e6c8e78116068b729d129f152bc398b6 Mon Sep 17 00:00:00 2001
From: gbMattN 
Date: Tue, 12 Nov 2024 16:52:27 +
Subject: [PATCH 2/2] [style] Tidied up comments, formatting, and polished test

---
 compiler-rt/lib/tysan/tysan.cpp   | 24 ++-
 .../test/tysan/global-struct-members.c|  7 +++---
 2 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/compiler-rt/lib/tysan/tysan.cpp b/compiler-rt/lib/tysan/tysan.cpp
index 5ba967c0782e08..d9029751208ea9 100644
--- a/compiler-rt/lib/tysan/tysan.cpp
+++ b/compiler-rt/lib/tysan/tysan.cpp
@@ -226,24 +226,26 @@ __tysan_check(void *addr, int size, tysan_type_descriptor 
*td, int flags) {
 OldTDPtr -= i;
 OldTD = *OldTDPtr;
 
-// When shadow memory is set for global objects, the entire object is 
tagged with the struct type
-// This means that when you access a member variable, tysan reads that as 
you accessing a struct midway
-// through, with 'i' being the offset
-// Therefore, if you are accessing a struct, we need to find the member 
type. We can go through the
-// members of the struct type and see if there is a member at the offset 
you are accessing the struct by.
-// If there is indeed a member starting at offset 'i' in the struct, we 
should check aliasing legality
-// with that type. If there isn't, we run alias checking on the struct 
with will give us the correct error.
-tysan_type_descriptor *InternalMember = OldTD;
+// When shadow memory is set for global objects, the entire object is 
tagged
+// with the struct type This means that when you access a member variable,
+// tysan reads that as you accessing a struct midway through, with 'i' 
being
+// the offset Therefore, if you are accessing a struct, we need to find the
+// member type. W

[llvm-branch-commits] [flang] [flang][hlfir] optimize hlfir.eval_in_mem bufferization (PR #118069)

2024-11-29 Thread Tom Eccles via llvm-branch-commits

https://github.com/tblah approved this pull request.

LGTM. Just some nitpicks. It is really good seeing how cleanly HLFIR extends to 
this new optimization.

https://github.com/llvm/llvm-project/pull/118069
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [flang] [flang][hlfir] optimize hlfir.eval_in_mem bufferization (PR #118069)

2024-11-29 Thread Tom Eccles via llvm-branch-commits

https://github.com/tblah edited https://github.com/llvm/llvm-project/pull/118069
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [flang] [flang][hlfir] optimize hlfir.eval_in_mem bufferization (PR #118069)

2024-11-29 Thread Tom Eccles via llvm-branch-commits


@@ -1108,6 +1108,113 @@ class ReductionMaskConversion : public 
mlir::OpRewritePattern {
   }
 };
 
+class EvaluateIntoMemoryAssignBufferization
+: public mlir::OpRewritePattern {
+
+public:
+  using mlir::OpRewritePattern::OpRewritePattern;
+
+  llvm::LogicalResult
+  matchAndRewrite(hlfir::EvaluateInMemoryOp,
+  mlir::PatternRewriter &rewriter) const override;
+};
+
+static bool mayReadOrWrite(mlir::Region ®ion, mlir::Value var) {

tblah wrote:

Please could you add documentation explaining that the side effects you are 
interested in cannot be modeled by `mlir::MemoryEffectOpInterface`. Without 
that information this function is surprising because it is checking mlir memory 
effect interfaces but without using the read or write effects from that 
interface (instead using the alias analysis to determine memory effects).

Maybe we need something in the name to make is clear this uses the high-cost 
high-precision model as a fallback when more precision is needed than just 
querying the mlir memory effects. Perhaps `mayReadOrWriteAA`.

https://github.com/llvm/llvm-project/pull/118069
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [flang] [flang][hlfir] optimize hlfir.eval_in_mem bufferization (PR #118069)

2024-11-29 Thread Tom Eccles via llvm-branch-commits


@@ -1108,6 +1108,113 @@ class ReductionMaskConversion : public 
mlir::OpRewritePattern {
   }
 };
 
+class EvaluateIntoMemoryAssignBufferization
+: public mlir::OpRewritePattern {
+
+public:
+  using mlir::OpRewritePattern::OpRewritePattern;
+
+  llvm::LogicalResult
+  matchAndRewrite(hlfir::EvaluateInMemoryOp,
+  mlir::PatternRewriter &rewriter) const override;
+};
+
+static bool mayReadOrWrite(mlir::Region ®ion, mlir::Value var) {
+  fir::AliasAnalysis aliasAnalysis;
+  for (mlir::Operation &op : region.getOps()) {
+if (op.hasTrait()) {
+  for (mlir::Region &subRegion : op.getRegions())
+if (mayReadOrWrite(subRegion, var))
+  return true;
+  // In MLIR, RecursiveMemoryEffects can be combined with
+  // MemoryEffectOpInterface to describe extra effects on top of the
+  // effects of the nested operations.  However, the presence of
+  // RecursiveMemoryEffects and the absence of MemoryEffectOpInterface
+  // implies the operation has no other memory effects than the one of its
+  // nested operations.
+  if (!mlir::isa(op))
+continue;
+}
+if (!aliasAnalysis.getModRef(&op, var).isNoModRef())
+  return true;
+  }
+  return false;
+}
+
+static llvm::LogicalResult
+tryUsingAssignLhsDirectly(hlfir::EvaluateInMemoryOp evalInMem,
+  mlir::PatternRewriter &rewriter) {
+  mlir::Location loc = evalInMem.getLoc();
+  hlfir::DestroyOp destroy;
+  hlfir::AssignOp assign;
+  for (auto user : llvm::enumerate(evalInMem->getUsers())) {
+if (user.index() > 2)
+  return mlir::failure();
+mlir::TypeSwitch(user.value())
+.Case([&](hlfir::AssignOp op) { assign = op; })
+.Case([&](hlfir::DestroyOp op) { destroy = op; });
+  }
+  if (!assign || !destroy || destroy.mustFinalizeExpr() ||
+  assign.isAllocatableAssignment())
+return mlir::failure();
+
+  hlfir::Entity lhs{assign.getLhs()};
+  // EvaluateInMemoryOp memory is contiguous, so in general, it can only be
+  // replace by the LHS if the LHS is contiguous.
+  if (!lhs.isSimplyContiguous())
+return mlir::failure();
+  // Character assignment may involves truncation/padding, so the LHS
+  // cannot be used to evaluate RHS in place without proving the LHS and
+  // RHS lengths are the same.
+  if (lhs.isCharacter())
+return mlir::failure();
+
+  // The region must not read or write the LHS.
+  if (mayReadOrWrite(evalInMem.getBody(), lhs))

tblah wrote:

Please could you add a comment explaining that currently this is used for 
optimizing function calls, and mlir memory effects aren't helpful for fir.call 
so there's no benefit in first filtering by mlir memory effects as is done 
below.

https://github.com/llvm/llvm-project/pull/118069
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [flang] [flang] optimize array function calls using hlfir.eval_in_mem (PR #118070)

2024-11-29 Thread Tom Eccles via llvm-branch-commits


@@ -134,7 +134,7 @@ end function f
 !CHECK-NEXT: run 1 save: where/mask
 !CHECK-NEXT: run 2 evaluate: where/region_assign1
 !CHECK-LABEL:  scheduling where in _QPonly_once 
-!CHECK-NEXT: unknown effect: %{{[0-9]+}} = llvm.intr.stacksave : !llvm.ptr
+!CHECK-NEXT: unknown effect: %11 = fir.call @_QPcall_me_only_once() 
fastmath : () -> !fir.array<10x!fir.logical<4>>

tblah wrote:

Why did this change?

https://github.com/llvm/llvm-project/pull/118070
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [flang] [flang] optimize array function calls using hlfir.eval_in_mem (PR #118070)

2024-11-29 Thread Tom Eccles via llvm-branch-commits


@@ -24,6 +24,10 @@
 
 namespace Fortran::lower {
 
+struct LoweredResult {
+  std::variant result;
+};

tblah wrote:

nit: Could this be simplified to
```c++
using LoweredResult = std::variant result;
```

This way callers wouldn't have to add a `.result`. 

https://github.com/llvm/llvm-project/pull/118070
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [flang] [flang] optimize array function calls using hlfir.eval_in_mem (PR #118070)

2024-11-29 Thread via llvm-branch-commits


@@ -134,7 +134,7 @@ end function f
 !CHECK-NEXT: run 1 save: where/mask
 !CHECK-NEXT: run 2 evaluate: where/region_assign1
 !CHECK-LABEL:  scheduling where in _QPonly_once 
-!CHECK-NEXT: unknown effect: %{{[0-9]+}} = llvm.intr.stacksave : !llvm.ptr
+!CHECK-NEXT: unknown effect: %11 = fir.call @_QPcall_me_only_once() 
fastmath : () -> !fir.array<10x!fir.logical<4>>

jeanPerier wrote:

Because the llvm.intr.stacksave is not emitted anymore (at that point and in 
general).

At the point of the pipeline where the FORALL/WHERE logic is 
optimized/implemented, the call is now wrapped inside an hlfir.eval_in_mem, so 
it has not yet been decided if and how to allocate the storage, so there is no 
point emitting those ops in lowering anymore.

In general because hlfir.eval_in_mem now uses heap allocation for dynamically 
sized results like all other temps created in bufferization (it is more 
consistent and easier).

The analysis stops at the first unknow side effects, so the unknown side effect 
of the function call is not new, but it is now the first one encountered (which 
is an improvement if anything).

https://github.com/llvm/llvm-project/pull/118070
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [flang] [flang][OpenMP] Use new modifiers in IF/LASTPRIVATE (PR #118128)

2024-11-29 Thread Krzysztof Parzyszek via llvm-branch-commits

https://github.com/kparzysz created 
https://github.com/llvm/llvm-project/pull/118128

The usual changes, added more references to OpenMP specs.

>From cfcf8d1e7ffdcec92dc0dfffccb3c620a2df804f Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek 
Date: Wed, 27 Nov 2024 08:34:33 -0600
Subject: [PATCH] [flang][OpenMP] Use new modifiers in IF/LASTPRIVATE

The usual changes, added more references to OpenMP specs.
---
 flang/examples/FeatureList/FeatureList.cpp|   3 +-
 .../FlangOmpReport/FlangOmpReportVisitor.cpp  |   5 +-
 .../FlangOmpReport/FlangOmpReportVisitor.h|   2 +-
 flang/include/flang/Parser/dump-parse-tree.h  |   7 +-
 flang/include/flang/Parser/parse-tree.h   |  50 ++--
 .../flang/Semantics/openmp-modifiers.h|   2 +
 flang/lib/Lower/OpenMP/Clauses.cpp|  36 ++
 flang/lib/Parser/CMakeLists.txt   |   1 +
 flang/lib/Parser/openmp-parsers.cpp   |  73 ---
 flang/lib/Parser/unparse.cpp  |  15 ++-
 flang/lib/Semantics/check-omp-structure.cpp   | 121 +++---
 flang/lib/Semantics/openmp-modifiers.cpp  |  34 +
 .../test/Parser/OpenMP/if-clause-unparse.f90  |  20 +--
 flang/test/Parser/OpenMP/if-clause.f90|  22 ++--
 .../test/Parser/OpenMP/lastprivate-clause.f90 |   4 +-
 .../Semantics/OpenMP/clause-validity01.f90|   4 +-
 flang/test/Semantics/OpenMP/if-clause.f90 |  64 -
 17 files changed, 297 insertions(+), 166 deletions(-)

diff --git a/flang/examples/FeatureList/FeatureList.cpp 
b/flang/examples/FeatureList/FeatureList.cpp
index c5cb8c8fdf40bb..41a6255207976d 100644
--- a/flang/examples/FeatureList/FeatureList.cpp
+++ b/flang/examples/FeatureList/FeatureList.cpp
@@ -492,7 +492,8 @@ struct NodeVisitor {
   READ_FEATURE(OmpPrescriptiveness)
   READ_FEATURE(OmpPrescriptiveness::Value)
   READ_FEATURE(OmpIfClause)
-  READ_FEATURE(OmpIfClause::DirectiveNameModifier)
+  READ_FEATURE(OmpIfClause::Modifier)
+  READ_FEATURE(OmpDirectiveNameModifier)
   READ_FEATURE(OmpLinearClause)
   READ_FEATURE(OmpLinearClause::WithModifier)
   READ_FEATURE(OmpLinearClause::WithoutModifier)
diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp 
b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
index afabd564ad5bdc..2dc480f0c901b1 100644
--- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
+++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
@@ -8,6 +8,7 @@
 
 #include "FlangOmpReportVisitor.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Frontend/OpenMP/OMP.h"
 
 namespace Fortran {
 namespace parser {
@@ -238,9 +239,9 @@ void OpenMPCounterVisitor::Post(const 
OmpScheduleClause::Kind &c) {
   clauseDetails +=
   "type=" + std::string{OmpScheduleClause::EnumToString(c)} + ";";
 }
-void OpenMPCounterVisitor::Post(const OmpIfClause::DirectiveNameModifier &c) {
+void OpenMPCounterVisitor::Post(const OmpDirectiveNameModifier &c) {
   clauseDetails +=
-  "name_modifier=" + std::string{OmpIfClause::EnumToString(c)} + ";";
+  "name_modifier=" + llvm::omp::getOpenMPDirectiveName(c.v).str() + ";";
 }
 void OpenMPCounterVisitor::Post(const OmpCancelType::Type &c) {
   clauseDetails += "type=" + std::string{OmpCancelType::EnumToString(c)} + ";";
diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h 
b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
index ed202e8ed2a4c7..59bdac8594cb7c 100644
--- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
+++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
@@ -77,7 +77,7 @@ struct OpenMPCounterVisitor {
   void Post(const OmpTaskDependenceType::Value &c);
   void Post(const OmpMapType::Value &c);
   void Post(const OmpScheduleClause::Kind &c);
-  void Post(const OmpIfClause::DirectiveNameModifier &c);
+  void Post(const OmpDirectiveNameModifier &c);
   void Post(const OmpCancelType::Type &c);
   void Post(const OmpClause &c);
   void PostClauseCommon(const ClauseInfo &ci);
diff --git a/flang/include/flang/Parser/dump-parse-tree.h 
b/flang/include/flang/Parser/dump-parse-tree.h
index 1ec38de29b85d6..b0b8d8d7ccc556 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -548,10 +548,13 @@ class ParseTreeDumper {
   NODE(OmpFromClause, Modifier)
   NODE(parser, OmpExpectation)
   NODE_ENUM(OmpExpectation, Value)
+  NODE(parser, OmpDirectiveNameModifier)
   NODE(parser, OmpIfClause)
-  NODE_ENUM(OmpIfClause, DirectiveNameModifier)
-  NODE_ENUM(OmpLastprivateClause, LastprivateModifier)
+  NODE(OmpIfClause, Modifier)
   NODE(parser, OmpLastprivateClause)
+  NODE(OmpLastprivateClause, Modifier)
+  NODE(parser, OmpLastprivateModifier)
+  NODE_ENUM(OmpLastprivateModifier, Value)
   NODE(parser, OmpLinearClause)
   NODE(OmpLinearClause, WithModifier)
   NODE(OmpLinearClause, WithoutModifier)
diff --git a/flang/include/flang/Parser/parse-tree.h 
b/flang/include/flang/Parser/parse-tree.h
index c00560b1f1726a..06c32831d2c60c 100644
--- a/flang

[llvm-branch-commits] [flang] [flang][OpenMP] Use new modifiers in IF/LASTPRIVATE (PR #118128)

2024-11-29 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-flang-semantics

Author: Krzysztof Parzyszek (kparzysz)


Changes

The usual changes, added more references to OpenMP specs.

---

Patch is 42.91 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/118128.diff


17 Files Affected:

- (modified) flang/examples/FeatureList/FeatureList.cpp (+2-1) 
- (modified) flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp (+3-2) 
- (modified) flang/examples/FlangOmpReport/FlangOmpReportVisitor.h (+1-1) 
- (modified) flang/include/flang/Parser/dump-parse-tree.h (+5-2) 
- (modified) flang/include/flang/Parser/parse-tree.h (+41-9) 
- (modified) flang/include/flang/Semantics/openmp-modifiers.h (+2) 
- (modified) flang/lib/Lower/OpenMP/Clauses.cpp (+11-25) 
- (modified) flang/lib/Parser/CMakeLists.txt (+1) 
- (modified) flang/lib/Parser/openmp-parsers.cpp (+55-18) 
- (modified) flang/lib/Parser/unparse.cpp (+8-7) 
- (modified) flang/lib/Semantics/check-omp-structure.cpp (+77-44) 
- (modified) flang/lib/Semantics/openmp-modifiers.cpp (+34) 
- (modified) flang/test/Parser/OpenMP/if-clause-unparse.f90 (+10-10) 
- (modified) flang/test/Parser/OpenMP/if-clause.f90 (+11-11) 
- (modified) flang/test/Parser/OpenMP/lastprivate-clause.f90 (+2-2) 
- (modified) flang/test/Semantics/OpenMP/clause-validity01.f90 (+2-2) 
- (modified) flang/test/Semantics/OpenMP/if-clause.f90 (+32-32) 


``diff
diff --git a/flang/examples/FeatureList/FeatureList.cpp 
b/flang/examples/FeatureList/FeatureList.cpp
index c5cb8c8fdf40bb..41a6255207976d 100644
--- a/flang/examples/FeatureList/FeatureList.cpp
+++ b/flang/examples/FeatureList/FeatureList.cpp
@@ -492,7 +492,8 @@ struct NodeVisitor {
   READ_FEATURE(OmpPrescriptiveness)
   READ_FEATURE(OmpPrescriptiveness::Value)
   READ_FEATURE(OmpIfClause)
-  READ_FEATURE(OmpIfClause::DirectiveNameModifier)
+  READ_FEATURE(OmpIfClause::Modifier)
+  READ_FEATURE(OmpDirectiveNameModifier)
   READ_FEATURE(OmpLinearClause)
   READ_FEATURE(OmpLinearClause::WithModifier)
   READ_FEATURE(OmpLinearClause::WithoutModifier)
diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp 
b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
index afabd564ad5bdc..2dc480f0c901b1 100644
--- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
+++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
@@ -8,6 +8,7 @@
 
 #include "FlangOmpReportVisitor.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Frontend/OpenMP/OMP.h"
 
 namespace Fortran {
 namespace parser {
@@ -238,9 +239,9 @@ void OpenMPCounterVisitor::Post(const 
OmpScheduleClause::Kind &c) {
   clauseDetails +=
   "type=" + std::string{OmpScheduleClause::EnumToString(c)} + ";";
 }
-void OpenMPCounterVisitor::Post(const OmpIfClause::DirectiveNameModifier &c) {
+void OpenMPCounterVisitor::Post(const OmpDirectiveNameModifier &c) {
   clauseDetails +=
-  "name_modifier=" + std::string{OmpIfClause::EnumToString(c)} + ";";
+  "name_modifier=" + llvm::omp::getOpenMPDirectiveName(c.v).str() + ";";
 }
 void OpenMPCounterVisitor::Post(const OmpCancelType::Type &c) {
   clauseDetails += "type=" + std::string{OmpCancelType::EnumToString(c)} + ";";
diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h 
b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
index ed202e8ed2a4c7..59bdac8594cb7c 100644
--- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
+++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
@@ -77,7 +77,7 @@ struct OpenMPCounterVisitor {
   void Post(const OmpTaskDependenceType::Value &c);
   void Post(const OmpMapType::Value &c);
   void Post(const OmpScheduleClause::Kind &c);
-  void Post(const OmpIfClause::DirectiveNameModifier &c);
+  void Post(const OmpDirectiveNameModifier &c);
   void Post(const OmpCancelType::Type &c);
   void Post(const OmpClause &c);
   void PostClauseCommon(const ClauseInfo &ci);
diff --git a/flang/include/flang/Parser/dump-parse-tree.h 
b/flang/include/flang/Parser/dump-parse-tree.h
index 1ec38de29b85d6..b0b8d8d7ccc556 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -548,10 +548,13 @@ class ParseTreeDumper {
   NODE(OmpFromClause, Modifier)
   NODE(parser, OmpExpectation)
   NODE_ENUM(OmpExpectation, Value)
+  NODE(parser, OmpDirectiveNameModifier)
   NODE(parser, OmpIfClause)
-  NODE_ENUM(OmpIfClause, DirectiveNameModifier)
-  NODE_ENUM(OmpLastprivateClause, LastprivateModifier)
+  NODE(OmpIfClause, Modifier)
   NODE(parser, OmpLastprivateClause)
+  NODE(OmpLastprivateClause, Modifier)
+  NODE(parser, OmpLastprivateModifier)
+  NODE_ENUM(OmpLastprivateModifier, Value)
   NODE(parser, OmpLinearClause)
   NODE(OmpLinearClause, WithModifier)
   NODE(OmpLinearClause, WithoutModifier)
diff --git a/flang/include/flang/Parser/parse-tree.h 
b/flang/include/flang/Parser/parse-tree.h
index c00560b1f1726a..06c32831d2c60c 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang

[llvm-branch-commits] [flang] [flang][OpenMP] Use new modifiers in IF/LASTPRIVATE (PR #118128)

2024-11-29 Thread Krzysztof Parzyszek via llvm-branch-commits

https://github.com/kparzysz updated 
https://github.com/llvm/llvm-project/pull/118128

>From cfcf8d1e7ffdcec92dc0dfffccb3c620a2df804f Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek 
Date: Wed, 27 Nov 2024 08:34:33 -0600
Subject: [PATCH 1/2] [flang][OpenMP] Use new modifiers in IF/LASTPRIVATE

The usual changes, added more references to OpenMP specs.
---
 flang/examples/FeatureList/FeatureList.cpp|   3 +-
 .../FlangOmpReport/FlangOmpReportVisitor.cpp  |   5 +-
 .../FlangOmpReport/FlangOmpReportVisitor.h|   2 +-
 flang/include/flang/Parser/dump-parse-tree.h  |   7 +-
 flang/include/flang/Parser/parse-tree.h   |  50 ++--
 .../flang/Semantics/openmp-modifiers.h|   2 +
 flang/lib/Lower/OpenMP/Clauses.cpp|  36 ++
 flang/lib/Parser/CMakeLists.txt   |   1 +
 flang/lib/Parser/openmp-parsers.cpp   |  73 ---
 flang/lib/Parser/unparse.cpp  |  15 ++-
 flang/lib/Semantics/check-omp-structure.cpp   | 121 +++---
 flang/lib/Semantics/openmp-modifiers.cpp  |  34 +
 .../test/Parser/OpenMP/if-clause-unparse.f90  |  20 +--
 flang/test/Parser/OpenMP/if-clause.f90|  22 ++--
 .../test/Parser/OpenMP/lastprivate-clause.f90 |   4 +-
 .../Semantics/OpenMP/clause-validity01.f90|   4 +-
 flang/test/Semantics/OpenMP/if-clause.f90 |  64 -
 17 files changed, 297 insertions(+), 166 deletions(-)

diff --git a/flang/examples/FeatureList/FeatureList.cpp 
b/flang/examples/FeatureList/FeatureList.cpp
index c5cb8c8fdf40bb..41a6255207976d 100644
--- a/flang/examples/FeatureList/FeatureList.cpp
+++ b/flang/examples/FeatureList/FeatureList.cpp
@@ -492,7 +492,8 @@ struct NodeVisitor {
   READ_FEATURE(OmpPrescriptiveness)
   READ_FEATURE(OmpPrescriptiveness::Value)
   READ_FEATURE(OmpIfClause)
-  READ_FEATURE(OmpIfClause::DirectiveNameModifier)
+  READ_FEATURE(OmpIfClause::Modifier)
+  READ_FEATURE(OmpDirectiveNameModifier)
   READ_FEATURE(OmpLinearClause)
   READ_FEATURE(OmpLinearClause::WithModifier)
   READ_FEATURE(OmpLinearClause::WithoutModifier)
diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp 
b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
index afabd564ad5bdc..2dc480f0c901b1 100644
--- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
+++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
@@ -8,6 +8,7 @@
 
 #include "FlangOmpReportVisitor.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Frontend/OpenMP/OMP.h"
 
 namespace Fortran {
 namespace parser {
@@ -238,9 +239,9 @@ void OpenMPCounterVisitor::Post(const 
OmpScheduleClause::Kind &c) {
   clauseDetails +=
   "type=" + std::string{OmpScheduleClause::EnumToString(c)} + ";";
 }
-void OpenMPCounterVisitor::Post(const OmpIfClause::DirectiveNameModifier &c) {
+void OpenMPCounterVisitor::Post(const OmpDirectiveNameModifier &c) {
   clauseDetails +=
-  "name_modifier=" + std::string{OmpIfClause::EnumToString(c)} + ";";
+  "name_modifier=" + llvm::omp::getOpenMPDirectiveName(c.v).str() + ";";
 }
 void OpenMPCounterVisitor::Post(const OmpCancelType::Type &c) {
   clauseDetails += "type=" + std::string{OmpCancelType::EnumToString(c)} + ";";
diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h 
b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
index ed202e8ed2a4c7..59bdac8594cb7c 100644
--- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
+++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h
@@ -77,7 +77,7 @@ struct OpenMPCounterVisitor {
   void Post(const OmpTaskDependenceType::Value &c);
   void Post(const OmpMapType::Value &c);
   void Post(const OmpScheduleClause::Kind &c);
-  void Post(const OmpIfClause::DirectiveNameModifier &c);
+  void Post(const OmpDirectiveNameModifier &c);
   void Post(const OmpCancelType::Type &c);
   void Post(const OmpClause &c);
   void PostClauseCommon(const ClauseInfo &ci);
diff --git a/flang/include/flang/Parser/dump-parse-tree.h 
b/flang/include/flang/Parser/dump-parse-tree.h
index 1ec38de29b85d6..b0b8d8d7ccc556 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -548,10 +548,13 @@ class ParseTreeDumper {
   NODE(OmpFromClause, Modifier)
   NODE(parser, OmpExpectation)
   NODE_ENUM(OmpExpectation, Value)
+  NODE(parser, OmpDirectiveNameModifier)
   NODE(parser, OmpIfClause)
-  NODE_ENUM(OmpIfClause, DirectiveNameModifier)
-  NODE_ENUM(OmpLastprivateClause, LastprivateModifier)
+  NODE(OmpIfClause, Modifier)
   NODE(parser, OmpLastprivateClause)
+  NODE(OmpLastprivateClause, Modifier)
+  NODE(parser, OmpLastprivateModifier)
+  NODE_ENUM(OmpLastprivateModifier, Value)
   NODE(parser, OmpLinearClause)
   NODE(OmpLinearClause, WithModifier)
   NODE(OmpLinearClause, WithoutModifier)
diff --git a/flang/include/flang/Parser/parse-tree.h 
b/flang/include/flang/Parser/parse-tree.h
index c00560b1f1726a..06c32831d2c60c 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/