[clang] [Clang][CodeGen] Emit `llvm.ptrmask` for `align_up` and `align_down` (PR #71238)

2023-11-04 Thread Markus Böck via cfe-commits


@@ -19671,41 +19671,38 @@ RValue CodeGenFunction::EmitBuiltinIsAligned(const 
CallExpr *E) {
 /// TODO: actually use ptrmask once most optimization passes know about it.

zero9178 wrote:

Can this TODO be removed now?

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


[clang] [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (PR #70837)

2023-11-04 Thread Balazs Benics via cfe-commits


@@ -30,3 +30,24 @@ void test(int i) {
   clang_analyzer_dump(g4);
   // expected-warning@-1 {{&i [as 64 bit integer]}}
 }
+
+struct A {
+  int n;
+  void set(int x) {
+n = x;
+  }
+};
+using ptr_size = decltype(sizeof(void *));
+void gh_69922(ptr_size p) {
+  // expected-warning-re@+1 {{(reg_${{[0-9]+}}) & 1U}}
+  clang_analyzer_dump(__builtin_bit_cast(A*, p & 1));

steakhal wrote:

Yes, that is to form a `SymExpr`, which is a `SymbolVal` (NonLoc) wrapping a 
`BO_And` `SymIntExpr` I think.

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


[clang] [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (PR #70837)

2023-11-04 Thread Balazs Benics via cfe-commits


@@ -30,3 +30,24 @@ void test(int i) {
   clang_analyzer_dump(g4);
   // expected-warning@-1 {{&i [as 64 bit integer]}}
 }
+
+struct A {
+  int n;
+  void set(int x) {
+n = x;
+  }
+};
+using ptr_size = decltype(sizeof(void *));

steakhal wrote:

Fixed. Now using `size_t`.

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


[clang] [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (PR #70837)

2023-11-04 Thread Balazs Benics via cfe-commits

https://github.com/steakhal updated 
https://github.com/llvm/llvm-project/pull/70837

>From 2de19fc8e14319674ce87c18771ba1b8ba22f79b Mon Sep 17 00:00:00 2001
From: Balazs Benics 
Date: Mon, 23 Oct 2023 18:10:29 +0200
Subject: [PATCH 1/3] [analyzer] Fix assertion failure in
 CXXInstanceCall::getCXXThisVal

Workaround the case when the `this` pointer is actually a `NonLoc`, by
returning `Unknown` instead.
The solution isn't ideal, as `this` should be really a `Loc`, but due to
how casts work, I feel this is our easiest and best option.

I've considered using `SVB.evalCast(ThisVal, Base->getType(), QualType())`,
but it doesn't work as `EvalCastVisitor::VisitNonLocSymbolVal()` only
evaluates casts that happen from NonLoc to NonLocs.

When I tried to actually implement that case, I figured:
1) Create a SymbolicRegion from that nonloc::SymbolVal; but SymbolRegion
   ctor expects a pointer type for the symbol.
2) Okay, just have a SymbolCast, getting us the pointer type; but
   SymbolRegion expects SymbolData symbols, not generic SymExprs, as stated:

> // Because pointer arithmetic is represented by ElementRegion layers,
> // the base symbol here should not contain any arithmetic.

3) We can't use ElementRegions to perform this cast because to have an
   ElementRegion, you already have to have a SubRegion that you want to
   cast, but the point is that we don't have that.

At this point, I gave up, and just returned `Unknown` xD
IMO this is still better than having a crash.

Fixes #69922
---
 clang/lib/StaticAnalyzer/Core/CallEvent.cpp |  5 ++---
 clang/test/Analysis/builtin_bitcast.cpp | 21 +
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp 
b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index ad5bb66c4fff3c8..20bc64dc2631cec 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -715,10 +715,9 @@ void CXXInstanceCall::getExtraInvalidatedValues(
 SVal CXXInstanceCall::getCXXThisVal() const {
   const Expr *Base = getCXXThisExpr();
   // FIXME: This doesn't handle an overloaded ->* operator.
-  if (!Base)
+  SVal ThisVal = Base ? getSVal(Base) : UnknownVal();
+  if (isa(ThisVal))
 return UnknownVal();
-
-  SVal ThisVal = getSVal(Base);
   assert(ThisVal.isUnknownOrUndef() || isa(ThisVal));
   return ThisVal;
 }
diff --git a/clang/test/Analysis/builtin_bitcast.cpp 
b/clang/test/Analysis/builtin_bitcast.cpp
index 396e7caa45f6acd..13475694d287a22 100644
--- a/clang/test/Analysis/builtin_bitcast.cpp
+++ b/clang/test/Analysis/builtin_bitcast.cpp
@@ -30,3 +30,24 @@ void test(int i) {
   clang_analyzer_dump(g4);
   // expected-warning@-1 {{&i [as 64 bit integer]}}
 }
+
+struct A {
+  int n;
+  void set(int x) {
+n = x;
+  }
+};
+using ptr_size = decltype(sizeof(void *));
+void gh_69922(ptr_size p) {
+  // expected-warning-re@+1 {{(reg_${{[0-9]+}}) & 1U}}
+  clang_analyzer_dump(__builtin_bit_cast(A*, p & 1));
+
+  __builtin_bit_cast(A*, p & 1)->set(2); // no-crash
+  // However, since the `this` pointer is expected to be a Loc, but we have
+  // NonLoc there, we simply give up and resolve it as `Unknown`.
+  // Then, inside the `set()` member function call we can't evaluate the
+  // store to the member variable `n`.
+
+  clang_analyzer_dump(__builtin_bit_cast(A*, p & 1)->n); // Ideally, this 
should print "2".
+  // expected-warning-re@-1 {{(reg_${{[0-9]+}}) & 1U}}
+}

>From bcb048c09dcc7bb2728d46afc0ff9a09cf71f663 Mon Sep 17 00:00:00 2001
From: Balazs Benics 
Date: Tue, 31 Oct 2023 19:20:16 +0100
Subject: [PATCH 2/3] Add fixme and add the ineffective evalCast

---
 clang/lib/StaticAnalyzer/Core/CallEvent.cpp   | 9 +++--
 clang/lib/StaticAnalyzer/Core/SValBuilder.cpp | 5 +
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp 
b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index 20bc64dc2631cec..76fb7481f65194b 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -716,8 +716,13 @@ SVal CXXInstanceCall::getCXXThisVal() const {
   const Expr *Base = getCXXThisExpr();
   // FIXME: This doesn't handle an overloaded ->* operator.
   SVal ThisVal = Base ? getSVal(Base) : UnknownVal();
-  if (isa(ThisVal))
-return UnknownVal();
+
+  if (isa(ThisVal)) {
+SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
+QualType OriginalTy = ThisVal.getType(SVB.getContext());
+return SVB.evalCast(ThisVal, Base->getType(), OriginalTy);
+  }
+
   assert(ThisVal.isUnknownOrUndef() || isa(ThisVal));
   return ThisVal;
 }
diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp 
b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index d89d82626f72694..9375f39b2d71dd4 100644
--- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -980,6 +980,11 @@ class EvalCastVisitor : public 
SValVisitor {
   re

[clang] 99e7e7a - [clang][NFC] Refactor `SourceLocExpr::IdentKind`

2023-11-04 Thread Vlad Serebrennikov via cfe-commits

Author: Vlad Serebrennikov
Date: 2023-11-04T12:43:26+03:00
New Revision: 99e7e7a597fa4ebaa8ebacdc42eae9f0b976f54c

URL: 
https://github.com/llvm/llvm-project/commit/99e7e7a597fa4ebaa8ebacdc42eae9f0b976f54c
DIFF: 
https://github.com/llvm/llvm-project/commit/99e7e7a597fa4ebaa8ebacdc42eae9f0b976f54c.diff

LOG: [clang][NFC] Refactor `SourceLocExpr::IdentKind`

This patch converts `SourceLocExpr::IdentKind` into a scoped enum at namespace 
scope, making it eligible to be forward-declared. This is needed by 
`preferred_type` annotations on bit-fields.

Added: 


Modified: 
clang/include/clang/AST/Expr.h
clang/include/clang/Sema/Sema.h
clang/lib/AST/Expr.cpp
clang/lib/Parse/ParseExpr.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriterStmt.cpp

Removed: 




diff  --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 87e80a5a37750ac..36f004d64617055 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -4735,6 +4735,16 @@ class VAArgExpr : public Expr {
   }
 };
 
+enum class SourceLocIdentKind {
+  Function,
+  FuncSig,
+  File,
+  FileName,
+  Line,
+  Column,
+  SourceLocStruct
+};
+
 /// Represents a function call to one of __builtin_LINE(), __builtin_COLUMN(),
 /// __builtin_FUNCTION(), __builtin_FUNCSIG(), __builtin_FILE(),
 /// __builtin_FILE_NAME() or __builtin_source_location().
@@ -4743,19 +4753,9 @@ class SourceLocExpr final : public Expr {
   DeclContext *ParentContext;
 
 public:
-  enum IdentKind {
-Function,
-FuncSig,
-File,
-FileName,
-Line,
-Column,
-SourceLocStruct
-  };
-
-  SourceLocExpr(const ASTContext &Ctx, IdentKind Type, QualType ResultTy,
-SourceLocation BLoc, SourceLocation RParenLoc,
-DeclContext *Context);
+  SourceLocExpr(const ASTContext &Ctx, SourceLocIdentKind Type,
+QualType ResultTy, SourceLocation BLoc,
+SourceLocation RParenLoc, DeclContext *Context);
 
   /// Build an empty call expression.
   explicit SourceLocExpr(EmptyShell Empty) : Expr(SourceLocExprClass, Empty) {}
@@ -4768,20 +4768,20 @@ class SourceLocExpr final : public Expr {
   /// Return a string representing the name of the specific builtin function.
   StringRef getBuiltinStr() const;
 
-  IdentKind getIdentKind() const {
-return static_cast(SourceLocExprBits.Kind);
+  SourceLocIdentKind getIdentKind() const {
+return static_cast(SourceLocExprBits.Kind);
   }
 
   bool isIntType() const {
 switch (getIdentKind()) {
-case File:
-case FileName:
-case Function:
-case FuncSig:
-case SourceLocStruct:
+case SourceLocIdentKind::File:
+case SourceLocIdentKind::FileName:
+case SourceLocIdentKind::Function:
+case SourceLocIdentKind::FuncSig:
+case SourceLocIdentKind::SourceLocStruct:
   return false;
-case Line:
-case Column:
+case SourceLocIdentKind::Line:
+case SourceLocIdentKind::Column:
   return true;
 }
 llvm_unreachable("unknown source location expression kind");

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index daed24be0a86d11..8a35cbe3e9502b6 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -6086,14 +6086,13 @@ class Sema final {
 
   // __builtin_LINE(), __builtin_FUNCTION(), __builtin_FUNCSIG(),
   // __builtin_FILE(), __builtin_COLUMN(), __builtin_source_location()
-  ExprResult ActOnSourceLocExpr(SourceLocExpr::IdentKind Kind,
+  ExprResult ActOnSourceLocExpr(SourceLocIdentKind Kind,
 SourceLocation BuiltinLoc,
 SourceLocation RPLoc);
 
   // Build a potentially resolved SourceLocExpr.
-  ExprResult BuildSourceLocExpr(SourceLocExpr::IdentKind Kind,
-QualType ResultTy, SourceLocation BuiltinLoc,
-SourceLocation RPLoc,
+  ExprResult BuildSourceLocExpr(SourceLocIdentKind Kind, QualType ResultTy,
+SourceLocation BuiltinLoc, SourceLocation 
RPLoc,
 DeclContext *ParentContext);
 
   // __null

diff  --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 5d3b510df1ef9b3..62467493e386e8d 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -2196,31 +2196,31 @@ bool 
BinaryOperator::isNullPointerArithmeticExtension(ASTContext &Ctx,
   return true;
 }
 
-SourceLocExpr::SourceLocExpr(const ASTContext &Ctx, IdentKind Kind,
+SourceLocExpr::SourceLocExpr(const ASTContext &Ctx, SourceLocIdentKind Kind,
  QualType ResultTy, SourceLocation BLoc,
  SourceLocation RParenLoc,
  DeclContext *ParentContext)
 : Expr(SourceLocExprClass,

[PATCH] D123235: [OpenMP] atomic compare fail : Parser & AST support

2023-11-04 Thread Sunil K via Phabricator via cfe-commits
koops updated this revision to Diff 558007.
koops added a comment.

1. Removing the Create methods from OMPFailClause class.
2. checkFailClauseParameters removed and the checking is now done in 
ActOnOpenMPAtomicDirective() itself.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D123235/new/

https://reviews.llvm.org/D123235

Files:
  clang/include/clang/AST/OpenMPClause.h
  clang/include/clang/AST/RecursiveASTVisitor.h
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/OpenMPKinds.def
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/OpenMPClause.cpp
  clang/lib/AST/StmtProfile.cpp
  clang/lib/Basic/OpenMPKinds.cpp
  clang/lib/CodeGen/CGStmtOpenMP.cpp
  clang/lib/Parse/ParseOpenMP.cpp
  clang/lib/Sema/SemaOpenMP.cpp
  clang/lib/Sema/TreeTransform.h
  clang/lib/Serialization/ASTReader.cpp
  clang/lib/Serialization/ASTWriter.cpp
  clang/test/OpenMP/atomic_ast_print.cpp
  clang/test/OpenMP/atomic_messages.cpp
  clang/tools/libclang/CIndex.cpp
  flang/lib/Semantics/check-omp-structure.cpp
  llvm/include/llvm/Frontend/OpenMP/OMP.td

Index: llvm/include/llvm/Frontend/OpenMP/OMP.td
===
--- llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -209,6 +209,7 @@
 def OMPC_Update : Clause<"update"> { let clangClass = "OMPUpdateClause"; }
 def OMPC_Capture : Clause<"capture"> { let clangClass = "OMPCaptureClause"; }
 def OMPC_Compare : Clause<"compare"> { let clangClass = "OMPCompareClause"; }
+def OMPC_Fail : Clause<"fail"> { let clangClass = "OMPFailClause"; }
 def OMPC_SeqCst : Clause<"seq_cst"> { let clangClass = "OMPSeqCstClause"; }
 def OMPC_AcqRel : Clause<"acq_rel"> { let clangClass = "OMPAcqRelClause"; }
 def OMPC_Acquire : Clause<"acquire"> { let clangClass = "OMPAcquireClause"; }
@@ -637,7 +638,8 @@
 VersionedClause,
 VersionedClause,
 VersionedClause,
-VersionedClause
+VersionedClause,
+VersionedClause
   ];
 }
 def OMP_Target : Directive<"target"> {
Index: flang/lib/Semantics/check-omp-structure.cpp
===
--- flang/lib/Semantics/check-omp-structure.cpp
+++ flang/lib/Semantics/check-omp-structure.cpp
@@ -2164,6 +2164,7 @@
 CHECK_SIMPLE_CLAUSE(Doacross, OMPC_doacross)
 CHECK_SIMPLE_CLAUSE(OmpxAttribute, OMPC_ompx_attribute)
 CHECK_SIMPLE_CLAUSE(OmpxBare, OMPC_ompx_bare)
+CHECK_SIMPLE_CLAUSE(Fail, OMPC_fail)
 
 CHECK_REQ_SCALAR_INT_CLAUSE(Grainsize, OMPC_grainsize)
 CHECK_REQ_SCALAR_INT_CLAUSE(NumTasks, OMPC_num_tasks)
Index: clang/tools/libclang/CIndex.cpp
===
--- clang/tools/libclang/CIndex.cpp
+++ clang/tools/libclang/CIndex.cpp
@@ -2402,6 +2402,8 @@
 
 void OMPClauseEnqueue::VisitOMPCompareClause(const OMPCompareClause *) {}
 
+void OMPClauseEnqueue::VisitOMPFailClause(const OMPFailClause *) {}
+
 void OMPClauseEnqueue::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
 
 void OMPClauseEnqueue::VisitOMPAcqRelClause(const OMPAcqRelClause *) {}
Index: clang/test/OpenMP/atomic_messages.cpp
===
--- clang/test/OpenMP/atomic_messages.cpp
+++ clang/test/OpenMP/atomic_messages.cpp
@@ -958,6 +958,24 @@
 // expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'capture' clause}}
 #pragma omp atomic compare compare capture capture
   { v = a; if (a > b) a = b; }
+// expected-error@+1 {{expected 'compare' clause with the 'fail' modifier}}
+#pragma omp atomic fail(seq_cst)
+  if(v == a) { v = a; }
+// expected-error@+1 {{expected '(' after 'fail'}}
+#pragma omp atomic compare fail
+  if(v < a) { v = a; }
+// expected-error@+1 {{expected a memory order clause}}
+#pragma omp atomic compare fail(capture)
+  if(v < a) { v = a; }
+ // expected-error@+2 {{expected ')'}}
+ // expected-note@+1 {{to match this '('}}
+#pragma omp atomic compare fail(seq_cst | acquire)
+  if(v < a) { v = a; }
+// expected-error@+1 {{directive '#pragma omp atomic' cannot contain more than one 'fail' clause}}
+#pragma omp atomic compare fail(relaxed) fail(seq_cst)
+  if(v < a) { v = a; }
+
+
 #endif
   // expected-note@+1 {{in instantiation of function template specialization 'mixed' requested here}}
   return mixed();
Index: clang/test/OpenMP/atomic_ast_print.cpp
===
--- clang/test/OpenMP/atomic_ast_print.cpp
+++ clang/test/OpenMP/atomic_ast_print.cpp
@@ -226,6 +226,16 @@
   { v = a; if (a < b) { a = b; } }
 #pragma omp atomic compare capture hint(6)
   { v = a == b; if (v) a = c; }
+#pragma omp atomic compare fail(acq_rel)
+  { if (a < c) { a = c; } }
+#pragma omp atomic compare fail(acquire)
+  { if (a < c) { a = c; } }
+#pragma omp atomic compare fail(release)
+  { if (a < c) { a = c; } }
+#pragma omp atomic compare fail(relaxed)
+  { if (a < c) { a = c; } }
+#pragma omp atomic compare fail(seq_cst)
+  { if (a < 

[clang] [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (PR #70837)

2023-11-04 Thread Balazs Benics via cfe-commits

https://github.com/steakhal closed 
https://github.com/llvm/llvm-project/pull/70837
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 51d15d1 - [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` (#70837)

2023-11-04 Thread via cfe-commits

Author: Balazs Benics
Date: 2023-11-04T11:11:24+01:00
New Revision: 51d15d13dea4325d1f76353af847d9de0b532e87

URL: 
https://github.com/llvm/llvm-project/commit/51d15d13dea4325d1f76353af847d9de0b532e87
DIFF: 
https://github.com/llvm/llvm-project/commit/51d15d13dea4325d1f76353af847d9de0b532e87.diff

LOG: [analyzer] Fix assertion failure in `CXXInstanceCall::getCXXThisVal` 
(#70837)

Workaround the case when the `this` pointer is actually a `NonLoc`, by
returning `Unknown` instead.
The solution isn't ideal, as `this` should be really a `Loc`, but due to
how casts work, I feel this is our easiest and best option.

As this patch presents, I'm evaluating a cast to transform the `NonLoc`.
However, given that `evalCast()` can't be cast from `NonLoc` to a
pointer type thingy (`Loc`), we end up with `Unknown`.
It is because `EvalCastVisitor::VisitNonLocSymbolVal()` only evaluates
casts that happen from NonLoc to NonLocs.

When I tried to actually implement that case, I figured:
1) Create a `SymbolicRegion` from that `nonloc::SymbolVal`; but
`SymbolRegion` ctor expects a pointer type for the symbol.
2) Okay, just have a `SymbolCast`, getting us the pointer type; but
`SymbolRegion` expects `SymbolData` symbols, not generic `SymExpr`s, as
stated:

> // Because pointer arithmetic is represented by ElementRegion layers,
> // the base symbol here should not contain any arithmetic.

3) We can't use `ElementRegion`s to perform this cast because to have an
`ElementRegion`, you already have to have a `SubRegion` that you want to
cast, but the point is that we don't have that.

At this point, I gave up, and just left a FIXME instead, while still
returning `Unknown` on that path.
IMO this is still better than having a crash.

Fixes #69922

Added: 


Modified: 
clang/lib/StaticAnalyzer/Core/CallEvent.cpp
clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
clang/test/Analysis/builtin_bitcast.cpp

Removed: 




diff  --git a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp 
b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
index ad5bb66c4fff3c8..76fb7481f65194b 100644
--- a/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ b/clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -715,10 +715,14 @@ void CXXInstanceCall::getExtraInvalidatedValues(
 SVal CXXInstanceCall::getCXXThisVal() const {
   const Expr *Base = getCXXThisExpr();
   // FIXME: This doesn't handle an overloaded ->* operator.
-  if (!Base)
-return UnknownVal();
+  SVal ThisVal = Base ? getSVal(Base) : UnknownVal();
+
+  if (isa(ThisVal)) {
+SValBuilder &SVB = getState()->getStateManager().getSValBuilder();
+QualType OriginalTy = ThisVal.getType(SVB.getContext());
+return SVB.evalCast(ThisVal, Base->getType(), OriginalTy);
+  }
 
-  SVal ThisVal = getSVal(Base);
   assert(ThisVal.isUnknownOrUndef() || isa(ThisVal));
   return ThisVal;
 }

diff  --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp 
b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index d89d82626f72694..9375f39b2d71dd4 100644
--- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -980,6 +980,11 @@ class EvalCastVisitor : public 
SValVisitor {
   return VB.makeNonLoc(SE, T, CastTy);
 }
 
+// FIXME: We should be able to cast NonLoc -> Loc
+// (when Loc::isLocType(CastTy) is true)
+// But it's hard to do as SymbolicRegions can't refer to SymbolCasts 
holding
+// generic SymExprs. Check the commit message for the details.
+
 // Symbol to pointer and whatever else.
 return UnknownVal();
   }

diff  --git a/clang/test/Analysis/builtin_bitcast.cpp 
b/clang/test/Analysis/builtin_bitcast.cpp
index 396e7caa45f6acd..5a0d9e7189b8edd 100644
--- a/clang/test/Analysis/builtin_bitcast.cpp
+++ b/clang/test/Analysis/builtin_bitcast.cpp
@@ -2,6 +2,7 @@
 // RUN:   -analyzer-checker=core,debug.ExprInspection
 
 template  void clang_analyzer_dump(T);
+using size_t = decltype(sizeof(int));
 
 __attribute__((always_inline)) static inline constexpr unsigned int 
_castf32_u32(float __A) {
   return __builtin_bit_cast(unsigned int, __A); // no-warning
@@ -30,3 +31,23 @@ void test(int i) {
   clang_analyzer_dump(g4);
   // expected-warning@-1 {{&i [as 64 bit integer]}}
 }
+
+struct A {
+  int n;
+  void set(int x) {
+n = x;
+  }
+};
+void gh_69922(size_t p) {
+  // expected-warning-re@+1 {{(reg_${{[0-9]+}}) & 1U}}
+  clang_analyzer_dump(__builtin_bit_cast(A*, p & 1));
+
+  __builtin_bit_cast(A*, p & 1)->set(2); // no-crash
+  // However, since the `this` pointer is expected to be a Loc, but we have
+  // NonLoc there, we simply give up and resolve it as `Unknown`.
+  // Then, inside the `set()` member function call we can't evaluate the
+  // store to the member variable `n`.
+
+  clang_analyzer_dump(__builtin_bit_cast(A*, p & 1)->n); // Ideally, this 
should print "2".
+  // expected-warning-re@-1 {{(reg_${{[0-9]+}}) & 1U}}
+}



__

[clang] [clang] Non-object types are non-trivially relocatable (PR #69734)

2023-11-04 Thread Amirreza Ashouri via cfe-commits

https://github.com/AMP999 updated 
https://github.com/llvm/llvm-project/pull/69734

>From a67c7b8f2af625145c805240fc51f1ecea392ef2 Mon Sep 17 00:00:00 2001
From: Amirreza Ashouri 
Date: Sat, 7 Oct 2023 15:18:55 +0330
Subject: [PATCH] [clang] Non-object types are non-trivially relocatable

Both active C++ proposals (P1144 and P2786) agree that
`is_trivially_relocatable_v` and `is_trivially_relocatable_v`
should be false, not true. Only complete object types
can be trivially relocatable.

Fixes #67498
---
 clang/lib/AST/Type.cpp|  2 ++
 clang/test/SemaCXX/type-traits-incomplete.cpp |  8 +++-
 clang/test/SemaCXX/type-traits-nonobject.cpp  | 16 
 3 files changed, 25 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/SemaCXX/type-traits-nonobject.cpp

diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 4dd4e926c8104a4..4d3cf937d36b904 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2648,6 +2648,8 @@ bool QualType::isTriviallyRelocatableType(const 
ASTContext &Context) const {
 
   if (BaseElementType->isIncompleteType()) {
 return false;
+  } else if (!BaseElementType->isObjectType()) {
+return false;
   } else if (const auto *RD = BaseElementType->getAsRecordDecl()) {
 return RD->canPassInRegisters();
   } else {
diff --git a/clang/test/SemaCXX/type-traits-incomplete.cpp 
b/clang/test/SemaCXX/type-traits-incomplete.cpp
index c0a520e167698af..3e341d648244075 100644
--- a/clang/test/SemaCXX/type-traits-incomplete.cpp
+++ b/clang/test/SemaCXX/type-traits-incomplete.cpp
@@ -1,8 +1,14 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s 
 
-struct S; // expected-note 2 {{forward declaration of 'S'}}
+struct S; // expected-note 6 {{forward declaration of 'S'}}
 
 void f() {
   __is_pod(S); // expected-error{{incomplete type 'S' used in type trait 
expression}}
   __is_pod(S[]); // expected-error{{incomplete type 'S' used in type trait 
expression}}
+
+  __is_trivially_copyable(S); // expected-error{{incomplete type 'S' used in 
type trait expression}}
+  __is_trivially_copyable(S[]); // expected-error{{incomplete type 'S' used in 
type trait expression}}
+
+  __is_trivially_relocatable(S); // expected-error{{incomplete type 'S' used 
in type trait expression}}
+  __is_trivially_relocatable(S[]); // expected-error{{incomplete type 'S' used 
in type trait expression}}
 }
diff --git a/clang/test/SemaCXX/type-traits-nonobject.cpp 
b/clang/test/SemaCXX/type-traits-nonobject.cpp
new file mode 100644
index 000..c9e3c30e5533d48
--- /dev/null
+++ b/clang/test/SemaCXX/type-traits-nonobject.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s
+
+// expected-no-diagnostics
+
+static_assert(!__is_pod(void), "");
+static_assert(!__is_pod(int&), "");
+static_assert(!__is_pod(int()), "");
+
+static_assert(!__is_trivially_copyable(void), "");
+static_assert(!__is_trivially_copyable(int&), "");
+static_assert(!__is_trivially_copyable(int()), "");
+
+static_assert(!__is_trivially_relocatable(void), "");
+static_assert(!__is_trivially_relocatable(int&), "");
+static_assert(!__is_trivially_relocatable(int()), "");

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Non-object types are non-trivially relocatable (PR #69734)

2023-11-04 Thread Amirreza Ashouri via cfe-commits

AMP999 wrote:

@cor3ntin Are these tests what you had in mind? Are they sufficient? What else 
should I add?

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


[clang-tools-extra] cd60229 - [clang][NFC] Refactor `ConstantExpr::ResultStorageKind`

2023-11-04 Thread Vlad Serebrennikov via cfe-commits

Author: Vlad Serebrennikov
Date: 2023-11-04T13:28:29+03:00
New Revision: cd6022916bff1d6fab007b554810b631549ba43c

URL: 
https://github.com/llvm/llvm-project/commit/cd6022916bff1d6fab007b554810b631549ba43c
DIFF: 
https://github.com/llvm/llvm-project/commit/cd6022916bff1d6fab007b554810b631549ba43c.diff

LOG: [clang][NFC] Refactor `ConstantExpr::ResultStorageKind`

This patch converts `ConstantExpr::ResultStorageKind` to a scoped enum in 
namespace scoped `ConstantResultStorageKind`. This patch makes it possible to 
forward-declare this enum where it's necessery, e.g. for `preferred_type` 
annotation for bit-fields.

Added: 


Modified: 
clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
clang/include/clang/AST/Expr.h
clang/include/clang/AST/Stmt.h
clang/lib/AST/Expr.cpp
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriterStmt.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp 
b/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
index a152fb5cfabd1db..43cfc769f7f71d1 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/PopulateSwitch.cpp
@@ -176,7 +176,7 @@ bool PopulateSwitch::prepare(const Selection &Sel) {
 
 // We need a stored value in order to continue; currently both C and ObjC
 // enums won't have one.
-if (CE->getResultStorageKind() == ConstantExpr::RSK_None)
+if (CE->getResultStorageKind() == ConstantResultStorageKind::None)
   return false;
 auto Iter = ExpectedCases.find(Normalize(CE->getResultAsAPSInt()));
 if (Iter != ExpectedCases.end())

diff  --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 36f004d64617055..37821982000ea1b 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -1049,6 +1049,9 @@ class FullExpr : public Expr {
   }
 };
 
+/// Describes the kind of result that can be tail-allocated.
+enum class ConstantResultStorageKind { None, Int64, APValue };
+
 /// ConstantExpr - An expression that occurs in a constant context and
 /// optionally the result of evaluating the expression.
 class ConstantExpr final
@@ -1061,20 +1064,15 @@ class ConstantExpr final
   friend class ASTStmtReader;
   friend class ASTStmtWriter;
 
-public:
-  /// Describes the kind of result that can be tail-allocated.
-  enum ResultStorageKind { RSK_None, RSK_Int64, RSK_APValue };
-
-private:
   size_t numTrailingObjects(OverloadToken) const {
-return ConstantExprBits.ResultKind == ConstantExpr::RSK_APValue;
+return getResultStorageKind() == ConstantResultStorageKind::APValue;
   }
   size_t numTrailingObjects(OverloadToken) const {
-return ConstantExprBits.ResultKind == ConstantExpr::RSK_Int64;
+return getResultStorageKind() == ConstantResultStorageKind::Int64;
   }
 
   uint64_t &Int64Result() {
-assert(ConstantExprBits.ResultKind == ConstantExpr::RSK_Int64 &&
+assert(getResultStorageKind() == ConstantResultStorageKind::Int64 &&
"invalid accessor");
 return *getTrailingObjects();
   }
@@ -1082,7 +1080,7 @@ class ConstantExpr final
 return const_cast(this)->Int64Result();
   }
   APValue &APValueResult() {
-assert(ConstantExprBits.ResultKind == ConstantExpr::RSK_APValue &&
+assert(getResultStorageKind() == ConstantResultStorageKind::APValue &&
"invalid accessor");
 return *getTrailingObjects();
   }
@@ -1090,22 +1088,23 @@ class ConstantExpr final
 return const_cast(this)->APValueResult();
   }
 
-  ConstantExpr(Expr *SubExpr, ResultStorageKind StorageKind,
+  ConstantExpr(Expr *SubExpr, ConstantResultStorageKind StorageKind,
bool IsImmediateInvocation);
-  ConstantExpr(EmptyShell Empty, ResultStorageKind StorageKind);
+  ConstantExpr(EmptyShell Empty, ConstantResultStorageKind StorageKind);
 
 public:
   static ConstantExpr *Create(const ASTContext &Context, Expr *E,
   const APValue &Result);
-  static ConstantExpr *Create(const ASTContext &Context, Expr *E,
-  ResultStorageKind Storage = RSK_None,
-  bool IsImmediateInvocation = false);
+  static ConstantExpr *
+  Create(const ASTContext &Context, Expr *E,
+ ConstantResultStorageKind Storage = ConstantResultStorageKind::None,
+ bool IsImmediateInvocation = false);
   static ConstantExpr *CreateEmpty(const ASTContext &Context,
-   ResultStorageKind StorageKind);
+   ConstantResultStorageKind StorageKind);
 
-  static ResultStorageKind getStorageKind(const APValue &Value);
-  static ResultStorageKind getStorageKind(const Type *T,
-  const ASTContext &Context);
+  static ConstantResultStorageKind getStorageKind(const APValue &Value)

[llvm] [clang] [clang-tools-extra] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-11-04 Thread Michal Paszkowski via cfe-commits

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

Thank you for working on this! LGTM!

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


[clang-tools-extra] [clangd] Resolve the dependent type from its single instantiation. Take 1 (PR #71279)

2023-11-04 Thread Younan Zhang via cfe-commits

https://github.com/zyn0217 created 
https://github.com/llvm/llvm-project/pull/71279

This is an enhancement to the HeuristicResolver, trying to extract the deduced 
type from the single instantiation for a template. This partially addresses the 
point #1 from
https://github.com/clangd/clangd/issues/1768.

This patch doesn't tackle CXXUnresolvedConstructExpr or similarities since I 
feel that is more arduous and would prefer to leave it for my future work.

>From d73a8e2ee683e6812c21cb1de7363b14565a96d1 Mon Sep 17 00:00:00 2001
From: Younan Zhang 
Date: Sat, 4 Nov 2023 18:43:58 +0800
Subject: [PATCH] [clangd] Resolve the dependent type from its single
 instantiation. Take 1

This is an enhancement to the HeuristicResolver, trying to extract
the deduced type from the single instantiation for a template. This
partially addresses the point #1 from
https://github.com/clangd/clangd/issues/1768.

This patch doesn't tackle CXXUnresolvedConstructExpr or similarities
since I feel that is more arduous and would prefer to leave it for
my future work.
---
 .../clangd/HeuristicResolver.cpp  | 101 ++
 .../clangd/unittests/XRefsTests.cpp   |  48 +
 2 files changed, 149 insertions(+)

diff --git a/clang-tools-extra/clangd/HeuristicResolver.cpp 
b/clang-tools-extra/clangd/HeuristicResolver.cpp
index 3c147b6b582bf0b..d3dced9b325367a 100644
--- a/clang-tools-extra/clangd/HeuristicResolver.cpp
+++ b/clang-tools-extra/clangd/HeuristicResolver.cpp
@@ -7,10 +7,14 @@
 
//===--===//
 
 #include "HeuristicResolver.h"
+#include "AST.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/CXXInheritance.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Type.h"
 
 namespace clang {
@@ -46,6 +50,98 @@ const Type *resolveDeclsToType(const std::vector &Decls,
   return nullptr;
 }
 
+// Visitor that helps to extract deduced type from instantiated entities.
+// This merely performs the source location comparison against each Decl
+// until it finds a Decl with the same location as the
+// dependent one. Its associated type will then be extracted.
+struct InstantiatedDeclVisitor : RecursiveASTVisitor {
+
+  InstantiatedDeclVisitor(NamedDecl *DependentDecl) : 
DependentDecl(DependentDecl) {}
+
+  bool shouldVisitTemplateInstantiations() const { return true; }
+
+  bool shouldVisitLambdaBody() const { return true; }
+
+  bool shouldVisitImplicitCode() const { return true; }
+
+  template 
+  bool onDeclVisited(D *MaybeInstantiated) {
+if (MaybeInstantiated->getDeclContext()->isDependentContext())
+  return true;
+auto *Dependent = dyn_cast(DependentDecl);
+if (!Dependent)
+  return true;
+auto LHS = MaybeInstantiated->getTypeSourceInfo(),
+ RHS = Dependent->getTypeSourceInfo();
+if (!LHS || !RHS)
+  return true;
+if (LHS->getTypeLoc().getSourceRange() !=
+RHS->getTypeLoc().getSourceRange())
+  return true;
+DeducedType = MaybeInstantiated->getType();
+return false;
+  }
+
+  bool VisitFieldDecl(FieldDecl *FD) {
+return onDeclVisited(FD);
+  }
+
+  bool VisitVarDecl(VarDecl *VD) {
+return onDeclVisited(VD);
+  }
+
+  NamedDecl *DependentDecl;
+  QualType DeducedType;
+};
+
+/// Attempt to resolve the dependent type from the surrounding context for 
which
+/// a single instantiation is available.
+const Type *
+resolveTypeFromInstantiatedTemplate(const CXXDependentScopeMemberExpr *Expr) {
+  if (Expr->isImplicitAccess())
+return nullptr;
+
+  auto *Base = Expr->getBase();
+  NamedDecl *ND = nullptr;
+  if (auto *CXXMember = dyn_cast(Base))
+ND = CXXMember->getMemberDecl();
+
+  if (auto *DRExpr = dyn_cast(Base))
+ND = DRExpr->getFoundDecl();
+
+  // FIXME: Handle CXXUnresolvedConstructExpr. This kind of type doesn't have
+  // available Decls to be matched against. Which inhibits the current 
heuristic
+  // from resolving expressions such as `T().fo^o()`, where T is a
+  // single-instantiated template parameter.
+  if (!ND)
+return nullptr;
+
+  NamedDecl *Instantiation = nullptr;
+
+  // Find out a single instantiation that we can start with. The enclosing
+  // context for the current Decl might not be a templated entity (e.g. a 
member
+  // function inside a class template), hence we shall walk up the decl
+  // contexts first.
+  for (auto *EnclosingContext = ND->getDeclContext(); EnclosingContext;
+   EnclosingContext = EnclosingContext->getParent()) {
+if (auto *ND = dyn_cast(EnclosingContext)) {
+  Instantiation = getOnlyInstantiation(ND);
+  if (Instantiation)
+break;
+}
+  }
+
+  if (!Instantiation)
+return nullptr;
+
+  // This will traverse down the instantiation entity, visit each Decl, and
+  // extract the deduced type for the undetermined Decl `ND`.

[clang-tools-extra] [clangd] Resolve the dependent type from its single instantiation. Take 1 (PR #71279)

2023-11-04 Thread Younan Zhang via cfe-commits


@@ -46,6 +50,98 @@ const Type *resolveDeclsToType(const std::vector &Decls,
   return nullptr;
 }
 
+// Visitor that helps to extract deduced type from instantiated entities.
+// This merely performs the source location comparison against each Decl
+// until it finds a Decl with the same location as the
+// dependent one. Its associated type will then be extracted.
+struct InstantiatedDeclVisitor : RecursiveASTVisitor {
+
+  InstantiatedDeclVisitor(NamedDecl *DependentDecl) : 
DependentDecl(DependentDecl) {}
+
+  bool shouldVisitTemplateInstantiations() const { return true; }
+
+  bool shouldVisitLambdaBody() const { return true; }
+
+  bool shouldVisitImplicitCode() const { return true; }
+
+  template 
+  bool onDeclVisited(D *MaybeInstantiated) {
+if (MaybeInstantiated->getDeclContext()->isDependentContext())
+  return true;
+auto *Dependent = dyn_cast(DependentDecl);
+if (!Dependent)
+  return true;
+auto LHS = MaybeInstantiated->getTypeSourceInfo(),
+ RHS = Dependent->getTypeSourceInfo();
+if (!LHS || !RHS)
+  return true;
+if (LHS->getTypeLoc().getSourceRange() !=
+RHS->getTypeLoc().getSourceRange())
+  return true;
+DeducedType = MaybeInstantiated->getType();
+return false;
+  }
+
+  bool VisitFieldDecl(FieldDecl *FD) {
+return onDeclVisited(FD);
+  }
+
+  bool VisitVarDecl(VarDecl *VD) {
+return onDeclVisited(VD);
+  }
+
+  NamedDecl *DependentDecl;
+  QualType DeducedType;
+};
+
+/// Attempt to resolve the dependent type from the surrounding context for 
which
+/// a single instantiation is available.
+const Type *
+resolveTypeFromInstantiatedTemplate(const CXXDependentScopeMemberExpr *Expr) {
+  if (Expr->isImplicitAccess())
+return nullptr;
+
+  auto *Base = Expr->getBase();
+  NamedDecl *ND = nullptr;
+  if (auto *CXXMember = dyn_cast(Base))
+ND = CXXMember->getMemberDecl();
+
+  if (auto *DRExpr = dyn_cast(Base))
+ND = DRExpr->getFoundDecl();
+
+  // FIXME: Handle CXXUnresolvedConstructExpr. This kind of type doesn't have
+  // available Decls to be matched against. Which inhibits the current 
heuristic
+  // from resolving expressions such as `T().fo^o()`, where T is a
+  // single-instantiated template parameter.
+  if (!ND)
+return nullptr;

zyn0217 wrote:

RFC: Do we have a neat approach to deal with such an expression? One approach 
that comes to mind is: 

1) Extract the TemplateTypeParmDecl (TTPD)  from the expression. 

2) Traverse every Decls inside the enclosing DeclContext for TTPD until we find 
a template entity whose template parameters contain TTPD. 

3) Find the instantiation for that entity. If succeeds, perform the similar 
steps below to extract the Stmt corresponding to the dependent expression (i.e. 
our interest). 

4) Figure out a way to extract the type from that expression, which can be 
intricate, as we don't know to which Decl the dependent expression is tied.

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


[clang-tools-extra] [clangd] Resolve the dependent type from its single instantiation. Take 1 (PR #71279)

2023-11-04 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clangd

Author: Younan Zhang (zyn0217)


Changes

This is an enhancement to the HeuristicResolver, trying to extract the deduced 
type from the single instantiation for a template. This partially addresses the 
point #1 from
https://github.com/clangd/clangd/issues/1768.

This patch doesn't tackle CXXUnresolvedConstructExpr or similarities since I 
feel that is more arduous and would prefer to leave it for my future work.

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


2 Files Affected:

- (modified) clang-tools-extra/clangd/HeuristicResolver.cpp (+101) 
- (modified) clang-tools-extra/clangd/unittests/XRefsTests.cpp (+48) 


``diff
diff --git a/clang-tools-extra/clangd/HeuristicResolver.cpp 
b/clang-tools-extra/clangd/HeuristicResolver.cpp
index 3c147b6b582bf0b..d3dced9b325367a 100644
--- a/clang-tools-extra/clangd/HeuristicResolver.cpp
+++ b/clang-tools-extra/clangd/HeuristicResolver.cpp
@@ -7,10 +7,14 @@
 
//===--===//
 
 #include "HeuristicResolver.h"
+#include "AST.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/CXXInheritance.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/Type.h"
 
 namespace clang {
@@ -46,6 +50,98 @@ const Type *resolveDeclsToType(const std::vector &Decls,
   return nullptr;
 }
 
+// Visitor that helps to extract deduced type from instantiated entities.
+// This merely performs the source location comparison against each Decl
+// until it finds a Decl with the same location as the
+// dependent one. Its associated type will then be extracted.
+struct InstantiatedDeclVisitor : RecursiveASTVisitor {
+
+  InstantiatedDeclVisitor(NamedDecl *DependentDecl) : 
DependentDecl(DependentDecl) {}
+
+  bool shouldVisitTemplateInstantiations() const { return true; }
+
+  bool shouldVisitLambdaBody() const { return true; }
+
+  bool shouldVisitImplicitCode() const { return true; }
+
+  template 
+  bool onDeclVisited(D *MaybeInstantiated) {
+if (MaybeInstantiated->getDeclContext()->isDependentContext())
+  return true;
+auto *Dependent = dyn_cast(DependentDecl);
+if (!Dependent)
+  return true;
+auto LHS = MaybeInstantiated->getTypeSourceInfo(),
+ RHS = Dependent->getTypeSourceInfo();
+if (!LHS || !RHS)
+  return true;
+if (LHS->getTypeLoc().getSourceRange() !=
+RHS->getTypeLoc().getSourceRange())
+  return true;
+DeducedType = MaybeInstantiated->getType();
+return false;
+  }
+
+  bool VisitFieldDecl(FieldDecl *FD) {
+return onDeclVisited(FD);
+  }
+
+  bool VisitVarDecl(VarDecl *VD) {
+return onDeclVisited(VD);
+  }
+
+  NamedDecl *DependentDecl;
+  QualType DeducedType;
+};
+
+/// Attempt to resolve the dependent type from the surrounding context for 
which
+/// a single instantiation is available.
+const Type *
+resolveTypeFromInstantiatedTemplate(const CXXDependentScopeMemberExpr *Expr) {
+  if (Expr->isImplicitAccess())
+return nullptr;
+
+  auto *Base = Expr->getBase();
+  NamedDecl *ND = nullptr;
+  if (auto *CXXMember = dyn_cast(Base))
+ND = CXXMember->getMemberDecl();
+
+  if (auto *DRExpr = dyn_cast(Base))
+ND = DRExpr->getFoundDecl();
+
+  // FIXME: Handle CXXUnresolvedConstructExpr. This kind of type doesn't have
+  // available Decls to be matched against. Which inhibits the current 
heuristic
+  // from resolving expressions such as `T().fo^o()`, where T is a
+  // single-instantiated template parameter.
+  if (!ND)
+return nullptr;
+
+  NamedDecl *Instantiation = nullptr;
+
+  // Find out a single instantiation that we can start with. The enclosing
+  // context for the current Decl might not be a templated entity (e.g. a 
member
+  // function inside a class template), hence we shall walk up the decl
+  // contexts first.
+  for (auto *EnclosingContext = ND->getDeclContext(); EnclosingContext;
+   EnclosingContext = EnclosingContext->getParent()) {
+if (auto *ND = dyn_cast(EnclosingContext)) {
+  Instantiation = getOnlyInstantiation(ND);
+  if (Instantiation)
+break;
+}
+  }
+
+  if (!Instantiation)
+return nullptr;
+
+  // This will traverse down the instantiation entity, visit each Decl, and
+  // extract the deduced type for the undetermined Decl `ND`.
+  InstantiatedDeclVisitor Visitor(ND);
+  Visitor.TraverseDecl(Instantiation);
+
+  return Visitor.DeducedType.getTypePtrOrNull();
+}
+
 } // namespace
 
 // Helper function for HeuristicResolver::resolveDependentMember()
@@ -150,6 +246,11 @@ std::vector 
HeuristicResolver::resolveMemberExpr(
   if (ME->isArrow()) {
 BaseType = getPointeeType(BaseType);
   }
+
+  if (BaseType->isDependentType())
+if (auto *MaybeResolved = resolveTypeFromInstantiatedTemplate(ME))
+  BaseType = MaybeResolved;
+
   if (!Ba

[clang-tools-extra] [clangd] Resolve the dependent type from its single instantiation. Take 1 (PR #71279)

2023-11-04 Thread Younan Zhang via cfe-commits

https://github.com/zyn0217 edited 
https://github.com/llvm/llvm-project/pull/71279
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clangd] Resolve the dependent type from its single instantiation. Take 1 (PR #71279)

2023-11-04 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff cd6022916bff1d6fab007b554810b631549ba43c 
d73a8e2ee683e6812c21cb1de7363b14565a96d1 -- 
clang-tools-extra/clangd/HeuristicResolver.cpp 
clang-tools-extra/clangd/unittests/XRefsTests.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang-tools-extra/clangd/HeuristicResolver.cpp 
b/clang-tools-extra/clangd/HeuristicResolver.cpp
index d3dced9b3253..96b9afa7d8ea 100644
--- a/clang-tools-extra/clangd/HeuristicResolver.cpp
+++ b/clang-tools-extra/clangd/HeuristicResolver.cpp
@@ -56,7 +56,8 @@ const Type *resolveDeclsToType(const std::vector &Decls,
 // dependent one. Its associated type will then be extracted.
 struct InstantiatedDeclVisitor : RecursiveASTVisitor {
 
-  InstantiatedDeclVisitor(NamedDecl *DependentDecl) : 
DependentDecl(DependentDecl) {}
+  InstantiatedDeclVisitor(NamedDecl *DependentDecl)
+  : DependentDecl(DependentDecl) {}
 
   bool shouldVisitTemplateInstantiations() const { return true; }
 
@@ -64,8 +65,7 @@ struct InstantiatedDeclVisitor : 
RecursiveASTVisitor {
 
   bool shouldVisitImplicitCode() const { return true; }
 
-  template 
-  bool onDeclVisited(D *MaybeInstantiated) {
+  template  bool onDeclVisited(D *MaybeInstantiated) {
 if (MaybeInstantiated->getDeclContext()->isDependentContext())
   return true;
 auto *Dependent = dyn_cast(DependentDecl);
@@ -82,13 +82,9 @@ struct InstantiatedDeclVisitor : 
RecursiveASTVisitor {
 return false;
   }
 
-  bool VisitFieldDecl(FieldDecl *FD) {
-return onDeclVisited(FD);
-  }
+  bool VisitFieldDecl(FieldDecl *FD) { return onDeclVisited(FD); }
 
-  bool VisitVarDecl(VarDecl *VD) {
-return onDeclVisited(VD);
-  }
+  bool VisitVarDecl(VarDecl *VD) { return onDeclVisited(VD); }
 
   NamedDecl *DependentDecl;
   QualType DeducedType;

``




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


[llvm] [clang-tools-extra] [clang] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-11-04 Thread Nikita Popov via cfe-commits


@@ -0,0 +1,637 @@
+//===--- IRNormalizer.cpp - IR Normalizer ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+/// \file
+/// This file implements the IRNormalizer class which aims to transform LLVM
+/// Modules into a canonical form by reordering and renaming instructions while
+/// preserving the same semantics. The normalizer makes it easier to spot
+/// semantic differences while diffing two modules which have undergone
+/// different passes.
+///
+//===--===//
+
+#include "llvm/Transforms/Utils/IRNormalizer.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Utils.h"
+#include 
+#include 
+
+#define DEBUG_TYPE "normalize"
+
+using namespace llvm;
+
+namespace {
+/// IRNormalizer aims to transform LLVM IR into canonical form.
+class IRNormalizer {
+public:
+  /// \name Normalizer flags.
+  /// @{
+  /// Preserves original order of instructions.
+  static cl::opt PreserveOrder;
+  /// Renames all instructions (including user-named).
+  static cl::opt RenameAll;
+  /// Folds all regular instructions (including pre-outputs).
+  static cl::opt FoldPreoutputs;
+  /// Sorts and reorders operands in commutative instructions.
+  static cl::opt ReorderOperands;
+  /// @}
+
+  bool runOnFunction(Function &F);
+
+private:
+  // Random constant for hashing, so the state isn't zero.
+  const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
+  DenseSet NamedInstructions;
+
+  /// \name Naming.
+  /// @{
+  void nameFunctionArguments(Function &F);
+  void nameBasicBlocks(Function &F);
+  void nameInstruction(Instruction *I);
+  void nameAsInitialInstruction(Instruction *I);
+  void nameAsRegularInstruction(Instruction *I);
+  void foldInstructionName(Instruction *I);
+  /// @}
+
+  /// \name Reordering.
+  /// @{
+  void reorderInstructions(SmallVector &Outputs);
+  void reorderInstruction(Instruction *Used, Instruction *User,
+  SmallPtrSet &Visited);
+  void reorderInstructionOperandsByNames(Instruction *I);
+  void reorderPHIIncomingValues(PHINode *PN);
+  /// @}
+
+  /// \name Utility methods.
+  /// @{
+  SmallVector collectOutputInstructions(Function &F);
+  bool isOutput(const Instruction *I);
+  bool isInitialInstruction(const Instruction *I);
+  bool hasOnlyImmediateOperands(const Instruction *I);
+  SetVector
+  getOutputFootprint(Instruction *I,
+ SmallPtrSet &Visited);
+  /// @}
+};
+} // namespace
+
+cl::opt IRNormalizer::PreserveOrder(
+"preserve-order", cl::Hidden,
+cl::desc("Preserves original instruction order"));
+cl::opt IRNormalizer::RenameAll(
+"rename-all", cl::Hidden,
+cl::desc("Renames all instructions (including user-named)"));
+cl::opt IRNormalizer::FoldPreoutputs(
+"fold-all", cl::Hidden,
+cl::desc("Folds all regular instructions (including pre-outputs)"));
+cl::opt IRNormalizer::ReorderOperands(
+"reorder-operands", cl::Hidden,
+cl::desc("Sorts and reorders operands in commutative instructions"));
+
+/// Entry method to the IRNormalizer.
+///
+/// \param M Module to normalize.
+bool IRNormalizer::runOnFunction(Function &F) {
+  nameFunctionArguments(F);
+  nameBasicBlocks(F);
+
+  SmallVector Outputs = collectOutputInstructions(F);
+
+  if (!PreserveOrder)
+reorderInstructions(Outputs);
+
+  for (auto &I : Outputs)
+nameInstruction(I);
+
+  for (auto &I : instructions(F)) {
+if (!PreserveOrder) {
+  if (ReorderOperands && I.isCommutative())
+reorderInstructionOperandsByNames(&I);
+
+  if (auto *PN = dyn_cast(&I))
+reorderPHIIncomingValues(PN);
+}
+
+foldInstructionName(&I);
+  }
+
+  return true;
+}
+
+/// Numbers arguments.
+///
+/// \param F Function whose arguments will be renamed.
+void IRNormalizer::nameFunctionArguments(Function &F) {
+  int ArgumentCounter = 0;
+  for (auto &A : F.args()) {
+if (RenameAll || A.getName().empty()) {
+  A.setName("a" + Twine(ArgumentCounter));
+  ++ArgumentCounter;
+}
+  }
+}
+
+/// Names basic blocks using a generated hash for each basic block in
+/// a function considering the opcode and the order of output instructions.
+///
+/// \param F Function containing basic blocks to rename.
+void IRNormalizer::nameBasicBlocks(Function &F) {
+  for (auto &B : F) {
+

[llvm] [clang] [clang-tools-extra] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-11-04 Thread Nikita Popov via cfe-commits


@@ -0,0 +1,637 @@
+//===--- IRNormalizer.cpp - IR Normalizer ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+/// \file
+/// This file implements the IRNormalizer class which aims to transform LLVM
+/// Modules into a canonical form by reordering and renaming instructions while
+/// preserving the same semantics. The normalizer makes it easier to spot
+/// semantic differences while diffing two modules which have undergone
+/// different passes.
+///
+//===--===//
+
+#include "llvm/Transforms/Utils/IRNormalizer.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Utils.h"
+#include 
+#include 
+
+#define DEBUG_TYPE "normalize"
+
+using namespace llvm;
+
+namespace {
+/// IRNormalizer aims to transform LLVM IR into canonical form.
+class IRNormalizer {
+public:
+  /// \name Normalizer flags.
+  /// @{
+  /// Preserves original order of instructions.
+  static cl::opt PreserveOrder;
+  /// Renames all instructions (including user-named).
+  static cl::opt RenameAll;
+  /// Folds all regular instructions (including pre-outputs).
+  static cl::opt FoldPreoutputs;
+  /// Sorts and reorders operands in commutative instructions.
+  static cl::opt ReorderOperands;
+  /// @}
+
+  bool runOnFunction(Function &F);
+
+private:
+  // Random constant for hashing, so the state isn't zero.
+  const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
+  DenseSet NamedInstructions;
+
+  /// \name Naming.
+  /// @{
+  void nameFunctionArguments(Function &F);
+  void nameBasicBlocks(Function &F);
+  void nameInstruction(Instruction *I);
+  void nameAsInitialInstruction(Instruction *I);
+  void nameAsRegularInstruction(Instruction *I);
+  void foldInstructionName(Instruction *I);
+  /// @}
+
+  /// \name Reordering.
+  /// @{
+  void reorderInstructions(SmallVector &Outputs);
+  void reorderInstruction(Instruction *Used, Instruction *User,
+  SmallPtrSet &Visited);
+  void reorderInstructionOperandsByNames(Instruction *I);
+  void reorderPHIIncomingValues(PHINode *PN);
+  /// @}
+
+  /// \name Utility methods.
+  /// @{
+  SmallVector collectOutputInstructions(Function &F);
+  bool isOutput(const Instruction *I);
+  bool isInitialInstruction(const Instruction *I);
+  bool hasOnlyImmediateOperands(const Instruction *I);
+  SetVector
+  getOutputFootprint(Instruction *I,
+ SmallPtrSet &Visited);
+  /// @}
+};
+} // namespace
+
+cl::opt IRNormalizer::PreserveOrder(
+"preserve-order", cl::Hidden,
+cl::desc("Preserves original instruction order"));
+cl::opt IRNormalizer::RenameAll(
+"rename-all", cl::Hidden,
+cl::desc("Renames all instructions (including user-named)"));
+cl::opt IRNormalizer::FoldPreoutputs(
+"fold-all", cl::Hidden,
+cl::desc("Folds all regular instructions (including pre-outputs)"));
+cl::opt IRNormalizer::ReorderOperands(
+"reorder-operands", cl::Hidden,
+cl::desc("Sorts and reorders operands in commutative instructions"));
+
+/// Entry method to the IRNormalizer.
+///
+/// \param M Module to normalize.

nikic wrote:

This accepts F not M.

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


[clang] [llvm] [clang-tools-extra] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-11-04 Thread Nikita Popov via cfe-commits


@@ -0,0 +1,637 @@
+//===--- IRNormalizer.cpp - IR Normalizer ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+/// \file
+/// This file implements the IRNormalizer class which aims to transform LLVM
+/// Modules into a canonical form by reordering and renaming instructions while
+/// preserving the same semantics. The normalizer makes it easier to spot
+/// semantic differences while diffing two modules which have undergone
+/// different passes.
+///
+//===--===//
+
+#include "llvm/Transforms/Utils/IRNormalizer.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Utils.h"
+#include 
+#include 
+
+#define DEBUG_TYPE "normalize"
+
+using namespace llvm;
+
+namespace {
+/// IRNormalizer aims to transform LLVM IR into canonical form.
+class IRNormalizer {
+public:
+  /// \name Normalizer flags.
+  /// @{
+  /// Preserves original order of instructions.
+  static cl::opt PreserveOrder;
+  /// Renames all instructions (including user-named).
+  static cl::opt RenameAll;
+  /// Folds all regular instructions (including pre-outputs).
+  static cl::opt FoldPreoutputs;
+  /// Sorts and reorders operands in commutative instructions.
+  static cl::opt ReorderOperands;
+  /// @}
+
+  bool runOnFunction(Function &F);
+
+private:
+  // Random constant for hashing, so the state isn't zero.
+  const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
+  DenseSet NamedInstructions;
+
+  /// \name Naming.
+  /// @{
+  void nameFunctionArguments(Function &F);
+  void nameBasicBlocks(Function &F);
+  void nameInstruction(Instruction *I);
+  void nameAsInitialInstruction(Instruction *I);
+  void nameAsRegularInstruction(Instruction *I);
+  void foldInstructionName(Instruction *I);
+  /// @}
+
+  /// \name Reordering.
+  /// @{
+  void reorderInstructions(SmallVector &Outputs);
+  void reorderInstruction(Instruction *Used, Instruction *User,
+  SmallPtrSet &Visited);
+  void reorderInstructionOperandsByNames(Instruction *I);
+  void reorderPHIIncomingValues(PHINode *PN);
+  /// @}
+
+  /// \name Utility methods.
+  /// @{
+  SmallVector collectOutputInstructions(Function &F);
+  bool isOutput(const Instruction *I);
+  bool isInitialInstruction(const Instruction *I);
+  bool hasOnlyImmediateOperands(const Instruction *I);
+  SetVector
+  getOutputFootprint(Instruction *I,
+ SmallPtrSet &Visited);
+  /// @}
+};
+} // namespace
+
+cl::opt IRNormalizer::PreserveOrder(
+"preserve-order", cl::Hidden,
+cl::desc("Preserves original instruction order"));
+cl::opt IRNormalizer::RenameAll(
+"rename-all", cl::Hidden,
+cl::desc("Renames all instructions (including user-named)"));
+cl::opt IRNormalizer::FoldPreoutputs(
+"fold-all", cl::Hidden,
+cl::desc("Folds all regular instructions (including pre-outputs)"));
+cl::opt IRNormalizer::ReorderOperands(
+"reorder-operands", cl::Hidden,
+cl::desc("Sorts and reorders operands in commutative instructions"));

nikic wrote:

Should probably prefix these option names? They're in the global namespace.

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


[llvm] [clang] [clang-tools-extra] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-11-04 Thread Nikita Popov via cfe-commits


@@ -543,6 +543,14 @@ variables with initializers are marked as internal.
 An interprocedural variant of :ref:`Sparse Conditional Constant Propagation
 `.
 
+``ir-normalizer``: Transforms IR into a canonical form that's easier to diff

nikic wrote:

Looks like there are lots of leftovers of "canonical" vs "normalized".

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


[clang] [llvm] [clang-tools-extra] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-11-04 Thread Nikita Popov via cfe-commits

https://github.com/nikic edited https://github.com/llvm/llvm-project/pull/68176
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang-tools-extra] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-11-04 Thread Nikita Popov via cfe-commits


@@ -0,0 +1,637 @@
+//===--- IRNormalizer.cpp - IR Normalizer ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+/// \file
+/// This file implements the IRNormalizer class which aims to transform LLVM
+/// Modules into a canonical form by reordering and renaming instructions while
+/// preserving the same semantics. The normalizer makes it easier to spot
+/// semantic differences while diffing two modules which have undergone
+/// different passes.
+///
+//===--===//
+
+#include "llvm/Transforms/Utils/IRNormalizer.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Utils.h"
+#include 
+#include 
+
+#define DEBUG_TYPE "normalize"
+
+using namespace llvm;
+
+namespace {
+/// IRNormalizer aims to transform LLVM IR into canonical form.
+class IRNormalizer {
+public:
+  /// \name Normalizer flags.
+  /// @{
+  /// Preserves original order of instructions.
+  static cl::opt PreserveOrder;
+  /// Renames all instructions (including user-named).
+  static cl::opt RenameAll;
+  /// Folds all regular instructions (including pre-outputs).
+  static cl::opt FoldPreoutputs;
+  /// Sorts and reorders operands in commutative instructions.
+  static cl::opt ReorderOperands;
+  /// @}
+
+  bool runOnFunction(Function &F);
+
+private:
+  // Random constant for hashing, so the state isn't zero.
+  const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
+  DenseSet NamedInstructions;
+
+  /// \name Naming.
+  /// @{
+  void nameFunctionArguments(Function &F);
+  void nameBasicBlocks(Function &F);
+  void nameInstruction(Instruction *I);
+  void nameAsInitialInstruction(Instruction *I);
+  void nameAsRegularInstruction(Instruction *I);
+  void foldInstructionName(Instruction *I);
+  /// @}
+
+  /// \name Reordering.
+  /// @{
+  void reorderInstructions(SmallVector &Outputs);
+  void reorderInstruction(Instruction *Used, Instruction *User,
+  SmallPtrSet &Visited);
+  void reorderInstructionOperandsByNames(Instruction *I);
+  void reorderPHIIncomingValues(PHINode *PN);
+  /// @}
+
+  /// \name Utility methods.
+  /// @{
+  SmallVector collectOutputInstructions(Function &F);
+  bool isOutput(const Instruction *I);
+  bool isInitialInstruction(const Instruction *I);
+  bool hasOnlyImmediateOperands(const Instruction *I);
+  SetVector
+  getOutputFootprint(Instruction *I,
+ SmallPtrSet &Visited);
+  /// @}
+};
+} // namespace
+
+cl::opt IRNormalizer::PreserveOrder(
+"preserve-order", cl::Hidden,
+cl::desc("Preserves original instruction order"));
+cl::opt IRNormalizer::RenameAll(
+"rename-all", cl::Hidden,
+cl::desc("Renames all instructions (including user-named)"));
+cl::opt IRNormalizer::FoldPreoutputs(
+"fold-all", cl::Hidden,
+cl::desc("Folds all regular instructions (including pre-outputs)"));
+cl::opt IRNormalizer::ReorderOperands(
+"reorder-operands", cl::Hidden,
+cl::desc("Sorts and reorders operands in commutative instructions"));
+
+/// Entry method to the IRNormalizer.
+///
+/// \param M Module to normalize.
+bool IRNormalizer::runOnFunction(Function &F) {
+  nameFunctionArguments(F);
+  nameBasicBlocks(F);
+
+  SmallVector Outputs = collectOutputInstructions(F);
+
+  if (!PreserveOrder)
+reorderInstructions(Outputs);
+
+  for (auto &I : Outputs)
+nameInstruction(I);
+
+  for (auto &I : instructions(F)) {
+if (!PreserveOrder) {
+  if (ReorderOperands && I.isCommutative())
+reorderInstructionOperandsByNames(&I);
+
+  if (auto *PN = dyn_cast(&I))
+reorderPHIIncomingValues(PN);
+}
+
+foldInstructionName(&I);
+  }
+
+  return true;
+}
+
+/// Numbers arguments.
+///
+/// \param F Function whose arguments will be renamed.
+void IRNormalizer::nameFunctionArguments(Function &F) {
+  int ArgumentCounter = 0;
+  for (auto &A : F.args()) {
+if (RenameAll || A.getName().empty()) {
+  A.setName("a" + Twine(ArgumentCounter));
+  ++ArgumentCounter;
+}
+  }
+}
+
+/// Names basic blocks using a generated hash for each basic block in
+/// a function considering the opcode and the order of output instructions.
+///
+/// \param F Function containing basic blocks to rename.
+void IRNormalizer::nameBasicBlocks(Function &F) {
+  for (auto &B : F) {
+

[clang] [llvm] [clang-tools-extra] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-11-04 Thread Nikita Popov via cfe-commits


@@ -0,0 +1,637 @@
+//===--- IRNormalizer.cpp - IR Normalizer ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+/// \file
+/// This file implements the IRNormalizer class which aims to transform LLVM
+/// Modules into a canonical form by reordering and renaming instructions while
+/// preserving the same semantics. The normalizer makes it easier to spot
+/// semantic differences while diffing two modules which have undergone
+/// different passes.
+///
+//===--===//
+
+#include "llvm/Transforms/Utils/IRNormalizer.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Utils.h"
+#include 
+#include 
+
+#define DEBUG_TYPE "normalize"
+
+using namespace llvm;
+
+namespace {
+/// IRNormalizer aims to transform LLVM IR into canonical form.
+class IRNormalizer {
+public:
+  /// \name Normalizer flags.
+  /// @{
+  /// Preserves original order of instructions.
+  static cl::opt PreserveOrder;
+  /// Renames all instructions (including user-named).
+  static cl::opt RenameAll;
+  /// Folds all regular instructions (including pre-outputs).
+  static cl::opt FoldPreoutputs;
+  /// Sorts and reorders operands in commutative instructions.
+  static cl::opt ReorderOperands;
+  /// @}
+
+  bool runOnFunction(Function &F);
+
+private:
+  // Random constant for hashing, so the state isn't zero.
+  const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
+  DenseSet NamedInstructions;
+
+  /// \name Naming.
+  /// @{
+  void nameFunctionArguments(Function &F);
+  void nameBasicBlocks(Function &F);
+  void nameInstruction(Instruction *I);
+  void nameAsInitialInstruction(Instruction *I);
+  void nameAsRegularInstruction(Instruction *I);
+  void foldInstructionName(Instruction *I);
+  /// @}
+
+  /// \name Reordering.
+  /// @{
+  void reorderInstructions(SmallVector &Outputs);
+  void reorderInstruction(Instruction *Used, Instruction *User,
+  SmallPtrSet &Visited);
+  void reorderInstructionOperandsByNames(Instruction *I);
+  void reorderPHIIncomingValues(PHINode *PN);
+  /// @}
+
+  /// \name Utility methods.
+  /// @{
+  SmallVector collectOutputInstructions(Function &F);
+  bool isOutput(const Instruction *I);
+  bool isInitialInstruction(const Instruction *I);
+  bool hasOnlyImmediateOperands(const Instruction *I);
+  SetVector
+  getOutputFootprint(Instruction *I,
+ SmallPtrSet &Visited);
+  /// @}
+};
+} // namespace
+
+cl::opt IRNormalizer::PreserveOrder(
+"preserve-order", cl::Hidden,
+cl::desc("Preserves original instruction order"));
+cl::opt IRNormalizer::RenameAll(
+"rename-all", cl::Hidden,
+cl::desc("Renames all instructions (including user-named)"));
+cl::opt IRNormalizer::FoldPreoutputs(
+"fold-all", cl::Hidden,
+cl::desc("Folds all regular instructions (including pre-outputs)"));
+cl::opt IRNormalizer::ReorderOperands(
+"reorder-operands", cl::Hidden,
+cl::desc("Sorts and reorders operands in commutative instructions"));
+
+/// Entry method to the IRNormalizer.
+///
+/// \param M Module to normalize.
+bool IRNormalizer::runOnFunction(Function &F) {
+  nameFunctionArguments(F);
+  nameBasicBlocks(F);
+
+  SmallVector Outputs = collectOutputInstructions(F);
+
+  if (!PreserveOrder)
+reorderInstructions(Outputs);
+
+  for (auto &I : Outputs)
+nameInstruction(I);
+
+  for (auto &I : instructions(F)) {
+if (!PreserveOrder) {
+  if (ReorderOperands && I.isCommutative())
+reorderInstructionOperandsByNames(&I);
+
+  if (auto *PN = dyn_cast(&I))
+reorderPHIIncomingValues(PN);
+}
+
+foldInstructionName(&I);
+  }
+
+  return true;
+}
+
+/// Numbers arguments.
+///
+/// \param F Function whose arguments will be renamed.
+void IRNormalizer::nameFunctionArguments(Function &F) {
+  int ArgumentCounter = 0;
+  for (auto &A : F.args()) {
+if (RenameAll || A.getName().empty()) {
+  A.setName("a" + Twine(ArgumentCounter));
+  ++ArgumentCounter;
+}
+  }
+}
+
+/// Names basic blocks using a generated hash for each basic block in
+/// a function considering the opcode and the order of output instructions.
+///
+/// \param F Function containing basic blocks to rename.
+void IRNormalizer::nameBasicBlocks(Function &F) {
+  for (auto &B : F) {
+

[clang] [clang-tools-extra] [llvm] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-11-04 Thread Nikita Popov via cfe-commits

https://github.com/nikic commented:

Could you please update the patch description with some information on what 
kind of normalization the pass does?

It would also be great to post some examples, because I don't really get what 
kind of renaming and reordering this does just looking at the test coverage.

One bit that's particularly non-obvious to me is why this normalization has to 
involve hashes? That seems like it would make things more unstable and hard to 
understand.

I would recommend trying to run this pass (with all options enabled) over all 
existing tests to make sure that it doesn't cause any crashes/verifier 
failures. You're moving instructions around, and it's easy to get that wrong 
when invoke, callbr or catchswitch are involved.

I would also try to add this pass at the end of the clang pipeline and run 
llvm-test-suite to verify that the normalization this does is indeed 
semantics-preserving.

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


[clang-tools-extra] [llvm] [clang] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-11-04 Thread Nikita Popov via cfe-commits


@@ -0,0 +1,637 @@
+//===--- IRNormalizer.cpp - IR Normalizer ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+/// \file
+/// This file implements the IRNormalizer class which aims to transform LLVM
+/// Modules into a canonical form by reordering and renaming instructions while
+/// preserving the same semantics. The normalizer makes it easier to spot
+/// semantic differences while diffing two modules which have undergone
+/// different passes.
+///
+//===--===//
+
+#include "llvm/Transforms/Utils/IRNormalizer.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Utils.h"
+#include 
+#include 
+
+#define DEBUG_TYPE "normalize"
+
+using namespace llvm;
+
+namespace {
+/// IRNormalizer aims to transform LLVM IR into canonical form.
+class IRNormalizer {
+public:
+  /// \name Normalizer flags.
+  /// @{
+  /// Preserves original order of instructions.
+  static cl::opt PreserveOrder;
+  /// Renames all instructions (including user-named).
+  static cl::opt RenameAll;
+  /// Folds all regular instructions (including pre-outputs).
+  static cl::opt FoldPreoutputs;
+  /// Sorts and reorders operands in commutative instructions.
+  static cl::opt ReorderOperands;
+  /// @}
+
+  bool runOnFunction(Function &F);
+
+private:
+  // Random constant for hashing, so the state isn't zero.
+  const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
+  DenseSet NamedInstructions;
+
+  /// \name Naming.
+  /// @{
+  void nameFunctionArguments(Function &F);
+  void nameBasicBlocks(Function &F);
+  void nameInstruction(Instruction *I);
+  void nameAsInitialInstruction(Instruction *I);
+  void nameAsRegularInstruction(Instruction *I);
+  void foldInstructionName(Instruction *I);
+  /// @}
+
+  /// \name Reordering.
+  /// @{
+  void reorderInstructions(SmallVector &Outputs);
+  void reorderInstruction(Instruction *Used, Instruction *User,
+  SmallPtrSet &Visited);
+  void reorderInstructionOperandsByNames(Instruction *I);
+  void reorderPHIIncomingValues(PHINode *PN);
+  /// @}
+
+  /// \name Utility methods.
+  /// @{
+  SmallVector collectOutputInstructions(Function &F);
+  bool isOutput(const Instruction *I);
+  bool isInitialInstruction(const Instruction *I);
+  bool hasOnlyImmediateOperands(const Instruction *I);
+  SetVector
+  getOutputFootprint(Instruction *I,
+ SmallPtrSet &Visited);
+  /// @}
+};
+} // namespace
+
+cl::opt IRNormalizer::PreserveOrder(
+"preserve-order", cl::Hidden,
+cl::desc("Preserves original instruction order"));
+cl::opt IRNormalizer::RenameAll(
+"rename-all", cl::Hidden,
+cl::desc("Renames all instructions (including user-named)"));
+cl::opt IRNormalizer::FoldPreoutputs(
+"fold-all", cl::Hidden,
+cl::desc("Folds all regular instructions (including pre-outputs)"));
+cl::opt IRNormalizer::ReorderOperands(
+"reorder-operands", cl::Hidden,
+cl::desc("Sorts and reorders operands in commutative instructions"));
+
+/// Entry method to the IRNormalizer.
+///
+/// \param M Module to normalize.
+bool IRNormalizer::runOnFunction(Function &F) {
+  nameFunctionArguments(F);
+  nameBasicBlocks(F);
+
+  SmallVector Outputs = collectOutputInstructions(F);
+
+  if (!PreserveOrder)
+reorderInstructions(Outputs);
+
+  for (auto &I : Outputs)
+nameInstruction(I);
+
+  for (auto &I : instructions(F)) {
+if (!PreserveOrder) {
+  if (ReorderOperands && I.isCommutative())
+reorderInstructionOperandsByNames(&I);
+
+  if (auto *PN = dyn_cast(&I))
+reorderPHIIncomingValues(PN);
+}
+
+foldInstructionName(&I);
+  }
+
+  return true;
+}
+
+/// Numbers arguments.
+///
+/// \param F Function whose arguments will be renamed.
+void IRNormalizer::nameFunctionArguments(Function &F) {
+  int ArgumentCounter = 0;
+  for (auto &A : F.args()) {
+if (RenameAll || A.getName().empty()) {
+  A.setName("a" + Twine(ArgumentCounter));
+  ++ArgumentCounter;
+}
+  }
+}
+
+/// Names basic blocks using a generated hash for each basic block in
+/// a function considering the opcode and the order of output instructions.
+///
+/// \param F Function containing basic blocks to rename.
+void IRNormalizer::nameBasicBlocks(Function &F) {
+  for (auto &B : F) {
+

[llvm] [clang-tools-extra] [clang] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-11-04 Thread Nikita Popov via cfe-commits


@@ -0,0 +1,637 @@
+//===--- IRNormalizer.cpp - IR Normalizer ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+/// \file
+/// This file implements the IRNormalizer class which aims to transform LLVM
+/// Modules into a canonical form by reordering and renaming instructions while
+/// preserving the same semantics. The normalizer makes it easier to spot
+/// semantic differences while diffing two modules which have undergone
+/// different passes.
+///
+//===--===//
+
+#include "llvm/Transforms/Utils/IRNormalizer.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Utils.h"
+#include 
+#include 
+
+#define DEBUG_TYPE "normalize"
+
+using namespace llvm;
+
+namespace {
+/// IRNormalizer aims to transform LLVM IR into canonical form.
+class IRNormalizer {
+public:
+  /// \name Normalizer flags.
+  /// @{
+  /// Preserves original order of instructions.
+  static cl::opt PreserveOrder;
+  /// Renames all instructions (including user-named).
+  static cl::opt RenameAll;
+  /// Folds all regular instructions (including pre-outputs).
+  static cl::opt FoldPreoutputs;
+  /// Sorts and reorders operands in commutative instructions.
+  static cl::opt ReorderOperands;
+  /// @}
+
+  bool runOnFunction(Function &F);
+
+private:
+  // Random constant for hashing, so the state isn't zero.
+  const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
+  DenseSet NamedInstructions;
+
+  /// \name Naming.
+  /// @{
+  void nameFunctionArguments(Function &F);
+  void nameBasicBlocks(Function &F);
+  void nameInstruction(Instruction *I);
+  void nameAsInitialInstruction(Instruction *I);
+  void nameAsRegularInstruction(Instruction *I);
+  void foldInstructionName(Instruction *I);
+  /// @}
+
+  /// \name Reordering.
+  /// @{
+  void reorderInstructions(SmallVector &Outputs);
+  void reorderInstruction(Instruction *Used, Instruction *User,
+  SmallPtrSet &Visited);
+  void reorderInstructionOperandsByNames(Instruction *I);
+  void reorderPHIIncomingValues(PHINode *PN);
+  /// @}
+
+  /// \name Utility methods.
+  /// @{
+  SmallVector collectOutputInstructions(Function &F);
+  bool isOutput(const Instruction *I);
+  bool isInitialInstruction(const Instruction *I);
+  bool hasOnlyImmediateOperands(const Instruction *I);
+  SetVector
+  getOutputFootprint(Instruction *I,
+ SmallPtrSet &Visited);
+  /// @}
+};
+} // namespace
+
+cl::opt IRNormalizer::PreserveOrder(
+"preserve-order", cl::Hidden,
+cl::desc("Preserves original instruction order"));
+cl::opt IRNormalizer::RenameAll(
+"rename-all", cl::Hidden,
+cl::desc("Renames all instructions (including user-named)"));
+cl::opt IRNormalizer::FoldPreoutputs(
+"fold-all", cl::Hidden,
+cl::desc("Folds all regular instructions (including pre-outputs)"));
+cl::opt IRNormalizer::ReorderOperands(
+"reorder-operands", cl::Hidden,
+cl::desc("Sorts and reorders operands in commutative instructions"));
+
+/// Entry method to the IRNormalizer.
+///
+/// \param M Module to normalize.
+bool IRNormalizer::runOnFunction(Function &F) {
+  nameFunctionArguments(F);
+  nameBasicBlocks(F);
+
+  SmallVector Outputs = collectOutputInstructions(F);
+
+  if (!PreserveOrder)
+reorderInstructions(Outputs);
+
+  for (auto &I : Outputs)
+nameInstruction(I);
+
+  for (auto &I : instructions(F)) {
+if (!PreserveOrder) {
+  if (ReorderOperands && I.isCommutative())
+reorderInstructionOperandsByNames(&I);
+
+  if (auto *PN = dyn_cast(&I))
+reorderPHIIncomingValues(PN);
+}
+
+foldInstructionName(&I);
+  }
+
+  return true;
+}
+
+/// Numbers arguments.
+///
+/// \param F Function whose arguments will be renamed.
+void IRNormalizer::nameFunctionArguments(Function &F) {
+  int ArgumentCounter = 0;
+  for (auto &A : F.args()) {
+if (RenameAll || A.getName().empty()) {
+  A.setName("a" + Twine(ArgumentCounter));
+  ++ArgumentCounter;
+}
+  }
+}
+
+/// Names basic blocks using a generated hash for each basic block in
+/// a function considering the opcode and the order of output instructions.
+///
+/// \param F Function containing basic blocks to rename.
+void IRNormalizer::nameBasicBlocks(Function &F) {
+  for (auto &B : F) {
+

[clang-tools-extra] [clang] [llvm] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-11-04 Thread Nikita Popov via cfe-commits


@@ -0,0 +1,637 @@
+//===--- IRNormalizer.cpp - IR Normalizer ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+/// \file
+/// This file implements the IRNormalizer class which aims to transform LLVM
+/// Modules into a canonical form by reordering and renaming instructions while
+/// preserving the same semantics. The normalizer makes it easier to spot
+/// semantic differences while diffing two modules which have undergone
+/// different passes.
+///
+//===--===//
+
+#include "llvm/Transforms/Utils/IRNormalizer.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Utils.h"
+#include 
+#include 
+
+#define DEBUG_TYPE "normalize"
+
+using namespace llvm;
+
+namespace {
+/// IRNormalizer aims to transform LLVM IR into canonical form.
+class IRNormalizer {
+public:
+  /// \name Normalizer flags.
+  /// @{
+  /// Preserves original order of instructions.
+  static cl::opt PreserveOrder;
+  /// Renames all instructions (including user-named).
+  static cl::opt RenameAll;
+  /// Folds all regular instructions (including pre-outputs).
+  static cl::opt FoldPreoutputs;
+  /// Sorts and reorders operands in commutative instructions.
+  static cl::opt ReorderOperands;
+  /// @}
+
+  bool runOnFunction(Function &F);
+
+private:
+  // Random constant for hashing, so the state isn't zero.
+  const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
+  DenseSet NamedInstructions;
+
+  /// \name Naming.
+  /// @{
+  void nameFunctionArguments(Function &F);
+  void nameBasicBlocks(Function &F);
+  void nameInstruction(Instruction *I);
+  void nameAsInitialInstruction(Instruction *I);
+  void nameAsRegularInstruction(Instruction *I);
+  void foldInstructionName(Instruction *I);
+  /// @}
+
+  /// \name Reordering.
+  /// @{
+  void reorderInstructions(SmallVector &Outputs);
+  void reorderInstruction(Instruction *Used, Instruction *User,
+  SmallPtrSet &Visited);
+  void reorderInstructionOperandsByNames(Instruction *I);
+  void reorderPHIIncomingValues(PHINode *PN);
+  /// @}
+
+  /// \name Utility methods.
+  /// @{
+  SmallVector collectOutputInstructions(Function &F);
+  bool isOutput(const Instruction *I);
+  bool isInitialInstruction(const Instruction *I);
+  bool hasOnlyImmediateOperands(const Instruction *I);
+  SetVector
+  getOutputFootprint(Instruction *I,
+ SmallPtrSet &Visited);
+  /// @}
+};
+} // namespace
+
+cl::opt IRNormalizer::PreserveOrder(
+"preserve-order", cl::Hidden,
+cl::desc("Preserves original instruction order"));
+cl::opt IRNormalizer::RenameAll(
+"rename-all", cl::Hidden,
+cl::desc("Renames all instructions (including user-named)"));
+cl::opt IRNormalizer::FoldPreoutputs(
+"fold-all", cl::Hidden,
+cl::desc("Folds all regular instructions (including pre-outputs)"));
+cl::opt IRNormalizer::ReorderOperands(
+"reorder-operands", cl::Hidden,
+cl::desc("Sorts and reorders operands in commutative instructions"));
+
+/// Entry method to the IRNormalizer.
+///
+/// \param M Module to normalize.
+bool IRNormalizer::runOnFunction(Function &F) {
+  nameFunctionArguments(F);
+  nameBasicBlocks(F);
+
+  SmallVector Outputs = collectOutputInstructions(F);
+
+  if (!PreserveOrder)
+reorderInstructions(Outputs);
+
+  for (auto &I : Outputs)
+nameInstruction(I);
+
+  for (auto &I : instructions(F)) {
+if (!PreserveOrder) {
+  if (ReorderOperands && I.isCommutative())
+reorderInstructionOperandsByNames(&I);
+
+  if (auto *PN = dyn_cast(&I))
+reorderPHIIncomingValues(PN);
+}
+
+foldInstructionName(&I);
+  }
+
+  return true;
+}
+
+/// Numbers arguments.
+///
+/// \param F Function whose arguments will be renamed.
+void IRNormalizer::nameFunctionArguments(Function &F) {
+  int ArgumentCounter = 0;
+  for (auto &A : F.args()) {
+if (RenameAll || A.getName().empty()) {
+  A.setName("a" + Twine(ArgumentCounter));
+  ++ArgumentCounter;
+}
+  }
+}
+
+/// Names basic blocks using a generated hash for each basic block in
+/// a function considering the opcode and the order of output instructions.
+///
+/// \param F Function containing basic blocks to rename.
+void IRNormalizer::nameBasicBlocks(Function &F) {
+  for (auto &B : F) {
+

[clang-tools-extra] [llvm] [clang] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-11-04 Thread Nikita Popov via cfe-commits


@@ -0,0 +1,637 @@
+//===--- IRNormalizer.cpp - IR Normalizer ---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+/// \file
+/// This file implements the IRNormalizer class which aims to transform LLVM
+/// Modules into a canonical form by reordering and renaming instructions while
+/// preserving the same semantics. The normalizer makes it easier to spot
+/// semantic differences while diffing two modules which have undergone
+/// different passes.
+///
+//===--===//
+
+#include "llvm/Transforms/Utils/IRNormalizer.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/PassRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Utils.h"
+#include 
+#include 
+
+#define DEBUG_TYPE "normalize"
+
+using namespace llvm;
+
+namespace {
+/// IRNormalizer aims to transform LLVM IR into canonical form.
+class IRNormalizer {
+public:
+  /// \name Normalizer flags.
+  /// @{
+  /// Preserves original order of instructions.
+  static cl::opt PreserveOrder;
+  /// Renames all instructions (including user-named).
+  static cl::opt RenameAll;
+  /// Folds all regular instructions (including pre-outputs).
+  static cl::opt FoldPreoutputs;
+  /// Sorts and reorders operands in commutative instructions.
+  static cl::opt ReorderOperands;
+  /// @}
+
+  bool runOnFunction(Function &F);
+
+private:
+  // Random constant for hashing, so the state isn't zero.
+  const uint64_t MagicHashConstant = 0x6acaa36bef8325c5ULL;
+  DenseSet NamedInstructions;
+
+  /// \name Naming.
+  /// @{
+  void nameFunctionArguments(Function &F);
+  void nameBasicBlocks(Function &F);
+  void nameInstruction(Instruction *I);
+  void nameAsInitialInstruction(Instruction *I);
+  void nameAsRegularInstruction(Instruction *I);
+  void foldInstructionName(Instruction *I);
+  /// @}
+
+  /// \name Reordering.
+  /// @{
+  void reorderInstructions(SmallVector &Outputs);
+  void reorderInstruction(Instruction *Used, Instruction *User,
+  SmallPtrSet &Visited);
+  void reorderInstructionOperandsByNames(Instruction *I);
+  void reorderPHIIncomingValues(PHINode *PN);
+  /// @}
+
+  /// \name Utility methods.
+  /// @{
+  SmallVector collectOutputInstructions(Function &F);
+  bool isOutput(const Instruction *I);
+  bool isInitialInstruction(const Instruction *I);
+  bool hasOnlyImmediateOperands(const Instruction *I);
+  SetVector
+  getOutputFootprint(Instruction *I,
+ SmallPtrSet &Visited);
+  /// @}
+};
+} // namespace
+
+cl::opt IRNormalizer::PreserveOrder(
+"preserve-order", cl::Hidden,
+cl::desc("Preserves original instruction order"));
+cl::opt IRNormalizer::RenameAll(
+"rename-all", cl::Hidden,
+cl::desc("Renames all instructions (including user-named)"));
+cl::opt IRNormalizer::FoldPreoutputs(
+"fold-all", cl::Hidden,
+cl::desc("Folds all regular instructions (including pre-outputs)"));
+cl::opt IRNormalizer::ReorderOperands(
+"reorder-operands", cl::Hidden,
+cl::desc("Sorts and reorders operands in commutative instructions"));
+
+/// Entry method to the IRNormalizer.
+///
+/// \param M Module to normalize.
+bool IRNormalizer::runOnFunction(Function &F) {
+  nameFunctionArguments(F);
+  nameBasicBlocks(F);
+
+  SmallVector Outputs = collectOutputInstructions(F);
+
+  if (!PreserveOrder)
+reorderInstructions(Outputs);
+
+  for (auto &I : Outputs)
+nameInstruction(I);
+
+  for (auto &I : instructions(F)) {
+if (!PreserveOrder) {
+  if (ReorderOperands && I.isCommutative())
+reorderInstructionOperandsByNames(&I);
+
+  if (auto *PN = dyn_cast(&I))
+reorderPHIIncomingValues(PN);
+}
+
+foldInstructionName(&I);
+  }
+
+  return true;
+}
+
+/// Numbers arguments.
+///
+/// \param F Function whose arguments will be renamed.
+void IRNormalizer::nameFunctionArguments(Function &F) {
+  int ArgumentCounter = 0;
+  for (auto &A : F.args()) {
+if (RenameAll || A.getName().empty()) {
+  A.setName("a" + Twine(ArgumentCounter));
+  ++ArgumentCounter;
+}
+  }
+}
+
+/// Names basic blocks using a generated hash for each basic block in
+/// a function considering the opcode and the order of output instructions.
+///
+/// \param F Function containing basic blocks to rename.
+void IRNormalizer::nameBasicBlocks(Function &F) {
+  for (auto &B : F) {
+

[clang-tools-extra] [llvm] [clang] [LLVM] Add IRNormalizer Pass (PR #68176)

2023-11-04 Thread Nikita Popov via cfe-commits

https://github.com/nikic edited https://github.com/llvm/llvm-project/pull/68176
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [analyzer][solver] On SymSym RelOps, check EQClass members for contradictions (PR #71284)

2023-11-04 Thread Balazs Benics via cfe-commits

https://github.com/steakhal created 
https://github.com/llvm/llvm-project/pull/71284

The idea is that if we see a `X RELOP Y` being constrained to a RangeSet `S`, 
then check the eqclasses of X and Y respectively and for `X' RELOP Y'` 
SymSymExprs and try to infer their ranges.
If there is no contradiction with any of the equivalent alternatives, then 
intersecting all these RangeSets should never be empty - aka. there should be a 
value satisfying the constraints we have.

It costs around `|eqclass(X)| + |eqclass(y)|`.

The approach has its limitations, as demonstrated by 
`gh_62215_contradicting_nested_right_equivalent`, where we would need to apply 
the same logic, but on a sub-expression of a direct operand.

Before the patch, line 90, 100, and 112 would be reachable; and become 
unreachable after this. Line 127 will remain still reachable, but keep in mind 
that when cross-checking with Z3 (aka. Z3 refutation), then all 4 reports would 
be eliminated.

The idea comes from
https://github.com/llvm/llvm-project/issues/62215#issuecomment-1792878474

Fixes #62215

>From 92ece501b340c3a2a52b5a4614ddb70bb3e35c93 Mon Sep 17 00:00:00 2001
From: Balazs Benics 
Date: Sat, 4 Nov 2023 13:44:28 +0100
Subject: [PATCH] [analyzer][solver] On SymSym RelOps, check EQClass members
 for contradictions

The idea is that if we see a `X RELOP Y` being constrained to a RangeSet `S`,
then check the eqclasses of X and Y respectively and for `X' RELOP Y'`
SymSymExprs and try to infer their ranges.
If there is no contradiction with any of the equivalent alternatives,
then intersecting all these RangeSets should never be empty - aka. there
should be a value satisfying the constraints we have.

It costs around `|eqclass(X)| + |eqclass(y)|`.

The approach has its limitations, as demonstrated by
`gh_62215_contradicting_nested_right_equivalent`, where we would need to
apply the same logic, but on a sub-expression of a direct operand.

Before the patch, line 90, 100, and 112 would be reachable; and become
unreachable after this. Line 127 will remain still reachable, but keep
in mind that when cross-checking with Z3 (aka. Z3 refutation), then all
4 reports would be eliminated.

The idea comes from
https://github.com/llvm/llvm-project/issues/62215#issuecomment-1792878474

Fixes #62215
---
 .../Core/RangeConstraintManager.cpp   | 53 +++
 clang/test/Analysis/constraint-assignor.c | 48 +
 2 files changed, 101 insertions(+)

diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp 
b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 5de99384449a4c8..d631369e895d3a9 100644
--- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -2067,6 +2067,12 @@ class ConstraintAssignor : public 
ConstraintAssignorBase {
 return Assignor.assign(CoS, NewConstraint);
   }
 
+  /// Check if using an equivalent operand alternative would lead to
+  /// contradiction.
+  /// If a contradiction is witnessed, returns false; otherwise returns true.
+  bool handleEquivalentAlternativeSymOperands(const SymSymExpr *SymSym,
+  RangeSet Constraint);
+
   /// Handle expressions like: a % b != 0.
   template 
   bool handleRemainderOp(const SymT *Sym, RangeSet Constraint) {
@@ -2218,11 +2224,58 @@ bool ConstraintAssignor::assignSymExprToConst(const 
SymExpr *Sym,
   return true;
 }
 
+bool ConstraintAssignor::handleEquivalentAlternativeSymOperands(
+const SymSymExpr *SymSym, RangeSet Constraint) {
+  SymbolRef LHS = SymSym->getLHS();
+  SymbolRef RHS = SymSym->getRHS();
+  EquivalenceClass LHSClass = EquivalenceClass::find(State, LHS);
+  EquivalenceClass RHSClass = EquivalenceClass::find(State, RHS);
+  SymbolSet SymbolsEqWithLHS = LHSClass.getClassMembers(State);
+  SymbolSet SymbolsEqWithRHS = RHSClass.getClassMembers(State);
+  llvm::SmallVector AlternativeSymSyms;
+
+  // Gather left alternatives.
+  for (SymbolRef AlternativeLHS : SymbolsEqWithLHS) {
+if (AlternativeLHS == LHS)
+  continue;
+AlternativeSymSyms.emplace_back(AlternativeLHS, SymSym->getOpcode(), RHS,
+SymSym->getType());
+  }
+
+  // Gather right alternatives.
+  for (SymbolRef AlternativeRHS : SymbolsEqWithRHS) {
+if (AlternativeRHS == RHS)
+  continue;
+AlternativeSymSyms.emplace_back(LHS, SymSym->getOpcode(), AlternativeRHS,
+SymSym->getType());
+  }
+
+  // Crosscheck the inferred ranges.
+  for (SymSymExpr AltSymSym : AlternativeSymSyms) {
+RangeSet AltSymSymConstrant =
+SymbolicRangeInferrer::inferRange(RangeFactory, State, &AltSymSym);
+Constraint = intersect(RangeFactory, Constraint, AltSymSymConstrant);
+
+// Check if we witnessed a contradiction with the equivalent alternative
+// operand.
+if (Constraint.isEmpty()) {
+  State = nullptr;
+  return false;
+}
+  }
+  r

[clang] [analyzer][solver] On SymSym RelOps, check EQClass members for contradictions (PR #71284)

2023-11-04 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-static-analyzer-1

Author: Balazs Benics (steakhal)


Changes

The idea is that if we see a `X RELOP Y` being constrained to a RangeSet `S`, 
then check the eqclasses of X and Y respectively and for `X' RELOP Y'` 
SymSymExprs and try to infer their ranges.
If there is no contradiction with any of the equivalent alternatives, then 
intersecting all these RangeSets should never be empty - aka. there should be a 
value satisfying the constraints we have.

It costs around `|eqclass(X)| + |eqclass(y)|`.

The approach has its limitations, as demonstrated by 
`gh_62215_contradicting_nested_right_equivalent`, where we would need to apply 
the same logic, but on a sub-expression of a direct operand.

Before the patch, line 90, 100, and 112 would be reachable; and become 
unreachable after this. Line 127 will remain still reachable, but keep in mind 
that when cross-checking with Z3 (aka. Z3 refutation), then all 4 reports would 
be eliminated.

The idea comes from
https://github.com/llvm/llvm-project/issues/62215#issuecomment-1792878474

Fixes #62215

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


2 Files Affected:

- (modified) clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp (+53) 
- (modified) clang/test/Analysis/constraint-assignor.c (+48) 


``diff
diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp 
b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 5de99384449a4c8..d631369e895d3a9 100644
--- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -2067,6 +2067,12 @@ class ConstraintAssignor : public 
ConstraintAssignorBase {
 return Assignor.assign(CoS, NewConstraint);
   }
 
+  /// Check if using an equivalent operand alternative would lead to
+  /// contradiction.
+  /// If a contradiction is witnessed, returns false; otherwise returns true.
+  bool handleEquivalentAlternativeSymOperands(const SymSymExpr *SymSym,
+  RangeSet Constraint);
+
   /// Handle expressions like: a % b != 0.
   template 
   bool handleRemainderOp(const SymT *Sym, RangeSet Constraint) {
@@ -2218,11 +2224,58 @@ bool ConstraintAssignor::assignSymExprToConst(const 
SymExpr *Sym,
   return true;
 }
 
+bool ConstraintAssignor::handleEquivalentAlternativeSymOperands(
+const SymSymExpr *SymSym, RangeSet Constraint) {
+  SymbolRef LHS = SymSym->getLHS();
+  SymbolRef RHS = SymSym->getRHS();
+  EquivalenceClass LHSClass = EquivalenceClass::find(State, LHS);
+  EquivalenceClass RHSClass = EquivalenceClass::find(State, RHS);
+  SymbolSet SymbolsEqWithLHS = LHSClass.getClassMembers(State);
+  SymbolSet SymbolsEqWithRHS = RHSClass.getClassMembers(State);
+  llvm::SmallVector AlternativeSymSyms;
+
+  // Gather left alternatives.
+  for (SymbolRef AlternativeLHS : SymbolsEqWithLHS) {
+if (AlternativeLHS == LHS)
+  continue;
+AlternativeSymSyms.emplace_back(AlternativeLHS, SymSym->getOpcode(), RHS,
+SymSym->getType());
+  }
+
+  // Gather right alternatives.
+  for (SymbolRef AlternativeRHS : SymbolsEqWithRHS) {
+if (AlternativeRHS == RHS)
+  continue;
+AlternativeSymSyms.emplace_back(LHS, SymSym->getOpcode(), AlternativeRHS,
+SymSym->getType());
+  }
+
+  // Crosscheck the inferred ranges.
+  for (SymSymExpr AltSymSym : AlternativeSymSyms) {
+RangeSet AltSymSymConstrant =
+SymbolicRangeInferrer::inferRange(RangeFactory, State, &AltSymSym);
+Constraint = intersect(RangeFactory, Constraint, AltSymSymConstrant);
+
+// Check if we witnessed a contradiction with the equivalent alternative
+// operand.
+if (Constraint.isEmpty()) {
+  State = nullptr;
+  return false;
+}
+  }
+  return true;
+}
+
 bool ConstraintAssignor::assignSymSymExprToRangeSet(const SymSymExpr *Sym,
 RangeSet Constraint) {
   if (!handleRemainderOp(Sym, Constraint))
 return false;
 
+  if (const auto *SymSym = dyn_cast(Sym);
+  SymSym && !handleEquivalentAlternativeSymOperands(SymSym, Constraint)) {
+return false;
+  }
+
   std::optional ConstraintAsBool = interpreteAsBool(Constraint);
 
   if (!ConstraintAsBool)
diff --git a/clang/test/Analysis/constraint-assignor.c 
b/clang/test/Analysis/constraint-assignor.c
index 8210e576c98bd21..d5078b406e12601 100644
--- a/clang/test/Analysis/constraint-assignor.c
+++ b/clang/test/Analysis/constraint-assignor.c
@@ -82,3 +82,51 @@ void remainder_with_adjustment_of_composit_lhs(int x, int y) 
{
   clang_analyzer_eval(x + y != -1);// expected-warning{{TRUE}}
   (void)(x * y); // keep the constraints alive.
 }
+
+void gh_62215(int x, int y, int z) {
+  if (x != y) return; // x == y
+  if (z <= x) return; // z > x
+  if (z >= y) return; // z < y
+  clang_analyzer_warnIfReached(); // no-warning: This should be dead

[clang] [analyzer][NFC] Rework SVal kind representation (PR #71039)

2023-11-04 Thread Balazs Benics via cfe-commits

https://github.com/steakhal updated 
https://github.com/llvm/llvm-project/pull/71039

>From 8f16d3000a91df33d416dd09381175ddeb7e5ed3 Mon Sep 17 00:00:00 2001
From: Balazs Benics 
Date: Sat, 4 Nov 2023 15:25:42 +0100
Subject: [PATCH] [analyzer][NFC] Rework SVal kind representation

The goal of this patch is to refine how the `SVal` base and sub-kinds
are represented by forming one unified enum describing the possible SVals.
This means that the `unsigned SVal::Kind` and the attached bit-packing
semantics would be replaced by a single unified enum.
This is more conventional and leads to a better debugging experience by default.
This eases the need of using debug pretty-printers, or the use of
runtime functions doing the printing for us like we do today by calling
`Val.dump()` whenever we inspect the values.

Previously, the first 2 bits of the `unsigned SVal::Kind` discriminated
the following quartet: `UndefinedVal`, `UnknownVal`, `Loc`, or `NonLoc`.
The rest of the upper bits represented the sub-kind, where the value
represented the index among only the `Loc`s or `NonLoc`s, effectively
attaching 2 meanings of the upper bits depending on the base-kind.
We don't need to pack these bits, as we have plenty even if we would use
just a plan-old `unsigned char`.

Consequently, in this patch, I propose to lay out all the (non-abstract)
`SVal` kinds into a single enum, along with some metadata (`BEGIN_Loc`,
`END_Loc`, `BEGIN_NonLoc`, `END_NonLoc`) artificial enum values, similar
how we do with the `MemRegions`.

Note that in the unified `SVal::Kind` enum, to differentiate
`nonloc::ConcreteInt` from `loc::ConcreteInt`, I had to prefix them with
`Loc` and `NonLoc` to resolve this ambiguity.
This should not surface in general, because I'm replacing the
`nonloc::Kind` enum items with `inline constexpr` global constants to
mimic the original behavior - and offer nicer spelling to these enum
values.

Some `SVal` constructors were not marked explicit, which I now mark as
such to follow best practices, and marked others as `/*implicit*/` to
clarify the intent.
During refactoring, I also found at least one function not marked
`LLVM_ATTRIBUTE_RETURNS_NONNULL`, so I did that.

The `TypeRetrievingVisitor` visitor had some accidental dead code,
namely: `VisitNonLocConcreteInt` and `VisitLocConcreteInt`.

Previously, the `SValVisitor` expected visit handlers of
`VisitNonLocX(nonloc::X)` and `VisitLocX(loc::X)`, where
I felt that envoding `NonLoc` and `Loc` in the name is not necessary as
the type of the parameter would select the right overload anyways, so I
simplified the naming of those visit functions.

The rest of the diff is a lot of times just formatting, because
`getKind()` by nature, frequently appears in switches, which means that
the whole switch gets automatically reformatted. I could probably undo
the formatting, but I didn't want to deviate from the rule unless
explicitly requested.
---
 .../StaticAnalyzer/Checkers/SValExplainer.h   |  10 +-
 .../Core/PathSensitive/SValVisitor.h  |  55 ++---
 .../Core/PathSensitive/SVals.def  |  38 ++-
 .../StaticAnalyzer/Core/PathSensitive/SVals.h | 226 ++
 clang/lib/StaticAnalyzer/Core/SValBuilder.cpp |  28 +--
 clang/lib/StaticAnalyzer/Core/SVals.cpp   |  87 ---
 .../Core/SimpleConstraintManager.cpp  |   4 +-
 .../StaticAnalyzer/Core/SimpleSValBuilder.cpp |  73 +++---
 clang/lib/StaticAnalyzer/Core/Store.cpp   |   2 +-
 9 files changed, 219 insertions(+), 304 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h 
b/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
index 3ae28c1dba3eb5a..43a70f596a4da28 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
+++ b/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
@@ -65,7 +65,7 @@ class SValExplainer : public FullSValVisitor {
 return "undefined value";
   }
 
-  std::string VisitLocMemRegionVal(loc::MemRegionVal V) {
+  std::string VisitMemRegionVal(loc::MemRegionVal V) {
 const MemRegion *R = V.getRegion();
 // Avoid the weird "pointer to pointee of ...".
 if (auto SR = dyn_cast(R)) {
@@ -76,7 +76,7 @@ class SValExplainer : public FullSValVisitor {
 return "pointer to " + Visit(R);
   }
 
-  std::string VisitLocConcreteInt(loc::ConcreteInt V) {
+  std::string VisitConcreteInt(loc::ConcreteInt V) {
 const llvm::APSInt &I = V.getValue();
 std::string Str;
 llvm::raw_string_ostream OS(Str);
@@ -84,11 +84,11 @@ class SValExplainer : public FullSValVisitor {
 return Str;
   }
 
-  std::string VisitNonLocSymbolVal(nonloc::SymbolVal V) {
+  std::string VisitSymbolVal(nonloc::SymbolVal V) {
 return Visit(V.getSymbol());
   }
 
-  std::string VisitNonLocConcreteInt(nonloc::ConcreteInt V) {
+  std::string VisitConcreteInt(nonloc::ConcreteInt V) {
 const llvm::APSInt &I = V.getValue();
 std::string Str;
 llvm::raw_string_ostream OS(Str);
@@ -97,7 +97

[clang] bde5717 - [analyzer][NFC] Rework SVal kind representation (#71039)

2023-11-04 Thread via cfe-commits

Author: Balazs Benics
Date: 2023-11-04T15:26:59+01:00
New Revision: bde5717d4638c27614d9d4a2e53df27087a69841

URL: 
https://github.com/llvm/llvm-project/commit/bde5717d4638c27614d9d4a2e53df27087a69841
DIFF: 
https://github.com/llvm/llvm-project/commit/bde5717d4638c27614d9d4a2e53df27087a69841.diff

LOG: [analyzer][NFC] Rework SVal kind representation (#71039)

The goal of this patch is to refine how the `SVal` base and sub-kinds
are represented by forming one unified enum describing the possible
SVals. This means that the `unsigned SVal::Kind` and the attached
bit-packing semantics would be replaced by a single unified enum. This
is more conventional and leads to a better debugging experience by
default. This eases the need of using debug pretty-printers, or the use
of runtime functions doing the printing for us like we do today by
calling `Val.dump()` whenever we inspect the values.

Previously, the first 2 bits of the `unsigned SVal::Kind` discriminated
the following quartet: `UndefinedVal`, `UnknownVal`, `Loc`, or `NonLoc`.
The rest of the upper bits represented the sub-kind, where the value
represented the index among only the `Loc`s or `NonLoc`s, effectively
attaching 2 meanings of the upper bits depending on the base-kind. We
don't need to pack these bits, as we have plenty even if we would use
just a plan-old `unsigned char`.

Consequently, in this patch, I propose to lay out all the (non-abstract)
`SVal` kinds into a single enum, along with some metadata (`BEGIN_Loc`,
`END_Loc`, `BEGIN_NonLoc`, `END_NonLoc`) artificial enum values, similar
how we do with the `MemRegions`.

Note that in the unified `SVal::Kind` enum, to differentiate
`nonloc::ConcreteInt` from `loc::ConcreteInt`, I had to prefix them with
`Loc` and `NonLoc` to resolve this ambiguity.
This should not surface in general, because I'm replacing the
`nonloc::Kind` enum items with `inline constexpr` global constants to
mimic the original behavior - and offer nicer spelling to these enum
values.

Some `SVal` constructors were not marked explicit, which I now mark as
such to follow best practices, and marked others as `/*implicit*/` to
clarify the intent.
During refactoring, I also found at least one function not marked
`LLVM_ATTRIBUTE_RETURNS_NONNULL`, so I did that.

The `TypeRetrievingVisitor` visitor had some accidental dead code,
namely: `VisitNonLocConcreteInt` and `VisitLocConcreteInt`.

Previously, the `SValVisitor` expected visit handlers of
`VisitNonLocX(nonloc::X)` and `VisitLocX(loc::X)`, where
I felt that envoding `NonLoc` and `Loc` in the name is not necessary as
the type of the parameter would select the right overload anyways, so I
simplified the naming of those visit functions.

The rest of the diff is a lot of times just formatting, because
`getKind()` by nature, frequently appears in switches, which means that
the whole switch gets automatically reformatted. I could probably undo
the formatting, but I didn't want to deviate from the rule unless
explicitly requested.

Added: 


Modified: 
clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h
clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.def
clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
clang/lib/StaticAnalyzer/Core/SVals.cpp
clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
clang/lib/StaticAnalyzer/Core/Store.cpp

Removed: 




diff  --git a/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h 
b/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
index 3ae28c1dba3eb5a..43a70f596a4da28 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
+++ b/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
@@ -65,7 +65,7 @@ class SValExplainer : public FullSValVisitor {
 return "undefined value";
   }
 
-  std::string VisitLocMemRegionVal(loc::MemRegionVal V) {
+  std::string VisitMemRegionVal(loc::MemRegionVal V) {
 const MemRegion *R = V.getRegion();
 // Avoid the weird "pointer to pointee of ...".
 if (auto SR = dyn_cast(R)) {
@@ -76,7 +76,7 @@ class SValExplainer : public FullSValVisitor {
 return "pointer to " + Visit(R);
   }
 
-  std::string VisitLocConcreteInt(loc::ConcreteInt V) {
+  std::string VisitConcreteInt(loc::ConcreteInt V) {
 const llvm::APSInt &I = V.getValue();
 std::string Str;
 llvm::raw_string_ostream OS(Str);
@@ -84,11 +84,11 @@ class SValExplainer : public FullSValVisitor {
 return Str;
   }
 
-  std::string VisitNonLocSymbolVal(nonloc::SymbolVal V) {
+  std::string VisitSymbolVal(nonloc::SymbolVal V) {
 return Visit(V.getSymbol());
   }
 
-  std::string VisitNonLocConcreteInt(nonloc::ConcreteInt V) {
+  std::string VisitConcreteInt(no

[clang] [analyzer][NFC] Rework SVal kind representation (PR #71039)

2023-11-04 Thread Balazs Benics via cfe-commits

https://github.com/steakhal closed 
https://github.com/llvm/llvm-project/pull/71039
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [compiler-rt] [libcxx] [clang-tools-extra] [openmp] [lldb] [flang] [OpenMP] Add memory diff dump for kernel record-replay (PR #70667)

2023-11-04 Thread Giorgis Georgakoudis via cfe-commits

https://github.com/ggeorgakoudis requested changes to this pull request.


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


[libcxx] [clang] [compiler-rt] [clang-tools-extra] [flang] [lldb] [openmp] [llvm] [OpenMP] Add memory diff dump for kernel record-replay (PR #70667)

2023-11-04 Thread Giorgis Georgakoudis via cfe-commits

https://github.com/ggeorgakoudis edited 
https://github.com/llvm/llvm-project/pull/70667
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[lldb] [openmp] [compiler-rt] [clang] [libcxx] [clang-tools-extra] [llvm] [flang] [OpenMP] Add memory diff dump for kernel record-replay (PR #70667)

2023-11-04 Thread Giorgis Georgakoudis via cfe-commits


@@ -151,6 +151,74 @@ struct RecordReplayTy {
 OS.close();
   }
 
+  void dumpDeviceMemoryDiff(StringRef Filename) {
+ErrorOr> DeviceMemoryMB =
+WritableMemoryBuffer::getNewUninitMemBuffer(MemorySize);
+if (!DeviceMemoryMB)
+  report_fatal_error("Error creating MemoryBuffer for device memory");
+
+auto Err = Device->dataRetrieve(DeviceMemoryMB.get()->getBufferStart(),
+MemoryStart, MemorySize, nullptr);
+if (Err)
+  report_fatal_error("Error retrieving data for target pointer");
+
+// Get the pre-record memory filename
+SmallString<128> InputFilename = {Filename.split('.').first, ".memory"};
+
+// Read the pre-record memorydump
+auto InputFileBuffer = MemoryBuffer::getFileOrSTDIN(InputFilename);
+if (std::error_code EC = InputFileBuffer.getError())
+  report_fatal_error("Error reading pre-record device memory");
+
+StringRef InputBufferContents = (*InputFileBuffer)->getBuffer();
+if (InputBufferContents.size() != MemorySize)
+  report_fatal_error("Error: Pre-record device memory size mismatch");
+
+std::error_code EC;
+raw_fd_ostream OS(Filename, EC);
+if (EC)
+  report_fatal_error("Error dumping memory to file " + Filename + " :" +
+ EC.message());
+
+// Get current memory contents
+StringRef DeviceMemoryContents(DeviceMemoryMB.get()->getBuffer().data(),
+   DeviceMemoryMB.get()->getBuffer().size());
+
+for (size_t I = 0; I < MemorySize; ++I) {
+  // If buffers are same, continue
+  if (InputBufferContents[I] == DeviceMemoryContents[I])
+continue;
+
+  // If mismatch is found create a new diff line
+  // Current format: location, size, differences
+  OS << I << " "; // Marks the start offset
+
+  SmallVector Modified;
+  Modified.push_back(DeviceMemoryContents[I]);
+
+  size_t J; // Length of current diff line
+  // Loop until next match is found
+  for (J = 1; J < MemorySize - I; ++J) {
+// If no more mismatch, break out of the loop
+if (InputBufferContents[I + J] == DeviceMemoryContents[I + J])
+  break;
+
+// If mismatch continues - push diff to Modified
+Modified.push_back(DeviceMemoryContents[I + J]);
+  }
+
+  OS << J << " "; // Marks the length of the mismatching sequence
+  for (const auto &value : Modified)

ggeorgakoudis wrote:

value -> Value

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


[compiler-rt] [openmp] [clang] [flang] [llvm] [lldb] [libcxx] [clang-tools-extra] [OpenMP] Add memory diff dump for kernel record-replay (PR #70667)

2023-11-04 Thread Giorgis Georgakoudis via cfe-commits


@@ -151,6 +151,74 @@ struct RecordReplayTy {
 OS.close();
   }
 
+  void dumpDeviceMemoryDiff(StringRef Filename) {
+ErrorOr> DeviceMemoryMB =
+WritableMemoryBuffer::getNewUninitMemBuffer(MemorySize);
+if (!DeviceMemoryMB)
+  report_fatal_error("Error creating MemoryBuffer for device memory");
+
+auto Err = Device->dataRetrieve(DeviceMemoryMB.get()->getBufferStart(),
+MemoryStart, MemorySize, nullptr);
+if (Err)
+  report_fatal_error("Error retrieving data for target pointer");
+
+// Get the pre-record memory filename
+SmallString<128> InputFilename = {Filename.split('.').first, ".memory"};
+
+// Read the pre-record memorydump
+auto InputFileBuffer = MemoryBuffer::getFileOrSTDIN(InputFilename);
+if (std::error_code EC = InputFileBuffer.getError())
+  report_fatal_error("Error reading pre-record device memory");
+
+StringRef InputBufferContents = (*InputFileBuffer)->getBuffer();
+if (InputBufferContents.size() != MemorySize)
+  report_fatal_error("Error: Pre-record device memory size mismatch");
+
+std::error_code EC;
+raw_fd_ostream OS(Filename, EC);
+if (EC)
+  report_fatal_error("Error dumping memory to file " + Filename + " :" +
+ EC.message());
+
+// Get current memory contents
+StringRef DeviceMemoryContents(DeviceMemoryMB.get()->getBuffer().data(),
+   DeviceMemoryMB.get()->getBuffer().size());
+
+for (size_t I = 0; I < MemorySize; ++I) {
+  // If buffers are same, continue
+  if (InputBufferContents[I] == DeviceMemoryContents[I])
+continue;
+
+  // If mismatch is found create a new diff line
+  // Current format: location, size, differences
+  OS << I << " "; // Marks the start offset
+
+  SmallVector Modified;
+  Modified.push_back(DeviceMemoryContents[I]);
+
+  size_t J; // Length of current diff line
+  // Loop until next match is found
+  for (J = 1; J < MemorySize - I; ++J) {
+// If no more mismatch, break out of the loop
+if (InputBufferContents[I + J] == DeviceMemoryContents[I + J])
+  break;
+
+// If mismatch continues - push diff to Modified
+Modified.push_back(DeviceMemoryContents[I + J]);
+  }
+
+  OS << J << " "; // Marks the length of the mismatching sequence
+  for (const auto &value : Modified)
+OS << value << " ";
+  OS << "\n";
+
+  // Increment I by J to skip ahead to next
+  // matching sequence in the buffer
+  I += J;

ggeorgakoudis wrote:

Simpler, more readable as:
```
for (I+=1; I < MemorySize; ++I) {
// If no more mismatch, break out of the loop
if (InputBufferContents[I] == DeviceMemoryContents[I])
  break;
// If mismatch continues - push diff to Modified
Modified.push_back(DeviceMemoryContents[I]);
  }
...
OS << Modified.size() << " ";
```
Avoids the skip-ahead increment too

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


[llvm] [clang-tools-extra] [openmp] [clang] [libcxx] [lldb] [compiler-rt] [flang] [OpenMP] Add memory diff dump for kernel record-replay (PR #70667)

2023-11-04 Thread Giorgis Georgakoudis via cfe-commits


@@ -151,6 +151,74 @@ struct RecordReplayTy {
 OS.close();
   }
 
+  void dumpDeviceMemoryDiff(StringRef Filename) {
+ErrorOr> DeviceMemoryMB =
+WritableMemoryBuffer::getNewUninitMemBuffer(MemorySize);
+if (!DeviceMemoryMB)
+  report_fatal_error("Error creating MemoryBuffer for device memory");
+
+auto Err = Device->dataRetrieve(DeviceMemoryMB.get()->getBufferStart(),
+MemoryStart, MemorySize, nullptr);
+if (Err)
+  report_fatal_error("Error retrieving data for target pointer");
+
+// Get the pre-record memory filename
+SmallString<128> InputFilename = {Filename.split('.').first, ".memory"};
+
+// Read the pre-record memorydump
+auto InputFileBuffer = MemoryBuffer::getFileOrSTDIN(InputFilename);
+if (std::error_code EC = InputFileBuffer.getError())
+  report_fatal_error("Error reading pre-record device memory");
+
+StringRef InputBufferContents = (*InputFileBuffer)->getBuffer();
+if (InputBufferContents.size() != MemorySize)
+  report_fatal_error("Error: Pre-record device memory size mismatch");
+
+std::error_code EC;
+raw_fd_ostream OS(Filename, EC);
+if (EC)
+  report_fatal_error("Error dumping memory to file " + Filename + " :" +
+ EC.message());
+
+// Get current memory contents
+StringRef DeviceMemoryContents(DeviceMemoryMB.get()->getBuffer().data(),
+   DeviceMemoryMB.get()->getBuffer().size());
+
+for (size_t I = 0; I < MemorySize; ++I) {
+  // If buffers are same, continue
+  if (InputBufferContents[I] == DeviceMemoryContents[I])
+continue;
+
+  // If mismatch is found create a new diff line
+  // Current format: location, size, differences
+  OS << I << " "; // Marks the start offset

ggeorgakoudis wrote:

Move comment above

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


[clang] [AArch64] Cast predicate operand of SVE gather loads/scater stores to the parameter type of the intrinsic (NFC) (PR #71289)

2023-11-04 Thread Momchil Velikov via cfe-commits

https://github.com/momchil-velikov created 
https://github.com/llvm/llvm-project/pull/71289

When emitting LLVM IR for gather loads/scatter stores, the predicate parameter 
is cast to a type that depends on the loaded, resp. stored type. That's correct 
for operation where we have a predicate per lane, however it is not correct for 
quadword loads and stores (`LD1Q`, `ST1Q`) where the predicate is per 128-bit 
chunk, independent from the ACLE intrinsic type.

This can be universally handled by cast to the corresponding parameter type of 
the intrinsic. The intrinsic itself should be defined in a way that enforces 
relations between parameter types.

>From 86f31ae5f7b76814fb4184a4cd310e06fe4622e6 Mon Sep 17 00:00:00 2001
From: Momchil Velikov 
Date: Fri, 3 Nov 2023 21:30:27 +
Subject: [PATCH] [AArch64] Cast predicate operand of SVE gather loads/scater
 stores to the parameter type of the intrinsic (NFC)

When emitting LLVM IR for gather loads/scatter stores, the predicate
parameter is cast to a type that depends on the loaded, resp. stored
type. That's correct for operation where we have a predicate per lane,
however it is not correct for quadword loads and stores (`LD1Q`, `ST1Q`)
where the predicate is per 128-bit chunk, independent from the ACLE
intrinsic type.

This can be universally handled by cast to the corresponding parameter
type of the intrinsic. The intrinsic itself should be defined in a way
that enforces relations between parameter types.
---
 clang/lib/CodeGen/CGBuiltin.cpp | 24 +++-
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 972aa1c708e5f65..abaa18dc22b971d 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -9413,13 +9413,6 @@ Value *CodeGenFunction::EmitSVEGatherLoad(const 
SVETypeFlags &TypeFlags,
   auto *OverloadedTy =
   llvm::ScalableVectorType::get(SVEBuiltinMemEltTy(TypeFlags), ResultTy);
 
-  // At the ACLE level there's only one predicate type, svbool_t, which is
-  // mapped to . However, this might be incompatible with the
-  // actual type being loaded. For example, when loading doubles (i64) the
-  // predicated should be  instead. At the IR level the type of
-  // the predicate and the data being loaded must match. Cast accordingly.
-  Ops[0] = EmitSVEPredicateCast(Ops[0], OverloadedTy);
-
   Function *F = nullptr;
   if (Ops[1]->getType()->isVectorTy())
 // This is the "vector base, scalar offset" case. In order to uniquely
@@ -9433,6 +9426,16 @@ Value *CodeGenFunction::EmitSVEGatherLoad(const 
SVETypeFlags &TypeFlags,
 // intrinsic.
 F = CGM.getIntrinsic(IntID, OverloadedTy);
 
+  // At the ACLE level there's only one predicate type, svbool_t, which is
+  // mapped to . However, this might be incompatible with the
+  // actual type being loaded. For example, when loading doubles (i64) the
+  // predicate should be  instead. At the IR level the type of
+  // the predicate and the data being loaded must match. Cast to the type
+  // expected by the intrinsic. The intrinsic itself should be defined in
+  // a way than enforces relations between parameter types.
+  Ops[0] = EmitSVEPredicateCast(
+  Ops[0], cast(F->getArg(0)->getType()));
+
   // Pass 0 when the offset is missing. This can only be applied when using
   // the "vector base" addressing mode for which ACLE allows no offset. The
   // corresponding LLVM IR always requires an offset.
@@ -9497,8 +9500,11 @@ Value *CodeGenFunction::EmitSVEScatterStore(const 
SVETypeFlags &TypeFlags,
   // mapped to . However, this might be incompatible with the
   // actual type being stored. For example, when storing doubles (i64) the
   // predicated should be  instead. At the IR level the type of
-  // the predicate and the data being stored must match. Cast accordingly.
-  Ops[1] = EmitSVEPredicateCast(Ops[1], OverloadedTy);
+  // the predicate and the data being stored must match. Cast to the type
+  // expected by the intrinsic. The intrinsic itself should be defined in
+  // a way that enforces relations between parameter types.
+  Ops[1] = EmitSVEPredicateCast(
+  Ops[1], cast(F->getArg(1)->getType()));
 
   // For "vector base, scalar index" scale the index so that it becomes a
   // scalar offset.

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [AArch64] Cast predicate operand of SVE gather loads/scater stores to the parameter type of the intrinsic (NFC) (PR #71289)

2023-11-04 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Momchil Velikov (momchil-velikov)


Changes

When emitting LLVM IR for gather loads/scatter stores, the predicate parameter 
is cast to a type that depends on the loaded, resp. stored type. That's correct 
for operation where we have a predicate per lane, however it is not correct for 
quadword loads and stores (`LD1Q`, `ST1Q`) where the predicate is per 128-bit 
chunk, independent from the ACLE intrinsic type.

This can be universally handled by cast to the corresponding parameter type of 
the intrinsic. The intrinsic itself should be defined in a way that enforces 
relations between parameter types.

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


1 Files Affected:

- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+15-9) 


``diff
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 972aa1c708e5f65..abaa18dc22b971d 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -9413,13 +9413,6 @@ Value *CodeGenFunction::EmitSVEGatherLoad(const 
SVETypeFlags &TypeFlags,
   auto *OverloadedTy =
   llvm::ScalableVectorType::get(SVEBuiltinMemEltTy(TypeFlags), ResultTy);
 
-  // At the ACLE level there's only one predicate type, svbool_t, which is
-  // mapped to . However, this might be incompatible with the
-  // actual type being loaded. For example, when loading doubles (i64) the
-  // predicated should be  instead. At the IR level the type of
-  // the predicate and the data being loaded must match. Cast accordingly.
-  Ops[0] = EmitSVEPredicateCast(Ops[0], OverloadedTy);
-
   Function *F = nullptr;
   if (Ops[1]->getType()->isVectorTy())
 // This is the "vector base, scalar offset" case. In order to uniquely
@@ -9433,6 +9426,16 @@ Value *CodeGenFunction::EmitSVEGatherLoad(const 
SVETypeFlags &TypeFlags,
 // intrinsic.
 F = CGM.getIntrinsic(IntID, OverloadedTy);
 
+  // At the ACLE level there's only one predicate type, svbool_t, which is
+  // mapped to . However, this might be incompatible with the
+  // actual type being loaded. For example, when loading doubles (i64) the
+  // predicate should be  instead. At the IR level the type of
+  // the predicate and the data being loaded must match. Cast to the type
+  // expected by the intrinsic. The intrinsic itself should be defined in
+  // a way than enforces relations between parameter types.
+  Ops[0] = EmitSVEPredicateCast(
+  Ops[0], cast(F->getArg(0)->getType()));
+
   // Pass 0 when the offset is missing. This can only be applied when using
   // the "vector base" addressing mode for which ACLE allows no offset. The
   // corresponding LLVM IR always requires an offset.
@@ -9497,8 +9500,11 @@ Value *CodeGenFunction::EmitSVEScatterStore(const 
SVETypeFlags &TypeFlags,
   // mapped to . However, this might be incompatible with the
   // actual type being stored. For example, when storing doubles (i64) the
   // predicated should be  instead. At the IR level the type of
-  // the predicate and the data being stored must match. Cast accordingly.
-  Ops[1] = EmitSVEPredicateCast(Ops[1], OverloadedTy);
+  // the predicate and the data being stored must match. Cast to the type
+  // expected by the intrinsic. The intrinsic itself should be defined in
+  // a way that enforces relations between parameter types.
+  Ops[1] = EmitSVEPredicateCast(
+  Ops[1], cast(F->getArg(1)->getType()));
 
   // For "vector base, scalar index" scale the index so that it becomes a
   // scalar offset.

``




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


[clang] [AArch64] Cast predicate operand of SVE gather loads/scater stores to the parameter type of the intrinsic (NFC) (PR #71289)

2023-11-04 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-codegen

Author: Momchil Velikov (momchil-velikov)


Changes

When emitting LLVM IR for gather loads/scatter stores, the predicate parameter 
is cast to a type that depends on the loaded, resp. stored type. That's correct 
for operation where we have a predicate per lane, however it is not correct for 
quadword loads and stores (`LD1Q`, `ST1Q`) where the predicate is per 128-bit 
chunk, independent from the ACLE intrinsic type.

This can be universally handled by cast to the corresponding parameter type of 
the intrinsic. The intrinsic itself should be defined in a way that enforces 
relations between parameter types.

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


1 Files Affected:

- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+15-9) 


``diff
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 972aa1c708e5f65..abaa18dc22b971d 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -9413,13 +9413,6 @@ Value *CodeGenFunction::EmitSVEGatherLoad(const 
SVETypeFlags &TypeFlags,
   auto *OverloadedTy =
   llvm::ScalableVectorType::get(SVEBuiltinMemEltTy(TypeFlags), ResultTy);
 
-  // At the ACLE level there's only one predicate type, svbool_t, which is
-  // mapped to . However, this might be incompatible with the
-  // actual type being loaded. For example, when loading doubles (i64) the
-  // predicated should be  instead. At the IR level the type of
-  // the predicate and the data being loaded must match. Cast accordingly.
-  Ops[0] = EmitSVEPredicateCast(Ops[0], OverloadedTy);
-
   Function *F = nullptr;
   if (Ops[1]->getType()->isVectorTy())
 // This is the "vector base, scalar offset" case. In order to uniquely
@@ -9433,6 +9426,16 @@ Value *CodeGenFunction::EmitSVEGatherLoad(const 
SVETypeFlags &TypeFlags,
 // intrinsic.
 F = CGM.getIntrinsic(IntID, OverloadedTy);
 
+  // At the ACLE level there's only one predicate type, svbool_t, which is
+  // mapped to . However, this might be incompatible with the
+  // actual type being loaded. For example, when loading doubles (i64) the
+  // predicate should be  instead. At the IR level the type of
+  // the predicate and the data being loaded must match. Cast to the type
+  // expected by the intrinsic. The intrinsic itself should be defined in
+  // a way than enforces relations between parameter types.
+  Ops[0] = EmitSVEPredicateCast(
+  Ops[0], cast(F->getArg(0)->getType()));
+
   // Pass 0 when the offset is missing. This can only be applied when using
   // the "vector base" addressing mode for which ACLE allows no offset. The
   // corresponding LLVM IR always requires an offset.
@@ -9497,8 +9500,11 @@ Value *CodeGenFunction::EmitSVEScatterStore(const 
SVETypeFlags &TypeFlags,
   // mapped to . However, this might be incompatible with the
   // actual type being stored. For example, when storing doubles (i64) the
   // predicated should be  instead. At the IR level the type of
-  // the predicate and the data being stored must match. Cast accordingly.
-  Ops[1] = EmitSVEPredicateCast(Ops[1], OverloadedTy);
+  // the predicate and the data being stored must match. Cast to the type
+  // expected by the intrinsic. The intrinsic itself should be defined in
+  // a way that enforces relations between parameter types.
+  Ops[1] = EmitSVEPredicateCast(
+  Ops[1], cast(F->getArg(1)->getType()));
 
   // For "vector base, scalar index" scale the index so that it becomes a
   // scalar offset.

``




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


[llvm] [clang] [AArch64][SVE2.1] Add intrinsics for quadword loads/stores with unscaled offset (PR #70474)

2023-11-04 Thread Momchil Velikov via cfe-commits


@@ -9671,28 +9677,47 @@ Value *CodeGenFunction::EmitSVEMaskedLoad(const 
CallExpr *E,
   // The vector type that is returned may be different from the
   // eventual type loaded from memory.
   auto VectorTy = cast(ReturnTy);
-  auto MemoryTy = llvm::ScalableVectorType::get(MemEltTy, VectorTy);
+  llvm::ScalableVectorType *MemoryTy = nullptr;
+  llvm::ScalableVectorType *PredTy = nullptr;
+  bool IsExtendingLoad = true;

momchil-velikov wrote:

Done

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


[llvm] [clang] [AArch64][SVE2.1] Add intrinsics for quadword loads/stores with unscaled offset (PR #70474)

2023-11-04 Thread Momchil Velikov via cfe-commits


@@ -2614,6 +2619,37 @@ def int_aarch64_sve_ld1_pn_x4 : 
SVE2p1_Load_PN_X4_Intrinsic;
 def int_aarch64_sve_ldnt1_pn_x2 : SVE2p1_Load_PN_X2_Intrinsic;
 def int_aarch64_sve_ldnt1_pn_x4 : SVE2p1_Load_PN_X4_Intrinsic;
 
+//
+// SVE2.1 - Contiguous loads to quadword (single vector)
+//
+
+class SVE2p1_Single_Load_Quadword
+: DefaultAttrsIntrinsic<[llvm_anyvector_ty],
+[llvm_nxv1i1_ty, llvm_ptr_ty],
+[IntrReadMem]>;

momchil-velikov wrote:

Done

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


[llvm] [clang] [AArch64][SVE2.1] Add intrinsics for quadword loads/stores with unscaled offset (PR #70474)

2023-11-04 Thread Momchil Velikov via cfe-commits


@@ -9702,17 +9727,34 @@ Value *CodeGenFunction::EmitSVEMaskedStore(const 
CallExpr *E,
   auto VectorTy = cast(Ops.back()->getType());
   auto MemoryTy = llvm::ScalableVectorType::get(MemEltTy, VectorTy);
 
-  Value *Predicate = EmitSVEPredicateCast(Ops[0], MemoryTy);
+  auto PredTy = MemoryTy;
+  auto AddrMemoryTy = MemoryTy;
+  bool IsTruncatingStore = true;

momchil-velikov wrote:

Done

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


[llvm] [clang] [AArch64][SVE2.1] Add intrinsics for quadword loads/stores with unscaled offset (PR #70474)

2023-11-04 Thread Momchil Velikov via cfe-commits


@@ -2614,6 +2619,37 @@ def int_aarch64_sve_ld1_pn_x4 : 
SVE2p1_Load_PN_X4_Intrinsic;
 def int_aarch64_sve_ldnt1_pn_x2 : SVE2p1_Load_PN_X2_Intrinsic;
 def int_aarch64_sve_ldnt1_pn_x4 : SVE2p1_Load_PN_X4_Intrinsic;
 
+//
+// SVE2.1 - Contiguous loads to quadword (single vector)
+//
+
+class SVE2p1_Single_Load_Quadword
+: DefaultAttrsIntrinsic<[llvm_anyvector_ty],
+[llvm_nxv1i1_ty, llvm_ptr_ty],
+[IntrReadMem]>;
+def int_aarch64_sve_ld1uwq : SVE2p1_Single_Load_Quadword;
+def int_aarch64_sve_ld1udq : SVE2p1_Single_Load_Quadword;
+
+//
+// SVE2.1 - Contiguous store from quadword (single vector)
+//
+
+class SVE2p1_Single_Store_Quadword
+: DefaultAttrsIntrinsic<[],
+[llvm_anyvector_ty, llvm_nxv1i1_ty, llvm_ptr_ty],
+[IntrArgMemOnly]>;

momchil-velikov wrote:

Done

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


[llvm] [clang] [AArch64][SVE2.1] Add intrinsics for quadword loads/stores with unscaled offset (PR #70474)

2023-11-04 Thread Momchil Velikov via cfe-commits


@@ -9671,28 +9677,47 @@ Value *CodeGenFunction::EmitSVEMaskedLoad(const 
CallExpr *E,
   // The vector type that is returned may be different from the
   // eventual type loaded from memory.
   auto VectorTy = cast(ReturnTy);
-  auto MemoryTy = llvm::ScalableVectorType::get(MemEltTy, VectorTy);
+  llvm::ScalableVectorType *MemoryTy = nullptr;
+  llvm::ScalableVectorType *PredTy = nullptr;
+  bool IsExtendingLoad = true;
+  switch (IntrinsicID) {
+  case Intrinsic::aarch64_sve_ld1uwq:
+  case Intrinsic::aarch64_sve_ld1udq:
+MemoryTy = llvm::ScalableVectorType::get(MemEltTy, 1);
+PredTy =
+llvm::ScalableVectorType::get(IntegerType::get(getLLVMContext(), 1), 
1);

momchil-velikov wrote:

One always falls through the cracks. Will fix it eventually.

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


[llvm] [clang] [AArch64][SVE2.1] Add intrinsics for quadword loads/stores with unscaled offset (PR #70474)

2023-11-04 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff e6bd68c90b1a386e276f53ba28fdfdfda48bcea1 
a3b7e136e2f045a1c9948b679da89ec9a406516e -- 
clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_ld1_single.c 
clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_loads.c 
clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_st1_single.c 
clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_store.c 
clang/lib/CodeGen/CGBuiltin.cpp llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp 
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp 
llvm/lib/Target/AArch64/AArch64ISelLowering.h
``





View the diff from clang-format here.


``diff
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp 
b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index e041c78b1e03..02e3d3b5cece 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -10293,7 +10293,7 @@ AArch64TargetLowering::getConstraintType(StringRef 
Constraint) const {
 }
   } else if (parsePredicateConstraint(Constraint) !=
  PredicateConstraint::Invalid)
-  return C_RegisterClass;
+return C_RegisterClass;
   else if (parseConstraintCode(Constraint) != AArch64CC::Invalid)
 return C_Other;
   return TargetLowering::getConstraintType(Constraint);

``




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


[llvm] [clang] [AArch64] Add quadword gather load/scatter store intrinsics with unscaled vector offset (PR #71290)

2023-11-04 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Momchil Velikov (momchil-velikov)


Changes

  This patch add intrinsics of the form
   
sv_t svld1q_gather_u64offset_(svbool_t pg, const 
_t *base, svuint64_t offs);
void svst1q_scatter_u64offset_(sbvool_t, _t *base, 
svuint64_t offst, sv_t data);

as well as their short forms.

ACLE spec: ARM-software/acle#257










---

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


20 Files Affected:

- (modified) clang/include/clang/Basic/arm_sve.td (+64) 
- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+66-19) 
- (added) clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_ld1_single.c 
(+255) 
- (added) clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_loads.c 
(+3035) 
- (added) clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_st1_single.c 
(+255) 
- (added) clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_store.c 
(+2664) 
- (modified) llvm/include/llvm/IR/IntrinsicsAArch64.td (+85) 
- (modified) llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp (+43-1) 
- (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (+38-9) 
- (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.h (+4) 
- (modified) llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td (+50-2) 
- (modified) llvm/lib/Target/AArch64/SVEInstrFormats.td (+39-2) 
- (added) 
llvm/test/CodeGen/AArch64/sve2p1-intrinsics-gather-loads-128bit-index.ll (+249) 
- (added) 
llvm/test/CodeGen/AArch64/sve2p1-intrinsics-gather-loads-128bit-unscaled-offset.ll
 (+232) 
- (added) llvm/test/CodeGen/AArch64/sve2p1-intrinsics-ld1-single.ll (+144) 
- (added) llvm/test/CodeGen/AArch64/sve2p1-intrinsics-multivec-loads.ll (+797) 
- (added) llvm/test/CodeGen/AArch64/sve2p1-intrinsics-multivec-stores.ll (+910) 
- (added) 
llvm/test/CodeGen/AArch64/sve2p1-intrinsics-scatter-stores-128bit-index.ll 
(+248) 
- (added) 
llvm/test/CodeGen/AArch64/sve2p1-intrinsics-scatter-stores-128bit-unscaled-offset.ll
 (+240) 
- (added) llvm/test/CodeGen/AArch64/sve2p1-intrinsics-st1-single.ll (+130) 


``diff
diff --git a/clang/include/clang/Basic/arm_sve.td 
b/clang/include/clang/Basic/arm_sve.td
index b5baafedd139602..74ca5d3aef06626 100644
--- a/clang/include/clang/Basic/arm_sve.td
+++ b/clang/include/clang/Basic/arm_sve.td
@@ -298,6 +298,38 @@ let TargetGuard = "sve,bf16" in {
   def SVBFMLALT_LANE : SInst<"svbfmlalt_lane[_{0}]", "MMddi", "b", MergeNone, 
"aarch64_sve_bfmlalt_lane_v2", [IsOverloadNone], [ImmCheck<3, ImmCheck0_7>]>;
 }
 
+let TargetGuard = "sve2p1" in {
+  // Contiguous zero-extending load to quadword (single vector).
+  def SVLD1UWQ  : MInst<"svld1uwq[_{d}]", "dPc",  "iUif", [IsLoad], 
MemEltTyInt32, "aarch64_sve_ld1uwq">;
+  def SVLD1UWQ_VNUM : MInst<"svld1uwq_vnum[_{d}]", "dPcl", "iUif", [IsLoad], 
MemEltTyInt32, "aarch64_sve_ld1uwq">;
+
+  def SVLD1UDQ  : MInst<"svld1udq[_{d}]", "dPc",  "lUld", [IsLoad], 
MemEltTyInt64, "aarch64_sve_ld1udq">;
+  def SVLD1UDQ_VNUM : MInst<"svld1udq_vnum[_{d}]", "dPcl", "lUld", [IsLoad], 
MemEltTyInt64, "aarch64_sve_ld1udq">;
+
+  // Load one vector (vector base + scalar offset)
+  def SVLD1Q_GATHER_U64BASE_OFFSET : 
MInst<"svld1q_gather[_{2}base]_offset_{d}", "dPgl", "cUcsUsiUilUlfhdb", 
[IsGatherLoad, IsByteIndexed], MemEltTyDefault, 
"aarch64_sve_ld1q_gather_scalar_offset">;
+  def SVLD1Q_GATHER_U64BASE : MInst<"svld1q_gather[_{2}base]_{d}", "dPg", 
"cUcsUsiUilUlfhdb", [IsGatherLoad, IsByteIndexed], MemEltTyDefault, 
"aarch64_sve_ld1q_gather_scalar_offset">;
+
+  // Load one vector (scalar base + vector offset)
+  def SVLD1Q_GATHER_U64OFFSET : MInst<"svld1q_gather_[{3}]offset[_{0}]", 
"dPcg", "cUcsUsiUilUlfhdb", [IsGatherLoad, IsByteIndexed], MemEltTyDefault, 
"aarch64_sve_ld1q_gather_vector_offset">;
+
+  // Load N-element structure into N vectors (scalar base)
+  defm SVLD2Q : StructLoad<"svld2q[_{2}]", "2Pc", "aarch64_sve_ld2q_sret">;
+  defm SVLD3Q : StructLoad<"svld3q[_{2}]", "3Pc", "aarch64_sve_ld3q_sret">;
+  defm SVLD4Q : StructLoad<"svld4q[_{2}]", "4Pc", "aarch64_sve_ld4q_sret">;
+
+  // Load N-element structure into N vectors (scalar base, VL displacement)
+  defm SVLD2Q_VNUM : StructLoad<"svld2q_vnum[_{2}]", "2Pcl", 
"aarch64_sve_ld2q_sret">;
+  defm SVLD3Q_VNUM : StructLoad<"svld3q_vnum[_{2}]", "3Pcl", 
"aarch64_sve_ld3q_sret">;
+  defm SVLD4Q_VNUM : StructLoad<"svld4q_vnum[_{2}]", "4Pcl", 
"aarch64_sve_ld4q_sret">;
+
+  // Load quadwords (scalar base + vector index)
+  def SVLD1Q_GATHER_INDICES_U : MInst<"svld1q_gather_[{3}]index[_{0}]",
"dPcg", "sUsiUilUlbhfd", [IsGatherLoad], MemEltTyDefault, 
"aarch64_sve_ld1q_gather_index">;
+
+  // Load quadwords (vector base + scalar index)
+  def SVLD1Q_GATHER_INDEX_S   : MInst<"svld1q_gather[_{2}base]_index_{0}", 
"dPgl", "sUsiUilUlbhfd", [IsGatherLoad], MemEltTyDefault, 
"aarch64_sve_ld1q_gather_scalar_offset">;
+}
+
 

[llvm] [clang] [AArch64] Add quadword gather load/scatter store intrinsics with unscaled vector offset (PR #71290)

2023-11-04 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff 1bb48c440b9299d251ec47d220f1c3a8db523041 
86954b958eff74c2b16b892ac2523d5c300ce897 -- 
clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_ld1_single.c 
clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_loads.c 
clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_st1_single.c 
clang/test/CodeGen/aarch64-sve2p1-intrinsics/acle_sve2p1_store.c 
clang/lib/CodeGen/CGBuiltin.cpp llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp 
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp 
llvm/lib/Target/AArch64/AArch64ISelLowering.h
``





View the diff from clang-format here.


``diff
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp 
b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index bae47a4f4c9c..8f3e28377cfb 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -10295,7 +10295,7 @@ AArch64TargetLowering::getConstraintType(StringRef 
Constraint) const {
 }
   } else if (parsePredicateConstraint(Constraint) !=
  PredicateConstraint::Invalid)
-  return C_RegisterClass;
+return C_RegisterClass;
   else if (parseConstraintCode(Constraint) != AArch64CC::Invalid)
 return C_Other;
   return TargetLowering::getConstraintType(Constraint);

``




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


[clang] [analyzer][solver] On SymSym RelOps, check EQClass members for contradictions (PR #71284)

2023-11-04 Thread Balazs Benics via cfe-commits

steakhal wrote:

For crossreference: I raised some related questions around having void casts 
artificially keeping constraints and symbols alive at discuss:
https://discourse.llvm.org/t/range-based-solver-and-eager-symbol-garbage-collection/74670

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


[clang] [Clang][CodeGen] Emit `llvm.ptrmask` for `align_up` and `align_down` (PR #71238)

2023-11-04 Thread via cfe-commits

https://github.com/goldsteinn updated 
https://github.com/llvm/llvm-project/pull/71238

>From 7df7db58bd40e1da8805542abf0a9c6e6396d068 Mon Sep 17 00:00:00 2001
From: Noah Goldstein 
Date: Fri, 3 Nov 2023 16:45:46 -0500
Subject: [PATCH] [Clang][CodeGen] Emit `llvm.ptrmask` for `align_up` and
 `align_down`

Since PR's #69343 and #67166 we probably have enough support for
`llvm.ptrmask` to make it preferable to the GEP stategy.
---
 clang/lib/CodeGen/CGBuiltin.cpp  | 44 
 clang/test/CodeGen/builtin-align-array.c | 36 +
 clang/test/CodeGen/builtin-align.c   | 64 ++--
 3 files changed, 58 insertions(+), 86 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 972aa1c708e5f65..978f6ffd145741d 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -19668,44 +19668,40 @@ RValue CodeGenFunction::EmitBuiltinIsAligned(const 
CallExpr *E) {
 /// Generate (x & ~(y-1)) to align down or ((x+(y-1)) & ~(y-1)) to align up.
 /// Note: For pointer types we can avoid ptrtoint/inttoptr pairs by using the
 /// llvm.ptrmask intrinsic (with a GEP before in the align_up case).
-/// TODO: actually use ptrmask once most optimization passes know about it.
 RValue CodeGenFunction::EmitBuiltinAlignTo(const CallExpr *E, bool AlignUp) {
   BuiltinAlignArgs Args(E, *this);
-  llvm::Value *SrcAddr = Args.Src;
-  if (Args.Src->getType()->isPointerTy())
-SrcAddr = Builder.CreatePtrToInt(Args.Src, Args.IntType, "intptr");
-  llvm::Value *SrcForMask = SrcAddr;
+  llvm::Value *SrcForMask = Args.Src;
   if (AlignUp) {
 // When aligning up we have to first add the mask to ensure we go over the
 // next alignment value and then align down to the next valid multiple.
 // By adding the mask, we ensure that align_up on an already aligned
 // value will not change the value.
-SrcForMask = Builder.CreateAdd(SrcForMask, Args.Mask, "over_boundary");
+if (Args.Src->getType()->isPointerTy()) {
+  if (getLangOpts().isSignedOverflowDefined())
+SrcForMask =
+Builder.CreateGEP(Int8Ty, SrcForMask, Args.Mask, "over_boundary");
+  else
+SrcForMask = EmitCheckedInBoundsGEP(Int8Ty, SrcForMask, Args.Mask,
+/*SignedIndices=*/true,
+/*isSubtraction=*/false,
+E->getExprLoc(), "over_boundary");
+} else {
+  SrcForMask = Builder.CreateAdd(SrcForMask, Args.Mask, "over_boundary");
+}
   }
   // Invert the mask to only clear the lower bits.
   llvm::Value *InvertedMask = Builder.CreateNot(Args.Mask, "inverted_mask");
-  llvm::Value *Result =
-  Builder.CreateAnd(SrcForMask, InvertedMask, "aligned_result");
+  llvm::Value *Result = nullptr;
   if (Args.Src->getType()->isPointerTy()) {
-/// TODO: Use ptrmask instead of ptrtoint+gep once it is optimized well.
-// Result = Builder.CreateIntrinsic(
-//  Intrinsic::ptrmask, {Args.SrcType, SrcForMask->getType(), 
Args.IntType},
-//  {SrcForMask, NegatedMask}, nullptr, "aligned_result");
-Result->setName("aligned_intptr");
-llvm::Value *Difference = Builder.CreateSub(Result, SrcAddr, "diff");
-// The result must point to the same underlying allocation. This means we
-// can use an inbounds GEP to enable better optimization.
-if (getLangOpts().isSignedOverflowDefined())
-  Result =
-  Builder.CreateGEP(Int8Ty, Args.Src, Difference, "aligned_result");
-else
-  Result = EmitCheckedInBoundsGEP(Int8Ty, Args.Src, Difference,
-  /*SignedIndices=*/true,
-  /*isSubtraction=*/!AlignUp,
-  E->getExprLoc(), "aligned_result");
+Result = Builder.CreateIntrinsic(
+Intrinsic::ptrmask, {Args.SrcType, Args.IntType},
+{SrcForMask, InvertedMask}, nullptr, "aligned_result");
+
 // Emit an alignment assumption to ensure that the new alignment is
 // propagated to loads/stores, etc.
 emitAlignmentAssumption(Result, E, E->getExprLoc(), Args.Alignment);
+  } else {
+Result = Builder.CreateAnd(SrcForMask, InvertedMask, "aligned_result");
   }
   assert(Result->getType() == Args.SrcType);
   return RValue::get(Result);
diff --git a/clang/test/CodeGen/builtin-align-array.c 
b/clang/test/CodeGen/builtin-align-array.c
index 5d1377b98d2814f..18a77b9a710db40 100644
--- a/clang/test/CodeGen/builtin-align-array.c
+++ b/clang/test/CodeGen/builtin-align-array.c
@@ -8,22 +8,16 @@ extern int func(char *c);
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:[[BUF:%.*]] = alloca [1024 x i8], align 16
 // CHECK-NEXT:[[ARRAYIDX:%.*]] = getelementptr inbounds [1024 x i8], ptr 
[[BUF]], i64 0, i64 44
-// CHECK-NEXT:[[INTPTR:%.*]] = ptrtoint ptr [[ARRAYIDX]] to i64
-// CHECK-NEXT:[[ALIGNED_INTPTR:%.*]] = and i64 [[INTPTR]], -16
-// CH

[llvm] [clang] [RISCV] Use BF16 in Xsfvfwmaccqqq intrinsics (PR #71140)

2023-11-04 Thread Yueh-Ting Chen via cfe-commits

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

Sorry I did not do this before you.

The patch looks good, I would say we also need tuples of bf16 for completeness. 
But I will be adding a suite of intrinsics around BFloat16 
(https://github.com/riscv-non-isa/rvv-intrinsic-doc/pull/293) so we can 
probably do that after this landed too.

I would recommend to mention that vector bfloat16 types is introduced in the 
title of this PR.

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


[llvm] [clang] [RISCV] Use BF16 in Xsfvfwmaccqqq intrinsics (PR #71140)

2023-11-04 Thread Yueh-Ting Chen via cfe-commits

eopXD wrote:

Approval is upon addressing Craig's comment.

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


[llvm] [clang] [Verifier] Check function attributes related to branch protection (NFC) (PR #70565)

2023-11-04 Thread Momchil Velikov via cfe-commits

https://github.com/momchil-velikov updated 
https://github.com/llvm/llvm-project/pull/70565

>From eb47903ad47f4a9e833948424a1c88bc2c72090e Mon Sep 17 00:00:00 2001
From: Momchil Velikov 
Date: Sat, 28 Oct 2023 15:01:36 +0100
Subject: [PATCH 1/4] [Verifier] Check function attributes related to branch
 protection (NFC)

---
 llvm/lib/IR/Verifier.cpp | 21 +
 1 file changed, 21 insertions(+)

diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index d3db7a16dc0d607..a65c5abb823011f 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -2244,6 +2244,27 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, 
AttributeList Attrs,
   checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-prefix", V);
   checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-entry", V);
   checkUnsignedBaseTenFuncAttr(Attrs, "warn-stack-size", V);
+
+  if (Attrs.hasFnAttr("sign-return-adress")) {
+StringRef S = Attrs.getFnAttr("sign-return-adress").getValueAsString();
+if (S != "none" && S != "all" && S != "non-leaf")
+  CheckFailed("invalid value for 'sign-return-adress' attribute: " + S, V);
+  }
+
+  if (Attrs.hasFnAttr("sign-return-adress-key")) {
+StringRef S = Attrs.getFnAttr("sign-return-adress-key").getValueAsString();
+if (!S.equals_insensitive("a_key") && !S.equals_insensitive("b_key"))
+  CheckFailed("invalid value for 'sign-return-adress-key' attribute: " + S,
+  V);
+  }
+
+  if (Attrs.hasFnAttr("branch-target-enforcement")) {
+StringRef S =
+Attrs.getFnAttr("branch-target-enforcement").getValueAsString();
+if (!S.equals_insensitive("true") && !S.equals_insensitive("false"))
+  CheckFailed(
+  "invalid value for 'branch-target-enforcement' attribute: " + S, V);
+  }
 }
 
 void Verifier::verifyFunctionMetadata(

>From e518faffb9ec822c6809a6b8e731425c3212a7eb Mon Sep 17 00:00:00 2001
From: Momchil Velikov 
Date: Mon, 30 Oct 2023 09:27:08 +
Subject: [PATCH 2/4] Fix typos, do attribute lookup once

---
 llvm/lib/IR/Verifier.cpp | 17 -
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index a65c5abb823011f..453a51b859d1ebe 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -2245,22 +2245,21 @@ void Verifier::verifyFunctionAttrs(FunctionType *FT, 
AttributeList Attrs,
   checkUnsignedBaseTenFuncAttr(Attrs, "patchable-function-entry", V);
   checkUnsignedBaseTenFuncAttr(Attrs, "warn-stack-size", V);
 
-  if (Attrs.hasFnAttr("sign-return-adress")) {
-StringRef S = Attrs.getFnAttr("sign-return-adress").getValueAsString();
+  if (auto A = Attrs.getFnAttr("sign-return-address"); A.isValid()) {
+StringRef S = A.getValueAsString();
 if (S != "none" && S != "all" && S != "non-leaf")
-  CheckFailed("invalid value for 'sign-return-adress' attribute: " + S, V);
+  CheckFailed("invalid value for 'sign-return-address' attribute: " + S, 
V);
   }
 
-  if (Attrs.hasFnAttr("sign-return-adress-key")) {
-StringRef S = Attrs.getFnAttr("sign-return-adress-key").getValueAsString();
+  if (auto A = Attrs.getFnAttr("sign-return-address-key"); A.isValid()) {
+StringRef S = A.getValueAsString();
 if (!S.equals_insensitive("a_key") && !S.equals_insensitive("b_key"))
-  CheckFailed("invalid value for 'sign-return-adress-key' attribute: " + S,
+  CheckFailed("invalid value for 'sign-return-address-key' attribute: " + 
S,
   V);
   }
 
-  if (Attrs.hasFnAttr("branch-target-enforcement")) {
-StringRef S =
-Attrs.getFnAttr("branch-target-enforcement").getValueAsString();
+  if (auto A = Attrs.getFnAttr("branch-target-enforcement"); A.isValid()) {
+StringRef S = A.getValueAsString();
 if (!S.equals_insensitive("true") && !S.equals_insensitive("false"))
   CheckFailed(
   "invalid value for 'branch-target-enforcement' attribute: " + S, V);

>From a3aeeb8ad28de3c102180d82d86a0d3aed760d00 Mon Sep 17 00:00:00 2001
From: Momchil Velikov 
Date: Mon, 30 Oct 2023 10:34:26 +
Subject: [PATCH 3/4] Add a test

---
 llvm/test/Verifier/branch-prot-attrs.ll | 13 +
 1 file changed, 13 insertions(+)
 create mode 100644 llvm/test/Verifier/branch-prot-attrs.ll

diff --git a/llvm/test/Verifier/branch-prot-attrs.ll 
b/llvm/test/Verifier/branch-prot-attrs.ll
new file mode 100644
index 000..123a8207cfe6b4f
--- /dev/null
+++ b/llvm/test/Verifier/branch-prot-attrs.ll
@@ -0,0 +1,13 @@
+; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
+
+define void @f() #0 {
+  ret void
+}
+
+attributes #0 = {
+; CHECK:  invalid value for 'sign-return-address' attribute: loaf
+  "sign-return-address"="loaf"
+; CHECK: invalid value for 'sign-return-address-key' attribute: bad-mkey
+  "sign-return-address-key"="bad-mkey"
+; CHECK:   invalid value for 'branch-target-enforcement' attribute: yes-please
+  "branch-target-enforcement"="yes-please" }

>From ccc

[llvm] [clang] [clang][AArch64] Pass down stack clash protection options to LLVM/Backend (PR #68993)

2023-11-04 Thread Momchil Velikov via cfe-commits

momchil-velikov wrote:

Ping?

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


[llvm] [clang] [AArch64] Stack probing for dynamic allocas in SelectionDAG (PR #66525)

2023-11-04 Thread Momchil Velikov via cfe-commits

momchil-velikov wrote:

Ping?

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


[llvm] [clang-tools-extra] [flang] [lldb] [clang] [IndVars] Add check of loop invariant for trunc instructions (PR #71072)

2023-11-04 Thread Markos Horro via cfe-commits


@@ -0,0 +1,28 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=indvars -S | FileCheck %s
+
+declare void @foo(i16 noundef)
+
+; Function Attrs: mustprogress noreturn uwtable
+define void @bar(i64 noundef %ptr) {
+; CHECK-LABEL: @bar(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:[[TMP0:%.*]] = trunc i64 [[PTR:%.*]] to i4
+; CHECK-NEXT:[[TMP1:%.*]] = zext i4 [[TMP0]] to i16
+; CHECK-NEXT:br label [[WHILE_BODY:%.*]]
+; CHECK:   while.body:
+; CHECK-NEXT:tail call void @foo(i16 noundef signext [[TMP1]])
+; CHECK-NEXT:br label [[WHILE_BODY]]
+;
+entry:
+  br label %while.body
+
+while.body:   ; preds = %entry, %while.body
+  %0 = phi i64 [ %ptr, %entry ], [ %add.ptr, %while.body ]
+  %1 = trunc i64 %0 to i16
+  %and = and i16 %1, 15   ; loop invariant
+  tail call void @foo(i16 noundef signext %and)

markoshorro wrote:

Having something like:

`declare void @foo(i2 noundef)

entry:
  %ptr.addr.0 = ptrtoint ptr %ptr to i64
  br label %while.body

while.body:   ; preds = %entry, %while.body
  %0 = phi i64 [ %ptr.addr.0, %entry ], [ %add.ptr, %while.body ]
  %1 = trunc i64 %0 to i2
  %and = and i2 %1, 15   ; loop invariant
  tail call void @foo(i2 noundef signext %and)
  %add.ptr = add nsw i64 %0,  16
  br label %while.body
}`

With this change, the IR generated is the following:

`declare void @foo(i2 noundef)

define void @bar(ptr noundef %ptr) {
entry:
  %ptr.addr.0 = ptrtoint ptr %ptr to i64
  %0 = trunc i64 %ptr.addr.0 to i2
  br label %while.body

while.body:   ; preds = %while.body, %entry
  %and = and i2 %0, -1
  tail call void @foo(i2 noundef signext %and)
  br label %while.body
}`

This is valid to me, when you say that `trunc` can affect the result, do you 
have any example in mind? Thanks!

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


[llvm] [clang-tools-extra] [flang] [lldb] [clang] [IndVars] Add check of loop invariant for trunc instructions (PR #71072)

2023-11-04 Thread Markos Horro via cfe-commits

https://github.com/markoshorro edited 
https://github.com/llvm/llvm-project/pull/71072
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][CodeGen] Emit `llvm.ptrmask` for `align_up` and `align_down` (PR #71238)

2023-11-04 Thread via cfe-commits

https://github.com/goldsteinn closed 
https://github.com/llvm/llvm-project/pull/71238
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 71be514 - [Clang][CodeGen] Emit `llvm.ptrmask` for `align_up` and `align_down`

2023-11-04 Thread Noah Goldstein via cfe-commits

Author: Noah Goldstein
Date: 2023-11-04T14:20:54-05:00
New Revision: 71be514fa0af996745186816735d69fa8a26f3c9

URL: 
https://github.com/llvm/llvm-project/commit/71be514fa0af996745186816735d69fa8a26f3c9
DIFF: 
https://github.com/llvm/llvm-project/commit/71be514fa0af996745186816735d69fa8a26f3c9.diff

LOG: [Clang][CodeGen] Emit `llvm.ptrmask` for `align_up` and `align_down`

Since PR's #69343 and #67166 we probably have enough support for
`llvm.ptrmask` to make it preferable to the GEP stategy.

Closes #71238

Added: 


Modified: 
clang/lib/CodeGen/CGBuiltin.cpp
clang/test/CodeGen/builtin-align-array.c
clang/test/CodeGen/builtin-align.c

Removed: 




diff  --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 972aa1c708e5f65..978f6ffd145741d 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -19668,44 +19668,40 @@ RValue CodeGenFunction::EmitBuiltinIsAligned(const 
CallExpr *E) {
 /// Generate (x & ~(y-1)) to align down or ((x+(y-1)) & ~(y-1)) to align up.
 /// Note: For pointer types we can avoid ptrtoint/inttoptr pairs by using the
 /// llvm.ptrmask intrinsic (with a GEP before in the align_up case).
-/// TODO: actually use ptrmask once most optimization passes know about it.
 RValue CodeGenFunction::EmitBuiltinAlignTo(const CallExpr *E, bool AlignUp) {
   BuiltinAlignArgs Args(E, *this);
-  llvm::Value *SrcAddr = Args.Src;
-  if (Args.Src->getType()->isPointerTy())
-SrcAddr = Builder.CreatePtrToInt(Args.Src, Args.IntType, "intptr");
-  llvm::Value *SrcForMask = SrcAddr;
+  llvm::Value *SrcForMask = Args.Src;
   if (AlignUp) {
 // When aligning up we have to first add the mask to ensure we go over the
 // next alignment value and then align down to the next valid multiple.
 // By adding the mask, we ensure that align_up on an already aligned
 // value will not change the value.
-SrcForMask = Builder.CreateAdd(SrcForMask, Args.Mask, "over_boundary");
+if (Args.Src->getType()->isPointerTy()) {
+  if (getLangOpts().isSignedOverflowDefined())
+SrcForMask =
+Builder.CreateGEP(Int8Ty, SrcForMask, Args.Mask, "over_boundary");
+  else
+SrcForMask = EmitCheckedInBoundsGEP(Int8Ty, SrcForMask, Args.Mask,
+/*SignedIndices=*/true,
+/*isSubtraction=*/false,
+E->getExprLoc(), "over_boundary");
+} else {
+  SrcForMask = Builder.CreateAdd(SrcForMask, Args.Mask, "over_boundary");
+}
   }
   // Invert the mask to only clear the lower bits.
   llvm::Value *InvertedMask = Builder.CreateNot(Args.Mask, "inverted_mask");
-  llvm::Value *Result =
-  Builder.CreateAnd(SrcForMask, InvertedMask, "aligned_result");
+  llvm::Value *Result = nullptr;
   if (Args.Src->getType()->isPointerTy()) {
-/// TODO: Use ptrmask instead of ptrtoint+gep once it is optimized well.
-// Result = Builder.CreateIntrinsic(
-//  Intrinsic::ptrmask, {Args.SrcType, SrcForMask->getType(), 
Args.IntType},
-//  {SrcForMask, NegatedMask}, nullptr, "aligned_result");
-Result->setName("aligned_intptr");
-llvm::Value *Difference = Builder.CreateSub(Result, SrcAddr, "
diff ");
-// The result must point to the same underlying allocation. This means we
-// can use an inbounds GEP to enable better optimization.
-if (getLangOpts().isSignedOverflowDefined())
-  Result =
-  Builder.CreateGEP(Int8Ty, Args.Src, Difference, "aligned_result");
-else
-  Result = EmitCheckedInBoundsGEP(Int8Ty, Args.Src, Difference,
-  /*SignedIndices=*/true,
-  /*isSubtraction=*/!AlignUp,
-  E->getExprLoc(), "aligned_result");
+Result = Builder.CreateIntrinsic(
+Intrinsic::ptrmask, {Args.SrcType, Args.IntType},
+{SrcForMask, InvertedMask}, nullptr, "aligned_result");
+
 // Emit an alignment assumption to ensure that the new alignment is
 // propagated to loads/stores, etc.
 emitAlignmentAssumption(Result, E, E->getExprLoc(), Args.Alignment);
+  } else {
+Result = Builder.CreateAnd(SrcForMask, InvertedMask, "aligned_result");
   }
   assert(Result->getType() == Args.SrcType);
   return RValue::get(Result);

diff  --git a/clang/test/CodeGen/builtin-align-array.c 
b/clang/test/CodeGen/builtin-align-array.c
index 5d1377b98d2814f..18a77b9a710db40 100644
--- a/clang/test/CodeGen/builtin-align-array.c
+++ b/clang/test/CodeGen/builtin-align-array.c
@@ -8,22 +8,16 @@ extern int func(char *c);
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:[[BUF:%.*]] = alloca [1024 x i8], align 16
 // CHECK-NEXT:[[ARRAYIDX:%.*]] = getelementptr inbounds [1024 x i8], ptr 
[[BUF]], i64 0, i64 44
-// CHECK-NEXT:[[INTPTR:%.*]] = ptrtoint ptr [[ARRAYIDX]] to

[clang] 2414e5c - [Serialization] Fix warnings

2023-11-04 Thread Kazu Hirata via cfe-commits

Author: Kazu Hirata
Date: 2023-11-04T12:24:06-07:00
New Revision: 2414e5cb9efa289b841bb814d20c7eb6f355fa4d

URL: 
https://github.com/llvm/llvm-project/commit/2414e5cb9efa289b841bb814d20c7eb6f355fa4d
DIFF: 
https://github.com/llvm/llvm-project/commit/2414e5cb9efa289b841bb814d20c7eb6f355fa4d.diff

LOG: [Serialization] Fix warnings

This patch fixes:

  clang/lib/Serialization/ASTWriterStmt.cpp:576:3: error: default
  label in switch which covers all enumeration values
  [-Werror,-Wcovered-switch-default]

  clang/lib/Serialization/ASTReaderStmt.cpp:561:3: error: default
  label in switch which covers all enumeration values
  [-Werror,-Wcovered-switch-default]

Added: 


Modified: 
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriterStmt.cpp

Removed: 




diff  --git a/clang/lib/Serialization/ASTReaderStmt.cpp 
b/clang/lib/Serialization/ASTReaderStmt.cpp
index ab62f8f17851517..21d33e1c57cc988 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -558,8 +558,6 @@ void ASTStmtReader::VisitConstantExpr(ConstantExpr *E) {
   Record.getContext().addDestruction(&E->APValueResult());
 }
 break;
-  default:
-llvm_unreachable("unexpected ResultKind!");
   }
 
   E->setSubExpr(Record.readSubExpr());

diff  --git a/clang/lib/Serialization/ASTWriterStmt.cpp 
b/clang/lib/Serialization/ASTWriterStmt.cpp
index 00b1e4261735990..edfa3fab6cd4576 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -573,8 +573,6 @@ void ASTStmtWriter::VisitConstantExpr(ConstantExpr *E) {
   case ConstantResultStorageKind::APValue:
 Record.AddAPValue(E->APValueResult());
 break;
-  default:
-llvm_unreachable("unexpected ResultKind!");
   }
 
   Record.AddStmt(E->getSubExpr());



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[compiler-rt] [flang] [libcxx] [clang] [openmp] [llvm] [clang-tools-extra] [lldb] [OpenMP] Add memory diff dump for kernel record-replay (PR #70667)

2023-11-04 Thread via cfe-commits

https://github.com/nmustakin updated 
https://github.com/llvm/llvm-project/pull/70667

>From 153c6d812939cd23bb71e53c71378117ed5b23c7 Mon Sep 17 00:00:00 2001
From: Nafis Mustakin 
Date: Mon, 30 Oct 2023 07:50:59 -0700
Subject: [PATCH 1/5] Add memory diff dump for kernel record-replay

---
 .../PluginInterface/PluginInterface.cpp   | 65 +++
 1 file changed, 54 insertions(+), 11 deletions(-)

diff --git 
a/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
 
b/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
index 0243f0205dbf0e5..8469e8eaf1593cd 100644
--- 
a/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
+++ 
b/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
@@ -83,7 +83,7 @@ struct RecordReplayTy {
 return Plugin::success();
   }
 
-  void dumpDeviceMemory(StringRef Filename) {
+  void dumpDeviceMemory(StringRef Filename, bool saveDiff) {
 ErrorOr> DeviceMemoryMB =
 WritableMemoryBuffer::getNewUninitMemBuffer(MemorySize);
 if (!DeviceMemoryMB)
@@ -93,15 +93,58 @@ struct RecordReplayTy {
 MemoryStart, MemorySize, nullptr);
 if (Err)
   report_fatal_error("Error retrieving data for target pointer");
-
-StringRef DeviceMemory(DeviceMemoryMB.get()->getBufferStart(), MemorySize);
-std::error_code EC;
-raw_fd_ostream OS(Filename, EC);
-if (EC)
+
+std::error_code EC; 
+raw_fd_ostream OS(Filename, EC); 
+if(EC)
   report_fatal_error("Error dumping memory to file " + Filename + " :" +
  EC.message());
-OS << DeviceMemory;
-OS.close();
+
+if (saveDiff){
+  //Get the pre-record memory filename  
+  SmallString<128> InputFilename = {Filename.split('.').first, ".memory"};
+  //read the pre-record memorydump
+  auto InputFileBuffer = MemoryBuffer::getFileOrSTDIN(InputFilename); 
+  if(std::error_code EC = InputFileBuffer.getError())
+report_fatal_error("Error reading pre-record device memory");
+  
+  StringRef InputBufferContents = (*InputFileBuffer)->getBuffer(); 
+  if(InputBufferContents.size() != MemorySize) 
+report_fatal_error("Error: Pre-record device memory size mismatch");
+  
+  //get current memory contents
+  StringRef DeviceMemoryContents(DeviceMemoryMB.get()->getBuffer().data(),
+ DeviceMemoryMB.get()->getBuffer().size());
+  
+  //compare pre-record memorydump to current contents
+  size_t i = 0;
+  while(i < MemorySize){
+//if mismatch found, create a new diff line
+//current format - location, size, differences ...
+if(InputBufferContents[i] != DeviceMemoryContents[i]){
+  OS << i << " "; //marks the start offset
+  SmallVector modified; 
+  modified.push_back(DeviceMemoryContents[i]);
+  size_t j = 1;
+  //loop until next match is found
+  while(InputBufferContents[i+j] != DeviceMemoryContents[i+j]){
+modified.push_back(DeviceMemoryContents[i+j]);
+j++;
+  }
+  OS << j << " "; //marks the length of the mismatching sequence
+  for(const auto &value : modified)
+OS << value << " ";
+  OS << "\n"; 
+  i+=j+1; 
+}
+else i++; 
+  }
+}
+else {
+  StringRef DeviceMemory(DeviceMemoryMB.get()->getBufferStart(), 
MemorySize);
+  OS << DeviceMemory;
+}
+OS.close();  
   }
 
 public:
@@ -209,7 +252,7 @@ struct RecordReplayTy {
 JsonKernelInfo["ArgOffsets"] = json::Value(std::move(JsonArgOffsets));
 
 SmallString<128> MemoryFilename = {Name, ".memory"};
-dumpDeviceMemory(MemoryFilename);
+dumpDeviceMemory(MemoryFilename, false);
 
 SmallString<128> GlobalsFilename = {Name, ".globals"};
 dumpGlobals(GlobalsFilename, Image);
@@ -227,7 +270,7 @@ struct RecordReplayTy {
   void saveKernelOutputInfo(const char *Name) {
 SmallString<128> OutputFilename = {
 Name, (isRecording() ? ".original.output" : ".replay.output")};
-dumpDeviceMemory(OutputFilename);
+dumpDeviceMemory(OutputFilename, true);
   }
 
   void *alloc(uint64_t Size) {
@@ -1307,7 +1350,7 @@ Error GenericDeviceTy::launchKernel(void *EntryPtr, void 
**ArgPtrs,
 GenericKernel.getName(), GenericKernel.getImage(), ArgPtrs, ArgOffsets,
 KernelArgs.NumArgs, KernelArgs.NumTeams[0], KernelArgs.ThreadLimit[0],
 KernelArgs.Tripcount);
-
+   
   if (RecordReplay.isRecording())
 RecordReplay.saveImage(GenericKernel.getName(), GenericKernel.getImage());
 

>From 8daffad57074dd09287d321acd79c74a667eb65f Mon Sep 17 00:00:00 2001
From: Nafis Mustakin 
Date: Mon, 30 Oct 2023 08:39:40 -0700
Subject: [PATCH 2/5] Fix clang-formatting issues, accept reviewed suggestions

---
 .../PluginInterface/PluginInterface.cpp   | 78 

[clang] [Clang][CodeGen] Stoping emitting alignment assumes for `align_{up,down}` (PR #71295)

2023-11-04 Thread via cfe-commits

https://github.com/goldsteinn created 
https://github.com/llvm/llvm-project/pull/71295

Now that `align_{up,down}` use `llvm.ptrmask` (as of #71238), the
assume doesn't preserve any information that is not still easily
re-computable.


>From c2e64a4d6a6800b29b04b05e1386dff0dfba3211 Mon Sep 17 00:00:00 2001
From: Noah Goldstein 
Date: Sat, 4 Nov 2023 14:56:33 -0500
Subject: [PATCH] [Clang][CodeGen] Stoping emitting alignment assumes for
 `align_{up,down}`

Now that `align_{up,down}` use `llvm.ptrmask` (as of #71238), the
assume doesn't preserve any information that is not still easily
re-computable.
---
 clang/lib/CodeGen/CGBuiltin.cpp  | 4 
 clang/test/CodeGen/builtin-align-array.c | 4 
 clang/test/CodeGen/builtin-align.c   | 4 
 3 files changed, 12 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 978f6ffd145741d..c13d5f5ba50c07c 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -19696,10 +19696,6 @@ RValue CodeGenFunction::EmitBuiltinAlignTo(const 
CallExpr *E, bool AlignUp) {
 Result = Builder.CreateIntrinsic(
 Intrinsic::ptrmask, {Args.SrcType, Args.IntType},
 {SrcForMask, InvertedMask}, nullptr, "aligned_result");
-
-// Emit an alignment assumption to ensure that the new alignment is
-// propagated to loads/stores, etc.
-emitAlignmentAssumption(Result, E, E->getExprLoc(), Args.Alignment);
   } else {
 Result = Builder.CreateAnd(SrcForMask, InvertedMask, "aligned_result");
   }
diff --git a/clang/test/CodeGen/builtin-align-array.c 
b/clang/test/CodeGen/builtin-align-array.c
index 18a77b9a710db40..cbe6641f672eb43 100644
--- a/clang/test/CodeGen/builtin-align-array.c
+++ b/clang/test/CodeGen/builtin-align-array.c
@@ -9,12 +9,10 @@ extern int func(char *c);
 // CHECK-NEXT:[[BUF:%.*]] = alloca [1024 x i8], align 16
 // CHECK-NEXT:[[ARRAYIDX:%.*]] = getelementptr inbounds [1024 x i8], ptr 
[[BUF]], i64 0, i64 44
 // CHECK-NEXT:[[ALIGNED_RESULT:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr 
[[ARRAYIDX]], i64 -16)
-// CHECK-NEXT:call void @llvm.assume(i1 true) [ "align"(ptr 
[[ALIGNED_RESULT]], i64 16) ]
 // CHECK-NEXT:[[CALL:%.*]] = call i32 @func(ptr noundef [[ALIGNED_RESULT]])
 // CHECK-NEXT:[[ARRAYIDX1:%.*]] = getelementptr inbounds [1024 x i8], ptr 
[[BUF]], i64 0, i64 22
 // CHECK-NEXT:[[OVER_BOUNDARY:%.*]] = getelementptr inbounds i8, ptr 
[[ARRAYIDX1]], i64 31
 // CHECK-NEXT:[[ALIGNED_RESULT2:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr 
[[OVER_BOUNDARY]], i64 -32)
-// CHECK-NEXT:call void @llvm.assume(i1 true) [ "align"(ptr 
[[ALIGNED_RESULT2]], i64 32) ]
 // CHECK-NEXT:[[CALL3:%.*]] = call i32 @func(ptr noundef 
[[ALIGNED_RESULT2]])
 // CHECK-NEXT:[[ARRAYIDX4:%.*]] = getelementptr inbounds [1024 x i8], ptr 
[[BUF]], i64 0, i64 16
 // CHECK-NEXT:[[SRC_ADDR:%.*]] = ptrtoint ptr [[ARRAYIDX4]] to i64
@@ -35,12 +33,10 @@ int test_array(void) {
 // CHECK-NEXT:[[BUF:%.*]] = alloca [1024 x i8], align 32
 // CHECK-NEXT:[[ARRAYIDX:%.*]] = getelementptr inbounds [1024 x i8], ptr 
[[BUF]], i64 0, i64 64
 // CHECK-NEXT:[[ALIGNED_RESULT:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr 
[[ARRAYIDX]], i64 -16)
-// CHECK-NEXT:call void @llvm.assume(i1 true) [ "align"(ptr 
[[ALIGNED_RESULT]], i64 16) ]
 // CHECK-NEXT:[[CALL:%.*]] = call i32 @func(ptr noundef [[ALIGNED_RESULT]])
 // CHECK-NEXT:[[ARRAYIDX1:%.*]] = getelementptr inbounds [1024 x i8], ptr 
[[BUF]], i64 0, i64 32
 // CHECK-NEXT:[[OVER_BOUNDARY:%.*]] = getelementptr inbounds i8, ptr 
[[ARRAYIDX1]], i64 31
 // CHECK-NEXT:[[ALIGNED_RESULT2:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr 
[[OVER_BOUNDARY]], i64 -32)
-// CHECK-NEXT:call void @llvm.assume(i1 true) [ "align"(ptr 
[[ALIGNED_RESULT2]], i64 32) ]
 // CHECK-NEXT:[[CALL3:%.*]] = call i32 @func(ptr noundef 
[[ALIGNED_RESULT2]])
 // CHECK-NEXT:ret i32 1
 //
diff --git a/clang/test/CodeGen/builtin-align.c 
b/clang/test/CodeGen/builtin-align.c
index b58d47078799eae..932b93972a85e66 100644
--- a/clang/test/CodeGen/builtin-align.c
+++ b/clang/test/CodeGen/builtin-align.c
@@ -119,7 +119,6 @@ _Bool is_aligned(TYPE ptr, unsigned align) {
 // CHECK-VOID_PTR-NEXT:[[OVER_BOUNDARY:%.*]] = getelementptr inbounds i8, 
ptr [[PTR:%.*]], i64 [[MASK]]
 // CHECK-VOID_PTR-NEXT:[[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
 // CHECK-VOID_PTR-NEXT:[[ALIGNED_RESULT:%.*]] = call ptr 
@llvm.ptrmask.p0.i64(ptr [[OVER_BOUNDARY]], i64 [[INVERTED_MASK]])
-// CHECK-VOID_PTR-NEXT:call void @llvm.assume(i1 true) [ "align"(ptr 
[[ALIGNED_RESULT]], i64 [[ALIGNMENT]]) ]
 // CHECK-VOID_PTR-NEXT:ret ptr [[ALIGNED_RESULT]]
 //
 // CHECK-FLOAT_PTR-LABEL: define {{[^@]+}}@align_up
@@ -130,7 +129,6 @@ _Bool is_aligned(TYPE ptr, unsigned align) {
 // CHECK-FLOAT_PTR-NEXT:[[OVER_BOUNDARY:%.*]] = getelementptr inbounds i8, 
ptr [[PTR:%.*]], i64 [[MASK]]
 // CHECK-FLOAT_PTR-NEXT:[[INVERTED_MASK:%.*]] = xo

[clang] [Clang][CodeGen] Stoping emitting alignment assumes for `align_{up,down}` (PR #71295)

2023-11-04 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-codegen

Author: None (goldsteinn)


Changes

Now that `align_{up,down}` use `llvm.ptrmask` (as of #71238), the
assume doesn't preserve any information that is not still easily
re-computable.


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


3 Files Affected:

- (modified) clang/lib/CodeGen/CGBuiltin.cpp (-4) 
- (modified) clang/test/CodeGen/builtin-align-array.c (-4) 
- (modified) clang/test/CodeGen/builtin-align.c (-4) 


``diff
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 978f6ffd145741d..c13d5f5ba50c07c 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -19696,10 +19696,6 @@ RValue CodeGenFunction::EmitBuiltinAlignTo(const 
CallExpr *E, bool AlignUp) {
 Result = Builder.CreateIntrinsic(
 Intrinsic::ptrmask, {Args.SrcType, Args.IntType},
 {SrcForMask, InvertedMask}, nullptr, "aligned_result");
-
-// Emit an alignment assumption to ensure that the new alignment is
-// propagated to loads/stores, etc.
-emitAlignmentAssumption(Result, E, E->getExprLoc(), Args.Alignment);
   } else {
 Result = Builder.CreateAnd(SrcForMask, InvertedMask, "aligned_result");
   }
diff --git a/clang/test/CodeGen/builtin-align-array.c 
b/clang/test/CodeGen/builtin-align-array.c
index 18a77b9a710db40..cbe6641f672eb43 100644
--- a/clang/test/CodeGen/builtin-align-array.c
+++ b/clang/test/CodeGen/builtin-align-array.c
@@ -9,12 +9,10 @@ extern int func(char *c);
 // CHECK-NEXT:[[BUF:%.*]] = alloca [1024 x i8], align 16
 // CHECK-NEXT:[[ARRAYIDX:%.*]] = getelementptr inbounds [1024 x i8], ptr 
[[BUF]], i64 0, i64 44
 // CHECK-NEXT:[[ALIGNED_RESULT:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr 
[[ARRAYIDX]], i64 -16)
-// CHECK-NEXT:call void @llvm.assume(i1 true) [ "align"(ptr 
[[ALIGNED_RESULT]], i64 16) ]
 // CHECK-NEXT:[[CALL:%.*]] = call i32 @func(ptr noundef [[ALIGNED_RESULT]])
 // CHECK-NEXT:[[ARRAYIDX1:%.*]] = getelementptr inbounds [1024 x i8], ptr 
[[BUF]], i64 0, i64 22
 // CHECK-NEXT:[[OVER_BOUNDARY:%.*]] = getelementptr inbounds i8, ptr 
[[ARRAYIDX1]], i64 31
 // CHECK-NEXT:[[ALIGNED_RESULT2:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr 
[[OVER_BOUNDARY]], i64 -32)
-// CHECK-NEXT:call void @llvm.assume(i1 true) [ "align"(ptr 
[[ALIGNED_RESULT2]], i64 32) ]
 // CHECK-NEXT:[[CALL3:%.*]] = call i32 @func(ptr noundef 
[[ALIGNED_RESULT2]])
 // CHECK-NEXT:[[ARRAYIDX4:%.*]] = getelementptr inbounds [1024 x i8], ptr 
[[BUF]], i64 0, i64 16
 // CHECK-NEXT:[[SRC_ADDR:%.*]] = ptrtoint ptr [[ARRAYIDX4]] to i64
@@ -35,12 +33,10 @@ int test_array(void) {
 // CHECK-NEXT:[[BUF:%.*]] = alloca [1024 x i8], align 32
 // CHECK-NEXT:[[ARRAYIDX:%.*]] = getelementptr inbounds [1024 x i8], ptr 
[[BUF]], i64 0, i64 64
 // CHECK-NEXT:[[ALIGNED_RESULT:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr 
[[ARRAYIDX]], i64 -16)
-// CHECK-NEXT:call void @llvm.assume(i1 true) [ "align"(ptr 
[[ALIGNED_RESULT]], i64 16) ]
 // CHECK-NEXT:[[CALL:%.*]] = call i32 @func(ptr noundef [[ALIGNED_RESULT]])
 // CHECK-NEXT:[[ARRAYIDX1:%.*]] = getelementptr inbounds [1024 x i8], ptr 
[[BUF]], i64 0, i64 32
 // CHECK-NEXT:[[OVER_BOUNDARY:%.*]] = getelementptr inbounds i8, ptr 
[[ARRAYIDX1]], i64 31
 // CHECK-NEXT:[[ALIGNED_RESULT2:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr 
[[OVER_BOUNDARY]], i64 -32)
-// CHECK-NEXT:call void @llvm.assume(i1 true) [ "align"(ptr 
[[ALIGNED_RESULT2]], i64 32) ]
 // CHECK-NEXT:[[CALL3:%.*]] = call i32 @func(ptr noundef 
[[ALIGNED_RESULT2]])
 // CHECK-NEXT:ret i32 1
 //
diff --git a/clang/test/CodeGen/builtin-align.c 
b/clang/test/CodeGen/builtin-align.c
index b58d47078799eae..932b93972a85e66 100644
--- a/clang/test/CodeGen/builtin-align.c
+++ b/clang/test/CodeGen/builtin-align.c
@@ -119,7 +119,6 @@ _Bool is_aligned(TYPE ptr, unsigned align) {
 // CHECK-VOID_PTR-NEXT:[[OVER_BOUNDARY:%.*]] = getelementptr inbounds i8, 
ptr [[PTR:%.*]], i64 [[MASK]]
 // CHECK-VOID_PTR-NEXT:[[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
 // CHECK-VOID_PTR-NEXT:[[ALIGNED_RESULT:%.*]] = call ptr 
@llvm.ptrmask.p0.i64(ptr [[OVER_BOUNDARY]], i64 [[INVERTED_MASK]])
-// CHECK-VOID_PTR-NEXT:call void @llvm.assume(i1 true) [ "align"(ptr 
[[ALIGNED_RESULT]], i64 [[ALIGNMENT]]) ]
 // CHECK-VOID_PTR-NEXT:ret ptr [[ALIGNED_RESULT]]
 //
 // CHECK-FLOAT_PTR-LABEL: define {{[^@]+}}@align_up
@@ -130,7 +129,6 @@ _Bool is_aligned(TYPE ptr, unsigned align) {
 // CHECK-FLOAT_PTR-NEXT:[[OVER_BOUNDARY:%.*]] = getelementptr inbounds i8, 
ptr [[PTR:%.*]], i64 [[MASK]]
 // CHECK-FLOAT_PTR-NEXT:[[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1
 // CHECK-FLOAT_PTR-NEXT:[[ALIGNED_RESULT:%.*]] = call ptr 
@llvm.ptrmask.p0.i64(ptr [[OVER_BOUNDARY]], i64 [[INVERTED_MASK]])
-// CHECK-FLOAT_PTR-NEXT:call void @llvm.assume(i1 true) [ "align"(ptr 
[[ALIGNED_RESULT]], i64 [[ALIGNMENT]]) ]
 // CHECK-FLOAT_PTR-

[PATCH] D134458: [AST] Add C++11 attribute 'msvc::no_unique_address'

2023-11-04 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt abandoned this revision.
RIscRIpt added a comment.

Abandoning due to lack of time and expertise. I might come back and tackle it 
in several months.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D134458/new/

https://reviews.llvm.org/D134458

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[libc] [clang] [libcxx] [flang] [llvm] [compiler-rt] [clang-tools-extra] [libc++] Implement ranges::iota (PR #68494)

2023-11-04 Thread James E T Smith via cfe-commits

https://github.com/jamesETsmith updated 
https://github.com/llvm/llvm-project/pull/68494

>From c4a3ccfbad090ad8314aa8ad53092edc8d5432bc Mon Sep 17 00:00:00 2001
From: James Smith 
Date: Thu, 28 Sep 2023 10:11:15 -0400
Subject: [PATCH 01/16] [libc++] Implement ranges::iota and
 ranges::out_value_result

---
 libcxx/include/CMakeLists.txt |   2 +
 libcxx/include/__algorithm/out_value_result.h |  52 +
 libcxx/include/__numeric/ranges_iota.h|  53 +
 libcxx/include/algorithm  |   4 +
 libcxx/include/numeric|   1 +
 libcxx/include/version|   2 +-
 .../out_value_result.pass.cpp | 102 ++
 .../numeric.iota/ranges.iota.pass.cpp |  52 +
 8 files changed, 267 insertions(+), 1 deletion(-)
 create mode 100644 libcxx/include/__algorithm/out_value_result.h
 create mode 100644 libcxx/include/__numeric/ranges_iota.h
 create mode 100644 
libcxx/test/std/algorithms/algorithms.results/out_value_result.pass.cpp
 create mode 100644 
libcxx/test/std/numerics/numeric.ops/numeric.iota/ranges.iota.pass.cpp

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 2ec755236dbaee2..c6eb03f1d68e984 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -63,6 +63,7 @@ set(files
   __algorithm/next_permutation.h
   __algorithm/none_of.h
   __algorithm/nth_element.h
+  __algorithm/out_value_result.h
   __algorithm/partial_sort.h
   __algorithm/partial_sort_copy.h
   __algorithm/partition.h
@@ -561,6 +562,7 @@ set(files
   __numeric/partial_sum.h
   __numeric/pstl_reduce.h
   __numeric/pstl_transform_reduce.h
+  __numeric/ranges_iota.h
   __numeric/reduce.h
   __numeric/transform_exclusive_scan.h
   __numeric/transform_inclusive_scan.h
diff --git a/libcxx/include/__algorithm/out_value_result.h 
b/libcxx/include/__algorithm/out_value_result.h
new file mode 100644
index 000..8baffec7b9ef4da
--- /dev/null
+++ b/libcxx/include/__algorithm/out_value_result.h
@@ -0,0 +1,52 @@
+// -*- C++ -*-
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef _LIBCPP___ALGORITHM_OUT_VALUE_RESULT_H
+#define _LIBCPP___ALGORITHM_OUT_VALUE_RESULT_H
+
+#include <__concepts/convertible_to.h>
+#include <__config>
+#include <__utility/move.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 23
+
+namespace ranges {
+
+template 
+struct out_value_result {
+  _LIBCPP_NO_UNIQUE_ADDRESS _OutIter1 out;
+  _LIBCPP_NO_UNIQUE_ADDRESS _ValType1 value;
+
+  template 
+requires convertible_to && 
convertible_to
+  constexpr operator out_value_result<_OutIter2, _ValType2>() const& { return 
{out, value}; }
+
+  template 
+requires convertible_to<_OutIter1, _OutIter2> && convertible_to<_ValType1, 
_ValType2>
+  constexpr operator out_value_result<_OutIter2, _ValType2>() && { return 
{std::move(out), std::move(value)}; }
+};
+
+} // namespace ranges
+
+#endif // _LIBCPP_STD_VER >= 23
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___ALGORITHM_OUT_VALUE_RESULT_H
diff --git a/libcxx/include/__numeric/ranges_iota.h 
b/libcxx/include/__numeric/ranges_iota.h
new file mode 100644
index 000..20311a68c2a348c
--- /dev/null
+++ b/libcxx/include/__numeric/ranges_iota.h
@@ -0,0 +1,53 @@
+// -*- C++ -*-
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef _LIBCPP___NUMERIC_RANGES_IOTA_H
+#define _LIBCPP___NUMERIC_RANGES_IOTA_H
+
+#include <__algorithm/out_value_result.h>
+#include <__config>
+#include <__ranges/concepts.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 23
+namespace ranges {
+template 
+using iota_result = ranges::out_value_result<_Out, _Tp>;
+
+struct __iota_fn {
+  template  _Sent, 
weakly_incrementable _Tp>
+requires indirectly_writable<_Out, const _Tp&>
+  constexpr iota_result<_Out, _Tp> operator()(_Out __first, _Sent __last, _Tp 
__value) const {
+while (__first != __last) {
+  *__first = static_cast(__value);
+  ++__first;
+  ++__value;
+}
+return {std::move(__first), std::move(__valu

[libc] [clang] [libcxx] [flang] [llvm] [compiler-rt] [clang-tools-extra] [libc++] Implement ranges::iota (PR #68494)

2023-11-04 Thread James E T Smith via cfe-commits

https://github.com/jamesETsmith updated 
https://github.com/llvm/llvm-project/pull/68494

>From c4a3ccfbad090ad8314aa8ad53092edc8d5432bc Mon Sep 17 00:00:00 2001
From: James Smith 
Date: Thu, 28 Sep 2023 10:11:15 -0400
Subject: [PATCH 01/16] [libc++] Implement ranges::iota and
 ranges::out_value_result

---
 libcxx/include/CMakeLists.txt |   2 +
 libcxx/include/__algorithm/out_value_result.h |  52 +
 libcxx/include/__numeric/ranges_iota.h|  53 +
 libcxx/include/algorithm  |   4 +
 libcxx/include/numeric|   1 +
 libcxx/include/version|   2 +-
 .../out_value_result.pass.cpp | 102 ++
 .../numeric.iota/ranges.iota.pass.cpp |  52 +
 8 files changed, 267 insertions(+), 1 deletion(-)
 create mode 100644 libcxx/include/__algorithm/out_value_result.h
 create mode 100644 libcxx/include/__numeric/ranges_iota.h
 create mode 100644 
libcxx/test/std/algorithms/algorithms.results/out_value_result.pass.cpp
 create mode 100644 
libcxx/test/std/numerics/numeric.ops/numeric.iota/ranges.iota.pass.cpp

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 2ec755236dbaee2..c6eb03f1d68e984 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -63,6 +63,7 @@ set(files
   __algorithm/next_permutation.h
   __algorithm/none_of.h
   __algorithm/nth_element.h
+  __algorithm/out_value_result.h
   __algorithm/partial_sort.h
   __algorithm/partial_sort_copy.h
   __algorithm/partition.h
@@ -561,6 +562,7 @@ set(files
   __numeric/partial_sum.h
   __numeric/pstl_reduce.h
   __numeric/pstl_transform_reduce.h
+  __numeric/ranges_iota.h
   __numeric/reduce.h
   __numeric/transform_exclusive_scan.h
   __numeric/transform_inclusive_scan.h
diff --git a/libcxx/include/__algorithm/out_value_result.h 
b/libcxx/include/__algorithm/out_value_result.h
new file mode 100644
index 000..8baffec7b9ef4da
--- /dev/null
+++ b/libcxx/include/__algorithm/out_value_result.h
@@ -0,0 +1,52 @@
+// -*- C++ -*-
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef _LIBCPP___ALGORITHM_OUT_VALUE_RESULT_H
+#define _LIBCPP___ALGORITHM_OUT_VALUE_RESULT_H
+
+#include <__concepts/convertible_to.h>
+#include <__config>
+#include <__utility/move.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 23
+
+namespace ranges {
+
+template 
+struct out_value_result {
+  _LIBCPP_NO_UNIQUE_ADDRESS _OutIter1 out;
+  _LIBCPP_NO_UNIQUE_ADDRESS _ValType1 value;
+
+  template 
+requires convertible_to && 
convertible_to
+  constexpr operator out_value_result<_OutIter2, _ValType2>() const& { return 
{out, value}; }
+
+  template 
+requires convertible_to<_OutIter1, _OutIter2> && convertible_to<_ValType1, 
_ValType2>
+  constexpr operator out_value_result<_OutIter2, _ValType2>() && { return 
{std::move(out), std::move(value)}; }
+};
+
+} // namespace ranges
+
+#endif // _LIBCPP_STD_VER >= 23
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___ALGORITHM_OUT_VALUE_RESULT_H
diff --git a/libcxx/include/__numeric/ranges_iota.h 
b/libcxx/include/__numeric/ranges_iota.h
new file mode 100644
index 000..20311a68c2a348c
--- /dev/null
+++ b/libcxx/include/__numeric/ranges_iota.h
@@ -0,0 +1,53 @@
+// -*- C++ -*-
+//===--===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef _LIBCPP___NUMERIC_RANGES_IOTA_H
+#define _LIBCPP___NUMERIC_RANGES_IOTA_H
+
+#include <__algorithm/out_value_result.h>
+#include <__config>
+#include <__ranges/concepts.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 23
+namespace ranges {
+template 
+using iota_result = ranges::out_value_result<_Out, _Tp>;
+
+struct __iota_fn {
+  template  _Sent, 
weakly_incrementable _Tp>
+requires indirectly_writable<_Out, const _Tp&>
+  constexpr iota_result<_Out, _Tp> operator()(_Out __first, _Sent __last, _Tp 
__value) const {
+while (__first != __last) {
+  *__first = static_cast(__value);
+  ++__first;
+  ++__value;
+}
+return {std::move(__first), std::move(__valu

[lld] [llvm] [clang] [mlir] [flang] [ELF] Merge exportDynamic into versionId (PR #71272)

2023-11-04 Thread Fangrui Song via cfe-commits

https://github.com/MaskRay updated 
https://github.com/llvm/llvm-project/pull/71272

>From e6a9f8c08ddab444f581a18c0d3c2ad242448e7c Mon Sep 17 00:00:00 2001
From: Fangrui Song 
Date: Fri, 3 Nov 2023 14:48:13 -0700
Subject: [PATCH 1/2] [ELF] Merge exportDynamic into versionId

For a Defined/Common symbol with a false `inDynamicList`, both
`versionId==VER_NDX_LOCAL` and `!exportDynamic` indicate that the symbol
should not be exported, which means that the two fields have overlapping
purposes. We can merge them together by reserving `versionId==-1` to
indicate a symbol that is not exported:

* -1 (initial): not exported, binding unchanged
* 0: VER_NDX_LOCAL, not exported, binding changed to STB_LOCAL
* 1: VER_NDX_GLOBAL, exported, binding unchanged
* others: verdef index, exported, binding unchanged

-1 and 0 are similar, but -1 does not change the binding to STB_LOCAL.

The saved bit can be use for another purpose, e.g. whether a symbol has
a DSO definition (#70130).

--version-script is almost never used for executables. If used, a minor behavior
change is that a version pattern that is not `local:` will export the matched
symbols.
---
 lld/ELF/Config.h |  1 +
 lld/ELF/Driver.cpp   |  9 --
 lld/ELF/InputFiles.cpp   |  4 +--
 lld/ELF/LTO.cpp  |  6 ++--
 lld/ELF/Relocations.cpp  |  4 +--
 lld/ELF/SymbolTable.cpp  |  2 +-
 lld/ELF/Symbols.cpp  | 16 +--
 lld/ELF/Symbols.h| 42 +---
 lld/ELF/SyntheticSections.cpp|  3 +-
 lld/test/ELF/symver-non-default.s|  6 ++--
 lld/test/ELF/version-script-symver.s |  4 +--
 11 files changed, 55 insertions(+), 42 deletions(-)

diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 56229334f9a44ae..06fef790d1e5439 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -225,6 +225,7 @@ struct Config {
   bool cref;
   llvm::SmallVector, 0>
   deadRelocInNonAlloc;
+  uint16_t defaultVersionId;
   bool demangle = true;
   bool dependentLibraries;
   bool disableVerify;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 6290880c43d3b95..555a396e1eccbb0 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1683,6 +1683,9 @@ static void readConfigs(opt::InputArgList &args) {
 }
   }
 
+  config->defaultVersionId =
+  config->exportDynamic ? ELF::VER_NDX_GLOBAL : nonExported;
+
   assert(config->versionDefinitions.empty());
   config->versionDefinitions.push_back(
   {"local", (uint16_t)VER_NDX_LOCAL, {}, {}});
@@ -2518,9 +2521,9 @@ static void combineVersionedSymbol(Symbol &sym,
 sym.symbolKind = Symbol::PlaceholderKind;
 sym.isUsedInRegularObj = false;
   } else if (auto *sym1 = dyn_cast(&sym)) {
-if (sym2->versionId > VER_NDX_GLOBAL
-? config->versionDefinitions[sym2->versionId].name == suffix1 + 1
-: sym1->section == sym2->section && sym1->value == sym2->value) {
+if (sym2->versionId == VER_NDX_GLOBAL || sym2->versionId == nonExported
+? sym1->section == sym2->section && sym1->value == sym2->value
+: config->versionDefinitions[sym2->versionId].name == suffix1 + 1) 
{
   // Due to an assembler design flaw, if foo is defined, .symver foo,
   // foo@v1 defines both foo and foo@v1. Unless foo is bound to a
   // different version, GNU ld makes foo@v1 canonical and eliminates
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index a0d4be8ff9885b0..1ac94e179688fee 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -1520,7 +1520,7 @@ template  void SharedFile::parse() {
   }
   Symbol *s = symtab.addSymbol(
   Undefined{this, name, sym.getBinding(), sym.st_other, 
sym.getType()});
-  s->exportDynamic = true;
+  s->versionId = VER_NDX_GLOBAL;
   if (s->isUndefined() && sym.getBinding() != STB_WEAK &&
   config->unresolvedSymbolsInShlib != UnresolvedPolicy::Ignore)
 requiredSymbols.push_back(s);
@@ -1698,7 +1698,7 @@ createBitcodeSymbol(Symbol *&sym, const std::vector 
&keptComdats,
   } else {
 Defined newSym(&f, StringRef(), binding, visibility, type, 0, 0, nullptr);
 if (objSym.canBeOmittedFromSymbolTable())
-  newSym.exportDynamic = false;
+  newSym.versionId = nonExported;
 sym->resolve(newSym);
   }
 }
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp
index 504c12aac6c5696..e534f159e5e42be 100644
--- a/lld/ELF/LTO.cpp
+++ b/lld/ELF/LTO.cpp
@@ -245,9 +245,9 @@ void BitcodeCompiler::add(BitcodeFile &f) {
 usedStartStop.count(objSym.getSectionName());
 // Identify symbols exported dynamically, and that therefore could be
 // referenced by a shared library not visible to the linker.
-r.ExportDynamic =
-sym->computeBinding() != STB_LOCAL &&
-(config->exportDynamic || sym->exportDynamic || sym->inDynamicList);
+r.ExportDynamic = sym->computeBinding() != STB_LOCAL &

[clang] [Clang][Driver][LTO] Fix empty stats filename when in LTO mode (PR #71197)

2023-11-04 Thread Fangrui Song via cfe-commits

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


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


[clang] [Clang][Driver][LTO] Fix empty stats filename when in LTO mode (PR #71197)

2023-11-04 Thread Fangrui Song via cfe-commits

https://github.com/MaskRay edited 
https://github.com/llvm/llvm-project/pull/71197
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Driver][LTO] Fix empty stats filename when in LTO mode (PR #71197)

2023-11-04 Thread Fangrui Song via cfe-commits


@@ -535,7 +535,15 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, 
const JobAction &JA,
 
   if (D.isUsingLTO()) {
 assert(!Inputs.empty() && "Must have at least one input.");
-addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0],
+// Find the first filename InputInfo object.
+auto Input = llvm::find_if(
+Inputs, [](const InputInfo &II) -> bool { return II.isFilename(); });
+if (Input == Inputs.end())
+  // For a very rare case, all of the inputs to the linker are
+  // flags. If that happens, just use the first InputInfo.

MaskRay wrote:

In Clang, flags only refer to boolean options (i.e. not `-fxxx=yy`). It seems 
that the canonical term here is `InputArg`.

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


[clang] [Clang][Driver][LTO] Fix empty stats filename when in LTO mode (PR #71197)

2023-11-04 Thread Fangrui Song via cfe-commits


@@ -20,6 +20,8 @@
 // CHECK-INVALID: invalid value 'bla' in '-save-stats=bla'
 
 // RUN: %clang -target x86_64-linux-unknown -save-stats -flto -o 
obj/dir/save-stats.exe %s -### 2>&1 | FileCheck %s -check-prefix=CHECK-LTO
+// Previously `-plugin-opt=stats-file` would use empty filename if a linker 
flag (i.e. -Wl) is presented before any input filename.
+// RUN: %clang -target x86_64-linux-unknown -save-stats -flto -o 
obj/dir/save-stats.exe -Wl,-plugin-opt=-dummy %s -### 2>&1 | FileCheck %s 
-check-prefix=CHECK-LTO

MaskRay wrote:

Use `--target=` for new tests. `-target ` has been deprecated since Clang 3.4.

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


[clang] bceb6a1 - [StaticAnalyzer] Fix -Wunused-variable in SVals.h (NFC)

2023-11-04 Thread Jie Fu via cfe-commits

Author: Jie Fu
Date: 2023-11-05T07:40:44+08:00
New Revision: bceb6a1f2e141be6ed66fa382ee280c2644174fd

URL: 
https://github.com/llvm/llvm-project/commit/bceb6a1f2e141be6ed66fa382ee280c2644174fd
DIFF: 
https://github.com/llvm/llvm-project/commit/bceb6a1f2e141be6ed66fa382ee280c2644174fd.diff

LOG: [StaticAnalyzer] Fix -Wunused-variable in SVals.h (NFC)

/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h:321:14:
 error: unused variable 'K' [-Werror,-Wunused-variable]
SValKind K = data.first.getKind();
 ^
1 error generated.

Added: 


Modified: 
clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h

Removed: 




diff  --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
index 5395cd6167b7ce5..c60528b7685fe82 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
@@ -318,7 +318,7 @@ class LocAsInteger : public NonLoc {
   : NonLoc(LocAsIntegerKind, &data) {
 // We do not need to represent loc::ConcreteInt as LocAsInteger,
 // as it'd collapse into a nonloc::ConcreteInt instead.
-SValKind K = data.first.getKind();
+[[maybe_unused]] SValKind K = data.first.getKind();
 assert(K == loc::MemRegionValKind || K == loc::GotoLabelKind);
   }
 



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute (PR #71300)

2023-11-04 Thread Richard Dzenis via cfe-commits

https://github.com/RIscRIpt created 
https://github.com/llvm/llvm-project/pull/71300

As per agreement with @AaronBallman and @erichkeane, I am re-opening this patch 
here.

The current version of the patch has undergone numerous revisions before it 
became the version I am sending to GitHub.

Below you can find a summary of the history of changes.
The full history of all comments (excluding code-inline comments) is available 
in this file:
[msvc-constexpr-D134475-comments.md](https://github.com/llvm/llvm-project/files/13257930/msvc-constexpr-D134475-comments.md)


---

Initially I submitted this patch to make `[[msvc::constexpr]]` visible in the 
AST, with no semantics, and no tests at all. @AaronBallman has told me that you 
typically don't accept such patches, so I started figuring out semantics of 
`[[msvc::constexpr]]`.

At first I tried to kind of reverse-engineer it myself, I made several 
observations, some of them were incorrect.

Later, @cpplearner noted:
> It appears that `[[msvc::constexpr]]` does not make a function `constexpr`, 
> but if `[[msvc::constexpr]]` is used in a function definition and in a call 
> to that function, then the annotated function call can be evaluated during 
> constant evaluation: https://godbolt.org/z/3MPTsz6Yn
>
> Apparently this is used to implement `constexpr std::construct_at`, which 
> needs to call placement operator new, but the latter is not `constexpr`.

Additionally I asked MSVC team to comment about `[[msvc::constexpr]]`. Cody 
Miller from Microsoft has shared semantics of `[[msvc::constexpr]]` 
[here](https://developercommunity.visualstudio.com/t/msvc::constexpr-specification/10259132).

Further testing and experiments revealed that, unfortunately not all of his 
points were correct.

After some trials and errors, I came up with the following definition of 
semantics for `[[msvc::constexpr]]`

The `[[msvc::constexpr]]` attribute can be applied only to a function 
definition or a `return` statement.
It does not impact function declarations.
A `[[msvc::constexpr]]` function cannot be `constexpr` or `consteval`.
A `[[msvc::constexpr]]` function is treated in the same way as a 
`constexpr` function
if it is evaluated in a constant context of `[[msvc::constexpr]] return` 
statement.
Otherwise, it is treated as a regular function.

This doc-note was added to `MSConstexprDocs`.

As per this definition, we need to be able to track whether current invocation 
of `[[msvc::constexpr]]` function comes from `[[msvc::constexpr]] return` 
statement, which in turn comes from a constant evaluation context (i.e. a 
`constexpr` function).
Thus I went with the approach, which I saw being used in some other cases: a 
RAII helper (`MSConstexprContextRAII`), and a `bool` flag in `CallStackFrame`.

>From d27897ade53ab6f983e442f24880260eed26238a Mon Sep 17 00:00:00 2001
From: Richard Dzenis 
Date: Thu, 20 Jul 2023 00:18:50 +0300
Subject: [PATCH 1/2] [clang-cl] Add support for [[msvc::constexpr]] C++11
 attribute

Differential Revision: https://reviews.llvm.org/D134475
---
 clang/include/clang/Basic/Attr.td |  8 +++
 clang/include/clang/Basic/AttrDocs.td | 16 ++
 .../clang/Basic/DiagnosticSemaKinds.td| 10 +++-
 clang/include/clang/Basic/LangOptions.h   |  1 +
 clang/lib/AST/ExprConstant.cpp| 34 +---
 clang/lib/Basic/Targets/OSTargets.cpp |  3 ++
 clang/lib/Sema/SemaDecl.cpp   |  4 +-
 clang/lib/Sema/SemaDeclAttr.cpp   | 24 +
 clang/lib/Sema/SemaDeclCXX.cpp|  5 +-
 clang/lib/Sema/SemaStmtAttr.cpp   | 16 ++
 clang/test/AST/ms-constexpr.cpp   | 28 ++
 ...a-attribute-supported-attributes-list.test |  1 +
 clang/test/SemaCXX/ms-constexpr-invalid.cpp   | 52 +++
 clang/test/SemaCXX/ms-constexpr-new.cpp   | 16 ++
 clang/test/SemaCXX/ms-constexpr.cpp   | 37 +
 15 files changed, 245 insertions(+), 10 deletions(-)
 create mode 100644 clang/test/AST/ms-constexpr.cpp
 create mode 100644 clang/test/SemaCXX/ms-constexpr-invalid.cpp
 create mode 100644 clang/test/SemaCXX/ms-constexpr-new.cpp
 create mode 100644 clang/test/SemaCXX/ms-constexpr.cpp

diff --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 60b54c155e5..771ac5575e25d8c 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -3602,6 +3602,14 @@ def : MutualExclusions<[Owner, Pointer]>;
 
 // Microsoft-related attributes
 
+def MSConstexpr : InheritableAttr {
+  let LangOpts = [MicrosoftExt];
+  let Spellings = [CXX11<"msvc", "constexpr">];
+  let Subjects = SubjectList<[Function, Stmt], ErrorDiag,
+ "functions and statements">;
+  let Documentation = [MSConstexprDocs];
+}
+
 def MSNoVTable : InheritableAttr, TargetSpecificAttr {
   let Spellings = [Declspec<"novtable">];
   let Subjects = SubjectList<[CXXRecord]>;
di

[clang] [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute (PR #71300)

2023-11-04 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-driver

Author: Richard Dzenis (RIscRIpt)


Changes

As per agreement with @AaronBallman and @erichkeane, I am 
re-opening this patch here.

The current version of the patch has undergone numerous revisions before it 
became the version I am sending to GitHub.

Below you can find a summary of the history of changes.
The full history of all comments (excluding code-inline comments) is available 
in this file:
[msvc-constexpr-D134475-comments.md](https://github.com/llvm/llvm-project/files/13257930/msvc-constexpr-D134475-comments.md)


---

Initially I submitted this patch to make `[[msvc::constexpr]]` visible in the 
AST, with no semantics, and no tests at all. @AaronBallman has told me 
that you typically don't accept such patches, so I started figuring out 
semantics of `[[msvc::constexpr]]`.

At first I tried to kind of reverse-engineer it myself, I made several 
observations, some of them were incorrect.

Later, @cpplearner noted:
> It appears that `[[msvc::constexpr]]` does not make a function 
`constexpr`, but if `[[msvc::constexpr]]` is used in a function definition and 
in a call to that function, then the annotated function call can be evaluated 
during constant evaluation: https://godbolt.org/z/3MPTsz6Yn
>
> Apparently this is used to implement `constexpr std::construct_at`, which 
needs to call placement operator new, but the latter is not `constexpr`.

Additionally I asked MSVC team to comment about `[[msvc::constexpr]]`. Cody 
Miller from Microsoft has shared semantics of `[[msvc::constexpr]]` 
[here](https://developercommunity.visualstudio.com/t/msvc::constexpr-specification/10259132).

Further testing and experiments revealed that, unfortunately not all of his 
points were correct.

After some trials and errors, I came up with the following definition of 
semantics for `[[msvc::constexpr]]`

The `[[msvc::constexpr]]` attribute can be applied only to a function 
definition or a `return` statement.
It does not impact function declarations.
A `[[msvc::constexpr]]` function cannot be `constexpr` or `consteval`.
A `[[msvc::constexpr]]` function is treated in the same way as a 
`constexpr` function
if it is evaluated in a constant context of `[[msvc::constexpr]] return` 
statement.
Otherwise, it is treated as a regular function.

This doc-note was added to `MSConstexprDocs`.

As per this definition, we need to be able to track whether current invocation 
of `[[msvc::constexpr]]` function comes from `[[msvc::constexpr]] return` 
statement, which in turn comes from a constant evaluation context (i.e. a 
`constexpr` function).
Thus I went with the approach, which I saw being used in some other cases: a 
RAII helper (`MSConstexprContextRAII`), and a `bool` flag in `CallStackFrame`.

---

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


19 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+2) 
- (modified) clang/docs/UsersManual.rst (+2-2) 
- (modified) clang/include/clang/Basic/Attr.td (+8) 
- (modified) clang/include/clang/Basic/AttrDocs.td (+16) 
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+8-2) 
- (modified) clang/include/clang/Basic/LangOptions.h (+1) 
- (modified) clang/lib/AST/ExprConstant.cpp (+28-6) 
- (modified) clang/lib/Basic/Targets/OSTargets.cpp (+3) 
- (modified) clang/lib/Driver/ToolChains/MSVC.cpp (+2-2) 
- (modified) clang/lib/Sema/SemaDecl.cpp (+3-1) 
- (modified) clang/lib/Sema/SemaDeclAttr.cpp (+24) 
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+4-1) 
- (modified) clang/lib/Sema/SemaStmtAttr.cpp (+16) 
- (added) clang/test/AST/ms-constexpr.cpp (+28) 
- (modified) clang/test/Driver/cl-options.c (+2-2) 
- (modified) clang/test/Misc/pragma-attribute-supported-attributes-list.test 
(+1) 
- (added) clang/test/SemaCXX/ms-constexpr-invalid.cpp (+52) 
- (added) clang/test/SemaCXX/ms-constexpr-new.cpp (+16) 
- (added) clang/test/SemaCXX/ms-constexpr.cpp (+37) 


``diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index afe7e2e79c2d087..ed0bfaf67aee449 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -211,6 +211,8 @@ C23 Feature Support
 
 Non-comprehensive list of changes in this release
 -
+- The default value of `_MSC_VER` was raised from 1920 to 1933.
+  MSVC 19.33 added undocumented attribute ``[[msvc::constexpr]]``.
 
 * Clang now has a ``__builtin_vectorelements()`` function that determines the 
number of elements in a vector.
   For fixed-sized vectors, e.g., defined via 
``__attribute__((vector_size(N)))`` or ARM NEON's vector types
diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst
index edc2bce6a964dc4..b849464e6dc3ca6 100644
--- a/clang/docs/UsersManual.rst
+++ b/clang/docs/UsersManual.rst
@@ -,8 +,8 @@ default for Windows targets.
 
 For compatibility with existing code that comp

[PATCH] D134475: [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute

2023-11-04 Thread Richard Dzenis via Phabricator via cfe-commits
RIscRIpt abandoned this revision.
RIscRIpt added a comment.

As per agreement, migrating to Github: 
https://github.com/llvm/llvm-project/pull/71300


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D134475/new/

https://reviews.llvm.org/D134475

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute (PR #71300)

2023-11-04 Thread Richard Dzenis via cfe-commits

RIscRIpt wrote:

Initially I replicated semantics of `[[msvc::constexpr]]` from MSVC, so that it 
was possible to use it the same way as in MSVC, even `[[msvc::constexpr]] 
return ::new` from non-std namespace. E.g. https://godbolt.org/z/7eKh5Envz
```cpp
// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 
-std=c++20 -ast-dump %s | FileCheck %s

// CHECK: used operator new
// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} 
[[nodiscard]] [[msvc::constexpr]] inline void* __cdecl operator 
new(decltype(sizeof(void*)), void* p) noexcept { return p; }

// CHECK: used constexpr construct_at
// CHECK: AttributedStmt 0x{{[0-9a-f]+}} 
// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} 
// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} 
constexpr int* construct_at(int* p, int v) { [[msvc::constexpr]] return ::new 
(p) int(v); }

constexpr bool check_construct_at() { int x; return *construct_at(&x, 42) == 
42; }

static_assert(check_construct_at());
```

However @rsmith raised a concern over changes in 
`PointerExprEvaluator::VisitCXXNewExpr`:
```diff
   bool IsNothrow = false;
   bool IsPlacement = false;
+  bool IsMSConstexpr = Info.CurrentCall->CanEvalMSConstexpr &&
+   OperatorNew->hasAttr();
  if (OperatorNew->isReservedGlobalPlacementOperator() &&
- Info.CurrentCall->isStdFunction() && !E->isArray()) {
+ (Info.CurrentCall->isStdFunction() || IsMSConstexpr) && !E->isArray()) {
```
> Do we really need this change? Was our existing check of whether the caller 
> is in namespace std not sufficient for MS' standard library? I'd strongly 
> prefer not to have a documented, user-visible attribute that gives permission 
> to use placement new directly.

If I could choose, I would opt to fully replicate the behavior of MSVC. 
However, I also acknowledge the concerns that have been raised.

@AaronBallman, @erichkeane, any comments?

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


[clang] [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute (PR #71300)

2023-11-04 Thread Richard Dzenis via cfe-commits

RIscRIpt wrote:

Discussion initiated by @AaronBallman of one of important design decisions, 
which was forgotten (?):

> @AaronBallman:
> It's a good question as to whether we want to support that only when passing 
> `-fms-extensions` or not (it seems like a generally useful attribute); we 
> don't do the same for GNU attributes, but maybe we don't want to follow that 
> pattern? This will be the first attribute we add with the `msvc` vendor 
> namespace.

> @RIscRIpt:
> IMO, this attribute is a clearly Microsoft's extension, thus it should be 
> available only when `-fms-extensions` are enabled.

Note: in the current implementation I enable `[[msvc::constexpr]]` only under 
`-fms-compatibility -fms-compatibility-version=19.33`, (MSVC 19.33), where this 
attribute has first appeared.

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


[clang] [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute (PR #71300)

2023-11-04 Thread Richard Dzenis via cfe-commits

https://github.com/RIscRIpt edited 
https://github.com/llvm/llvm-project/pull/71300
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-cl] Add support for [[msvc::constexpr]] C++11 attribute (PR #71300)

2023-11-04 Thread Richard Dzenis via cfe-commits


@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 
-std=c++20 -verify %s
+// expected-no-diagnostics
+
+[[msvc::constexpr]] int log2(int x) { [[msvc::constexpr]] return x > 1 ? 1 + 
log2(x / 2) : 0; }
+constexpr bool test_log2() { [[msvc::constexpr]] return log2(32) == 5; }
+static_assert(test_log2());
+
+[[msvc::constexpr]] int get_value(int x)
+{
+  switch (x)
+  {
+case 42: return 1337;
+default:
+ if (x < 0) [[msvc::constexpr]] return log2(-x);
+ else return x;
+  }
+}
+
+constexpr bool test_complex_expr() {
+  [[msvc::constexpr]] return get_value(get_value(42) - 1337 + get_value(-32) - 
5 + (get_value(1) ? get_value(0) : get_value(2))) == get_value(0);
+}
+static_assert(test_complex_expr());
+
+constexpr bool get_constexpr_true() { return true; }
+[[msvc::constexpr]] bool get_msconstexpr_true() { return get_constexpr_true(); 
}
+constexpr bool test_get_msconstexpr_true() { [[msvc::constexpr]] return 
get_msconstexpr_true(); }
+static_assert(test_get_msconstexpr_true());
+
+/*
+// TODO: Add support for [[msvc::constexpr]] constructor

RIscRIpt wrote:

Note: this is a long-term TODO, which is quite difficult to implement with 
reasonably small changes.

Please let me know, how you typically deal with such cases.

---

Redacted comment from https://reviews.llvm.org/D134475#4288759:

Regarding on absolute matching MSVC implementation, I am not sure we will be 
able to achieve it with reasonable changes. I am skeptical, because I 
discovered the following test case: (which you see in the code).

It's a valid code for MSVC; nothing special https://godbolt.org/z/znnaonEhM
However supporting this code seems to be difficult in Clang:

`S2` fails checks of "literal type" in this callstack:
1. 
[clang::CXXRecordDecl::isLiteral](https://github.com/llvm/llvm-project/blob/d27897ade53ab6f983e442f24880260eed26238a/clang/include/clang/AST/DeclCXX.h#L1425-L1451)
2. 
[clang::Type::isLiteralType](https://github.com/llvm/llvm-project/blob/d27897ade53ab6f983e442f24880260eed26238a/clang/lib/AST/Type.cpp#L2795)
3. 
[CheckLiteralType](https://github.com/llvm/llvm-project/blob/d27897ade53ab6f983e442f24880260eed26238a/clang/lib/AST/ExprConstant.cpp#L2392-L2397)

We have information about `CanEvalMSConstexpr` only in `CheckLiteralType`. So, 
currently, I don't see how we can reasonably check whether `S2` is a valid 
literal type in context of `[[msvc::constexpr]]`. Two obvious ugly solutions 
are:
1. Copy all checks from `clang::CXXRecordDecl::isLiteral` to `CheckLiteralType` 
- two places shall be maintained.
2. Propagate `CanEvalMSConstexpr` down to `clang::CXXRecordDecl::isLiteral`. We 
could add bool args for both `clang::CXXRecordDecl::isLiteral` and 
`clang::Type::isLiteralType`. But I don't think it's reasonable for supporting 
rare vendor-specific attribute. Or is it?

I'll try to dive into this problem again, when I start addressing another round 
of review comments.

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


[clang] 9e90027 - [CGException] Remove no-op ptr-to-ptr bitcasts (NFC)

2023-11-04 Thread Youngsuk Kim via cfe-commits

Author: Youngsuk Kim
Date: 2023-11-04T19:17:21-05:00
New Revision: 9e90027d618687f3d744e21ad3eda5735a167503

URL: 
https://github.com/llvm/llvm-project/commit/9e90027d618687f3d744e21ad3eda5735a167503
DIFF: 
https://github.com/llvm/llvm-project/commit/9e90027d618687f3d744e21ad3eda5735a167503.diff

LOG: [CGException] Remove no-op ptr-to-ptr bitcasts (NFC)

Opaque ptr cleanup effort (NFC).

Added: 


Modified: 
clang/lib/CodeGen/CGException.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CGException.cpp 
b/clang/lib/CodeGen/CGException.cpp
index 87594f71b26ec53..4a54b2040154dad 100644
--- a/clang/lib/CodeGen/CGException.cpp
+++ b/clang/lib/CodeGen/CGException.cpp
@@ -263,12 +263,7 @@ static llvm::FunctionCallee getPersonalityFn(CodeGenModule 
&CGM,
 static llvm::Constant *getOpaquePersonalityFn(CodeGenModule &CGM,
 const EHPersonality &Personality) {
   llvm::FunctionCallee Fn = getPersonalityFn(CGM, Personality);
-  llvm::PointerType* Int8PtrTy = llvm::PointerType::get(
-  llvm::Type::getInt8Ty(CGM.getLLVMContext()),
-  CGM.getDataLayout().getProgramAddressSpace());
-
-  return llvm::ConstantExpr::getBitCast(cast(Fn.getCallee()),
-Int8PtrTy);
+  return cast(Fn.getCallee());
 }
 
 /// Check whether a landingpad instruction only uses C++ features.
@@ -1838,13 +1833,11 @@ Address 
CodeGenFunction::recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF,
 auto InsertPair = ParentCGF.EscapedLocals.insert(
 std::make_pair(ParentAlloca, ParentCGF.EscapedLocals.size()));
 int FrameEscapeIdx = InsertPair.first->second;
-// call i8* @llvm.localrecover(i8* bitcast(@parentFn), i8* %fp, i32 N)
+// call ptr @llvm.localrecover(ptr @parentFn, ptr %fp, i32 N)
 llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration(
 &CGM.getModule(), llvm::Intrinsic::localrecover);
-llvm::Constant *ParentI8Fn =
-llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
 RecoverCall = Builder.CreateCall(
-FrameRecoverFn, {ParentI8Fn, ParentFP,
+FrameRecoverFn, {ParentCGF.CurFn, ParentFP,
  llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)});
 
   } else {
@@ -1907,9 +1900,7 @@ void CodeGenFunction::EmitCapturedLocals(CodeGenFunction 
&ParentCGF,
 // since finally funclets recover the parent FP for us.
 llvm::Function *RecoverFPIntrin =
 CGM.getIntrinsic(llvm::Intrinsic::eh_recoverfp);
-llvm::Constant *ParentI8Fn =
-llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
-ParentFP = Builder.CreateCall(RecoverFPIntrin, {ParentI8Fn, EntryFP});
+ParentFP = Builder.CreateCall(RecoverFPIntrin, {ParentCGF.CurFn, EntryFP});
 
 // if the parent is a _finally, the passed-in ParentFP is the FP
 // of parent _finally, not Establisher's FP (FP of outermost function).
@@ -1937,19 +1928,15 @@ void 
CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
   int FrameEscapeIdx = InsertPair.first->second;
 
   // an example of a filter's prolog::
-  // %0 = call i8* @llvm.eh.recoverfp(bitcast(@"?fin$0@0@main@@"),..)
-  // %1 = call i8* @llvm.localrecover(bitcast(@"?fin$0@0@main@@"),..)
-  // %2 = bitcast i8* %1 to i8**
-  // %3 = load i8*, i8* *%2, align 8
-  //   ==> %3 is the frame-pointer of outermost host function
+  // %0 = call ptr @llvm.eh.recoverfp(@"?fin$0@0@main@@",..)
+  // %1 = call ptr @llvm.localrecover(@"?fin$0@0@main@@",..)
+  // %2 = load ptr, ptr %1, align 8
+  //   ==> %2 is the frame-pointer of outermost host function
   llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration(
   &CGM.getModule(), llvm::Intrinsic::localrecover);
-  llvm::Constant *ParentI8Fn =
-  llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
   ParentFP = Builder.CreateCall(
-  FrameRecoverFn, {ParentI8Fn, ParentFP,
+  FrameRecoverFn, {ParentCGF.CurFn, ParentFP,
llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)});
-  ParentFP = Builder.CreateBitCast(ParentFP, CGM.VoidPtrPtrTy);
   ParentFP = Builder.CreateLoad(
   Address(ParentFP, CGM.VoidPtrTy, getPointerAlign()));
 }
@@ -2206,9 +2193,7 @@ void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt 
&S) {
   // in place of the RTTI typeinfo global that C++ EH uses.
   llvm::Function *FilterFunc =
   HelperCGF.GenerateSEHFilterFunction(*this, *Except);
-  llvm::Constant *OpaqueFunc =
-  llvm::ConstantExpr::getBitCast(FilterFunc, Int8PtrTy);
-  CatchScope->setHandler(0, OpaqueFunc, createBasicBlock("__except.ret"));
+  CatchScope->setHandler(0, FilterFunc, createBasicBlock("__except.ret"));
 }
 
 void CodeGenFunction::ExitSEHTryStmt(const SEHTryStmt &S) {



___
cfe-commits mailing l

[clang] 730d313 - [CGObjC] Remove no-op ptr-to-ptr bitcasts (NFC)

2023-11-04 Thread Youngsuk Kim via cfe-commits

Author: Youngsuk Kim
Date: 2023-11-04T19:59:39-05:00
New Revision: 730d313041f73760aacc3fa3b12b5b5b0c92a12c

URL: 
https://github.com/llvm/llvm-project/commit/730d313041f73760aacc3fa3b12b5b5b0c92a12c
DIFF: 
https://github.com/llvm/llvm-project/commit/730d313041f73760aacc3fa3b12b5b5b0c92a12c.diff

LOG: [CGObjC] Remove no-op ptr-to-ptr bitcasts (NFC)

Opaque ptr cleanup effort (NFC)

Added: 


Modified: 
clang/lib/CodeGen/CGObjC.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp
index 5c967f97018f800..fff89c8939a55a4 100644
--- a/clang/lib/CodeGen/CGObjC.cpp
+++ b/clang/lib/CodeGen/CGObjC.cpp
@@ -52,8 +52,7 @@ llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const 
ObjCStringLiteral *E)
 {
   llvm::Constant *C =
   CGM.getObjCRuntime().GenerateConstantString(E->getString()).getPointer();
-  // FIXME: This bitcast should just be made an invariant on the Runtime.
-  return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType()));
+  return C;
 }
 
 /// EmitObjCBoxedExpr - This routine generates code to call
@@ -3710,7 +3709,7 @@ 
CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
 CharUnits Alignment = C.getTypeAlignInChars(Ty);
 llvm::Constant *Fn = getNonTrivialCStructMoveAssignmentOperator(
 CGM, Alignment, Alignment, Ty.isVolatileQualified(), Ty);
-return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
+return Fn;
   }
 
   if (!getLangOpts().CPlusPlus ||
@@ -3790,7 +3789,7 @@ 
CodeGenFunction::GenerateObjCAtomicSetterCopyHelperFunction(
   EmitStmt(TheCall);
 
   FinishFunction();
-  HelperFn = llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
+  HelperFn = Fn;
   CGM.setAtomicSetterHelperFnMap(Ty, HelperFn);
   return HelperFn;
 }
@@ -3808,7 +3807,7 @@ llvm::Constant 
*CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
 CharUnits Alignment = C.getTypeAlignInChars(Ty);
 llvm::Constant *Fn = getNonTrivialCStructCopyConstructor(
 CGM, Alignment, Alignment, Ty.isVolatileQualified(), Ty);
-return llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
+return Fn;
   }
 
   if (!getLangOpts().CPlusPlus ||
@@ -3909,7 +3908,7 @@ llvm::Constant 
*CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
   AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap));
 
   FinishFunction();
-  HelperFn = llvm::ConstantExpr::getBitCast(Fn, VoidPtrTy);
+  HelperFn = Fn;
   CGM.setAtomicGetterHelperFnMap(Ty, HelperFn);
   return HelperFn;
 }



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[libcxx] [clang-tools-extra] [llvm] [libc] [clang] [compiler-rt] [flang] [libc++] Implement ranges::iota (PR #68494)

2023-11-04 Thread James E T Smith via cfe-commits

jamesETsmith wrote:

@philnik777, I think this is ready to go. Let me know if there's anything else 
you'd like me to change

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


[clang] f0535c7 - [Driver] Check crt* when shared linking on OpenBSD

2023-11-04 Thread Brad Smith via cfe-commits

Author: Brad Smith
Date: 2023-11-04T21:11:21-04:00
New Revision: f0535c72bf574fe4c5a46925670591e79ce39959

URL: 
https://github.com/llvm/llvm-project/commit/f0535c72bf574fe4c5a46925670591e79ce39959
DIFF: 
https://github.com/llvm/llvm-project/commit/f0535c72bf574fe4c5a46925670591e79ce39959.diff

LOG: [Driver] Check crt* when shared linking on OpenBSD

Added: 


Modified: 
clang/test/Driver/openbsd.c

Removed: 




diff  --git a/clang/test/Driver/openbsd.c b/clang/test/Driver/openbsd.c
index f42da97110b5020..586c65f502a0d15 100644
--- a/clang/test/Driver/openbsd.c
+++ b/clang/test/Driver/openbsd.c
@@ -10,6 +10,12 @@
 // CHECK-PG: "-cc1" "-triple" "i686-pc-openbsd"
 // CHECK-PG: ld{{.*}}" "-e" "__start" "--eh-frame-hdr" "-dynamic-linker" 
"{{.*}}ld.so" "-nopie" "-o" "a.out" "{{.*}}gcrt0.o" "{{.*}}crtbegin.o" 
"{{.*}}.o" "-lcompiler_rt" "-lpthread_p" "-lc_p" "-lcompiler_rt" 
"{{.*}}crtend.o"
 
+// Check for variants of crt* when creating shared libs
+// RUN: %clang --target=i686-pc-openbsd -pthread -shared -### %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=CHECK-SHARED %s
+// CHECK-SHARED: "-cc1" "-triple" "i686-pc-openbsd"
+// CHECK-SHARED: ld{{.*}}" "--eh-frame-hdr" "-shared" "-o" "a.out" 
"{{.*}}crtbeginS.o" "{{.*}}.o" "-lcompiler_rt" "-lpthread" "-lcompiler_rt" 
"{{.*}}crtendS.o"
+
 // Check CPU type for i386
 // RUN: %clang --target=i386-unknown-openbsd -### -c %s 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-i386-CPU %s



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Driver][Solaris][NFC] A little bit of clean up (PR #69867)

2023-11-04 Thread Brad Smith via cfe-commits

brad0 wrote:

@MaskRay Ping.

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


[clang-tools-extra] [clang-tidy] Improve `container-data-pointer` check to use `c_str()` (PR #71304)

2023-11-04 Thread Eli Black via cfe-commits

https://github.com/neoncube2 created 
https://github.com/llvm/llvm-project/pull/71304

Improve clang-tidy's `container-data-pointer` check to use `c_str()`, when 
available.

Fixes #55026

This is my first Clang PR! :)

>From 08fa26a6d6f0fbc242ec803f537110694d645e93 Mon Sep 17 00:00:00 2001
From: Eli Black 
Date: Sun, 5 Nov 2023 13:43:20 +0800
Subject: [PATCH] [clang-tidy] Improve `container-data-pointer` check to use
 `c_str()` instead of `data()` when it's available.

Fixes #55026
---
 .../readability/ContainerDataPointerCheck.cpp | 26 ---
 clang-tools-extra/docs/ReleaseNotes.rst   |  4 +++
 .../readability/container-data-pointer.rst|  8 ++
 .../readability/container-data-pointer.cpp| 12 -
 4 files changed, 28 insertions(+), 22 deletions(-)

diff --git 
a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp
index a05e228520c9ef1..c20050063338281 100644
--- a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp
@@ -40,8 +40,10 @@ void ContainerDataPointerCheck::registerMatchers(MatchFinder 
*Finder) {
   cxxRecordDecl(
   unless(matchers::matchesAnyListedName(IgnoredContainers)),
   isSameOrDerivedFrom(
-  namedDecl(
-  has(cxxMethodDecl(isPublic(), hasName("data")).bind("data")))
+  namedDecl(anyOf(has(cxxMethodDecl(isPublic(), hasName("c_str"))
+  .bind("c_str")),
+  has(cxxMethodDecl(isPublic(), hasName("data"))
+  .bind("data"
   .bind("container")))
   .bind("record");
 
@@ -93,6 +95,8 @@ void ContainerDataPointerCheck::check(const 
MatchFinder::MatchResult &Result) {
   const auto *DCE = Result.Nodes.getNodeAs(DerefContainerExprName);
   const auto *ACE = Result.Nodes.getNodeAs(AddrOfContainerExprName);
 
+  const auto *CStrMethod = Result.Nodes.getNodeAs("c_str");
+
   if (!UO || !CE)
 return;
 
@@ -111,16 +115,18 @@ void ContainerDataPointerCheck::check(const 
MatchFinder::MatchResult &Result) {
MemberExpr>(CE))
 ReplacementText = "(" + ReplacementText + ")";
 
-  if (CE->getType()->isPointerType())
-ReplacementText += "->data()";
-  else
-ReplacementText += ".data()";
+  ReplacementText += CE->getType()->isPointerType() ? "->" : ".";
+  ReplacementText += CStrMethod != NULL ? "c_str()" : "data()";
+
+  std::string Description =
+  CStrMethod != NULL
+  ? "'c_str' should be used instead of taking the address of the 0-th "
+"element"
+  : "'data' should be used for accessing the data pointer instead of "
+"taking the address of the 0-th element";
 
   FixItHint Hint =
   FixItHint::CreateReplacement(UO->getSourceRange(), ReplacementText);
-  diag(UO->getBeginLoc(),
-   "'data' should be used for accessing the data pointer instead of taking 
"
-   "the address of the 0-th element")
-  << Hint;
+  diag(UO->getBeginLoc(), Description) << Hint;
 }
 } // namespace clang::tidy::readability
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index ecfb3aa9267f140..6477f2243d31e18 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -238,6 +238,10 @@ Changes in existing checks
   Casting to ``void`` no longer suppresses issues by default, control this
   behavior with the new `AllowCastToVoid` option.
 
+- Improved :doc:`container-data-pointer
+  ` check
+  to use ``c_str()`` when it's present on a container.
+
 - Improved :doc:`cppcoreguidelines-avoid-non-const-global-variables
   ` check
   to ignore ``static`` variables declared within the scope of
diff --git 
a/clang-tools-extra/docs/clang-tidy/checks/readability/container-data-pointer.rst
 
b/clang-tools-extra/docs/clang-tidy/checks/readability/container-data-pointer.rst
index 0d10829ed3c2f9b..8a6b48c58005bf2 100644
--- 
a/clang-tools-extra/docs/clang-tidy/checks/readability/container-data-pointer.rst
+++ 
b/clang-tools-extra/docs/clang-tidy/checks/readability/container-data-pointer.rst
@@ -3,13 +3,9 @@
 readability-container-data-pointer
 ==
 
-Finds cases where code could use ``data()`` rather than the address of the
-element at index 0 in a container. This pattern is commonly used to materialize
-a pointer to the backing data of a container. ``std::vector`` and
-``std::string`` provide a ``data()`` accessor to retrieve the data pointer 
which
-should be preferred.
+Finds cases where code references the address of the element at index 0 in a 
container and replaces them with calls to ``data()`` or ``c_str()``.
 
-This also ensures that in the case that the container is empty, the data 
pointer
+Using ``data()`` or ``c_str()`` is mor

[clang-tools-extra] [clang-tidy] Improve `container-data-pointer` check to use `c_str()` (PR #71304)

2023-11-04 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-tidy

Author: Eli Black (neoncube2)


Changes

Improve clang-tidy's `container-data-pointer` check to use `c_str()`, when 
available.

Fixes #55026

This is my first Clang PR! :)

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


4 Files Affected:

- (modified) 
clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp (+16-10) 
- (modified) clang-tools-extra/docs/ReleaseNotes.rst (+4) 
- (modified) 
clang-tools-extra/docs/clang-tidy/checks/readability/container-data-pointer.rst 
(+2-6) 
- (modified) 
clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
 (+6-6) 


``diff
diff --git 
a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp
index a05e228520c9ef1..c20050063338281 100644
--- a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp
@@ -40,8 +40,10 @@ void ContainerDataPointerCheck::registerMatchers(MatchFinder 
*Finder) {
   cxxRecordDecl(
   unless(matchers::matchesAnyListedName(IgnoredContainers)),
   isSameOrDerivedFrom(
-  namedDecl(
-  has(cxxMethodDecl(isPublic(), hasName("data")).bind("data")))
+  namedDecl(anyOf(has(cxxMethodDecl(isPublic(), hasName("c_str"))
+  .bind("c_str")),
+  has(cxxMethodDecl(isPublic(), hasName("data"))
+  .bind("data"
   .bind("container")))
   .bind("record");
 
@@ -93,6 +95,8 @@ void ContainerDataPointerCheck::check(const 
MatchFinder::MatchResult &Result) {
   const auto *DCE = Result.Nodes.getNodeAs(DerefContainerExprName);
   const auto *ACE = Result.Nodes.getNodeAs(AddrOfContainerExprName);
 
+  const auto *CStrMethod = Result.Nodes.getNodeAs("c_str");
+
   if (!UO || !CE)
 return;
 
@@ -111,16 +115,18 @@ void ContainerDataPointerCheck::check(const 
MatchFinder::MatchResult &Result) {
MemberExpr>(CE))
 ReplacementText = "(" + ReplacementText + ")";
 
-  if (CE->getType()->isPointerType())
-ReplacementText += "->data()";
-  else
-ReplacementText += ".data()";
+  ReplacementText += CE->getType()->isPointerType() ? "->" : ".";
+  ReplacementText += CStrMethod != NULL ? "c_str()" : "data()";
+
+  std::string Description =
+  CStrMethod != NULL
+  ? "'c_str' should be used instead of taking the address of the 0-th "
+"element"
+  : "'data' should be used for accessing the data pointer instead of "
+"taking the address of the 0-th element";
 
   FixItHint Hint =
   FixItHint::CreateReplacement(UO->getSourceRange(), ReplacementText);
-  diag(UO->getBeginLoc(),
-   "'data' should be used for accessing the data pointer instead of taking 
"
-   "the address of the 0-th element")
-  << Hint;
+  diag(UO->getBeginLoc(), Description) << Hint;
 }
 } // namespace clang::tidy::readability
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index ecfb3aa9267f140..6477f2243d31e18 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -238,6 +238,10 @@ Changes in existing checks
   Casting to ``void`` no longer suppresses issues by default, control this
   behavior with the new `AllowCastToVoid` option.
 
+- Improved :doc:`container-data-pointer
+  ` check
+  to use ``c_str()`` when it's present on a container.
+
 - Improved :doc:`cppcoreguidelines-avoid-non-const-global-variables
   ` check
   to ignore ``static`` variables declared within the scope of
diff --git 
a/clang-tools-extra/docs/clang-tidy/checks/readability/container-data-pointer.rst
 
b/clang-tools-extra/docs/clang-tidy/checks/readability/container-data-pointer.rst
index 0d10829ed3c2f9b..8a6b48c58005bf2 100644
--- 
a/clang-tools-extra/docs/clang-tidy/checks/readability/container-data-pointer.rst
+++ 
b/clang-tools-extra/docs/clang-tidy/checks/readability/container-data-pointer.rst
@@ -3,13 +3,9 @@
 readability-container-data-pointer
 ==
 
-Finds cases where code could use ``data()`` rather than the address of the
-element at index 0 in a container. This pattern is commonly used to materialize
-a pointer to the backing data of a container. ``std::vector`` and
-``std::string`` provide a ``data()`` accessor to retrieve the data pointer 
which
-should be preferred.
+Finds cases where code references the address of the element at index 0 in a 
container and replaces them with calls to ``data()`` or ``c_str()``.
 
-This also ensures that in the case that the container is empty, the data 
pointer
+Using ``data()`` or ``c_str()`` is more readable and ensures that if the 
container is empty, the data pointer
 access does not perform an

[clang] [Clang][CodeGen] Stoping emitting alignment assumes for `align_{up,down}` (PR #71295)

2023-11-04 Thread Alexander Richardson via cfe-commits

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

LGTM 

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


[clang-tools-extra] [clang-tidy] Improve `container-data-pointer` check to use `c_str()` (PR #71304)

2023-11-04 Thread Piotr Zegar via cfe-commits


@@ -3,13 +3,9 @@
 readability-container-data-pointer
 ==
 
-Finds cases where code could use ``data()`` rather than the address of the
-element at index 0 in a container. This pattern is commonly used to materialize
-a pointer to the backing data of a container. ``std::vector`` and
-``std::string`` provide a ``data()`` accessor to retrieve the data pointer 
which
-should be preferred.
+Finds cases where code references the address of the element at index 0 in a 
container and replaces them with calls to ``data()`` or ``c_str()``.

PiotrZSL wrote:

Wrap on 80 column,
And first sentence of documentation should be in sync with class description.

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


[clang-tools-extra] [clang-tidy] Improve `container-data-pointer` check to use `c_str()` (PR #71304)

2023-11-04 Thread Piotr Zegar via cfe-commits

https://github.com/PiotrZSL requested changes to this pull request.

It's not so easy, because if result of &[] is used as non-const, then using 
c_str will make code non-compilable. Some additional checks wuold be required, 
like checking if object is const, or checking if there is implicit cast to 
const pointer from an nonconst pointer, only then c_str could be used.

Make "f" function take non-const pointer, then you will see.
Also there can be an issue when for example, container have only-const version 
of some functions (c_str).

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


[clang] [clang] Change representation of CurLexerKind (PR #70381)

2023-11-04 Thread via cfe-commits

https://github.com/serge-sans-paille updated 
https://github.com/llvm/llvm-project/pull/70381

>From c815ac1403fac8f6bb147573d65ec9906158b9d6 Mon Sep 17 00:00:00 2001
From: serge-sans-paille 
Date: Thu, 26 Oct 2023 22:31:43 +0200
Subject: [PATCH 1/4] [clang] Change representation of CurLexerKind

Previous representation used an enumeration combined to a switch to
dispatch to the appropriate lexer.

Use function pointer so that the dispatching is just an indirect call,
which is actually better because lexing is a costly task compared to a
function call.

This also makes the code slightly cleaner, speedup on
compile time tracker are consistent and range form -0.05% to -0.20%
for NewPM-O0-g, see


https://llvm-compile-time-tracker.com/compare.php?from=f9906508bc4f05d3950e2219b4c56f6c078a61ef&to=608c85ec1283638db949d73e062bcc3355001ce4&stat=instructions:u

Considering just the preprocessing task, preprocessing the sqlite
amalgametion takes -0.6% instructions (according to valgrind
--tool=callgrind)
---
 clang/include/clang/Lex/Preprocessor.h| 46 +++-
 clang/lib/Lex/PPCaching.cpp   |  8 +--
 clang/lib/Lex/PPLexerChange.cpp   | 20 +++
 clang/lib/Lex/Preprocessor.cpp| 67 ++-
 clang/utils/ClangVisualizers/clang.natvis |  2 +-
 5 files changed, 62 insertions(+), 81 deletions(-)

diff --git a/clang/include/clang/Lex/Preprocessor.h 
b/clang/include/clang/Lex/Preprocessor.h
index 4a99447e757c6ac..82792c5ec48dae5 100644
--- a/clang/include/clang/Lex/Preprocessor.h
+++ b/clang/include/clang/Lex/Preprocessor.h
@@ -751,13 +751,8 @@ class Preprocessor {
   std::unique_ptr CurTokenLexer;
 
   /// The kind of lexer we're currently working with.
-  enum CurLexerKind {
-CLK_Lexer,
-CLK_TokenLexer,
-CLK_CachingLexer,
-CLK_DependencyDirectivesLexer,
-CLK_LexAfterModuleImport
-  } CurLexerKind = CLK_Lexer;
+  typedef bool (*LexerCallback)(Preprocessor &, Token &);
+  LexerCallback CurLexerCallback = &CLK_Lexer;
 
   /// If the current lexer is for a submodule that is being built, this
   /// is that submodule.
@@ -767,7 +762,7 @@ class Preprocessor {
   /// \#included, and macros currently being expanded from, not counting
   /// CurLexer/CurTokenLexer.
   struct IncludeStackInfo {
-enum CurLexerKind   CurLexerKind;
+LexerCallback CurLexerCallback;
 Module *TheSubmodule;
 std::unique_ptr  TheLexer;
 PreprocessorLexer  *ThePPLexer;
@@ -776,12 +771,12 @@ class Preprocessor {
 
 // The following constructors are completely useless copies of the default
 // versions, only needed to pacify MSVC.
-IncludeStackInfo(enum CurLexerKind CurLexerKind, Module *TheSubmodule,
+IncludeStackInfo(LexerCallback CurLexerCallback, Module *TheSubmodule,
  std::unique_ptr &&TheLexer,
  PreprocessorLexer *ThePPLexer,
  std::unique_ptr &&TheTokenLexer,
  ConstSearchDirIterator TheDirLookup)
-: CurLexerKind(std::move(CurLexerKind)),
+: CurLexerCallback(std::move(CurLexerCallback)),
   TheSubmodule(std::move(TheSubmodule)), TheLexer(std::move(TheLexer)),
   ThePPLexer(std::move(ThePPLexer)),
   TheTokenLexer(std::move(TheTokenLexer)),
@@ -1901,7 +1896,7 @@ class Preprocessor {
   /// Determine whether it's possible for a future call to Lex to produce an
   /// annotation token created by a previous call to EnterAnnotationToken.
   bool mightHavePendingAnnotationTokens() {
-return CurLexerKind != CLK_Lexer;
+return CurLexerCallback != CLK_Lexer;
   }
 
   /// Update the current token to represent the provided
@@ -1914,7 +1909,7 @@ class Preprocessor {
 
   /// Recompute the current lexer kind based on the CurLexer/
   /// CurTokenLexer pointers.
-  void recomputeCurLexerKind();
+  void recomputeCurLexerCallback();
 
   /// Returns true if incremental processing is enabled
   bool isIncrementalProcessingEnabled() const { return IncrementalProcessing; }
@@ -2430,8 +2425,9 @@ class Preprocessor {
   friend void TokenLexer::ExpandFunctionArguments();
 
   void PushIncludeMacroStack() {
-assert(CurLexerKind != CLK_CachingLexer && "cannot push a caching lexer");
-IncludeMacroStack.emplace_back(CurLexerKind, CurLexerSubmodule,
+assert(CurLexerCallback != CLK_CachingLexer &&
+   "cannot push a caching lexer");
+IncludeMacroStack.emplace_back(CurLexerCallback, CurLexerSubmodule,
std::move(CurLexer), CurPPLexer,
std::move(CurTokenLexer), CurDirLookup);
 CurPPLexer = nullptr;
@@ -2443,7 +2439,7 @@ class Preprocessor {
 CurTokenLexer = std::move(IncludeMacroStack.back().TheTokenLexer);
 CurDirLookup  = IncludeMacroStack.back().TheDirLookup;
 CurLexerSubmodule = IncludeMacroStack.back().TheSubmodule;
-CurLexerKind = IncludeMacroStack.back().CurLexerKind;
+