[clang] [CIR] Upstream CastOp and scalar conversions (PR #130690)

2025-03-11 Thread Morris Hafner via cfe-commits


@@ -78,6 +79,67 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return create(loc, val, dst);
   }
 
+  
//======//
+  // Cast/Conversion Operators
+  
//======//
+
+  mlir::Value createCast(mlir::Location loc, cir::CastKind kind,
+ mlir::Value src, mlir::Type newTy) {
+if (newTy == src.getType())
+  return src;
+return create(loc, newTy, kind, src);
+  }
+
+  mlir::Value createCast(cir::CastKind kind, mlir::Value src,
+ mlir::Type newTy) {
+if (newTy == src.getType())
+  return src;
+return createCast(src.getLoc(), kind, src, newTy);
+  }
+
+  mlir::Value createIntCast(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::integral, src, newTy);
+  }
+
+  mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::int_to_ptr, src, newTy);
+  }
+
+  mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::ptr_to_int, src, newTy);
+  }
+
+  mlir::Value createPtrToBoolCast(mlir::Value v) {
+return createCast(cir::CastKind::ptr_to_bool, v, getBoolTy());
+  }
+
+  mlir::Value createBoolToInt(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::bool_to_int, src, newTy);
+  }
+
+  mlir::Value createBitcast(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::bitcast, src, newTy);
+  }
+
+  mlir::Value createBitcast(mlir::Location loc, mlir::Value src,
+mlir::Type newTy) {
+return createCast(loc, cir::CastKind::bitcast, src, newTy);
+  }
+
+  mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy) {

mmha wrote:

This is a utility function used in a couple of other `create` or `emit` 
functions in the incubator, for example to cast the pointer type in 
`createLoad` and `createStore` in the incubator. 

Looking at it again this function isn't used in this patch and I copied this by 
accident. I'll remove it for now.

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


[clang] [CIR] Upstream global variable linkage types (PR #129072)

2025-02-27 Thread Morris Hafner via cfe-commits

https://github.com/mmha created https://github.com/llvm/llvm-project/pull/129072

This change implements variable linkage types in ClangIR except for common 
linkage which requires Comdat support.

>From b9453787a96008cfe347c2ae2d027d5de12871ae Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Thu, 27 Feb 2025 16:49:57 +0100
Subject: [PATCH] [CIR] Upstream global variable linkage types

This change implements variable linkage types in ClangIR except for common 
linkage which requires Comdat support.
---
 .../include/clang/CIR/Dialect/IR/CIRDialect.h |   2 +
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  83 ++-
 .../clang/CIR/Dialect/IR/CIROpsEnums.h| 119 +++
 .../clang/CIR/Dialect/IR/CMakeLists.txt   |   4 +-
 .../clang/CIR/Interfaces/CIROpInterfaces.h|  29 +++
 .../clang/CIR/Interfaces/CIROpInterfaces.td   |  63 ++
 .../clang/CIR/Interfaces/CMakeLists.txt   |   9 +
 clang/include/clang/CIR/MissingFeatures.h |   4 +
 clang/lib/CIR/CodeGen/CIRGenModule.cpp| 202 +-
 clang/lib/CIR/CodeGen/CIRGenModule.h  |  12 ++
 clang/lib/CIR/CodeGen/CMakeLists.txt  |   1 +
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp   |   8 +-
 clang/lib/CIR/Dialect/IR/CMakeLists.txt   |   3 +-
 clang/lib/CIR/FrontendAction/CMakeLists.txt   |   4 +
 clang/lib/CIR/Interfaces/CIROpInterfaces.cpp  |  22 ++
 clang/lib/CIR/Interfaces/CMakeLists.txt   |   4 +-
 .../CIR/Lowering/DirectToLLVM/CMakeLists.txt  |   5 +
 clang/test/CIR/global-var-simple.cpp  |  64 +++---
 clang/test/CIR/global_var_linkage.cpp |  11 +
 19 files changed, 608 insertions(+), 41 deletions(-)
 create mode 100644 clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h
 create mode 100644 clang/include/clang/CIR/Interfaces/CIROpInterfaces.h
 create mode 100644 clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
 create mode 100644 clang/lib/CIR/Interfaces/CIROpInterfaces.cpp
 create mode 100644 clang/test/CIR/global_var_linkage.cpp

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h 
b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
index 683176b139ca4..0684cf5034f5d 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -28,6 +28,8 @@
 
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIROpsDialect.h.inc"
+#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
+#include "clang/CIR/Interfaces/CIROpInterfaces.h"
 
 // TableGen'erated files for MLIR dialects require that a macro be defined when
 // they are included.  GET_OP_CLASSES tells the file to define the classes for
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index f9ce38588e436..7c5d339130ec5 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -18,6 +18,8 @@ include "clang/CIR/Dialect/IR/CIRDialect.td"
 include "clang/CIR/Dialect/IR/CIRTypes.td"
 include "clang/CIR/Dialect/IR/CIRAttrs.td"
 
+include "clang/CIR/Interfaces/CIROpInterfaces.td"
+
 include "mlir/IR/BuiltinAttributeInterfaces.td"
 include "mlir/IR/EnumAttr.td"
 include "mlir/IR/SymbolInterfaces.td"
@@ -278,6 +280,59 @@ def ScopeOp : CIR_Op<"scope", [
 // GlobalOp
 
//===--===//
 
+// Linkage types. This is currently a replay of llvm/IR/GlobalValue.h, this is
+// currently handy as part of forwarding appropriate linkage types for LLVM
+// lowering, specially useful for C++ support.
+
+// Externally visible function
+def Global_ExternalLinkage :
+  I32EnumAttrCase<"ExternalLinkage", 0, "external">;
+// Available for inspection, not emission.
+def Global_AvailableExternallyLinkage :
+  I32EnumAttrCase<"AvailableExternallyLinkage", 1, "available_externally">;
+// Keep one copy of function when linking (inline)
+def Global_LinkOnceAnyLinkage :
+  I32EnumAttrCase<"LinkOnceAnyLinkage", 2, "linkonce">;
+// Same, but only replaced by something equivalent.
+def Global_LinkOnceODRLinkage :
+  I32EnumAttrCase<"LinkOnceODRLinkage", 3, "linkonce_odr">;
+// Keep one copy of named function when linking (weak)
+def Global_WeakAnyLinkage :
+  I32EnumAttrCase<"WeakAnyLinkage", 4, "weak">;
+// Same, but only replaced by something equivalent.
+def Global_WeakODRLinkage :
+  I32EnumAttrCase<"WeakODRLinkage", 5, "weak_odr">;
+// TODO: should we add something like appending linkage too?
+// Special purpose, only applies to global arrays
+// def Global_AppendingLinkage :
+//   I32EnumAttrCase<"AppendingLinkage", 6, "appending">;
+// Rename collisions when linking (static functions).
+def Global_InternalLinkage :
+  I32EnumAttrCase<"InternalLinkage", 7, "internal">;
+// Like Internal, but omit from symbol table, prefix it with
+// "cir_" to prevent clash with MLIR's symbol "private".
+def Global_PrivateLinkage :
+  I32EnumAttrCase<"PrivateLinkage", 8, "cir_private">;
+// ExternalWeak linkage description.

[clang] [CIR] Upstream CastOp and scalar conversions (PR #130690)

2025-03-11 Thread Morris Hafner via cfe-commits


@@ -78,6 +79,67 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return create(loc, val, dst);
   }
 
+  
//======//
+  // Cast/Conversion Operators
+  
//======//
+
+  mlir::Value createCast(mlir::Location loc, cir::CastKind kind,
+ mlir::Value src, mlir::Type newTy) {
+if (newTy == src.getType())
+  return src;
+return create(loc, newTy, kind, src);
+  }
+
+  mlir::Value createCast(cir::CastKind kind, mlir::Value src,
+ mlir::Type newTy) {
+if (newTy == src.getType())
+  return src;
+return createCast(src.getLoc(), kind, src, newTy);
+  }
+
+  mlir::Value createIntCast(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::integral, src, newTy);
+  }
+
+  mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::int_to_ptr, src, newTy);
+  }
+
+  mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::ptr_to_int, src, newTy);
+  }
+
+  mlir::Value createPtrToBoolCast(mlir::Value v) {
+return createCast(cir::CastKind::ptr_to_bool, v, getBoolTy());
+  }
+
+  mlir::Value createBoolToInt(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::bool_to_int, src, newTy);
+  }
+
+  mlir::Value createBitcast(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::bitcast, src, newTy);
+  }
+
+  mlir::Value createBitcast(mlir::Location loc, mlir::Value src,
+mlir::Type newTy) {
+return createCast(loc, cir::CastKind::bitcast, src, newTy);
+  }
+
+  mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy) {
+assert(mlir::isa(src.getType()) && "expected ptr src");
+return createBitcast(src, getPointerTo(newPointeeTy));
+  }
+
+  mlir::Value createAddrSpaceCast(mlir::Location loc, mlir::Value src,

mmha wrote:

Correct. I removed these two functions again for now.

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


[clang] [CIR] Don't generate ClangIR after an unrecoverable error occured (PR #130971)

2025-03-12 Thread Morris Hafner via cfe-commits


@@ -43,6 +43,8 @@ void CIRGenerator::Initialize(ASTContext &astContext) {
 mlir::ModuleOp CIRGenerator::getModule() const { return cgm->getModule(); }
 
 bool CIRGenerator::HandleTopLevelDecl(DeclGroupRef group) {
+  if (diags.hasUnrecoverableErrorOccurred())
+return true;

mmha wrote:

I chose to let parsing continue here mostly because this is what's being done 
in other ASTConsumers, but is there a reason to do so?

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


[clang] [CIR] Don't generate ClangIR after an unrecoverable error occured (PR #130971)

2025-03-12 Thread Morris Hafner via cfe-commits

https://github.com/mmha created https://github.com/llvm/llvm-project/pull/130971

None

>From 92066054a6a14f2e16b7f2256bf730762ab5d5d6 Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Wed, 12 Mar 2025 07:28:09 -0700
Subject: [PATCH] [CIR] Don't generate ClangIR after an unrecoverable error
 occured

---
 clang/lib/CIR/CodeGen/CIRGenerator.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clang/lib/CIR/CodeGen/CIRGenerator.cpp 
b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
index 91070eda7d45a..6fa31ab707139 100644
--- a/clang/lib/CIR/CodeGen/CIRGenerator.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenerator.cpp
@@ -43,6 +43,8 @@ void CIRGenerator::Initialize(ASTContext &astContext) {
 mlir::ModuleOp CIRGenerator::getModule() const { return cgm->getModule(); }
 
 bool CIRGenerator::HandleTopLevelDecl(DeclGroupRef group) {
+  if (diags.hasUnrecoverableErrorOccurred())
+return true;
 
   for (Decl *decl : group)
 cgm->emitTopLevelDecl(decl);

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


[clang] [CIR] Add cir-translate and cir-lsp-server tools (PR #131181)

2025-03-13 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/131181

>From 5847660fc62645844e009f6b67a0c238b66f99ae Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Thu, 13 Mar 2025 10:57:12 -0700
Subject: [PATCH 1/3] [CIR] Add cir-translate tool

---
 clang/test/CIR/Tools/cir-translate-triple.cir |  11 ++
 .../CIR/Tools/has-triple-and-data-layout.cir  |  24 +++
 .../CIR/Tools/has-triple-no-data-layout.cir   |  23 +++
 .../CIR/Tools/invalid-translate-triple.cir|   8 +
 .../CIR/Tools/no-triple-has-data-layout.cir   |  18 ++
 .../CIR/Tools/no-triple-no-data-layout.cir|  16 ++
 clang/test/CIR/Tools/warn-default-triple.cir  |   8 +
 clang/tools/CMakeLists.txt|   1 +
 clang/tools/cir-translate/CMakeLists.txt  |  35 
 clang/tools/cir-translate/cir-translate.cpp   | 166 ++
 10 files changed, 310 insertions(+)
 create mode 100644 clang/test/CIR/Tools/cir-translate-triple.cir
 create mode 100644 clang/test/CIR/Tools/has-triple-and-data-layout.cir
 create mode 100644 clang/test/CIR/Tools/has-triple-no-data-layout.cir
 create mode 100644 clang/test/CIR/Tools/invalid-translate-triple.cir
 create mode 100644 clang/test/CIR/Tools/no-triple-has-data-layout.cir
 create mode 100644 clang/test/CIR/Tools/no-triple-no-data-layout.cir
 create mode 100644 clang/test/CIR/Tools/warn-default-triple.cir
 create mode 100644 clang/tools/cir-translate/CMakeLists.txt
 create mode 100644 clang/tools/cir-translate/cir-translate.cpp

diff --git a/clang/test/CIR/Tools/cir-translate-triple.cir 
b/clang/test/CIR/Tools/cir-translate-triple.cir
new file mode 100644
index 0..fa653ef3de25f
--- /dev/null
+++ b/clang/test/CIR/Tools/cir-translate-triple.cir
@@ -0,0 +1,11 @@
+// RUN: cir-translate --cir-to-llvmir --target x86_64-unknown-linux-gnu 
--disable-cc-lowering %s -o %t.ll
+// RUN: FileCheck %s -input-file %t.ll -check-prefix=LLVM
+
+module {
+  cir.func @foo() {
+cir.return
+  }
+}
+
+// LLVM-DAG: target triple = "x86_64-unknown-linux-gnu"
+// LLVM-DAG: target datalayout = "{{.*}}"
diff --git a/clang/test/CIR/Tools/has-triple-and-data-layout.cir 
b/clang/test/CIR/Tools/has-triple-and-data-layout.cir
new file mode 100644
index 0..81da113f1d648
--- /dev/null
+++ b/clang/test/CIR/Tools/has-triple-and-data-layout.cir
@@ -0,0 +1,24 @@
+// RUN: cir-translate --cir-to-llvmir --target x86_64-unknown-linux-gnu 
--disable-cc-lowering %s -o %t.x86.ll
+// RUN: FileCheck %s -input-file %t.x86.ll -check-prefix=X86
+// RUN: cir-translate --cir-to-llvmir --target spirv64-unknown-unknown 
--disable-cc-lowering %s -o %t.spirv64.ll
+// RUN: FileCheck %s -input-file %t.spirv64.ll -check-prefix=SPIRV64
+// RUN: cir-translate --cir-to-llvmir --disable-cc-lowering %s -o %t.default.ll
+// RUN: FileCheck %s -input-file %t.default.ll -check-prefix=DEFAULT
+
+module attributes {
+  cir.triple = "spirv64-unknown-unknown",
+  dlti.dl_spec = #dlti.dl_spec<"dlti.global_memory_space" = 7 : ui64>
+} {
+  cir.func @foo() {
+cir.return
+  }
+}
+
+// X86-NOT: target datalayout = "G7"
+// X86-DAG: target triple = "x86_64-unknown-linux-gnu"
+
+// SPIRV64-NOT: target datalayout = "G7"
+// SPIRV64-DAG: target triple = "spirv64-unknown-unknown"
+
+// DEFAULT-DAG: target datalayout = "G7"
+// DEFAULT-DAG: target triple = "spirv64-unknown-unknown"
diff --git a/clang/test/CIR/Tools/has-triple-no-data-layout.cir 
b/clang/test/CIR/Tools/has-triple-no-data-layout.cir
new file mode 100644
index 0..34c543362bed1
--- /dev/null
+++ b/clang/test/CIR/Tools/has-triple-no-data-layout.cir
@@ -0,0 +1,23 @@
+// RUN: cir-translate --cir-to-llvmir --target x86_64-unknown-linux-gnu 
--disable-cc-lowering %s -o %t.x86.ll
+// RUN: FileCheck %s -input-file %t.x86.ll -check-prefix=X86
+// RUN: cir-translate --cir-to-llvmir --target spirv64-unknown-unknown 
--disable-cc-lowering %s -o %t.spirv64.ll
+// RUN: FileCheck %s -input-file %t.spirv64.ll -check-prefix=SPIRV64
+// RUN: cir-translate --cir-to-llvmir --disable-cc-lowering %s -o %t.default.ll
+// RUN: FileCheck %s -input-file %t.default.ll -check-prefix=DEFAULT
+
+module attributes {
+  cir.triple = "spirv64-unknown-unknown"
+} {
+  cir.func @foo() {
+cir.return
+  }
+}
+
+// X86-DAG: target triple = "x86_64-unknown-linux-gnu"
+// X86-DAG: target datalayout = "{{.*}}"
+
+// SPIRV64-DAG: target triple = "spirv64-unknown-unknown"
+// SPIRV64-DAG: target datalayout = "{{.*}}"
+
+// DEFAULT-DAG: target triple = "spirv64-unknown-unknown"
+// DEFAULT-DAG: target datalayout = "{{.*}}"
diff --git a/clang/test/CIR/Tools/invalid-translate-triple.cir 
b/clang/test/CIR/Tools/invalid-translate-triple.cir
new file mode 100644
index 0..07bd766a37875
--- /dev/null
+++ b/clang/test/CIR/Tools/invalid-translate-triple.cir
@@ -0,0 +1,8 @@
+// RUN: cir-translate -verify-diagnostics --cir-to-llvmir --target foobar 
--disable-cc-lowering %s 2>&1
+
+// expected-error@below {{invalid target triple 'foobar'}}
+module {
+  cir.func @foo() {
+cir.r

[clang] [CIR] Add cir-translate and cir-lsp-server tools (PR #131181)

2025-03-13 Thread Morris Hafner via cfe-commits

https://github.com/mmha created https://github.com/llvm/llvm-project/pull/131181

@erichkeane @andykaylor @dkolsen-pgi 

>From 5847660fc62645844e009f6b67a0c238b66f99ae Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Thu, 13 Mar 2025 10:57:12 -0700
Subject: [PATCH 1/2] [CIR] Add cir-translate tool

---
 clang/test/CIR/Tools/cir-translate-triple.cir |  11 ++
 .../CIR/Tools/has-triple-and-data-layout.cir  |  24 +++
 .../CIR/Tools/has-triple-no-data-layout.cir   |  23 +++
 .../CIR/Tools/invalid-translate-triple.cir|   8 +
 .../CIR/Tools/no-triple-has-data-layout.cir   |  18 ++
 .../CIR/Tools/no-triple-no-data-layout.cir|  16 ++
 clang/test/CIR/Tools/warn-default-triple.cir  |   8 +
 clang/tools/CMakeLists.txt|   1 +
 clang/tools/cir-translate/CMakeLists.txt  |  35 
 clang/tools/cir-translate/cir-translate.cpp   | 166 ++
 10 files changed, 310 insertions(+)
 create mode 100644 clang/test/CIR/Tools/cir-translate-triple.cir
 create mode 100644 clang/test/CIR/Tools/has-triple-and-data-layout.cir
 create mode 100644 clang/test/CIR/Tools/has-triple-no-data-layout.cir
 create mode 100644 clang/test/CIR/Tools/invalid-translate-triple.cir
 create mode 100644 clang/test/CIR/Tools/no-triple-has-data-layout.cir
 create mode 100644 clang/test/CIR/Tools/no-triple-no-data-layout.cir
 create mode 100644 clang/test/CIR/Tools/warn-default-triple.cir
 create mode 100644 clang/tools/cir-translate/CMakeLists.txt
 create mode 100644 clang/tools/cir-translate/cir-translate.cpp

diff --git a/clang/test/CIR/Tools/cir-translate-triple.cir 
b/clang/test/CIR/Tools/cir-translate-triple.cir
new file mode 100644
index 0..fa653ef3de25f
--- /dev/null
+++ b/clang/test/CIR/Tools/cir-translate-triple.cir
@@ -0,0 +1,11 @@
+// RUN: cir-translate --cir-to-llvmir --target x86_64-unknown-linux-gnu 
--disable-cc-lowering %s -o %t.ll
+// RUN: FileCheck %s -input-file %t.ll -check-prefix=LLVM
+
+module {
+  cir.func @foo() {
+cir.return
+  }
+}
+
+// LLVM-DAG: target triple = "x86_64-unknown-linux-gnu"
+// LLVM-DAG: target datalayout = "{{.*}}"
diff --git a/clang/test/CIR/Tools/has-triple-and-data-layout.cir 
b/clang/test/CIR/Tools/has-triple-and-data-layout.cir
new file mode 100644
index 0..81da113f1d648
--- /dev/null
+++ b/clang/test/CIR/Tools/has-triple-and-data-layout.cir
@@ -0,0 +1,24 @@
+// RUN: cir-translate --cir-to-llvmir --target x86_64-unknown-linux-gnu 
--disable-cc-lowering %s -o %t.x86.ll
+// RUN: FileCheck %s -input-file %t.x86.ll -check-prefix=X86
+// RUN: cir-translate --cir-to-llvmir --target spirv64-unknown-unknown 
--disable-cc-lowering %s -o %t.spirv64.ll
+// RUN: FileCheck %s -input-file %t.spirv64.ll -check-prefix=SPIRV64
+// RUN: cir-translate --cir-to-llvmir --disable-cc-lowering %s -o %t.default.ll
+// RUN: FileCheck %s -input-file %t.default.ll -check-prefix=DEFAULT
+
+module attributes {
+  cir.triple = "spirv64-unknown-unknown",
+  dlti.dl_spec = #dlti.dl_spec<"dlti.global_memory_space" = 7 : ui64>
+} {
+  cir.func @foo() {
+cir.return
+  }
+}
+
+// X86-NOT: target datalayout = "G7"
+// X86-DAG: target triple = "x86_64-unknown-linux-gnu"
+
+// SPIRV64-NOT: target datalayout = "G7"
+// SPIRV64-DAG: target triple = "spirv64-unknown-unknown"
+
+// DEFAULT-DAG: target datalayout = "G7"
+// DEFAULT-DAG: target triple = "spirv64-unknown-unknown"
diff --git a/clang/test/CIR/Tools/has-triple-no-data-layout.cir 
b/clang/test/CIR/Tools/has-triple-no-data-layout.cir
new file mode 100644
index 0..34c543362bed1
--- /dev/null
+++ b/clang/test/CIR/Tools/has-triple-no-data-layout.cir
@@ -0,0 +1,23 @@
+// RUN: cir-translate --cir-to-llvmir --target x86_64-unknown-linux-gnu 
--disable-cc-lowering %s -o %t.x86.ll
+// RUN: FileCheck %s -input-file %t.x86.ll -check-prefix=X86
+// RUN: cir-translate --cir-to-llvmir --target spirv64-unknown-unknown 
--disable-cc-lowering %s -o %t.spirv64.ll
+// RUN: FileCheck %s -input-file %t.spirv64.ll -check-prefix=SPIRV64
+// RUN: cir-translate --cir-to-llvmir --disable-cc-lowering %s -o %t.default.ll
+// RUN: FileCheck %s -input-file %t.default.ll -check-prefix=DEFAULT
+
+module attributes {
+  cir.triple = "spirv64-unknown-unknown"
+} {
+  cir.func @foo() {
+cir.return
+  }
+}
+
+// X86-DAG: target triple = "x86_64-unknown-linux-gnu"
+// X86-DAG: target datalayout = "{{.*}}"
+
+// SPIRV64-DAG: target triple = "spirv64-unknown-unknown"
+// SPIRV64-DAG: target datalayout = "{{.*}}"
+
+// DEFAULT-DAG: target triple = "spirv64-unknown-unknown"
+// DEFAULT-DAG: target datalayout = "{{.*}}"
diff --git a/clang/test/CIR/Tools/invalid-translate-triple.cir 
b/clang/test/CIR/Tools/invalid-translate-triple.cir
new file mode 100644
index 0..07bd766a37875
--- /dev/null
+++ b/clang/test/CIR/Tools/invalid-translate-triple.cir
@@ -0,0 +1,8 @@
+// RUN: cir-translate -verify-diagnostics --cir-to-llvmir --target foobar 
--disable-cc-lowering %s 2>&1
+
+// expected-error@below {{invalid target triple 'foobar'}}
+m

[clang] [CIR] Add cir-translate and cir-lsp-server tools (PR #131181)

2025-03-13 Thread Morris Hafner via cfe-commits


@@ -0,0 +1,166 @@
+//===--===//
+//
+// 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
+//
+//===--===//
+//
+// Converts CIR directly to LLVM IR, similar to mlir-translate or LLVM llc.
+//
+//===--===//
+
+#include "mlir/Dialect/DLTI/DLTI.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/MLIRContext.h"
+#include "mlir/InitAllTranslations.h"
+#include "mlir/Support/LogicalResult.h"
+#include "mlir/Target/LLVMIR/Dialect/All.h"
+#include "mlir/Target/LLVMIR/Import.h"
+#include "mlir/Tools/mlir-translate/MlirTranslateMain.h"
+#include "mlir/Tools/mlir-translate/Translation.h"
+
+#include "llvm/IR/Module.h"
+#include "llvm/TargetParser/Host.h"
+
+#include "clang/Basic/TargetInfo.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/Passes.h"
+#include "clang/CIR/LowerToLLVM.h"
+#include "clang/CIR/MissingFeatures.h"
+
+namespace cir {
+namespace direct {
+extern void registerCIRDialectTranslation(mlir::DialectRegistry ®istry);
+} // namespace direct
+
+namespace {
+
+/// The goal of this option is to ensure that the triple and data layout specs
+/// are always available in the ClangIR module. With this requirement met, the
+/// behavior of this option is designed to be as intuitive as possible, as 
shown
+/// in the table below:
+///
+/// +++-+-+---+
+/// | Option | Triple | Data Layout | Behavior Triple | Behavior Data Layout  |
+/// +++=+=+===+
+/// | T  | T  | T   | Overwrite   | Derive from triple|
+/// | T  | T  | F   | Overwrite   | Derive from triple|
+/// | T  | F  | T   | Overwrite   | Derive from triple|
+/// | T  | F  | F   | Overwrite   | Derive from triple|
+/// | F  | T  | T   | |   |
+/// | F  | T  | F   | | Derive from triple|
+/// | F  | F  | T   | Set default | Derive from triple|
+/// | F  | F  | F   | Set default | Derive from triple|
+/// +++-+-+---+
+llvm::cl::opt
+targetTripleOption("target",
+   llvm::cl::desc("Specify a default target triple when "
+  "it's not available in the module"),
+   llvm::cl::init(""));
+
+std::string prepareCIRModuleTriple(mlir::ModuleOp mod) {
+  std::string triple = targetTripleOption;
+
+  // Treat "" as the default target machine.
+  if (triple.empty()) {
+triple = llvm::sys::getDefaultTargetTriple();

mmha wrote:

This differs from the incubator which defaults to `"x86_64-unknown-linux-gnu"`.

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


[clang] [CIR] Upstream CastOp and scalar conversions (PR #130690)

2025-03-12 Thread Morris Hafner via cfe-commits


@@ -121,29 +375,174 @@ mlir::Value CIRGenFunction::emitScalarExpr(const Expr 
*e) {
   return ScalarExprEmitter(*this, builder).Visit(const_cast(e));
 }
 
+[[maybe_unused]] static bool MustVisitNullValue(const Expr *e) {
+  // If a null pointer expression's type is the C++0x nullptr_t, then
+  // it's not necessarily a simple constant and it must be evaluated
+  // for its potential side effects.
+  return e->getType()->isNullPtrType();
+}
+
 // Emit code for an explicit or implicit cast.  Implicit
 // casts have to handle a more broad range of conversions than explicit
 // casts, as they handle things like function to ptr-to-function decay
 // etc.
 mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
-  Expr *e = ce->getSubExpr();
+  Expr *subExpr = ce->getSubExpr();
   QualType destTy = ce->getType();
   CastKind kind = ce->getCastKind();
 
+  // These cases are generally not written to ignore the result of evaluating
+  // their sub-expressions, so we clear this now.
+  ignoreResultAssign = false;
+
   switch (kind) {
+  case clang::CK_Dependent:
+llvm_unreachable("dependent cast kind in CIR gen!");
+  case clang::CK_BuiltinFnToFnPtr:
+llvm_unreachable("builtin functions are handled elsewhere");
+
+  case CK_CPointerToObjCPointerCast:
+  case CK_BlockPointerToObjCPointerCast:
+  case CK_AnyPointerToBlockPointerCast:
+  case CK_BitCast: {
+mlir::Value src = Visit(const_cast(subExpr));
+mlir::Type dstTy = cgf.convertType(destTy);
+
+assert(!cir::MissingFeatures::addressSpace());
+
+if (cgf.sanOpts.has(SanitizerKind::CFIUnrelatedCast))
+  cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
+ "sanitizer support");
+
+if (cgf.cgm.getCodeGenOpts().StrictVTablePointers)
+  cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
+ "strict vtable pointers");
+
+// Update heapallocsite metadata when there is an explicit pointer cast.
+assert(!cir::MissingFeatures::addHeapAllocSiteMetadata());
+
+// If Src is a fixed vector and Dst is a scalable vector, and both have the
+// same element type, use the llvm.vector.insert intrinsic to perform the
+// bitcast.
+assert(!cir::MissingFeatures::scalableVectors());
+
+// If Src is a scalable vector and Dst is a fixed vector, and both have the
+// same element type, use the llvm.vector.extract intrinsic to perform the
+// bitcast.
+assert(!cir::MissingFeatures::scalableVectors());
+
+// Perform VLAT <-> VLST bitcast through memory.
+// TODO: since the llvm.experimental.vector.{insert,extract} intrinsics
+//   require the element types of the vectors to be the same, we
+//   need to keep this around for bitcasts between VLAT <-> VLST where
+//   the element types of the vectors are not the same, until we figure
+//   out a better way of doing these casts.
+assert(!cir::MissingFeatures::scalableVectors());
+
+return 
cgf.getBuilder().createBitcast(cgf.getLoc(subExpr->getSourceRange()),
+  src, dstTy);
+  }
+
+  case CK_AtomicToNonAtomic:
+cgf.getCIRGenModule().errorNYI(subExpr->getSourceRange(),
+   "CastExpr: ", ce->getCastKindName());
+break;
+  case CK_NonAtomicToAtomic:
+  case CK_UserDefinedConversion:
+return Visit(const_cast(subExpr));
+  case CK_NoOp: {
+auto v = Visit(const_cast(subExpr));
+if (v) {
+  // CK_NoOp can model a pointer qualification conversion, which can remove
+  // an array bound and change the IR type.
+  // FIXME: Once pointee types are removed from IR, remove this.
+  mlir::Type t = cgf.convertType(destTy);
+  if (t != v.getType())
+cgf.getCIRGenModule().errorNYI("pointer qualification conversion");
+}
+return v;
+  }
+
+  case CK_NullToPointer: {
+if (MustVisitNullValue(subExpr))
+  cgf.getCIRGenModule().errorNYI(
+  subExpr->getSourceRange(),
+  "ignored expression on null to pointer cast");
+
+// Note that DestTy is used as the MLIR type instead of a custom
+// nullptr type.
+mlir::Type ty = cgf.convertType(destTy);
+return builder.getNullPtr(ty, cgf.getLoc(subExpr->getExprLoc()));
+  }
+
   case CK_LValueToRValue:
-assert(cgf.getContext().hasSameUnqualifiedType(e->getType(), destTy));
-assert(e->isGLValue() && "lvalue-to-rvalue applied to r-value!");
-return Visit(const_cast(e));
+assert(cgf.getContext().hasSameUnqualifiedType(subExpr->getType(), 
destTy));
+assert(subExpr->isGLValue() && "lvalue-to-rvalue applied to r-value!");
+return Visit(const_cast(subExpr));
 
   case CK_IntegralCast: {
-assert(!cir::MissingFeatures::scalarConversionOpts());
-return emitScalarConversion(Visit(e), e->getType(), destTy,
+ScalarConversionOpts opts;
+if (auto *ice = dyn_cast(ce)) {
+  if (!ice->isPartOfExplicitCast())
+

[clang] [CIR] Upstream CastOp and scalar conversions (PR #130690)

2025-03-12 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/130690

>From a945e21869e5276c66ac979acd893d9bd9afe2cc Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Mon, 10 Mar 2025 16:18:34 -0700
Subject: [PATCH 1/4] [CIR] Upstream CastOp and scalar conversions

This patch upstreams ClangIR's CastOp with the following exceptions:
- No Fixed/FP conversions
- No casts between value categories
- No complex casts
- No array_to_ptrdecay
- No address_space
- No casts involving record types (member pointers, base/derived casts)
- No casts specific to ObjC or OpenCL
---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h  |  62 +++
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 105 +
 clang/include/clang/CIR/MissingFeatures.h |  14 +-
 clang/lib/CIR/CodeGen/CIRGenBuilder.h |   9 +
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp| 400 +-
 clang/lib/CIR/CodeGen/CIRGenFunction.h|   3 +
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp   | 170 
 clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp|  27 ++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 207 +
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  16 +
 clang/test/CIR/CodeGen/cast.cpp   |  58 +++
 clang/test/CIR/IR/cast.cir|  23 +
 clang/test/CIR/Lowering/cast.cir  |  92 
 13 files changed, 1174 insertions(+), 12 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/cast.cpp
 create mode 100644 clang/test/CIR/IR/cast.cir
 create mode 100644 clang/test/CIR/Lowering/cast.cir

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 017ae0c53a984..e5e8132e9f527 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -13,6 +13,7 @@
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
+#include "llvm/Support/ErrorHandling.h"
 
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinTypes.h"
@@ -78,6 +79,67 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return create(loc, val, dst);
   }
 
+  
//======//
+  // Cast/Conversion Operators
+  
//======//
+
+  mlir::Value createCast(mlir::Location loc, cir::CastKind kind,
+ mlir::Value src, mlir::Type newTy) {
+if (newTy == src.getType())
+  return src;
+return create(loc, newTy, kind, src);
+  }
+
+  mlir::Value createCast(cir::CastKind kind, mlir::Value src,
+ mlir::Type newTy) {
+if (newTy == src.getType())
+  return src;
+return createCast(src.getLoc(), kind, src, newTy);
+  }
+
+  mlir::Value createIntCast(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::integral, src, newTy);
+  }
+
+  mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::int_to_ptr, src, newTy);
+  }
+
+  mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::ptr_to_int, src, newTy);
+  }
+
+  mlir::Value createPtrToBoolCast(mlir::Value v) {
+return createCast(cir::CastKind::ptr_to_bool, v, getBoolTy());
+  }
+
+  mlir::Value createBoolToInt(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::bool_to_int, src, newTy);
+  }
+
+  mlir::Value createBitcast(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::bitcast, src, newTy);
+  }
+
+  mlir::Value createBitcast(mlir::Location loc, mlir::Value src,
+mlir::Type newTy) {
+return createCast(loc, cir::CastKind::bitcast, src, newTy);
+  }
+
+  mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy) {
+assert(mlir::isa(src.getType()) && "expected ptr src");
+return createBitcast(src, getPointerTo(newPointeeTy));
+  }
+
+  mlir::Value createAddrSpaceCast(mlir::Location loc, mlir::Value src,
+  mlir::Type newTy) {
+return createCast(loc, cir::CastKind::address_space, src, newTy);
+  }
+
+  mlir::Value createAddrSpaceCast(mlir::Value src, mlir::Type newTy) {
+return createAddrSpaceCast(src.getLoc(), src, newTy);
+  }
+
   //
   // Block handling helpers
   // --
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 77c43e5ace64a..9797960e00867 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -78,6 +78,111 @@ class LLVMLoweringInfo {
 class CIR_Op traits = []> :
 Op, LLVMLoweringInfo;
 
+//===--===//
+// CastOp
+//===--

[clang] [CIR] Upstream global variable linkage types (PR #129072)

2025-03-05 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/129072

>From 1432050465c1e351edfdfe908de52d1d6d1cf15e Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Mon, 3 Mar 2025 18:44:40 +0100
Subject: [PATCH 1/7] [CIR] Upstream global variable linkage types

This change implements variable linkage types in ClangIR except for common 
linkage which requires Comdat support.
---
 .../include/clang/CIR/Dialect/IR/CIRDialect.h |   2 +
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  83 ++-
 .../clang/CIR/Dialect/IR/CIROpsEnums.h| 119 +++
 .../clang/CIR/Dialect/IR/CMakeLists.txt   |   4 +-
 .../clang/CIR/Interfaces/CIROpInterfaces.h|  29 +++
 .../clang/CIR/Interfaces/CIROpInterfaces.td   |  63 ++
 .../clang/CIR/Interfaces/CMakeLists.txt   |   9 +
 clang/include/clang/CIR/MissingFeatures.h |   4 +
 clang/lib/CIR/CodeGen/CIRGenModule.cpp| 202 +-
 clang/lib/CIR/CodeGen/CIRGenModule.h  |  12 ++
 clang/lib/CIR/CodeGen/CMakeLists.txt  |   1 +
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp   |   8 +-
 clang/lib/CIR/Dialect/IR/CMakeLists.txt   |   3 +-
 clang/lib/CIR/FrontendAction/CMakeLists.txt   |   4 +
 clang/lib/CIR/Interfaces/CIROpInterfaces.cpp  |  22 ++
 clang/lib/CIR/Interfaces/CMakeLists.txt   |   4 +-
 .../CIR/Lowering/DirectToLLVM/CMakeLists.txt  |   5 +
 clang/test/CIR/global-var-simple.cpp  |  64 +++---
 clang/test/CIR/global_var_linkage.cpp |  11 +
 19 files changed, 608 insertions(+), 41 deletions(-)
 create mode 100644 clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h
 create mode 100644 clang/include/clang/CIR/Interfaces/CIROpInterfaces.h
 create mode 100644 clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
 create mode 100644 clang/lib/CIR/Interfaces/CIROpInterfaces.cpp
 create mode 100644 clang/test/CIR/global_var_linkage.cpp

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h 
b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
index 683176b139ca4..0684cf5034f5d 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -28,6 +28,8 @@
 
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIROpsDialect.h.inc"
+#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
+#include "clang/CIR/Interfaces/CIROpInterfaces.h"
 
 // TableGen'erated files for MLIR dialects require that a macro be defined when
 // they are included.  GET_OP_CLASSES tells the file to define the classes for
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 48178b0ff247d..2cef98099fdbb 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -18,6 +18,8 @@ include "clang/CIR/Dialect/IR/CIRDialect.td"
 include "clang/CIR/Dialect/IR/CIRTypes.td"
 include "clang/CIR/Dialect/IR/CIRAttrs.td"
 
+include "clang/CIR/Interfaces/CIROpInterfaces.td"
+
 include "mlir/IR/BuiltinAttributeInterfaces.td"
 include "mlir/IR/EnumAttr.td"
 include "mlir/IR/SymbolInterfaces.td"
@@ -430,6 +432,59 @@ def ScopeOp : CIR_Op<"scope", [
 // GlobalOp
 
//===--===//
 
+// Linkage types. This is currently a replay of llvm/IR/GlobalValue.h, this is
+// currently handy as part of forwarding appropriate linkage types for LLVM
+// lowering, specially useful for C++ support.
+
+// Externally visible function
+def Global_ExternalLinkage :
+  I32EnumAttrCase<"ExternalLinkage", 0, "external">;
+// Available for inspection, not emission.
+def Global_AvailableExternallyLinkage :
+  I32EnumAttrCase<"AvailableExternallyLinkage", 1, "available_externally">;
+// Keep one copy of function when linking (inline)
+def Global_LinkOnceAnyLinkage :
+  I32EnumAttrCase<"LinkOnceAnyLinkage", 2, "linkonce">;
+// Same, but only replaced by something equivalent.
+def Global_LinkOnceODRLinkage :
+  I32EnumAttrCase<"LinkOnceODRLinkage", 3, "linkonce_odr">;
+// Keep one copy of named function when linking (weak)
+def Global_WeakAnyLinkage :
+  I32EnumAttrCase<"WeakAnyLinkage", 4, "weak">;
+// Same, but only replaced by something equivalent.
+def Global_WeakODRLinkage :
+  I32EnumAttrCase<"WeakODRLinkage", 5, "weak_odr">;
+// TODO: should we add something like appending linkage too?
+// Special purpose, only applies to global arrays
+// def Global_AppendingLinkage :
+//   I32EnumAttrCase<"AppendingLinkage", 6, "appending">;
+// Rename collisions when linking (static functions).
+def Global_InternalLinkage :
+  I32EnumAttrCase<"InternalLinkage", 7, "internal">;
+// Like Internal, but omit from symbol table, prefix it with
+// "cir_" to prevent clash with MLIR's symbol "private".
+def Global_PrivateLinkage :
+  I32EnumAttrCase<"PrivateLinkage", 8, "cir_private">;
+// ExternalWeak linkage description.
+def Global_ExternalWeakLinkage :
+  I32EnumAttrCase<"ExternalWeakLinkage", 9, "extern_weak">;
+// Tentative defi

[clang] [CIR] Upstream global variable linkage types (PR #129072)

2025-03-05 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/129072

>From f19e6f6c5da44bd47c71a1b3d047aa1a0df96568 Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Wed, 5 Mar 2025 16:36:21 +0100
Subject: [PATCH 1/7] [CIR] Upstream global variable linkage types

This change implements variable linkage types in ClangIR except for common 
linkage which requires Comdat support.
---
 .../include/clang/CIR/Dialect/IR/CIRDialect.h |   2 +
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  83 ++-
 .../clang/CIR/Dialect/IR/CIROpsEnums.h| 119 +++
 .../clang/CIR/Dialect/IR/CMakeLists.txt   |   4 +-
 .../clang/CIR/Interfaces/CIROpInterfaces.h|  29 +++
 .../clang/CIR/Interfaces/CIROpInterfaces.td   |  63 ++
 .../clang/CIR/Interfaces/CMakeLists.txt   |   9 +
 clang/include/clang/CIR/MissingFeatures.h |   4 +
 clang/lib/CIR/CodeGen/CIRGenModule.cpp| 202 +-
 clang/lib/CIR/CodeGen/CIRGenModule.h  |  12 ++
 clang/lib/CIR/CodeGen/CMakeLists.txt  |   1 +
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp   |   8 +-
 clang/lib/CIR/Dialect/IR/CMakeLists.txt   |   3 +-
 clang/lib/CIR/FrontendAction/CMakeLists.txt   |   4 +
 clang/lib/CIR/Interfaces/CIROpInterfaces.cpp  |  22 ++
 clang/lib/CIR/Interfaces/CMakeLists.txt   |   4 +-
 .../CIR/Lowering/DirectToLLVM/CMakeLists.txt  |   5 +
 clang/test/CIR/global-var-simple.cpp  |  64 +++---
 clang/test/CIR/global_var_linkage.cpp |  11 +
 19 files changed, 608 insertions(+), 41 deletions(-)
 create mode 100644 clang/include/clang/CIR/Dialect/IR/CIROpsEnums.h
 create mode 100644 clang/include/clang/CIR/Interfaces/CIROpInterfaces.h
 create mode 100644 clang/include/clang/CIR/Interfaces/CIROpInterfaces.td
 create mode 100644 clang/lib/CIR/Interfaces/CIROpInterfaces.cpp
 create mode 100644 clang/test/CIR/global_var_linkage.cpp

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h 
b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
index 683176b139ca4..0684cf5034f5d 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h
@@ -28,6 +28,8 @@
 
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIROpsDialect.h.inc"
+#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
+#include "clang/CIR/Interfaces/CIROpInterfaces.h"
 
 // TableGen'erated files for MLIR dialects require that a macro be defined when
 // they are included.  GET_OP_CLASSES tells the file to define the classes for
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 48178b0ff247d..2cef98099fdbb 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -18,6 +18,8 @@ include "clang/CIR/Dialect/IR/CIRDialect.td"
 include "clang/CIR/Dialect/IR/CIRTypes.td"
 include "clang/CIR/Dialect/IR/CIRAttrs.td"
 
+include "clang/CIR/Interfaces/CIROpInterfaces.td"
+
 include "mlir/IR/BuiltinAttributeInterfaces.td"
 include "mlir/IR/EnumAttr.td"
 include "mlir/IR/SymbolInterfaces.td"
@@ -430,6 +432,59 @@ def ScopeOp : CIR_Op<"scope", [
 // GlobalOp
 
//===--===//
 
+// Linkage types. This is currently a replay of llvm/IR/GlobalValue.h, this is
+// currently handy as part of forwarding appropriate linkage types for LLVM
+// lowering, specially useful for C++ support.
+
+// Externally visible function
+def Global_ExternalLinkage :
+  I32EnumAttrCase<"ExternalLinkage", 0, "external">;
+// Available for inspection, not emission.
+def Global_AvailableExternallyLinkage :
+  I32EnumAttrCase<"AvailableExternallyLinkage", 1, "available_externally">;
+// Keep one copy of function when linking (inline)
+def Global_LinkOnceAnyLinkage :
+  I32EnumAttrCase<"LinkOnceAnyLinkage", 2, "linkonce">;
+// Same, but only replaced by something equivalent.
+def Global_LinkOnceODRLinkage :
+  I32EnumAttrCase<"LinkOnceODRLinkage", 3, "linkonce_odr">;
+// Keep one copy of named function when linking (weak)
+def Global_WeakAnyLinkage :
+  I32EnumAttrCase<"WeakAnyLinkage", 4, "weak">;
+// Same, but only replaced by something equivalent.
+def Global_WeakODRLinkage :
+  I32EnumAttrCase<"WeakODRLinkage", 5, "weak_odr">;
+// TODO: should we add something like appending linkage too?
+// Special purpose, only applies to global arrays
+// def Global_AppendingLinkage :
+//   I32EnumAttrCase<"AppendingLinkage", 6, "appending">;
+// Rename collisions when linking (static functions).
+def Global_InternalLinkage :
+  I32EnumAttrCase<"InternalLinkage", 7, "internal">;
+// Like Internal, but omit from symbol table, prefix it with
+// "cir_" to prevent clash with MLIR's symbol "private".
+def Global_PrivateLinkage :
+  I32EnumAttrCase<"PrivateLinkage", 8, "cir_private">;
+// ExternalWeak linkage description.
+def Global_ExternalWeakLinkage :
+  I32EnumAttrCase<"ExternalWeakLinkage", 9, "extern_weak">;
+// Tentative defi

[clang] [CIR] Upstream global variable linkage types (PR #129072)

2025-03-05 Thread Morris Hafner via cfe-commits

mmha wrote:

Great! I don't have committer status, yet, if that's your question.

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


[clang] [CIR] Don't generate ClangIR after an unrecoverable error occured (PR #130971)

2025-03-12 Thread Morris Hafner via cfe-commits

mmha wrote:

@ekeane @dkolsen-pgi @andykaylor 

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


[clang] [CIR] Upstream CastOp and scalar conversions (PR #130690)

2025-03-11 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/130690

>From b9a55d112998c468cce5cabff33939e4412e7ded Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Mon, 10 Mar 2025 16:18:34 -0700
Subject: [PATCH 1/2] [CIR] Upstream CastOp and scalar conversions

This patch upstreams ClangIR's CastOp with the following exceptions:
- No Fixed/FP conversions
- No casts between value categories
- No complex casts
- No array_to_ptrdecay
- No address_space
- No casts involving record types (member pointers, base/derived casts)
- No casts specific to ObjC or OpenCL
---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h  |  62 +++
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 105 +
 clang/include/clang/CIR/MissingFeatures.h |  14 +-
 clang/lib/CIR/CodeGen/CIRGenBuilder.h |   9 +
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp| 400 +-
 clang/lib/CIR/CodeGen/CIRGenFunction.h|   3 +
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp   | 170 
 clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp|  27 ++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 207 +
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  16 +
 clang/test/CIR/CodeGen/cast.cpp   |  58 +++
 clang/test/CIR/IR/cast.cir|  23 +
 clang/test/CIR/Lowering/cast.cir  |  92 
 13 files changed, 1174 insertions(+), 12 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/cast.cpp
 create mode 100644 clang/test/CIR/IR/cast.cir
 create mode 100644 clang/test/CIR/Lowering/cast.cir

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 017ae0c53a984..e5e8132e9f527 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -13,6 +13,7 @@
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
+#include "llvm/Support/ErrorHandling.h"
 
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinTypes.h"
@@ -78,6 +79,67 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return create(loc, val, dst);
   }
 
+  
//======//
+  // Cast/Conversion Operators
+  
//======//
+
+  mlir::Value createCast(mlir::Location loc, cir::CastKind kind,
+ mlir::Value src, mlir::Type newTy) {
+if (newTy == src.getType())
+  return src;
+return create(loc, newTy, kind, src);
+  }
+
+  mlir::Value createCast(cir::CastKind kind, mlir::Value src,
+ mlir::Type newTy) {
+if (newTy == src.getType())
+  return src;
+return createCast(src.getLoc(), kind, src, newTy);
+  }
+
+  mlir::Value createIntCast(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::integral, src, newTy);
+  }
+
+  mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::int_to_ptr, src, newTy);
+  }
+
+  mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::ptr_to_int, src, newTy);
+  }
+
+  mlir::Value createPtrToBoolCast(mlir::Value v) {
+return createCast(cir::CastKind::ptr_to_bool, v, getBoolTy());
+  }
+
+  mlir::Value createBoolToInt(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::bool_to_int, src, newTy);
+  }
+
+  mlir::Value createBitcast(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::bitcast, src, newTy);
+  }
+
+  mlir::Value createBitcast(mlir::Location loc, mlir::Value src,
+mlir::Type newTy) {
+return createCast(loc, cir::CastKind::bitcast, src, newTy);
+  }
+
+  mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy) {
+assert(mlir::isa(src.getType()) && "expected ptr src");
+return createBitcast(src, getPointerTo(newPointeeTy));
+  }
+
+  mlir::Value createAddrSpaceCast(mlir::Location loc, mlir::Value src,
+  mlir::Type newTy) {
+return createCast(loc, cir::CastKind::address_space, src, newTy);
+  }
+
+  mlir::Value createAddrSpaceCast(mlir::Value src, mlir::Type newTy) {
+return createAddrSpaceCast(src.getLoc(), src, newTy);
+  }
+
   //
   // Block handling helpers
   // --
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index e2ab50c78ec2d..caef0947d0b16 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -78,6 +78,111 @@ class LLVMLoweringInfo {
 class CIR_Op traits = []> :
 Op, LLVMLoweringInfo;
 
+//===--===//
+// CastOp
+//===--

[clang] [CIR] Upstream CastOp and scalar conversions (PR #130690)

2025-03-11 Thread Morris Hafner via cfe-commits


@@ -36,6 +36,18 @@ class ScalarExprEmitter : public 
StmtVisitor {
 bool ira = false)
   : cgf(cgf), builder(builder), ignoreResultAssign(ira) {}
 
+  
//======//
+  //   Utilities
+  
//======//
+
+  bool TestAndClearIgnoreResultAssign() {

mmha wrote:

I noticed that the underlying variable is never read from, making this dead 
code. I removed it.

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


[clang] [CIR] Upstream CastOp and scalar conversions (PR #130690)

2025-03-12 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/130690

>From a945e21869e5276c66ac979acd893d9bd9afe2cc Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Mon, 10 Mar 2025 16:18:34 -0700
Subject: [PATCH 1/5] [CIR] Upstream CastOp and scalar conversions

This patch upstreams ClangIR's CastOp with the following exceptions:
- No Fixed/FP conversions
- No casts between value categories
- No complex casts
- No array_to_ptrdecay
- No address_space
- No casts involving record types (member pointers, base/derived casts)
- No casts specific to ObjC or OpenCL
---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h  |  62 +++
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 105 +
 clang/include/clang/CIR/MissingFeatures.h |  14 +-
 clang/lib/CIR/CodeGen/CIRGenBuilder.h |   9 +
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp| 400 +-
 clang/lib/CIR/CodeGen/CIRGenFunction.h|   3 +
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp   | 170 
 clang/lib/CIR/Dialect/IR/CIRMemorySlot.cpp|  27 ++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 207 +
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  16 +
 clang/test/CIR/CodeGen/cast.cpp   |  58 +++
 clang/test/CIR/IR/cast.cir|  23 +
 clang/test/CIR/Lowering/cast.cir  |  92 
 13 files changed, 1174 insertions(+), 12 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/cast.cpp
 create mode 100644 clang/test/CIR/IR/cast.cir
 create mode 100644 clang/test/CIR/Lowering/cast.cir

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 017ae0c53a984..e5e8132e9f527 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -13,6 +13,7 @@
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
+#include "llvm/Support/ErrorHandling.h"
 
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinTypes.h"
@@ -78,6 +79,67 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return create(loc, val, dst);
   }
 
+  
//======//
+  // Cast/Conversion Operators
+  
//======//
+
+  mlir::Value createCast(mlir::Location loc, cir::CastKind kind,
+ mlir::Value src, mlir::Type newTy) {
+if (newTy == src.getType())
+  return src;
+return create(loc, newTy, kind, src);
+  }
+
+  mlir::Value createCast(cir::CastKind kind, mlir::Value src,
+ mlir::Type newTy) {
+if (newTy == src.getType())
+  return src;
+return createCast(src.getLoc(), kind, src, newTy);
+  }
+
+  mlir::Value createIntCast(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::integral, src, newTy);
+  }
+
+  mlir::Value createIntToPtr(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::int_to_ptr, src, newTy);
+  }
+
+  mlir::Value createPtrToInt(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::ptr_to_int, src, newTy);
+  }
+
+  mlir::Value createPtrToBoolCast(mlir::Value v) {
+return createCast(cir::CastKind::ptr_to_bool, v, getBoolTy());
+  }
+
+  mlir::Value createBoolToInt(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::bool_to_int, src, newTy);
+  }
+
+  mlir::Value createBitcast(mlir::Value src, mlir::Type newTy) {
+return createCast(cir::CastKind::bitcast, src, newTy);
+  }
+
+  mlir::Value createBitcast(mlir::Location loc, mlir::Value src,
+mlir::Type newTy) {
+return createCast(loc, cir::CastKind::bitcast, src, newTy);
+  }
+
+  mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy) {
+assert(mlir::isa(src.getType()) && "expected ptr src");
+return createBitcast(src, getPointerTo(newPointeeTy));
+  }
+
+  mlir::Value createAddrSpaceCast(mlir::Location loc, mlir::Value src,
+  mlir::Type newTy) {
+return createCast(loc, cir::CastKind::address_space, src, newTy);
+  }
+
+  mlir::Value createAddrSpaceCast(mlir::Value src, mlir::Type newTy) {
+return createAddrSpaceCast(src.getLoc(), src, newTy);
+  }
+
   //
   // Block handling helpers
   // --
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 77c43e5ace64a..9797960e00867 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -78,6 +78,111 @@ class LLVMLoweringInfo {
 class CIR_Op traits = []> :
 Op, LLVMLoweringInfo;
 
+//===--===//
+// CastOp
+//===--

[clang] [CIR] Upstream CastOp and scalar conversions (PR #130690)

2025-03-15 Thread Morris Hafner via cfe-commits


@@ -78,6 +78,111 @@ class LLVMLoweringInfo {
 class CIR_Op traits = []> :
 Op, LLVMLoweringInfo;
 
+//===--===//
+// CastOp
+//===--===//
+
+// The enumaration value isn't in sync with clang.

mmha wrote:

I tried to get the enums in sync. Good news is I found a couple of unused 
casting kinds wrt. complex numbers which I removed. Bad news is I found one 
casting kind (bool to float) that's specific to CIR: llvm/clangir#290. I moved 
it to the bottom on the list so the enum values of classic CG and CIR match up.

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


[clang] [CIR] Upstream initial support for unary op (PR #131369)

2025-03-15 Thread Morris Hafner via cfe-commits


@@ -568,6 +568,128 @@ mlir::LogicalResult 
CIRToLLVMGlobalOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+mlir::LogicalResult CIRToLLVMUnaryOpLowering::matchAndRewrite(
+cir::UnaryOp op, OpAdaptor adaptor,
+mlir::ConversionPatternRewriter &rewriter) const {
+  assert(op.getType() == op.getInput().getType() &&
+ "Unary operation's operand type and result type are different");
+  mlir::Type type = op.getType();
+  mlir::Type elementType = type;
+  bool isVector = false;
+  assert(!cir::MissingFeatures::vectorType());
+  mlir::Type llvmType = getTypeConverter()->convertType(type);
+  mlir::Location loc = op.getLoc();
+
+  auto createIntConstant = [&](int64_t value) -> mlir::Value {

mmha wrote:

I just had to create a boolean constant. I don't think this will be the last 
instance of that, so maybe having utility functions for some fundamental types 
is a good idea.

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


[clang] [CIR] Add binary operators (PR #132420)

2025-03-21 Thread Morris Hafner via cfe-commits

https://github.com/mmha created https://github.com/llvm/llvm-project/pull/132420

This patch adds upstreams support for BinOp and BinOverflowOp including lvalue 
assignments and rudimentary support for pointer arithmetic. Note that this does 
not include ternary ops, ShiftOp and SelectOp which are required for logical 
binary operators.

>From 594005c964b5c1e6605dc8ac170f1b43aa018bea Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Fri, 21 Mar 2025 17:55:00 +0100
Subject: [PATCH] [CIR] Add binary operators

This patch adds upstreams support for BinOp and BinOverflowOp including lvalue 
assignments and rudimentary support for pointer arithmetic. Note that this does 
not include ternary ops, ShiftOp and SelectOp which are required for logical 
binary operators.
---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h  | 114 ++-
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 123 +++
 clang/include/clang/CIR/Dialect/IR/CIRTypes.h |   1 +
 clang/include/clang/CIR/MissingFeatures.h |  13 +-
 clang/lib/CIR/CodeGen/CIRGenBuilder.h | 116 ++-
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp  |  64 +-
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp| 730 +-
 clang/lib/CIR/CodeGen/CIRGenFunction.cpp  |   2 +
 clang/lib/CIR/CodeGen/CIRGenFunction.h|  30 +-
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp   |  41 +-
 clang/lib/CIR/Dialect/IR/CIRTypes.cpp |  10 +
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 243 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  33 +
 clang/test/CIR/CodeGen/binop.cpp  |  33 +
 clang/test/CIR/Lowering/binop-bool.cir|  18 +
 clang/test/CIR/Lowering/binop-fp.cir  |  68 ++
 clang/test/CIR/Lowering/binop-overflow.cir|  63 ++
 clang/test/CIR/Lowering/binop-signed-int.cir  |  60 ++
 .../test/CIR/Lowering/binop-unsigned-int.cir  |  73 ++
 19 files changed, 1794 insertions(+), 41 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/binop.cpp
 create mode 100644 clang/test/CIR/Lowering/binop-bool.cir
 create mode 100644 clang/test/CIR/Lowering/binop-fp.cir
 create mode 100644 clang/test/CIR/Lowering/binop-overflow.cir
 create mode 100644 clang/test/CIR/Lowering/binop-signed-int.cir
 create mode 100644 clang/test/CIR/Lowering/binop-unsigned-int.cir

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index c6aea10d46b63..9fe80cde261a9 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -10,7 +10,6 @@
 #define LLVM_CLANG_CIR_DIALECT_BUILDER_CIRBASEBUILDER_H
 
 #include "clang/AST/CharUnits.h"
-#include "clang/AST/Type.h"
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
@@ -28,6 +27,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
   CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
   : mlir::OpBuilder(&mlirContext) {}
 
+  mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ,
+const llvm::APInt &val) {
+return create(loc, typ, getAttr(typ, val));
+  }
+
   cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr) {
 return create(loc, attr.getType(), attr);
   }
@@ -143,6 +147,114 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return createCast(loc, cir::CastKind::bitcast, src, newTy);
   }
 
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  const llvm::APInt &rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs,
+  getConstAPInt(lhs.getLoc(), lhs.getType(), rhs));
+  }
+
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  mlir::Value rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createBinop(mlir::Location loc, mlir::Value lhs,
+  cir::BinOpKind kind, mlir::Value rhs) {
+return create(loc, lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createLowBitsSet(mlir::Location loc, unsigned size,
+   unsigned bits) {
+llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits);
+auto type = cir::IntType::get(getContext(), size, false);
+return getConstAPInt(loc, type, val);
+  }
+
+  mlir::Value createAnd(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getType(), rhs);
+return createBinop(lhs, cir::BinOpKind::And, val);
+  }
+
+  mlir::Value createAnd(mlir::Value lhs, mlir::Value rhs) {
+return createBinop(lhs, cir::BinOpKind::And, rhs);
+  }
+
+  mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+return createBinop(loc, lhs, cir::BinOpKind::And, rhs);
+  }
+
+  mlir::Value createOr(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getT

[clang] [CIR] Add binary operators (PR #132420)

2025-03-21 Thread Morris Hafner via cfe-commits

mmha wrote:

@erichkeane @dkolsen-pgi @andykaylor 

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


[clang] [CIR] Add binary operators (PR #132420)

2025-03-24 Thread Morris Hafner via cfe-commits


@@ -143,6 +147,114 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return createCast(loc, cir::CastKind::bitcast, src, newTy);
   }
 
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  const llvm::APInt &rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs,
+  getConstAPInt(lhs.getLoc(), lhs.getType(), rhs));
+  }
+
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  mlir::Value rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs, rhs);

mmha wrote:

Very nice catch. The source locations of all binops except for division were 
not passed through. I changed the signature of the builder functions to require 
an `mlir::Location`. If there's a future need for an overload without a 
location we can add those later.

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


[clang] [CIR] Add binary operators (PR #132420)

2025-03-24 Thread Morris Hafner via cfe-commits


@@ -826,6 +826,129 @@ def ForOp : CIR_Op<"for", [LoopOpInterface, 
NoRegionArguments]> {
   }];
 }
 
+//===--===//
+// BinOp
+//===--===//
+
+// FIXME: represent Commutative, Idempotent traits for appropriate binops
+def BinOpKind_Mul : I32EnumAttrCase<"Mul", 1, "mul">;
+def BinOpKind_Div : I32EnumAttrCase<"Div", 2, "div">;
+def BinOpKind_Rem : I32EnumAttrCase<"Rem", 3, "rem">;
+def BinOpKind_Add : I32EnumAttrCase<"Add", 4, "add">;
+def BinOpKind_Sub : I32EnumAttrCase<"Sub", 5, "sub">;
+def BinOpKind_And : I32EnumAttrCase<"And", 8, "and">;
+def BinOpKind_Xor : I32EnumAttrCase<"Xor", 9, "xor">;
+def BinOpKind_Or  : I32EnumAttrCase<"Or", 10, "or">;
+// TODO(cir): Do we need a min binop?
+def BinOpKind_Max : I32EnumAttrCase<"Max", 11, "max">;

mmha wrote:

This is to support `__builtin_elementwise_max` and at least one corresponding 
SIMD intrinsic function (see https://github.com/llvm/clangir/pull/1201).

I can't find that `TODO` in the git history of the incubator for some reason. 
But since there is a `__builtin_elementwise_min` I assume there needs to be a 
min as well.

Both builtins are still NYI though so I could remove them for the time being.

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


[clang] [CIR] Emit allocas into the proper lexical scope (PR #132468)

2025-03-24 Thread Morris Hafner via cfe-commits


@@ -0,0 +1,81 @@
+//===--===//
+//
+// 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
+//
+//===--===//
+
+#include "PassDetail.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/IR/PatternMatch.h"
+#include "mlir/Support/LogicalResult.h"
+#include "mlir/Transforms/DialectConversion.h"
+#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/Passes.h"
+#include "clang/CIR/MissingFeatures.h"
+#include "llvm/Support/TimeProfiler.h"
+
+using namespace mlir;
+using namespace cir;
+
+namespace {
+
+struct HoistAllocasPass : public HoistAllocasBase {
+
+  HoistAllocasPass() = default;
+  void runOnOperation() override;
+};
+
+static void process(mlir::ModuleOp mod, cir::FuncOp func) {
+  if (func.getRegion().empty())
+return;
+
+  // Hoist all static allocas to the entry block.
+  mlir::Block &entryBlock = func.getRegion().front();
+  llvm::SmallVector allocas;
+  func.getBody().walk([&](cir::AllocaOp alloca) {

mmha wrote:

As far as I know `walk` traverses post order, so the entry block should come 
last. I don't know what happens within a block, but then again you're also 
modifying the list in the second loop.

But I don't know for sure if it works.

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


[clang] [CIR] Add binary operators (PR #132420)

2025-03-24 Thread Morris Hafner via cfe-commits


@@ -143,6 +147,114 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return createCast(loc, cir::CastKind::bitcast, src, newTy);
   }
 
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  const llvm::APInt &rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs,
+  getConstAPInt(lhs.getLoc(), lhs.getType(), rhs));
+  }
+
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  mlir::Value rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createBinop(mlir::Location loc, mlir::Value lhs,
+  cir::BinOpKind kind, mlir::Value rhs) {
+return create(loc, lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createLowBitsSet(mlir::Location loc, unsigned size,
+   unsigned bits) {
+llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits);
+auto type = cir::IntType::get(getContext(), size, false);
+return getConstAPInt(loc, type, val);
+  }
+
+  mlir::Value createAnd(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getType(), rhs);
+return createBinop(lhs, cir::BinOpKind::And, val);
+  }
+
+  mlir::Value createAnd(mlir::Value lhs, mlir::Value rhs) {
+return createBinop(lhs, cir::BinOpKind::And, rhs);
+  }
+
+  mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+return createBinop(loc, lhs, cir::BinOpKind::And, rhs);
+  }
+
+  mlir::Value createOr(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getType(), rhs);
+return createBinop(lhs, cir::BinOpKind::Or, val);
+  }
+
+  mlir::Value createOr(mlir::Value lhs, mlir::Value rhs) {
+return createBinop(lhs, cir::BinOpKind::Or, rhs);
+  }
+
+  mlir::Value createMul(mlir::Value lhs, mlir::Value rhs, bool hasNUW = false,
+bool hasNSW = false) {
+auto op = create(lhs.getLoc(), lhs.getType(),
+ cir::BinOpKind::Mul, lhs, rhs);
+if (hasNUW)
+  op.setNoUnsignedWrap(true);
+if (hasNSW)
+  op.setNoSignedWrap(true);
+return op;
+  }
+  mlir::Value createNSWMul(mlir::Value lhs, mlir::Value rhs) {
+return createMul(lhs, rhs, false, true);
+  }
+  mlir::Value createNUWAMul(mlir::Value lhs, mlir::Value rhs) {
+return createMul(lhs, rhs, true, false);
+  }
+
+  mlir::Value createMul(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getType(), rhs);
+return createBinop(lhs, cir::BinOpKind::Mul, val);
+  }
+
+  mlir::Value createSub(mlir::Value lhs, mlir::Value rhs, bool hasNUW = false,

mmha wrote:

I think I prefer Erich's suggestion here as seting these attributes in the 
`create*` functions would lead to more code duplication (if I understand you 
correctly).

For creating that bitfield enum I'd like to reuse 
`CV_DEFINE_ENUM_CLASS_FLAGS_OPERATORS` from 
`llvm/include/llvm/DebugInfo/CodeView/CodeView.h`. What would be a good place 
to move this macro to? `clang::CodeGen::FnInfoOpts` could use that as well.

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


[clang] [CIR] Add binary operators (PR #132420)

2025-03-24 Thread Morris Hafner via cfe-commits


@@ -143,6 +147,114 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return createCast(loc, cir::CastKind::bitcast, src, newTy);
   }
 
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  const llvm::APInt &rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs,
+  getConstAPInt(lhs.getLoc(), lhs.getType(), rhs));
+  }
+
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  mlir::Value rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createBinop(mlir::Location loc, mlir::Value lhs,
+  cir::BinOpKind kind, mlir::Value rhs) {
+return create(loc, lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createLowBitsSet(mlir::Location loc, unsigned size,
+   unsigned bits) {
+llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits);
+auto type = cir::IntType::get(getContext(), size, false);

mmha wrote:

`/*isSigned*/` but yes :)

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


[clang] [CIR] Add binary operators (PR #132420)

2025-03-24 Thread Morris Hafner via cfe-commits

mmha wrote:

As @andykaylor suggested, I'm going to split off `BinOpOverflowOp` and the 
pointer arithmetic bits into a separate patch next.

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


[clang] [CIR] Add binary operators (PR #132420)

2025-03-24 Thread Morris Hafner via cfe-commits


@@ -93,16 +96,20 @@ struct MissingFeatures {
   static bool stackSaveOp() { return false; }
   static bool aggValueSlot() { return false; }
   static bool generateDebugInfo() { return false; }
+  static bool getFPFeaturesInEffect() { return false; }
+  static bool pointerOverflowSanitizer() { return false; }
   static bool fpConstraints() { return false; }
   static bool sanitizers() { return false; }
   static bool addHeapAllocSiteMetadata() { return false; }
   static bool targetCodeGenInfoGetNullPointer() { return false; }
-  static bool CGFPOptionsRAII() { return false; }
   static bool loopInfoStack() { return false; }
   static bool requiresCleanups() { return false; }
   static bool createProfileWeightsForLoop() { return false; }
   static bool emitCondLikelihoodViaExpectIntrinsic() { return false; }
   static bool pgoUse() { return false; }
+  static bool cgFPOptionsRAII() { return false; }
+  static bool metaDataNode() { return false; }
+  static bool foldBinOpFMF() { return false; }

mmha wrote:

What do you suggest? `fastMath()`? Or just leave it entirely?

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


[clang] [CIR] Upstream CastOp and scalar conversions (PR #130690)

2025-03-14 Thread Morris Hafner via cfe-commits


@@ -121,29 +364,173 @@ mlir::Value CIRGenFunction::emitScalarExpr(const Expr 
*e) {
   return ScalarExprEmitter(*this, builder).Visit(const_cast(e));
 }
 
+[[maybe_unused]] static bool MustVisitNullValue(const Expr *e) {
+  // If a null pointer expression's type is the C++0x nullptr_t, then
+  // it's not necessarily a simple constant and it must be evaluated
+  // for its potential side effects.
+  return e->getType()->isNullPtrType();
+}
+
 // Emit code for an explicit or implicit cast.  Implicit
 // casts have to handle a more broad range of conversions than explicit
 // casts, as they handle things like function to ptr-to-function decay
 // etc.
 mlir::Value ScalarExprEmitter::VisitCastExpr(CastExpr *ce) {
-  Expr *e = ce->getSubExpr();
+  Expr *subExpr = ce->getSubExpr();
   QualType destTy = ce->getType();
   CastKind kind = ce->getCastKind();
 
+  // These cases are generally not written to ignore the result of evaluating
+  // their sub-expressions, so we clear this now.
+  ignoreResultAssign = false;

mmha wrote:

Note that `ignoreResultAssign` is a member variable and retains its value while 
we visit the expression. We might get called recursively so we should keep this 
store.

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


[clang] [CIR] Upstream CastOp and scalar conversions (PR #130690)

2025-03-14 Thread Morris Hafner via cfe-commits


@@ -0,0 +1,79 @@
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir 
-emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s
+
+unsigned char cxxstaticcast_0(unsigned int x) {
+  return static_cast(x);
+}
+
+// CHECK: cir.func @cxxstaticcast_0
+// CHECK:%0 = cir.alloca !cir.int, !cir.ptr>, ["x", 
init] {alignment = 4 : i64}
+// CHECK:cir.store %arg0, %0 : !cir.int, !cir.ptr>
+// CHECK:%1 = cir.load %0 : !cir.ptr>, !cir.int
+// CHECK:%2 = cir.cast(integral, %1 : !cir.int), !cir.int
+// CHECK:cir.return %2 : !cir.int
+// CHECK:  }
+
+
+int cStyleCasts_0(unsigned x1, int x2, float x3, short x4, double x5) {
+// CHECK: cir.func @cStyleCasts_0
+
+  char a = (char)x1; // truncate
+  // CHECK: %{{[0-9]+}} = cir.cast(integral, %{{[0-9]+}} : !cir.int), 
!cir.int

mmha wrote:

I expanded the tests to include LLVM lowering where feasible. `int_to_bool` is 
implemented in CIR but not in the lowering (as that requires comparisons) so I 
`ifdef`ed those out for the LLVM checks.

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


[clang] [CIR] Upstream support for type aliases (PR #131912)

2025-03-19 Thread Morris Hafner via cfe-commits


@@ -89,6 +89,7 @@ list(APPEND CLANG_TEST_DEPS
 if(CLANG_ENABLE_CIR)
   list(APPEND CLANG_TEST_DEPS
 cir-opt
+cir-translate

mmha wrote:

Thanks! I missed that. I can see that the incubator has `mlir-translate` as a 
dependency, too. Should we add this now as well?

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


[clang] [CIR] Upstream support for type aliases (PR #131912)

2025-03-19 Thread Morris Hafner via cfe-commits


@@ -1,5 +1,5 @@
 # Test runner infrastructure for Clang. This configures the Clang test trees
-# for use by Lit, and delegates to LLVM's lit test handlers.
+# for use by Lit, and delegates to LLVM's lit test handlers.int

mmha wrote:

copy/paste error?

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


[clang] [CIR] Add binary operators (PR #132420)

2025-04-05 Thread Morris Hafner via cfe-commits


@@ -558,8 +624,225 @@ class ScalarExprEmitter : public 
StmtVisitor {
 
 return res;
   }
+
+  BinOpInfo emitBinOps(const BinaryOperator *e,
+   QualType promotionType = QualType()) {
+BinOpInfo result;
+result.lhs = cgf.emitPromotedScalarExpr(e->getLHS(), promotionType);
+result.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionType);
+if (!promotionType.isNull())
+  result.fullType = promotionType;
+else
+  result.fullType = e->getType();
+result.compType = result.fullType;
+if (const auto *vecType = dyn_cast_or_null(result.fullType)) {
+  result.compType = vecType->getElementType();
+}
+result.opcode = e->getOpcode();
+result.loc = e->getSourceRange();
+// TODO(cir): Result.FPFeatures
+assert(!cir::MissingFeatures::getFPFeaturesInEffect());
+result.e = e;
+return result;
+  }
+
+  mlir::Value emitMul(const BinOpInfo &ops);
+  mlir::Value emitDiv(const BinOpInfo &ops);
+  mlir::Value emitRem(const BinOpInfo &ops);
+  mlir::Value emitAdd(const BinOpInfo &ops);
+  mlir::Value emitSub(const BinOpInfo &ops);
+  mlir::Value emitShl(const BinOpInfo &ops);
+  mlir::Value emitShr(const BinOpInfo &ops);
+  mlir::Value emitAnd(const BinOpInfo &ops);
+  mlir::Value emitXor(const BinOpInfo &ops);
+  mlir::Value emitOr(const BinOpInfo &ops);
+
+  LValue emitCompoundAssignLValue(
+  const CompoundAssignOperator *e,
+  mlir::Value (ScalarExprEmitter::*f)(const BinOpInfo &),
+  mlir::Value &result);
+  mlir::Value
+  emitCompoundAssign(const CompoundAssignOperator *e,
+ mlir::Value (ScalarExprEmitter::*f)(const BinOpInfo &));
+
+  // TODO(cir): Candidate to be in a common AST helper between CIR and LLVM
+  // codegen.
+  QualType getPromotionType(QualType ty) {

mmha wrote:

I think we should leave this as a TODO in this patch. It's easier to have a 
mostly unimplemented `getPromotionType` and change the calls later on than to 
go back and figure out where it's supposed to be called.

There's a `getPromotionType` `CGExprScalar.cpp` and another one in 
`CGExprComplex.cpp`. So refactoring that should probably be done in a separate 
patch.

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


[clang] [CIR] Upstream CmpOp (PR #133159)

2025-04-05 Thread Morris Hafner via cfe-commits

mmha wrote:

cc @andykaylor @erichkeane @dkolsen-pgi 

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


[clang] [CIR] Add binary operators (PR #132420)

2025-03-25 Thread Morris Hafner via cfe-commits


@@ -200,7 +200,7 @@ class ASTContext : public RefCountedBase {
   mutable llvm::ContextualFoldingSet
   ConstantArrayTypes;
   mutable llvm::FoldingSet IncompleteArrayTypes;
-  mutable std::vector VariableArrayTypes;
+  mutable std::vector VariableArrayTypes;

mmha wrote:

That was `git clang-format` in action, yes.

(Why is ASTContext.h/cpp not clang-format clean?)

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


[clang] [CIR] Add BinOpOverflowOp and basic pointer arithmetic support (PR #133118)

2025-03-26 Thread Morris Hafner via cfe-commits

mmha wrote:

cc @andykaylor @erichkeane @dkolsen-pgi 

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


[clang] [CIR][NFC] Fix warnings in ClangIR code (PR #133134)

2025-03-26 Thread Morris Hafner via cfe-commits


@@ -170,7 +170,7 @@ mlir::Value CIRGenFunction::evaluateExprAsBool(const Expr 
*e) {
   SourceLocation loc = e->getExprLoc();
 
   assert(!cir::MissingFeatures::pgoUse());
-  if (const MemberPointerType *MPT = e->getType()->getAs()) 
{
+  if (e->getType()->getAs()) {

mmha wrote:

I wonder why `getAs` is not `[[nodiscard]]` but hey it's not so no new warning 
here.

(Maybe `isa` is still better?)

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


[clang] [CIR][NFC] Fix warnings in ClangIR code (PR #133134)

2025-03-26 Thread Morris Hafner via cfe-commits

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

LGTM, just a few nits.

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


[clang] [CIR] Add BinOpOverflowOp and basic pointer arithmetic support (PR #133118)

2025-03-26 Thread Morris Hafner via cfe-commits


@@ -1117,6 +1118,122 @@ mlir::LogicalResult 
CIRToLLVMBinOpLowering::matchAndRewrite(
   return mlir::LogicalResult::success();
 }
 
+mlir::LogicalResult CIRToLLVMBinOpOverflowOpLowering::matchAndRewrite(
+cir::BinOpOverflowOp op, OpAdaptor adaptor,
+mlir::ConversionPatternRewriter &rewriter) const {
+  mlir::Location loc = op.getLoc();
+  BinOpOverflowKind arithKind = op.getKind();
+  IntType operandTy = op.getLhs().getType();
+  IntType resultTy = op.getResult().getType();
+
+  EncompassedTypeInfo encompassedTyInfo =
+  computeEncompassedTypeWidth(operandTy, resultTy);
+  mlir::IntegerType encompassedLLVMTy =
+  rewriter.getIntegerType(encompassedTyInfo.width);
+
+  mlir::Value lhs = adaptor.getLhs();
+  mlir::Value rhs = adaptor.getRhs();
+  if (operandTy.getWidth() < encompassedTyInfo.width) {
+if (operandTy.isSigned()) {
+  lhs = rewriter.create(loc, encompassedLLVMTy, lhs);
+  rhs = rewriter.create(loc, encompassedLLVMTy, rhs);
+} else {
+  lhs = rewriter.create(loc, encompassedLLVMTy, lhs);
+  rhs = rewriter.create(loc, encompassedLLVMTy, rhs);
+}
+  }
+
+  std::string intrinName = getLLVMIntrinName(arithKind, encompassedTyInfo.sign,
+ encompassedTyInfo.width);
+  auto intrinNameAttr = mlir::StringAttr::get(op.getContext(), intrinName);
+
+  mlir::IntegerType overflowLLVMTy = rewriter.getI1Type();
+  auto intrinRetTy = mlir::LLVM::LLVMStructType::getLiteral(
+  rewriter.getContext(), {encompassedLLVMTy, overflowLLVMTy});
+
+  auto callLLVMIntrinOp = rewriter.create(
+  loc, intrinRetTy, intrinNameAttr, mlir::ValueRange{lhs, rhs});
+  mlir::Value intrinRet = callLLVMIntrinOp.getResult(0);
+
+  mlir::Value result = rewriter
+   .create(
+   loc, intrinRet, ArrayRef{0})
+   .getResult();
+  mlir::Value overflow = rewriter
+ .create(
+ loc, intrinRet, ArrayRef{1})
+ .getResult();
+
+  if (resultTy.getWidth() < encompassedTyInfo.width) {
+mlir::Type resultLLVMTy = getTypeConverter()->convertType(resultTy);
+auto truncResult =
+rewriter.create(loc, resultLLVMTy, result);
+
+// Extend the truncated result back to the encompassing type to check for
+// any overflows during the truncation.
+mlir::Value truncResultExt;
+if (resultTy.isSigned())
+  truncResultExt = rewriter.create(
+  loc, encompassedLLVMTy, truncResult);
+else
+  truncResultExt = rewriter.create(
+  loc, encompassedLLVMTy, truncResult);
+auto truncOverflow = rewriter.create(
+loc, mlir::LLVM::ICmpPredicate::ne, truncResultExt, result);
+
+result = truncResult;
+overflow = rewriter.create(loc, overflow, truncOverflow);
+  }
+
+  mlir::Type boolLLVMTy =
+  getTypeConverter()->convertType(op.getOverflow().getType());
+  if (boolLLVMTy != rewriter.getI1Type())
+overflow = rewriter.create(loc, boolLLVMTy, overflow);
+
+  rewriter.replaceOp(op, mlir::ValueRange{result, overflow});
+
+  return mlir::success();
+}
+
+std::string CIRToLLVMBinOpOverflowOpLowering::getLLVMIntrinName(
+cir::BinOpOverflowKind opKind, bool isSigned, unsigned width) {
+  // The intrinsic name is `@llvm.{s|u}{opKind}.with.overflow.i{width}`
+
+  std::string name = "llvm.";

mmha wrote:

I wonder if this should use `llvm::raw_string_ostream` or `Twine`.

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


[clang] [CIR][NFC] Fix warnings in ClangIR code (PR #133134)

2025-03-26 Thread Morris Hafner via cfe-commits


@@ -1251,13 +1236,12 @@ void ConvertCIRToLLVMPass::runOnOperation() {
   patterns.add(converter, patterns.getContext(), dl);
   patterns.add(converter, patterns.getContext(), 
dl);
   patterns.add(converter, patterns.getContext(), dl);
-  patterns.add(converter, patterns.getContext(),
-dl);
   patterns.add<
   // clang-format off
CIRToLLVMBinOpLowering,
CIRToLLVMBrCondOpLowering,
CIRToLLVMBrOpLowering,
+   CIRToLLVMConstantOpLowering,

mmha wrote:

The comment right above says we'd like to keep these patterns separate because 
their signature is going to change in the future. That's still the case here.

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


[clang] [CIR][NFC] Fix warnings in ClangIR code (PR #133134)

2025-03-26 Thread Morris Hafner via cfe-commits


@@ -1366,8 +1366,7 @@ mlir::Value 
ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
   const mlir::Location loc = cgf.getLoc(e->getSourceRange());
   if (auto kind = e->getKind();
   kind == UETT_SizeOf || kind == UETT_DataSizeOf) {
-if (const VariableArrayType *variableArrTy =
-cgf.getContext().getAsVariableArrayType(typeToSize)) {
+if (cgf.getContext().getAsVariableArrayType(typeToSize)) {

mmha wrote:

Same here.

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


[clang] [CIR][NFC] Fix warnings in ClangIR code (PR #133134)

2025-03-26 Thread Morris Hafner via cfe-commits

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


[clang] [CIR] Add BinOpOverflowOp and basic pointer arithmetic support (PR #133118)

2025-03-26 Thread Morris Hafner via cfe-commits

https://github.com/mmha created https://github.com/llvm/llvm-project/pull/133118

This was part of #132420 originally but split off to reduce the diff size.

This patch adds support for overflowing binary operators and all the plumbing 
required for pointer arithmetic except for the actual Ops (`PtrDiffOp` and 
`PtrStrideOp` - we emit dummy values instead).

>From 27e177c48194c660a36ab4ceef363314e2306e6e Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Tue, 25 Mar 2025 16:47:55 +
Subject: [PATCH 1/3] Revert "Remove BinOpOverflowOp and pointer arithmetic"

This reverts commit 56fbcba68c38c77c8a7b867abb0f3406807d772d.
---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  59 +
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp| 115 +-
 clang/lib/CIR/CodeGen/CIRGenFunction.h|  10 ++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 113 +
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  22 
 5 files changed, 317 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 455cc2b8b0277..3d49f88b032cb 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -889,6 +889,65 @@ def BinOp : CIR_Op<"binop", [Pure,
   let hasVerifier = 1;
 }
 
+
+//===--===//
+// BinOpOverflowOp
+//===--===//
+
+def BinOpOverflowKind : I32EnumAttr<
+"BinOpOverflowKind",
+"checked binary arithmetic operation kind",
+[BinOpKind_Add, BinOpKind_Sub, BinOpKind_Mul]> {
+  let cppNamespace = "::cir";
+}
+
+def BinOpOverflowOp : CIR_Op<"binop.overflow", [Pure, SameTypeOperands]> {
+  let summary = "Perform binary integral arithmetic with overflow checking";
+  let description = [{
+`cir.binop.overflow` performs binary arithmetic operations with overflow
+checking on integral operands.
+
+The `kind` argument specifies the kind of arithmetic operation to perform.
+It can be either `add`, `sub`, or `mul`. The `lhs` and `rhs` arguments
+specify the input operands of the arithmetic operation. The types of `lhs`
+and `rhs` must be the same.
+
+`cir.binop.overflow` produces two SSA values. `result` is the result of the
+arithmetic operation truncated to its specified type. `overflow` is a
+boolean value indicating whether overflow happens during the operation.
+
+The exact semantic of this operation is as follows:
+
+  - `lhs` and `rhs` are promoted to an imaginary integral type that has
+infinite precision.
+  - The arithmetic operation is performed on the promoted operands.
+  - The infinite-precision result is truncated to the type of `result`. The
+truncated result is assigned to `result`.
+  - If the truncated result is equal to the un-truncated result, `overflow`
+is assigned to false. Otherwise, `overflow` is assigned to true.
+  }];
+
+  let arguments = (ins Arg:$kind,
+   CIR_IntType:$lhs, CIR_IntType:$rhs);
+  let results = (outs CIR_IntType:$result, CIR_BoolType:$overflow);
+
+  let assemblyFormat = [{
+`(` $kind `,` $lhs `,` $rhs `)` `:` type($lhs) `,`
+`(` type($result) `,` type($overflow) `)`
+attr-dict
+  }];
+
+  let builders = [
+OpBuilder<(ins "cir::IntType":$resultTy,
+   "cir::BinOpOverflowKind":$kind,
+   "mlir::Value":$lhs,
+   "mlir::Value":$rhs), [{
+  auto overflowTy = cir::BoolType::get($_builder.getContext());
+  build($_builder, $_state, resultTy, overflowTy, kind, lhs, rhs);
+}]>
+  ];
+}
+
 
//===--===//
 // GlobalOp
 
//===--===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 52bd3b2933744..010240273b5b9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -936,8 +936,102 @@ getUnwidenedIntegerType(const ASTContext &astContext, 
const Expr *e) {
 static mlir::Value emitPointerArithmetic(CIRGenFunction &cgf,
  const BinOpInfo &op,
  bool isSubtraction) {
-  cgf.cgm.errorNYI(op.loc, "pointer arithmetic");
-  return {};
+  // Must have binary (not unary) expr here.  Unary pointer
+  // increment/decrement doesn't use this path.
+  const BinaryOperator *expr = cast(op.e);
+
+  mlir::Value pointer = op.lhs;
+  Expr *pointerOperand = expr->getLHS();
+  mlir::Value index = op.rhs;
+  Expr *indexOperand = expr->getRHS();
+
+  // In a subtraction, the LHS is always the pointer.
+  if (!isSubtraction && !mlir::isa(pointer.getType())) {
+std::swap(pointer, index);
+std::swap(pointerOpera

[clang] [CIR] Add BinOpOverflowOp and basic pointer arithmetic support (PR #133118)

2025-03-26 Thread Morris Hafner via cfe-commits


@@ -223,6 +223,16 @@ class CIRGenFunction : public CIRGenTypeCache {
 
   void emitDecl(const clang::Decl &d);
 
+  /// Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check to
+  /// detect undefined behavior when the pointer overflow sanitizer is enabled.
+  /// \p SignedIndices indicates whether any of the GEP indices are signed.
+  /// \p IsSubtraction indicates whether the expression used to form the GEP
+  /// is a subtraction.
+  mlir::Value emitCheckedInBoundsGEP(mlir::Type elemTy, mlir::Value ptr,

mmha wrote:

Sure 👍 

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


[clang] [CIR] Upstream CmpOp (PR #133159)

2025-03-26 Thread Morris Hafner via cfe-commits

https://github.com/mmha created https://github.com/llvm/llvm-project/pull/133159

This patch adds support for comparison operators with ClangIR, both integral 
and floating point.

>From 6db5880fa7cdf6363d7e0025f811f42ec273df52 Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Wed, 26 Mar 2025 20:50:57 +
Subject: [PATCH] [CIR] Upstream CmpOp

This patch adds support for comparison operators with ClangIR, both integral 
and floating point.
---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h  |   5 +
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  44 
 clang/include/clang/CIR/MissingFeatures.h |   1 -
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp|  83 +++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  94 ++-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  14 ++
 clang/test/CIR/CodeGen/cmp.cpp| 233 ++
 7 files changed, 471 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/cmp.cpp

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index ac7658276ec37..b94e9f8490be5 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -265,6 +265,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return createAdd(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
   }
 
+  cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind,
+   mlir::Value lhs, mlir::Value rhs) {
+return create(loc, getBoolTy(), kind, lhs, rhs);
+  }
+
   //
   // Block handling helpers
   // --
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 455cc2b8b0277..3fba7566e9f1b 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -826,6 +826,50 @@ def ForOp : CIR_Op<"for", [LoopOpInterface, 
NoRegionArguments]> {
   }];
 }
 
+//===--===//
+// CmpOp
+//===--===//
+
+def CmpOpKind_LT : I32EnumAttrCase<"lt", 1>;
+def CmpOpKind_LE : I32EnumAttrCase<"le", 2>;
+def CmpOpKind_GT : I32EnumAttrCase<"gt", 3>;
+def CmpOpKind_GE : I32EnumAttrCase<"ge", 4>;
+def CmpOpKind_EQ : I32EnumAttrCase<"eq", 5>;
+def CmpOpKind_NE : I32EnumAttrCase<"ne", 6>;
+
+def CmpOpKind : I32EnumAttr<
+"CmpOpKind",
+"compare operation kind",
+[CmpOpKind_LT, CmpOpKind_LE, CmpOpKind_GT,
+ CmpOpKind_GE, CmpOpKind_EQ, CmpOpKind_NE]> {
+  let cppNamespace = "::cir";
+}
+
+def CmpOp : CIR_Op<"cmp", [Pure, SameTypeOperands]> {
+
+  let summary = "Compare values two values and produce a boolean result";
+  let description = [{
+`cir.cmp` compares two input operands of the same type and produces a
+`cir.bool` result. The kinds of comparison available are:
+[lt,gt,ge,eq,ne]
+
+```mlir
+%7 = cir.cmp(gt, %1, %2) : i32, !cir.bool
+```
+  }];
+
+  let results = (outs CIR_BoolType:$result);
+  let arguments = (ins Arg:$kind,
+   CIR_AnyType:$lhs, CIR_AnyType:$rhs);
+
+  let assemblyFormat = [{
+`(` $kind `,` $lhs `,` $rhs  `)` `:` type($lhs) `,` type($result) attr-dict
+  }];
+
+  // Already covered by the traits
+  let hasVerifier = 0;
+}
+
 
//===--===//
 // BinOp
 
//===--===//
diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 3a102d90aba8f..6e93f50ac83e6 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -89,7 +89,6 @@ struct MissingFeatures {
   static bool opGlobalViewAttr() { return false; }
   static bool lowerModeOptLevel() { return false; }
   static bool opTBAA() { return false; }
-  static bool opCmp() { return false; }
   static bool objCLifetime() { return false; }
   static bool emitNullabilityCheck() { return false; }
   static bool astVarDeclInterface() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 52bd3b2933744..992c92635369d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -710,6 +710,89 @@ class ScalarExprEmitter : public 
StmtVisitor {
   HANDLEBINOP(Xor)
   HANDLEBINOP(Or)
 #undef HANDLEBINOP
+
+  mlir::Value emitCmp(const BinaryOperator *e) {
+mlir::Value result;
+QualType lhsTy = e->getLHS()->getType();
+QualType rhsTy = e->getRHS()->getType();
+
+auto clangCmpToCIRCmp =
+[](clang::BinaryOperatorKind clangCmp) -> cir::CmpOpKind {
+  switch (clangCmp) {
+  case BO_LT:
+return cir::CmpOpKind::lt;
+  case BO_GT:
+return cir::CmpOpKind::gt

[clang] [CIR] Upstream CmpOp (PR #133159)

2025-03-26 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/133159

>From 6db5880fa7cdf6363d7e0025f811f42ec273df52 Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Wed, 26 Mar 2025 20:50:57 +
Subject: [PATCH 1/2] [CIR] Upstream CmpOp

This patch adds support for comparison operators with ClangIR, both integral 
and floating point.
---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h  |   5 +
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  44 
 clang/include/clang/CIR/MissingFeatures.h |   1 -
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp|  83 +++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  94 ++-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  14 ++
 clang/test/CIR/CodeGen/cmp.cpp| 233 ++
 7 files changed, 471 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/cmp.cpp

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index ac7658276ec37..b94e9f8490be5 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -265,6 +265,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return createAdd(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
   }
 
+  cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind,
+   mlir::Value lhs, mlir::Value rhs) {
+return create(loc, getBoolTy(), kind, lhs, rhs);
+  }
+
   //
   // Block handling helpers
   // --
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 455cc2b8b0277..3fba7566e9f1b 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -826,6 +826,50 @@ def ForOp : CIR_Op<"for", [LoopOpInterface, 
NoRegionArguments]> {
   }];
 }
 
+//===--===//
+// CmpOp
+//===--===//
+
+def CmpOpKind_LT : I32EnumAttrCase<"lt", 1>;
+def CmpOpKind_LE : I32EnumAttrCase<"le", 2>;
+def CmpOpKind_GT : I32EnumAttrCase<"gt", 3>;
+def CmpOpKind_GE : I32EnumAttrCase<"ge", 4>;
+def CmpOpKind_EQ : I32EnumAttrCase<"eq", 5>;
+def CmpOpKind_NE : I32EnumAttrCase<"ne", 6>;
+
+def CmpOpKind : I32EnumAttr<
+"CmpOpKind",
+"compare operation kind",
+[CmpOpKind_LT, CmpOpKind_LE, CmpOpKind_GT,
+ CmpOpKind_GE, CmpOpKind_EQ, CmpOpKind_NE]> {
+  let cppNamespace = "::cir";
+}
+
+def CmpOp : CIR_Op<"cmp", [Pure, SameTypeOperands]> {
+
+  let summary = "Compare values two values and produce a boolean result";
+  let description = [{
+`cir.cmp` compares two input operands of the same type and produces a
+`cir.bool` result. The kinds of comparison available are:
+[lt,gt,ge,eq,ne]
+
+```mlir
+%7 = cir.cmp(gt, %1, %2) : i32, !cir.bool
+```
+  }];
+
+  let results = (outs CIR_BoolType:$result);
+  let arguments = (ins Arg:$kind,
+   CIR_AnyType:$lhs, CIR_AnyType:$rhs);
+
+  let assemblyFormat = [{
+`(` $kind `,` $lhs `,` $rhs  `)` `:` type($lhs) `,` type($result) attr-dict
+  }];
+
+  // Already covered by the traits
+  let hasVerifier = 0;
+}
+
 
//===--===//
 // BinOp
 
//===--===//
diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 3a102d90aba8f..6e93f50ac83e6 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -89,7 +89,6 @@ struct MissingFeatures {
   static bool opGlobalViewAttr() { return false; }
   static bool lowerModeOptLevel() { return false; }
   static bool opTBAA() { return false; }
-  static bool opCmp() { return false; }
   static bool objCLifetime() { return false; }
   static bool emitNullabilityCheck() { return false; }
   static bool astVarDeclInterface() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 52bd3b2933744..992c92635369d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -710,6 +710,89 @@ class ScalarExprEmitter : public 
StmtVisitor {
   HANDLEBINOP(Xor)
   HANDLEBINOP(Or)
 #undef HANDLEBINOP
+
+  mlir::Value emitCmp(const BinaryOperator *e) {
+mlir::Value result;
+QualType lhsTy = e->getLHS()->getType();
+QualType rhsTy = e->getRHS()->getType();
+
+auto clangCmpToCIRCmp =
+[](clang::BinaryOperatorKind clangCmp) -> cir::CmpOpKind {
+  switch (clangCmp) {
+  case BO_LT:
+return cir::CmpOpKind::lt;
+  case BO_GT:
+return cir::CmpOpKind::gt;
+  case BO_LE:
+return cir::CmpOpKind::le;
+  case BO_GE:
+return cir

[clang] [CIR] Upstream CmpOp (PR #133159)

2025-03-27 Thread Morris Hafner via cfe-commits

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


[clang] [CIR] Upstream CmpOp (PR #133159)

2025-03-27 Thread Morris Hafner via cfe-commits


@@ -710,6 +710,89 @@ class ScalarExprEmitter : public 
StmtVisitor {
   HANDLEBINOP(Xor)
   HANDLEBINOP(Or)
 #undef HANDLEBINOP
+
+  mlir::Value emitCmp(const BinaryOperator *e) {
+mlir::Value result;
+QualType lhsTy = e->getLHS()->getType();
+QualType rhsTy = e->getRHS()->getType();
+
+auto clangCmpToCIRCmp =
+[](clang::BinaryOperatorKind clangCmp) -> cir::CmpOpKind {
+  switch (clangCmp) {
+  case BO_LT:
+return cir::CmpOpKind::lt;
+  case BO_GT:
+return cir::CmpOpKind::gt;
+  case BO_LE:
+return cir::CmpOpKind::le;
+  case BO_GE:
+return cir::CmpOpKind::ge;
+  case BO_EQ:
+return cir::CmpOpKind::eq;
+  case BO_NE:
+return cir::CmpOpKind::ne;
+  default:
+llvm_unreachable("unsupported comparison kind");
+  }
+};
+
+if (lhsTy->getAs()) {
+  assert(e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE);
+  mlir::Value lhs = cgf.emitScalarExpr(e->getLHS());
+  mlir::Value rhs = cgf.emitScalarExpr(e->getRHS());
+  cir::CmpOpKind kind = clangCmpToCIRCmp(e->getOpcode());
+  result =
+  builder.createCompare(cgf.getLoc(e->getExprLoc()), kind, lhs, rhs);
+} else if (!lhsTy->isAnyComplexType() && !rhsTy->isAnyComplexType()) {
+  BinOpInfo boInfo = emitBinOps(e);
+  mlir::Value lhs = boInfo.lhs;
+  mlir::Value rhs = boInfo.rhs;
+
+  if (lhsTy->isVectorType()) {
+assert(!cir::MissingFeatures::vectorType());
+cgf.cgm.errorNYI(boInfo.loc, "vector comparisons");
+result = builder.getBool(false, cgf.getLoc(boInfo.loc));
+  } else if (boInfo.isFixedPointOp()) {
+assert(!cir::MissingFeatures::fixedPointType());
+cgf.cgm.errorNYI(boInfo.loc, "fixed point comparisons");
+result = builder.getBool(false, cgf.getLoc(boInfo.loc));
+  } else if (lhsTy->hasSignedIntegerRepresentation()) {

mmha wrote:

I think it's better to remove that branch altogether and let the `else` deal 
with it.

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


[clang] [CIR] Upstream CmpOp (PR #133159)

2025-03-27 Thread Morris Hafner via cfe-commits


@@ -710,6 +710,89 @@ class ScalarExprEmitter : public 
StmtVisitor {
   HANDLEBINOP(Xor)
   HANDLEBINOP(Or)
 #undef HANDLEBINOP
+
+  mlir::Value emitCmp(const BinaryOperator *e) {
+mlir::Value result;
+QualType lhsTy = e->getLHS()->getType();
+QualType rhsTy = e->getRHS()->getType();
+
+auto clangCmpToCIRCmp =
+[](clang::BinaryOperatorKind clangCmp) -> cir::CmpOpKind {
+  switch (clangCmp) {
+  case BO_LT:
+return cir::CmpOpKind::lt;
+  case BO_GT:
+return cir::CmpOpKind::gt;
+  case BO_LE:
+return cir::CmpOpKind::le;
+  case BO_GE:
+return cir::CmpOpKind::ge;
+  case BO_EQ:
+return cir::CmpOpKind::eq;
+  case BO_NE:
+return cir::CmpOpKind::ne;
+  default:
+llvm_unreachable("unsupported comparison kind");
+  }
+};
+
+if (lhsTy->getAs()) {
+  assert(e->getOpcode() == BO_EQ || e->getOpcode() == BO_NE);
+  mlir::Value lhs = cgf.emitScalarExpr(e->getLHS());
+  mlir::Value rhs = cgf.emitScalarExpr(e->getRHS());
+  cir::CmpOpKind kind = clangCmpToCIRCmp(e->getOpcode());
+  result =
+  builder.createCompare(cgf.getLoc(e->getExprLoc()), kind, lhs, rhs);
+} else if (!lhsTy->isAnyComplexType() && !rhsTy->isAnyComplexType()) {
+  BinOpInfo boInfo = emitBinOps(e);
+  mlir::Value lhs = boInfo.lhs;
+  mlir::Value rhs = boInfo.rhs;
+
+  if (lhsTy->isVectorType()) {
+assert(!cir::MissingFeatures::vectorType());
+cgf.cgm.errorNYI(boInfo.loc, "vector comparisons");
+result = builder.getBool(false, cgf.getLoc(boInfo.loc));
+  } else if (boInfo.isFixedPointOp()) {
+assert(!cir::MissingFeatures::fixedPointType());
+cgf.cgm.errorNYI(boInfo.loc, "fixed point comparisons");
+result = builder.getBool(false, cgf.getLoc(boInfo.loc));
+  } else if (lhsTy->hasSignedIntegerRepresentation()) {
+cir::CmpOpKind kind = clangCmpToCIRCmp(e->getOpcode());
+result = builder.createCompare(cgf.getLoc(boInfo.loc), kind, lhs, rhs);
+  } else {
+// Unsigned integers and pointers.
+if (cgf.cgm.getCodeGenOpts().StrictVTablePointers &&
+mlir::isa(lhs.getType()) &&
+mlir::isa(rhs.getType())) {
+  cgf.cgm.errorNYI(boInfo.loc, "strict vtable pointer comparisons");
+  result = builder.getBool(false, cgf.getLoc(boInfo.loc));
+}
+
+cir::CmpOpKind kind = clangCmpToCIRCmp(e->getOpcode());
+result = builder.createCompare(cgf.getLoc(boInfo.loc), kind, lhs, rhs);
+  }
+} else {
+  // Complex Comparison: can only be an equality comparison.
+  assert(!cir::MissingFeatures::complexType());
+  const mlir::Location loc = cgf.getLoc(e->getSourceRange());
+  cgf.cgm.errorNYI(loc, "complex comparison");
+  result = builder.getBool(false, loc);
+}
+
+return emitScalarConversion(result, cgf.getContext().BoolTy, e->getType(),
+e->getExprLoc());
+  }

mmha wrote:

FWIW classic codegen uses `getExprLoc` and doesnt emit a range.

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


[clang] [CIR] Upstream CmpOp (PR #133159)

2025-03-27 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/133159

>From 6db5880fa7cdf6363d7e0025f811f42ec273df52 Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Wed, 26 Mar 2025 20:50:57 +
Subject: [PATCH 1/3] [CIR] Upstream CmpOp

This patch adds support for comparison operators with ClangIR, both integral 
and floating point.
---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h  |   5 +
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  44 
 clang/include/clang/CIR/MissingFeatures.h |   1 -
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp|  83 +++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  94 ++-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  14 ++
 clang/test/CIR/CodeGen/cmp.cpp| 233 ++
 7 files changed, 471 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/cmp.cpp

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index ac7658276ec37..b94e9f8490be5 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -265,6 +265,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return createAdd(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
   }
 
+  cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind,
+   mlir::Value lhs, mlir::Value rhs) {
+return create(loc, getBoolTy(), kind, lhs, rhs);
+  }
+
   //
   // Block handling helpers
   // --
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 455cc2b8b0277..3fba7566e9f1b 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -826,6 +826,50 @@ def ForOp : CIR_Op<"for", [LoopOpInterface, 
NoRegionArguments]> {
   }];
 }
 
+//===--===//
+// CmpOp
+//===--===//
+
+def CmpOpKind_LT : I32EnumAttrCase<"lt", 1>;
+def CmpOpKind_LE : I32EnumAttrCase<"le", 2>;
+def CmpOpKind_GT : I32EnumAttrCase<"gt", 3>;
+def CmpOpKind_GE : I32EnumAttrCase<"ge", 4>;
+def CmpOpKind_EQ : I32EnumAttrCase<"eq", 5>;
+def CmpOpKind_NE : I32EnumAttrCase<"ne", 6>;
+
+def CmpOpKind : I32EnumAttr<
+"CmpOpKind",
+"compare operation kind",
+[CmpOpKind_LT, CmpOpKind_LE, CmpOpKind_GT,
+ CmpOpKind_GE, CmpOpKind_EQ, CmpOpKind_NE]> {
+  let cppNamespace = "::cir";
+}
+
+def CmpOp : CIR_Op<"cmp", [Pure, SameTypeOperands]> {
+
+  let summary = "Compare values two values and produce a boolean result";
+  let description = [{
+`cir.cmp` compares two input operands of the same type and produces a
+`cir.bool` result. The kinds of comparison available are:
+[lt,gt,ge,eq,ne]
+
+```mlir
+%7 = cir.cmp(gt, %1, %2) : i32, !cir.bool
+```
+  }];
+
+  let results = (outs CIR_BoolType:$result);
+  let arguments = (ins Arg:$kind,
+   CIR_AnyType:$lhs, CIR_AnyType:$rhs);
+
+  let assemblyFormat = [{
+`(` $kind `,` $lhs `,` $rhs  `)` `:` type($lhs) `,` type($result) attr-dict
+  }];
+
+  // Already covered by the traits
+  let hasVerifier = 0;
+}
+
 
//===--===//
 // BinOp
 
//===--===//
diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 3a102d90aba8f..6e93f50ac83e6 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -89,7 +89,6 @@ struct MissingFeatures {
   static bool opGlobalViewAttr() { return false; }
   static bool lowerModeOptLevel() { return false; }
   static bool opTBAA() { return false; }
-  static bool opCmp() { return false; }
   static bool objCLifetime() { return false; }
   static bool emitNullabilityCheck() { return false; }
   static bool astVarDeclInterface() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 52bd3b2933744..992c92635369d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -710,6 +710,89 @@ class ScalarExprEmitter : public 
StmtVisitor {
   HANDLEBINOP(Xor)
   HANDLEBINOP(Or)
 #undef HANDLEBINOP
+
+  mlir::Value emitCmp(const BinaryOperator *e) {
+mlir::Value result;
+QualType lhsTy = e->getLHS()->getType();
+QualType rhsTy = e->getRHS()->getType();
+
+auto clangCmpToCIRCmp =
+[](clang::BinaryOperatorKind clangCmp) -> cir::CmpOpKind {
+  switch (clangCmp) {
+  case BO_LT:
+return cir::CmpOpKind::lt;
+  case BO_GT:
+return cir::CmpOpKind::gt;
+  case BO_LE:
+return cir::CmpOpKind::le;
+  case BO_GE:
+return cir

[clang] [CIR] Upstream CmpOp (PR #133159)

2025-03-27 Thread Morris Hafner via cfe-commits


@@ -514,9 +515,17 @@ mlir::LogicalResult 
CIRToLLVMCastOpLowering::matchAndRewrite(
 assert(!MissingFeatures::cxxABI());
 assert(!MissingFeatures::dataMemberType());
 break;
-  case cir::CastKind::ptr_to_bool:
-assert(!cir::MissingFeatures::opCmp());
+  case cir::CastKind::ptr_to_bool: {

mmha wrote:

I wanted to ask you the same question so I guess the answer is no :D

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


[clang] [CIR] Upstream CmpOp (PR #133159)

2025-03-27 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/133159

>From 6db5880fa7cdf6363d7e0025f811f42ec273df52 Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Wed, 26 Mar 2025 20:50:57 +
Subject: [PATCH 1/4] [CIR] Upstream CmpOp

This patch adds support for comparison operators with ClangIR, both integral 
and floating point.
---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h  |   5 +
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  44 
 clang/include/clang/CIR/MissingFeatures.h |   1 -
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp|  83 +++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  94 ++-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  14 ++
 clang/test/CIR/CodeGen/cmp.cpp| 233 ++
 7 files changed, 471 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/cmp.cpp

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index ac7658276ec37..b94e9f8490be5 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -265,6 +265,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return createAdd(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
   }
 
+  cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind,
+   mlir::Value lhs, mlir::Value rhs) {
+return create(loc, getBoolTy(), kind, lhs, rhs);
+  }
+
   //
   // Block handling helpers
   // --
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 455cc2b8b0277..3fba7566e9f1b 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -826,6 +826,50 @@ def ForOp : CIR_Op<"for", [LoopOpInterface, 
NoRegionArguments]> {
   }];
 }
 
+//===--===//
+// CmpOp
+//===--===//
+
+def CmpOpKind_LT : I32EnumAttrCase<"lt", 1>;
+def CmpOpKind_LE : I32EnumAttrCase<"le", 2>;
+def CmpOpKind_GT : I32EnumAttrCase<"gt", 3>;
+def CmpOpKind_GE : I32EnumAttrCase<"ge", 4>;
+def CmpOpKind_EQ : I32EnumAttrCase<"eq", 5>;
+def CmpOpKind_NE : I32EnumAttrCase<"ne", 6>;
+
+def CmpOpKind : I32EnumAttr<
+"CmpOpKind",
+"compare operation kind",
+[CmpOpKind_LT, CmpOpKind_LE, CmpOpKind_GT,
+ CmpOpKind_GE, CmpOpKind_EQ, CmpOpKind_NE]> {
+  let cppNamespace = "::cir";
+}
+
+def CmpOp : CIR_Op<"cmp", [Pure, SameTypeOperands]> {
+
+  let summary = "Compare values two values and produce a boolean result";
+  let description = [{
+`cir.cmp` compares two input operands of the same type and produces a
+`cir.bool` result. The kinds of comparison available are:
+[lt,gt,ge,eq,ne]
+
+```mlir
+%7 = cir.cmp(gt, %1, %2) : i32, !cir.bool
+```
+  }];
+
+  let results = (outs CIR_BoolType:$result);
+  let arguments = (ins Arg:$kind,
+   CIR_AnyType:$lhs, CIR_AnyType:$rhs);
+
+  let assemblyFormat = [{
+`(` $kind `,` $lhs `,` $rhs  `)` `:` type($lhs) `,` type($result) attr-dict
+  }];
+
+  // Already covered by the traits
+  let hasVerifier = 0;
+}
+
 
//===--===//
 // BinOp
 
//===--===//
diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 3a102d90aba8f..6e93f50ac83e6 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -89,7 +89,6 @@ struct MissingFeatures {
   static bool opGlobalViewAttr() { return false; }
   static bool lowerModeOptLevel() { return false; }
   static bool opTBAA() { return false; }
-  static bool opCmp() { return false; }
   static bool objCLifetime() { return false; }
   static bool emitNullabilityCheck() { return false; }
   static bool astVarDeclInterface() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 52bd3b2933744..992c92635369d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -710,6 +710,89 @@ class ScalarExprEmitter : public 
StmtVisitor {
   HANDLEBINOP(Xor)
   HANDLEBINOP(Or)
 #undef HANDLEBINOP
+
+  mlir::Value emitCmp(const BinaryOperator *e) {
+mlir::Value result;
+QualType lhsTy = e->getLHS()->getType();
+QualType rhsTy = e->getRHS()->getType();
+
+auto clangCmpToCIRCmp =
+[](clang::BinaryOperatorKind clangCmp) -> cir::CmpOpKind {
+  switch (clangCmp) {
+  case BO_LT:
+return cir::CmpOpKind::lt;
+  case BO_GT:
+return cir::CmpOpKind::gt;
+  case BO_LE:
+return cir::CmpOpKind::le;
+  case BO_GE:
+return cir

[clang] [CIR] Upstream CmpOp (PR #133159)

2025-03-27 Thread Morris Hafner via cfe-commits


@@ -0,0 +1,233 @@
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir 
-emit-cir -DCIR_ONLY %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM

mmha wrote:

Done. I also added tests for int/ptr to bool in the casting tests.

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


[clang] [CIR] Upstream binary assignments and comma (PR #135115)

2025-04-09 Thread Morris Hafner via cfe-commits

https://github.com/mmha created https://github.com/llvm/llvm-project/pull/135115

This patch adds `VisitBinAssign` and `VisitBinComma` to the ClangIR 
`ScalarExprEmitter` to enable assignments and the comma operator.

>From bcaeadf7fff01d2d92b0d234b40f8d5884974e4c Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Thu, 10 Apr 2025 03:53:43 +0200
Subject: [PATCH] [CIR] Upstream binary assignments and comma

This patch adds `VisitBinAssign` and `VisitBinComma` to the ClangIR 
`ScalarExprEmitter` to enable assignments and the comma operator.
---
 clang/include/clang/CIR/MissingFeatures.h  |  1 +
 clang/lib/CIR/CodeGen/CIRGenDecl.cpp   |  8 +++
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp   |  7 +++
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 60 ++
 clang/lib/CIR/CodeGen/CIRGenFunction.h |  8 +++
 clang/test/CIR/CodeGen/binassign.c | 56 
 clang/test/CIR/CodeGen/comma.c | 53 +++
 clang/test/CIR/IR/binassign.cir| 45 
 8 files changed, 238 insertions(+)
 create mode 100644 clang/test/CIR/CodeGen/binassign.c
 create mode 100644 clang/test/CIR/CodeGen/comma.c
 create mode 100644 clang/test/CIR/IR/binassign.cir

diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 3188429ea3b1b..19cd9c03635b3 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -113,6 +113,7 @@ struct MissingFeatures {
   static bool incrementProfileCounter() { return false; }
   static bool insertBuiltinUnpredictable() { return false; }
   static bool objCGC() { return false; }
+  static bool bitfields() { return false; }
 
   // Missing types
   static bool dataMemberType() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp 
b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index b8e72f299acb6..58797c5dd253a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -277,3 +277,11 @@ void CIRGenFunction::emitDecl(const Decl &d) {
 cgm.errorNYI(d.getSourceRange(), "emitDecl: unhandled decl type");
   }
 }
+
+void CIRGenFunction::emitNullabilityCheck(LValue lhs, mlir::Value rhs,
+  SourceLocation loc) {
+  if (!sanOpts.has(SanitizerKind::NullabilityAssign))
+return;
+
+  assert(!cir::MissingFeatures::sanitizers());
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 4b6652ad0b9e6..66caea26c3636 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -219,6 +219,13 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, 
Address addr,
   assert(!cir::MissingFeatures::opTBAA());
 }
 
+void CIRGenFunction::emitStoreThroughBitfieldLValue(RValue src, LValue dst,
+mlir::Value &result) {
+  assert(!cir::MissingFeatures::bitfields());
+  cgm.errorNYI("bitfields");
+  result = {};
+}
+
 mlir::Value CIRGenFunction::emitToMemory(mlir::Value value, QualType ty) {
   // Bool has a different representation in memory than in registers,
   // but in ClangIR, it is simply represented as a cir.bool value.
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 4042f5dc23e4b..955082047bd38 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -21,6 +21,7 @@
 #include "mlir/IR/Value.h"
 
 #include 
+#include 
 
 using namespace clang;
 using namespace clang::CIRGen;
@@ -807,6 +808,65 @@ class ScalarExprEmitter : public 
StmtVisitor {
   VISITCOMP(EQ)
   VISITCOMP(NE)
 #undef VISITCOMP
+
+  mlir::Value VisitBinAssign(const BinaryOperator *e) {
+const bool ignore = std::exchange(ignoreResultAssign, false);
+
+mlir::Value rhs;
+LValue lhs;
+
+switch (e->getLHS()->getType().getObjCLifetime()) {
+case Qualifiers::OCL_Strong:
+case Qualifiers::OCL_Autoreleasing:
+case Qualifiers::OCL_ExplicitNone:
+case Qualifiers::OCL_Weak:
+  assert(!cir::MissingFeatures::objCLifetime());
+  break;
+case Qualifiers::OCL_None:
+  // __block variables need to have the rhs evaluated first, plus this
+  // should improve codegen just a little.
+  rhs = Visit(e->getRHS());
+  assert(!cir::MissingFeatures::sanitizers());
+  // TODO(cir): This needs to be emitCheckedLValue() once we support
+  // sanitizers
+  lhs = cgf.emitLValue(e->getLHS());
+
+  // Store the value into the LHS. Bit-fields are handled specially because
+  // the result is altered by the store, i.e., [C99 6.5.16p1]
+  // 'An assignment expression has the value of the left operand after the
+  // assignment...'.
+  if (lhs.isBitField()) {
+cgf.emitStoreThroughBitfieldLValue(RValue::get(rhs), lhs, rhs);
+  } else {
+cgf.emitNullabilityCheck(lhs, rhs, e->getExprLoc());
+ 

[clang] [CIR] Upstream binary assignments and comma (PR #135115)

2025-04-10 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/135115

>From bcaeadf7fff01d2d92b0d234b40f8d5884974e4c Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Thu, 10 Apr 2025 03:53:43 +0200
Subject: [PATCH 1/2] [CIR] Upstream binary assignments and comma

This patch adds `VisitBinAssign` and `VisitBinComma` to the ClangIR 
`ScalarExprEmitter` to enable assignments and the comma operator.
---
 clang/include/clang/CIR/MissingFeatures.h  |  1 +
 clang/lib/CIR/CodeGen/CIRGenDecl.cpp   |  8 +++
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp   |  7 +++
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 60 ++
 clang/lib/CIR/CodeGen/CIRGenFunction.h |  8 +++
 clang/test/CIR/CodeGen/binassign.c | 56 
 clang/test/CIR/CodeGen/comma.c | 53 +++
 clang/test/CIR/IR/binassign.cir| 45 
 8 files changed, 238 insertions(+)
 create mode 100644 clang/test/CIR/CodeGen/binassign.c
 create mode 100644 clang/test/CIR/CodeGen/comma.c
 create mode 100644 clang/test/CIR/IR/binassign.cir

diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 3188429ea3b1b..19cd9c03635b3 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -113,6 +113,7 @@ struct MissingFeatures {
   static bool incrementProfileCounter() { return false; }
   static bool insertBuiltinUnpredictable() { return false; }
   static bool objCGC() { return false; }
+  static bool bitfields() { return false; }
 
   // Missing types
   static bool dataMemberType() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp 
b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index b8e72f299acb6..58797c5dd253a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -277,3 +277,11 @@ void CIRGenFunction::emitDecl(const Decl &d) {
 cgm.errorNYI(d.getSourceRange(), "emitDecl: unhandled decl type");
   }
 }
+
+void CIRGenFunction::emitNullabilityCheck(LValue lhs, mlir::Value rhs,
+  SourceLocation loc) {
+  if (!sanOpts.has(SanitizerKind::NullabilityAssign))
+return;
+
+  assert(!cir::MissingFeatures::sanitizers());
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 4b6652ad0b9e6..66caea26c3636 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -219,6 +219,13 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, 
Address addr,
   assert(!cir::MissingFeatures::opTBAA());
 }
 
+void CIRGenFunction::emitStoreThroughBitfieldLValue(RValue src, LValue dst,
+mlir::Value &result) {
+  assert(!cir::MissingFeatures::bitfields());
+  cgm.errorNYI("bitfields");
+  result = {};
+}
+
 mlir::Value CIRGenFunction::emitToMemory(mlir::Value value, QualType ty) {
   // Bool has a different representation in memory than in registers,
   // but in ClangIR, it is simply represented as a cir.bool value.
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 4042f5dc23e4b..955082047bd38 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -21,6 +21,7 @@
 #include "mlir/IR/Value.h"
 
 #include 
+#include 
 
 using namespace clang;
 using namespace clang::CIRGen;
@@ -807,6 +808,65 @@ class ScalarExprEmitter : public 
StmtVisitor {
   VISITCOMP(EQ)
   VISITCOMP(NE)
 #undef VISITCOMP
+
+  mlir::Value VisitBinAssign(const BinaryOperator *e) {
+const bool ignore = std::exchange(ignoreResultAssign, false);
+
+mlir::Value rhs;
+LValue lhs;
+
+switch (e->getLHS()->getType().getObjCLifetime()) {
+case Qualifiers::OCL_Strong:
+case Qualifiers::OCL_Autoreleasing:
+case Qualifiers::OCL_ExplicitNone:
+case Qualifiers::OCL_Weak:
+  assert(!cir::MissingFeatures::objCLifetime());
+  break;
+case Qualifiers::OCL_None:
+  // __block variables need to have the rhs evaluated first, plus this
+  // should improve codegen just a little.
+  rhs = Visit(e->getRHS());
+  assert(!cir::MissingFeatures::sanitizers());
+  // TODO(cir): This needs to be emitCheckedLValue() once we support
+  // sanitizers
+  lhs = cgf.emitLValue(e->getLHS());
+
+  // Store the value into the LHS. Bit-fields are handled specially because
+  // the result is altered by the store, i.e., [C99 6.5.16p1]
+  // 'An assignment expression has the value of the left operand after the
+  // assignment...'.
+  if (lhs.isBitField()) {
+cgf.emitStoreThroughBitfieldLValue(RValue::get(rhs), lhs, rhs);
+  } else {
+cgf.emitNullabilityCheck(lhs, rhs, e->getExprLoc());
+CIRGenFunction::SourceLocRAIIObject loc{
+cgf, cgf.getLoc(e->getSourceRange())};
+cgf.emitStoreThroughLVa

[clang] [CIR] Upstream binary assignments and comma (PR #135115)

2025-04-10 Thread Morris Hafner via cfe-commits


@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -std=c23 -triple x86_64-unknown-linux-gnu -fclangir 
-emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -std=c23 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -std=c23 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+void comma(void) {
+bool b;
+char c;
+float f;
+int i;
+
+b = true, c = 65, f = 3.14f, i = 42;

mmha wrote:

So, I did add another test for `i = 100, 200;` but we don't support ParenExprs, 
yet, so I can't really check that the result of that expression is `200` for 
now.

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


[clang] [CIR] Upstream binary assignments and comma (PR #135115)

2025-04-09 Thread Morris Hafner via cfe-commits

mmha wrote:

cc @erichkeane @andykaylor @dkolsen-pgi 

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


[clang] [CIR] Upstream CmpOp (PR #133159)

2025-04-08 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/133159

>From 57b1d4e30ab61c1723b34fea137e2e900b53e30e Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Tue, 8 Apr 2025 15:02:12 +0200
Subject: [PATCH 1/5] [CIR] Upstream CmpOp

This patch adds support for comparison operators with ClangIR, both integral 
and floating point.
---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h  |   5 +
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  44 
 clang/include/clang/CIR/MissingFeatures.h |   1 -
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp|  83 +++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  82 ++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  14 ++
 clang/test/CIR/CodeGen/cmp.cpp| 233 ++
 7 files changed, 461 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CIR/CodeGen/cmp.cpp

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index c1e93fe790c08..429d217541e28 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -335,6 +335,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return createAdd(loc, lhs, rhs, OverflowBehavior::NoUnsignedWrap);
   }
 
+  cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind,
+   mlir::Value lhs, mlir::Value rhs) {
+return create(loc, getBoolTy(), kind, lhs, rhs);
+  }
+
   //
   // Block handling helpers
   // --
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 609e60ca74b49..0d9864e1866fc 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -1001,6 +1001,50 @@ def ForOp : LoopOpBase<"for"> {
   }];
 }
 
+//===--===//
+// CmpOp
+//===--===//
+
+def CmpOpKind_LT : I32EnumAttrCase<"lt", 1>;
+def CmpOpKind_LE : I32EnumAttrCase<"le", 2>;
+def CmpOpKind_GT : I32EnumAttrCase<"gt", 3>;
+def CmpOpKind_GE : I32EnumAttrCase<"ge", 4>;
+def CmpOpKind_EQ : I32EnumAttrCase<"eq", 5>;
+def CmpOpKind_NE : I32EnumAttrCase<"ne", 6>;
+
+def CmpOpKind : I32EnumAttr<
+"CmpOpKind",
+"compare operation kind",
+[CmpOpKind_LT, CmpOpKind_LE, CmpOpKind_GT,
+ CmpOpKind_GE, CmpOpKind_EQ, CmpOpKind_NE]> {
+  let cppNamespace = "::cir";
+}
+
+def CmpOp : CIR_Op<"cmp", [Pure, SameTypeOperands]> {
+
+  let summary = "Compare values two values and produce a boolean result";
+  let description = [{
+`cir.cmp` compares two input operands of the same type and produces a
+`cir.bool` result. The kinds of comparison available are:
+[lt,gt,ge,eq,ne]
+
+```mlir
+%7 = cir.cmp(gt, %1, %2) : i32, !cir.bool
+```
+  }];
+
+  let results = (outs CIR_BoolType:$result);
+  let arguments = (ins Arg:$kind,
+   CIR_AnyType:$lhs, CIR_AnyType:$rhs);
+
+  let assemblyFormat = [{
+`(` $kind `,` $lhs `,` $rhs  `)` `:` type($lhs) `,` type($result) attr-dict
+  }];
+
+  // Already covered by the traits
+  let hasVerifier = 0;
+}
+
 
//===--===//
 // BinOp
 
//===--===//
diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 86fdaf1ddaf51..c1963b15e3199 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -88,7 +88,6 @@ struct MissingFeatures {
   static bool opGlobalViewAttr() { return false; }
   static bool lowerModeOptLevel() { return false; }
   static bool opTBAA() { return false; }
-  static bool opCmp() { return false; }
   static bool objCLifetime() { return false; }
   static bool emitNullabilityCheck() { return false; }
   static bool astVarDeclInterface() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 3863d21487531..478234fb579a9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -707,6 +707,89 @@ class ScalarExprEmitter : public 
StmtVisitor {
   HANDLEBINOP(Xor)
   HANDLEBINOP(Or)
 #undef HANDLEBINOP
+
+  mlir::Value emitCmp(const BinaryOperator *e) {
+mlir::Value result;
+QualType lhsTy = e->getLHS()->getType();
+QualType rhsTy = e->getRHS()->getType();
+
+auto clangCmpToCIRCmp =
+[](clang::BinaryOperatorKind clangCmp) -> cir::CmpOpKind {
+  switch (clangCmp) {
+  case BO_LT:
+return cir::CmpOpKind::lt;
+  case BO_GT:
+return cir::CmpOpKind::gt;
+  case BO_LE:
+return cir::CmpOpKind::le;
+  case BO_GE:
+return cir::CmpOpKind::ge;
+  case BO_EQ:

[clang] [CIR] Upstream binary assignments and comma (PR #135115)

2025-04-11 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/135115

>From bcaeadf7fff01d2d92b0d234b40f8d5884974e4c Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Thu, 10 Apr 2025 03:53:43 +0200
Subject: [PATCH 1/3] [CIR] Upstream binary assignments and comma

This patch adds `VisitBinAssign` and `VisitBinComma` to the ClangIR 
`ScalarExprEmitter` to enable assignments and the comma operator.
---
 clang/include/clang/CIR/MissingFeatures.h  |  1 +
 clang/lib/CIR/CodeGen/CIRGenDecl.cpp   |  8 +++
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp   |  7 +++
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 60 ++
 clang/lib/CIR/CodeGen/CIRGenFunction.h |  8 +++
 clang/test/CIR/CodeGen/binassign.c | 56 
 clang/test/CIR/CodeGen/comma.c | 53 +++
 clang/test/CIR/IR/binassign.cir| 45 
 8 files changed, 238 insertions(+)
 create mode 100644 clang/test/CIR/CodeGen/binassign.c
 create mode 100644 clang/test/CIR/CodeGen/comma.c
 create mode 100644 clang/test/CIR/IR/binassign.cir

diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 3188429ea3b1b..19cd9c03635b3 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -113,6 +113,7 @@ struct MissingFeatures {
   static bool incrementProfileCounter() { return false; }
   static bool insertBuiltinUnpredictable() { return false; }
   static bool objCGC() { return false; }
+  static bool bitfields() { return false; }
 
   // Missing types
   static bool dataMemberType() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp 
b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index b8e72f299acb6..58797c5dd253a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -277,3 +277,11 @@ void CIRGenFunction::emitDecl(const Decl &d) {
 cgm.errorNYI(d.getSourceRange(), "emitDecl: unhandled decl type");
   }
 }
+
+void CIRGenFunction::emitNullabilityCheck(LValue lhs, mlir::Value rhs,
+  SourceLocation loc) {
+  if (!sanOpts.has(SanitizerKind::NullabilityAssign))
+return;
+
+  assert(!cir::MissingFeatures::sanitizers());
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 4b6652ad0b9e6..66caea26c3636 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -219,6 +219,13 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, 
Address addr,
   assert(!cir::MissingFeatures::opTBAA());
 }
 
+void CIRGenFunction::emitStoreThroughBitfieldLValue(RValue src, LValue dst,
+mlir::Value &result) {
+  assert(!cir::MissingFeatures::bitfields());
+  cgm.errorNYI("bitfields");
+  result = {};
+}
+
 mlir::Value CIRGenFunction::emitToMemory(mlir::Value value, QualType ty) {
   // Bool has a different representation in memory than in registers,
   // but in ClangIR, it is simply represented as a cir.bool value.
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 4042f5dc23e4b..955082047bd38 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -21,6 +21,7 @@
 #include "mlir/IR/Value.h"
 
 #include 
+#include 
 
 using namespace clang;
 using namespace clang::CIRGen;
@@ -807,6 +808,65 @@ class ScalarExprEmitter : public 
StmtVisitor {
   VISITCOMP(EQ)
   VISITCOMP(NE)
 #undef VISITCOMP
+
+  mlir::Value VisitBinAssign(const BinaryOperator *e) {
+const bool ignore = std::exchange(ignoreResultAssign, false);
+
+mlir::Value rhs;
+LValue lhs;
+
+switch (e->getLHS()->getType().getObjCLifetime()) {
+case Qualifiers::OCL_Strong:
+case Qualifiers::OCL_Autoreleasing:
+case Qualifiers::OCL_ExplicitNone:
+case Qualifiers::OCL_Weak:
+  assert(!cir::MissingFeatures::objCLifetime());
+  break;
+case Qualifiers::OCL_None:
+  // __block variables need to have the rhs evaluated first, plus this
+  // should improve codegen just a little.
+  rhs = Visit(e->getRHS());
+  assert(!cir::MissingFeatures::sanitizers());
+  // TODO(cir): This needs to be emitCheckedLValue() once we support
+  // sanitizers
+  lhs = cgf.emitLValue(e->getLHS());
+
+  // Store the value into the LHS. Bit-fields are handled specially because
+  // the result is altered by the store, i.e., [C99 6.5.16p1]
+  // 'An assignment expression has the value of the left operand after the
+  // assignment...'.
+  if (lhs.isBitField()) {
+cgf.emitStoreThroughBitfieldLValue(RValue::get(rhs), lhs, rhs);
+  } else {
+cgf.emitNullabilityCheck(lhs, rhs, e->getExprLoc());
+CIRGenFunction::SourceLocRAIIObject loc{
+cgf, cgf.getLoc(e->getSourceRange())};
+cgf.emitStoreThroughLVa

[clang] [CIR] Upstream binary assignments and comma (PR #135115)

2025-04-11 Thread Morris Hafner via cfe-commits


@@ -807,6 +808,65 @@ class ScalarExprEmitter : public 
StmtVisitor {
   VISITCOMP(EQ)
   VISITCOMP(NE)
 #undef VISITCOMP
+
+  mlir::Value VisitBinAssign(const BinaryOperator *e) {
+const bool ignore = std::exchange(ignoreResultAssign, false);
+
+mlir::Value rhs;
+LValue lhs;
+
+switch (e->getLHS()->getType().getObjCLifetime()) {

mmha wrote:

Hmm, I don't know about the performance implications (I'd expect them to be 
insignificant) but I find your suggestion to be less readable. I still need a 
`case Qualifiers::OCL_None:` with an `llvm_unreachable()` to satisfy clang-tidy 
and it just adds more branches to the function to follow

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


[clang] [CIR] Upstream binary assignments and comma (PR #135115)

2025-04-11 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/135115

>From 2a9a282dc3227710ce6462d2847876565ba5eb49 Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Fri, 11 Apr 2025 16:17:45 +0200
Subject: [PATCH 1/3] [CIR] Upstream binary assignments and comma

This patch adds `VisitBinAssign` and `VisitBinComma` to the ClangIR 
`ScalarExprEmitter` to enable assignments and the comma operator.
---
 clang/include/clang/CIR/MissingFeatures.h  |  1 +
 clang/lib/CIR/CodeGen/CIRGenDecl.cpp   |  8 +++
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp   |  7 +++
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 60 ++
 clang/lib/CIR/CodeGen/CIRGenFunction.h |  8 +++
 clang/test/CIR/CodeGen/binassign.c | 56 
 clang/test/CIR/CodeGen/comma.c | 53 +++
 clang/test/CIR/IR/binassign.cir| 45 
 8 files changed, 238 insertions(+)
 create mode 100644 clang/test/CIR/CodeGen/binassign.c
 create mode 100644 clang/test/CIR/CodeGen/comma.c
 create mode 100644 clang/test/CIR/IR/binassign.cir

diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index c39590421b647..d6a28d4324b32 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -143,6 +143,7 @@ struct MissingFeatures {
   static bool openMP() { return false; }
   static bool emitCheckedInBoundsGEP() { return false; }
   static bool preservedAccessIndexRegion() { return false; }
+  static bool bitfields() { return false; }
 
   // Missing types
   static bool dataMemberType() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp 
b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index b8e72f299acb6..58797c5dd253a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -277,3 +277,11 @@ void CIRGenFunction::emitDecl(const Decl &d) {
 cgm.errorNYI(d.getSourceRange(), "emitDecl: unhandled decl type");
   }
 }
+
+void CIRGenFunction::emitNullabilityCheck(LValue lhs, mlir::Value rhs,
+  SourceLocation loc) {
+  if (!sanOpts.has(SanitizerKind::NullabilityAssign))
+return;
+
+  assert(!cir::MissingFeatures::sanitizers());
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index b38ed4d0a14e8..26c3169df7713 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -257,6 +257,13 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, 
Address addr,
   assert(!cir::MissingFeatures::opTBAA());
 }
 
+void CIRGenFunction::emitStoreThroughBitfieldLValue(RValue src, LValue dst,
+mlir::Value &result) {
+  assert(!cir::MissingFeatures::bitfields());
+  cgm.errorNYI("bitfields");
+  result = {};
+}
+
 mlir::Value CIRGenFunction::emitToMemory(mlir::Value value, QualType ty) {
   // Bool has a different representation in memory than in registers,
   // but in ClangIR, it is simply represented as a cir.bool value.
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index c2b4110a772a0..6f3ddcf447f2c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -21,6 +21,7 @@
 #include "mlir/IR/Value.h"
 
 #include 
+#include 
 
 using namespace clang;
 using namespace clang::CIRGen;
@@ -818,6 +819,65 @@ class ScalarExprEmitter : public 
StmtVisitor {
   VISITCOMP(EQ)
   VISITCOMP(NE)
 #undef VISITCOMP
+
+  mlir::Value VisitBinAssign(const BinaryOperator *e) {
+const bool ignore = std::exchange(ignoreResultAssign, false);
+
+mlir::Value rhs;
+LValue lhs;
+
+switch (e->getLHS()->getType().getObjCLifetime()) {
+case Qualifiers::OCL_Strong:
+case Qualifiers::OCL_Autoreleasing:
+case Qualifiers::OCL_ExplicitNone:
+case Qualifiers::OCL_Weak:
+  assert(!cir::MissingFeatures::objCLifetime());
+  break;
+case Qualifiers::OCL_None:
+  // __block variables need to have the rhs evaluated first, plus this
+  // should improve codegen just a little.
+  rhs = Visit(e->getRHS());
+  assert(!cir::MissingFeatures::sanitizers());
+  // TODO(cir): This needs to be emitCheckedLValue() once we support
+  // sanitizers
+  lhs = cgf.emitLValue(e->getLHS());
+
+  // Store the value into the LHS. Bit-fields are handled specially because
+  // the result is altered by the store, i.e., [C99 6.5.16p1]
+  // 'An assignment expression has the value of the left operand after the
+  // assignment...'.
+  if (lhs.isBitField()) {
+cgf.emitStoreThroughBitfieldLValue(RValue::get(rhs), lhs, rhs);
+  } else {
+cgf.emitNullabilityCheck(lhs, rhs, e->getExprLoc());
+CIRGenFunction::SourceLocRAIIObject loc{
+cgf, cgf.getLoc(e->getSourceRange())};
+cgf.emitStoreThroughLVal

[clang] [CIR] Upstream binary assignments and comma (PR #135115)

2025-04-11 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/135115

>From 2a9a282dc3227710ce6462d2847876565ba5eb49 Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Fri, 11 Apr 2025 16:17:45 +0200
Subject: [PATCH 1/4] [CIR] Upstream binary assignments and comma

This patch adds `VisitBinAssign` and `VisitBinComma` to the ClangIR 
`ScalarExprEmitter` to enable assignments and the comma operator.
---
 clang/include/clang/CIR/MissingFeatures.h  |  1 +
 clang/lib/CIR/CodeGen/CIRGenDecl.cpp   |  8 +++
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp   |  7 +++
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 60 ++
 clang/lib/CIR/CodeGen/CIRGenFunction.h |  8 +++
 clang/test/CIR/CodeGen/binassign.c | 56 
 clang/test/CIR/CodeGen/comma.c | 53 +++
 clang/test/CIR/IR/binassign.cir| 45 
 8 files changed, 238 insertions(+)
 create mode 100644 clang/test/CIR/CodeGen/binassign.c
 create mode 100644 clang/test/CIR/CodeGen/comma.c
 create mode 100644 clang/test/CIR/IR/binassign.cir

diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index c39590421b647..d6a28d4324b32 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -143,6 +143,7 @@ struct MissingFeatures {
   static bool openMP() { return false; }
   static bool emitCheckedInBoundsGEP() { return false; }
   static bool preservedAccessIndexRegion() { return false; }
+  static bool bitfields() { return false; }
 
   // Missing types
   static bool dataMemberType() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp 
b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index b8e72f299acb6..58797c5dd253a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -277,3 +277,11 @@ void CIRGenFunction::emitDecl(const Decl &d) {
 cgm.errorNYI(d.getSourceRange(), "emitDecl: unhandled decl type");
   }
 }
+
+void CIRGenFunction::emitNullabilityCheck(LValue lhs, mlir::Value rhs,
+  SourceLocation loc) {
+  if (!sanOpts.has(SanitizerKind::NullabilityAssign))
+return;
+
+  assert(!cir::MissingFeatures::sanitizers());
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index b38ed4d0a14e8..26c3169df7713 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -257,6 +257,13 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, 
Address addr,
   assert(!cir::MissingFeatures::opTBAA());
 }
 
+void CIRGenFunction::emitStoreThroughBitfieldLValue(RValue src, LValue dst,
+mlir::Value &result) {
+  assert(!cir::MissingFeatures::bitfields());
+  cgm.errorNYI("bitfields");
+  result = {};
+}
+
 mlir::Value CIRGenFunction::emitToMemory(mlir::Value value, QualType ty) {
   // Bool has a different representation in memory than in registers,
   // but in ClangIR, it is simply represented as a cir.bool value.
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index c2b4110a772a0..6f3ddcf447f2c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -21,6 +21,7 @@
 #include "mlir/IR/Value.h"
 
 #include 
+#include 
 
 using namespace clang;
 using namespace clang::CIRGen;
@@ -818,6 +819,65 @@ class ScalarExprEmitter : public 
StmtVisitor {
   VISITCOMP(EQ)
   VISITCOMP(NE)
 #undef VISITCOMP
+
+  mlir::Value VisitBinAssign(const BinaryOperator *e) {
+const bool ignore = std::exchange(ignoreResultAssign, false);
+
+mlir::Value rhs;
+LValue lhs;
+
+switch (e->getLHS()->getType().getObjCLifetime()) {
+case Qualifiers::OCL_Strong:
+case Qualifiers::OCL_Autoreleasing:
+case Qualifiers::OCL_ExplicitNone:
+case Qualifiers::OCL_Weak:
+  assert(!cir::MissingFeatures::objCLifetime());
+  break;
+case Qualifiers::OCL_None:
+  // __block variables need to have the rhs evaluated first, plus this
+  // should improve codegen just a little.
+  rhs = Visit(e->getRHS());
+  assert(!cir::MissingFeatures::sanitizers());
+  // TODO(cir): This needs to be emitCheckedLValue() once we support
+  // sanitizers
+  lhs = cgf.emitLValue(e->getLHS());
+
+  // Store the value into the LHS. Bit-fields are handled specially because
+  // the result is altered by the store, i.e., [C99 6.5.16p1]
+  // 'An assignment expression has the value of the left operand after the
+  // assignment...'.
+  if (lhs.isBitField()) {
+cgf.emitStoreThroughBitfieldLValue(RValue::get(rhs), lhs, rhs);
+  } else {
+cgf.emitNullabilityCheck(lhs, rhs, e->getExprLoc());
+CIRGenFunction::SourceLocRAIIObject loc{
+cgf, cgf.getLoc(e->getSourceRange())};
+cgf.emitStoreThroughLVal

[clang] [CIR] Upstream binary assignments and comma (PR #135115)

2025-04-11 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/135115

>From 2a9a282dc3227710ce6462d2847876565ba5eb49 Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Fri, 11 Apr 2025 16:17:45 +0200
Subject: [PATCH 1/4] [CIR] Upstream binary assignments and comma

This patch adds `VisitBinAssign` and `VisitBinComma` to the ClangIR 
`ScalarExprEmitter` to enable assignments and the comma operator.
---
 clang/include/clang/CIR/MissingFeatures.h  |  1 +
 clang/lib/CIR/CodeGen/CIRGenDecl.cpp   |  8 +++
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp   |  7 +++
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 60 ++
 clang/lib/CIR/CodeGen/CIRGenFunction.h |  8 +++
 clang/test/CIR/CodeGen/binassign.c | 56 
 clang/test/CIR/CodeGen/comma.c | 53 +++
 clang/test/CIR/IR/binassign.cir| 45 
 8 files changed, 238 insertions(+)
 create mode 100644 clang/test/CIR/CodeGen/binassign.c
 create mode 100644 clang/test/CIR/CodeGen/comma.c
 create mode 100644 clang/test/CIR/IR/binassign.cir

diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index c39590421b647..d6a28d4324b32 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -143,6 +143,7 @@ struct MissingFeatures {
   static bool openMP() { return false; }
   static bool emitCheckedInBoundsGEP() { return false; }
   static bool preservedAccessIndexRegion() { return false; }
+  static bool bitfields() { return false; }
 
   // Missing types
   static bool dataMemberType() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp 
b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index b8e72f299acb6..58797c5dd253a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -277,3 +277,11 @@ void CIRGenFunction::emitDecl(const Decl &d) {
 cgm.errorNYI(d.getSourceRange(), "emitDecl: unhandled decl type");
   }
 }
+
+void CIRGenFunction::emitNullabilityCheck(LValue lhs, mlir::Value rhs,
+  SourceLocation loc) {
+  if (!sanOpts.has(SanitizerKind::NullabilityAssign))
+return;
+
+  assert(!cir::MissingFeatures::sanitizers());
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index b38ed4d0a14e8..26c3169df7713 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -257,6 +257,13 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, 
Address addr,
   assert(!cir::MissingFeatures::opTBAA());
 }
 
+void CIRGenFunction::emitStoreThroughBitfieldLValue(RValue src, LValue dst,
+mlir::Value &result) {
+  assert(!cir::MissingFeatures::bitfields());
+  cgm.errorNYI("bitfields");
+  result = {};
+}
+
 mlir::Value CIRGenFunction::emitToMemory(mlir::Value value, QualType ty) {
   // Bool has a different representation in memory than in registers,
   // but in ClangIR, it is simply represented as a cir.bool value.
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index c2b4110a772a0..6f3ddcf447f2c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -21,6 +21,7 @@
 #include "mlir/IR/Value.h"
 
 #include 
+#include 
 
 using namespace clang;
 using namespace clang::CIRGen;
@@ -818,6 +819,65 @@ class ScalarExprEmitter : public 
StmtVisitor {
   VISITCOMP(EQ)
   VISITCOMP(NE)
 #undef VISITCOMP
+
+  mlir::Value VisitBinAssign(const BinaryOperator *e) {
+const bool ignore = std::exchange(ignoreResultAssign, false);
+
+mlir::Value rhs;
+LValue lhs;
+
+switch (e->getLHS()->getType().getObjCLifetime()) {
+case Qualifiers::OCL_Strong:
+case Qualifiers::OCL_Autoreleasing:
+case Qualifiers::OCL_ExplicitNone:
+case Qualifiers::OCL_Weak:
+  assert(!cir::MissingFeatures::objCLifetime());
+  break;
+case Qualifiers::OCL_None:
+  // __block variables need to have the rhs evaluated first, plus this
+  // should improve codegen just a little.
+  rhs = Visit(e->getRHS());
+  assert(!cir::MissingFeatures::sanitizers());
+  // TODO(cir): This needs to be emitCheckedLValue() once we support
+  // sanitizers
+  lhs = cgf.emitLValue(e->getLHS());
+
+  // Store the value into the LHS. Bit-fields are handled specially because
+  // the result is altered by the store, i.e., [C99 6.5.16p1]
+  // 'An assignment expression has the value of the left operand after the
+  // assignment...'.
+  if (lhs.isBitField()) {
+cgf.emitStoreThroughBitfieldLValue(RValue::get(rhs), lhs, rhs);
+  } else {
+cgf.emitNullabilityCheck(lhs, rhs, e->getExprLoc());
+CIRGenFunction::SourceLocRAIIObject loc{
+cgf, cgf.getLoc(e->getSourceRange())};
+cgf.emitStoreThroughLVal

[clang] [CIR] Upstream binary assignments and comma (PR #135115)

2025-04-11 Thread Morris Hafner via cfe-commits


@@ -219,6 +219,13 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, 
Address addr,
   assert(!cir::MissingFeatures::opTBAA());
 }
 
+void CIRGenFunction::emitStoreThroughBitfieldLValue(RValue src, LValue dst,
+mlir::Value &result) {

mmha wrote:

I don't and you raise a good point. OGCG uses a `llvm::Value **` here as an 
optional return value and it makes sense there because that results in fewer 
dead instruction emitted if the result is discarded but for CIR that doesn't 
apply.

I changed the signature.

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


[clang] [CIR] Add binary operators (PR #132420)

2025-03-24 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/132420

>From 594005c964b5c1e6605dc8ac170f1b43aa018bea Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Fri, 21 Mar 2025 17:55:00 +0100
Subject: [PATCH 1/5] [CIR] Add binary operators

This patch adds upstreams support for BinOp and BinOverflowOp including lvalue 
assignments and rudimentary support for pointer arithmetic. Note that this does 
not include ternary ops, ShiftOp and SelectOp which are required for logical 
binary operators.
---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h  | 114 ++-
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 123 +++
 clang/include/clang/CIR/Dialect/IR/CIRTypes.h |   1 +
 clang/include/clang/CIR/MissingFeatures.h |  13 +-
 clang/lib/CIR/CodeGen/CIRGenBuilder.h | 116 ++-
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp  |  64 +-
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp| 730 +-
 clang/lib/CIR/CodeGen/CIRGenFunction.cpp  |   2 +
 clang/lib/CIR/CodeGen/CIRGenFunction.h|  30 +-
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp   |  41 +-
 clang/lib/CIR/Dialect/IR/CIRTypes.cpp |  10 +
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 243 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  33 +
 clang/test/CIR/CodeGen/binop.cpp  |  33 +
 clang/test/CIR/Lowering/binop-bool.cir|  18 +
 clang/test/CIR/Lowering/binop-fp.cir  |  68 ++
 clang/test/CIR/Lowering/binop-overflow.cir|  63 ++
 clang/test/CIR/Lowering/binop-signed-int.cir  |  60 ++
 .../test/CIR/Lowering/binop-unsigned-int.cir  |  73 ++
 19 files changed, 1794 insertions(+), 41 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/binop.cpp
 create mode 100644 clang/test/CIR/Lowering/binop-bool.cir
 create mode 100644 clang/test/CIR/Lowering/binop-fp.cir
 create mode 100644 clang/test/CIR/Lowering/binop-overflow.cir
 create mode 100644 clang/test/CIR/Lowering/binop-signed-int.cir
 create mode 100644 clang/test/CIR/Lowering/binop-unsigned-int.cir

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index c6aea10d46b63..9fe80cde261a9 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -10,7 +10,6 @@
 #define LLVM_CLANG_CIR_DIALECT_BUILDER_CIRBASEBUILDER_H
 
 #include "clang/AST/CharUnits.h"
-#include "clang/AST/Type.h"
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
@@ -28,6 +27,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
   CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
   : mlir::OpBuilder(&mlirContext) {}
 
+  mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ,
+const llvm::APInt &val) {
+return create(loc, typ, getAttr(typ, val));
+  }
+
   cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr) {
 return create(loc, attr.getType(), attr);
   }
@@ -143,6 +147,114 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return createCast(loc, cir::CastKind::bitcast, src, newTy);
   }
 
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  const llvm::APInt &rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs,
+  getConstAPInt(lhs.getLoc(), lhs.getType(), rhs));
+  }
+
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  mlir::Value rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createBinop(mlir::Location loc, mlir::Value lhs,
+  cir::BinOpKind kind, mlir::Value rhs) {
+return create(loc, lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createLowBitsSet(mlir::Location loc, unsigned size,
+   unsigned bits) {
+llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits);
+auto type = cir::IntType::get(getContext(), size, false);
+return getConstAPInt(loc, type, val);
+  }
+
+  mlir::Value createAnd(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getType(), rhs);
+return createBinop(lhs, cir::BinOpKind::And, val);
+  }
+
+  mlir::Value createAnd(mlir::Value lhs, mlir::Value rhs) {
+return createBinop(lhs, cir::BinOpKind::And, rhs);
+  }
+
+  mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+return createBinop(loc, lhs, cir::BinOpKind::And, rhs);
+  }
+
+  mlir::Value createOr(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getType(), rhs);
+return createBinop(lhs, cir::BinOpKind::Or, val);
+  }
+
+  mlir::Value createOr(mlir::Value lhs, mlir::Value rhs) {
+return createBinop(lhs, cir::BinOpKind::Or, rhs);
+  }
+
+  mlir::Value createMul(mlir::Value lhs, mlir::Value rhs

[clang] [CIR] Add binary operators (PR #132420)

2025-03-24 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/132420

>From 594005c964b5c1e6605dc8ac170f1b43aa018bea Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Fri, 21 Mar 2025 17:55:00 +0100
Subject: [PATCH 1/6] [CIR] Add binary operators

This patch adds upstreams support for BinOp and BinOverflowOp including lvalue 
assignments and rudimentary support for pointer arithmetic. Note that this does 
not include ternary ops, ShiftOp and SelectOp which are required for logical 
binary operators.
---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h  | 114 ++-
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 123 +++
 clang/include/clang/CIR/Dialect/IR/CIRTypes.h |   1 +
 clang/include/clang/CIR/MissingFeatures.h |  13 +-
 clang/lib/CIR/CodeGen/CIRGenBuilder.h | 116 ++-
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp  |  64 +-
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp| 730 +-
 clang/lib/CIR/CodeGen/CIRGenFunction.cpp  |   2 +
 clang/lib/CIR/CodeGen/CIRGenFunction.h|  30 +-
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp   |  41 +-
 clang/lib/CIR/Dialect/IR/CIRTypes.cpp |  10 +
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 243 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  33 +
 clang/test/CIR/CodeGen/binop.cpp  |  33 +
 clang/test/CIR/Lowering/binop-bool.cir|  18 +
 clang/test/CIR/Lowering/binop-fp.cir  |  68 ++
 clang/test/CIR/Lowering/binop-overflow.cir|  63 ++
 clang/test/CIR/Lowering/binop-signed-int.cir  |  60 ++
 .../test/CIR/Lowering/binop-unsigned-int.cir  |  73 ++
 19 files changed, 1794 insertions(+), 41 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/binop.cpp
 create mode 100644 clang/test/CIR/Lowering/binop-bool.cir
 create mode 100644 clang/test/CIR/Lowering/binop-fp.cir
 create mode 100644 clang/test/CIR/Lowering/binop-overflow.cir
 create mode 100644 clang/test/CIR/Lowering/binop-signed-int.cir
 create mode 100644 clang/test/CIR/Lowering/binop-unsigned-int.cir

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index c6aea10d46b63..9fe80cde261a9 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -10,7 +10,6 @@
 #define LLVM_CLANG_CIR_DIALECT_BUILDER_CIRBASEBUILDER_H
 
 #include "clang/AST/CharUnits.h"
-#include "clang/AST/Type.h"
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
@@ -28,6 +27,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
   CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
   : mlir::OpBuilder(&mlirContext) {}
 
+  mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ,
+const llvm::APInt &val) {
+return create(loc, typ, getAttr(typ, val));
+  }
+
   cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr) {
 return create(loc, attr.getType(), attr);
   }
@@ -143,6 +147,114 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return createCast(loc, cir::CastKind::bitcast, src, newTy);
   }
 
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  const llvm::APInt &rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs,
+  getConstAPInt(lhs.getLoc(), lhs.getType(), rhs));
+  }
+
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  mlir::Value rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createBinop(mlir::Location loc, mlir::Value lhs,
+  cir::BinOpKind kind, mlir::Value rhs) {
+return create(loc, lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createLowBitsSet(mlir::Location loc, unsigned size,
+   unsigned bits) {
+llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits);
+auto type = cir::IntType::get(getContext(), size, false);
+return getConstAPInt(loc, type, val);
+  }
+
+  mlir::Value createAnd(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getType(), rhs);
+return createBinop(lhs, cir::BinOpKind::And, val);
+  }
+
+  mlir::Value createAnd(mlir::Value lhs, mlir::Value rhs) {
+return createBinop(lhs, cir::BinOpKind::And, rhs);
+  }
+
+  mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+return createBinop(loc, lhs, cir::BinOpKind::And, rhs);
+  }
+
+  mlir::Value createOr(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getType(), rhs);
+return createBinop(lhs, cir::BinOpKind::Or, val);
+  }
+
+  mlir::Value createOr(mlir::Value lhs, mlir::Value rhs) {
+return createBinop(lhs, cir::BinOpKind::Or, rhs);
+  }
+
+  mlir::Value createMul(mlir::Value lhs, mlir::Value rhs

[clang] [CIR] Emit allocas into the proper lexical scope (PR #132468)

2025-03-24 Thread Morris Hafner via cfe-commits

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

LGTM

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


[clang] [CIR] Emit allocas into the proper lexical scope (PR #132468)

2025-03-24 Thread Morris Hafner via cfe-commits


@@ -44,3 +44,100 @@ void l0() {
 // OGCG:   br label %[[FOR_COND:.*]]
 // OGCG: [[FOR_COND]]:
 // OGCG:   br label %[[FOR_COND]]
+
+void l1() {
+  for (int i = 0; ; ) {
+  }
+}
+
+// CIR:  cir.func @l1
+// CIR-NEXT:   cir.scope {
+// CIR-NEXT: %[[I:.*]] = cir.alloca !s32i, !cir.ptr, ["i", init] 
{alignment = 4 : i64}
+// CIR-NEXT: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
+// CIR-NEXT: cir.store %[[ZERO]], %[[I]] : !s32i, !cir.ptr
+// CIR-NEXT: cir.for : cond {
+// CIR-NEXT:   %[[TRUE:.*]] = cir.const #true
+// CIR-NEXT:   cir.condition(%[[TRUE]])
+// CIR-NEXT: } body {
+// CIR-NEXT:   cir.yield
+// CIR-NEXT: } step {
+// CIR-NEXT:   cir.yield
+// CIR-NEXT: }
+// CIR-NEXT:   }
+// CIR-NEXT:   cir.return
+// CIR-NEXT: }
+
+// LLVM: define void @l1()
+// LLVM:   %[[I:.*]] = alloca i32, i64 1, align 4
+// LLVM:   br label %[[LABEL1:.*]]
+// LLVM: [[LABEL1]]:
+// LLVM:   store i32 0, ptr %[[I]], align 4
+// LLVM:   br label %[[LABEL2:.*]]
+// LLVM: [[LABEL2]]:
+// LLVM:   br i1 true, label %[[LABEL3:.*]], label %[[LABEL5:.*]]
+// LLVM: [[LABEL3]]:
+// LLVM:   br label %[[LABEL4:.*]]
+// LLVM: [[LABEL4]]:
+// LLVM:   br label %[[LABEL2]]
+// LLVM: [[LABEL5]]:
+// LLVM:   br label %[[LABEL6:.*]]
+// LLVM: [[LABEL6]]:
+// LLVM:   ret void
+
+// OGCG: define{{.*}} void @_Z2l1v()
+// OGCG: entry:
+// OGCG:   %[[I:.*]] = alloca i32, align 4
+// OGCG:   store i32 0, ptr %[[I]], align 4
+// OGCG:   br label %[[FOR_COND:.*]]
+// OGCG: [[FOR_COND]]:
+// OGCG:   br label %[[FOR_COND]]
+
+void l2() {
+  for (;;) {

mmha wrote:

Can you add another test without any braces so we have a for loop body without 
a `CompoundStmt`?

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


[clang] [CIR] Emit allocas into the proper lexical scope (PR #132468)

2025-03-24 Thread Morris Hafner via cfe-commits


@@ -293,7 +294,8 @@ void CIRGenFunction::startFunction(GlobalDecl gd, QualType 
returnType,
 
 mlir::Value addrVal =
 emitAlloca(cast(paramVar)->getName(),
-   convertType(paramVar->getType()), paramLoc, alignment);
+   convertType(paramVar->getType()), paramLoc, alignment,
+   /*insertIntoFnEntryBlock=*/false);

mmha wrote:

It doesn't really make a difference because this is called by `startFunction` 
but shouldn't the return value always be in the function entry block?

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


[clang] [CIR] Emit allocas into the proper lexical scope (PR #132468)

2025-03-24 Thread Morris Hafner via cfe-commits


@@ -0,0 +1,81 @@
+//===--===//
+//
+// 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
+//
+//===--===//
+
+#include "PassDetail.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/IR/PatternMatch.h"
+#include "mlir/Support/LogicalResult.h"
+#include "mlir/Transforms/DialectConversion.h"
+#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/Passes.h"
+#include "clang/CIR/MissingFeatures.h"
+#include "llvm/Support/TimeProfiler.h"
+
+using namespace mlir;
+using namespace cir;
+
+namespace {
+
+struct HoistAllocasPass : public HoistAllocasBase {
+
+  HoistAllocasPass() = default;
+  void runOnOperation() override;
+};
+
+static void process(mlir::ModuleOp mod, cir::FuncOp func) {
+  if (func.getRegion().empty())
+return;
+
+  // Hoist all static allocas to the entry block.
+  mlir::Block &entryBlock = func.getRegion().front();
+  llvm::SmallVector allocas;
+  func.getBody().walk([&](cir::AllocaOp alloca) {

mmha wrote:

You create a `SmallVector` of `AllocaOp`s here only to iterate that list again 
right below.

Can you merge these two loops? It would save us the creation of that vector.

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


[clang] [CIR] Emit allocas into the proper lexical scope (PR #132468)

2025-03-24 Thread Morris Hafner via cfe-commits

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


[clang] [CIR] Add binary operators (PR #132420)

2025-03-24 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/132420

>From 594005c964b5c1e6605dc8ac170f1b43aa018bea Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Fri, 21 Mar 2025 17:55:00 +0100
Subject: [PATCH 1/2] [CIR] Add binary operators

This patch adds upstreams support for BinOp and BinOverflowOp including lvalue 
assignments and rudimentary support for pointer arithmetic. Note that this does 
not include ternary ops, ShiftOp and SelectOp which are required for logical 
binary operators.
---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h  | 114 ++-
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 123 +++
 clang/include/clang/CIR/Dialect/IR/CIRTypes.h |   1 +
 clang/include/clang/CIR/MissingFeatures.h |  13 +-
 clang/lib/CIR/CodeGen/CIRGenBuilder.h | 116 ++-
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp  |  64 +-
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp| 730 +-
 clang/lib/CIR/CodeGen/CIRGenFunction.cpp  |   2 +
 clang/lib/CIR/CodeGen/CIRGenFunction.h|  30 +-
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp   |  41 +-
 clang/lib/CIR/Dialect/IR/CIRTypes.cpp |  10 +
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 243 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  33 +
 clang/test/CIR/CodeGen/binop.cpp  |  33 +
 clang/test/CIR/Lowering/binop-bool.cir|  18 +
 clang/test/CIR/Lowering/binop-fp.cir  |  68 ++
 clang/test/CIR/Lowering/binop-overflow.cir|  63 ++
 clang/test/CIR/Lowering/binop-signed-int.cir  |  60 ++
 .../test/CIR/Lowering/binop-unsigned-int.cir  |  73 ++
 19 files changed, 1794 insertions(+), 41 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/binop.cpp
 create mode 100644 clang/test/CIR/Lowering/binop-bool.cir
 create mode 100644 clang/test/CIR/Lowering/binop-fp.cir
 create mode 100644 clang/test/CIR/Lowering/binop-overflow.cir
 create mode 100644 clang/test/CIR/Lowering/binop-signed-int.cir
 create mode 100644 clang/test/CIR/Lowering/binop-unsigned-int.cir

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index c6aea10d46b63..9fe80cde261a9 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -10,7 +10,6 @@
 #define LLVM_CLANG_CIR_DIALECT_BUILDER_CIRBASEBUILDER_H
 
 #include "clang/AST/CharUnits.h"
-#include "clang/AST/Type.h"
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
@@ -28,6 +27,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
   CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
   : mlir::OpBuilder(&mlirContext) {}
 
+  mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ,
+const llvm::APInt &val) {
+return create(loc, typ, getAttr(typ, val));
+  }
+
   cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr) {
 return create(loc, attr.getType(), attr);
   }
@@ -143,6 +147,114 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return createCast(loc, cir::CastKind::bitcast, src, newTy);
   }
 
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  const llvm::APInt &rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs,
+  getConstAPInt(lhs.getLoc(), lhs.getType(), rhs));
+  }
+
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  mlir::Value rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createBinop(mlir::Location loc, mlir::Value lhs,
+  cir::BinOpKind kind, mlir::Value rhs) {
+return create(loc, lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createLowBitsSet(mlir::Location loc, unsigned size,
+   unsigned bits) {
+llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits);
+auto type = cir::IntType::get(getContext(), size, false);
+return getConstAPInt(loc, type, val);
+  }
+
+  mlir::Value createAnd(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getType(), rhs);
+return createBinop(lhs, cir::BinOpKind::And, val);
+  }
+
+  mlir::Value createAnd(mlir::Value lhs, mlir::Value rhs) {
+return createBinop(lhs, cir::BinOpKind::And, rhs);
+  }
+
+  mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+return createBinop(loc, lhs, cir::BinOpKind::And, rhs);
+  }
+
+  mlir::Value createOr(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getType(), rhs);
+return createBinop(lhs, cir::BinOpKind::Or, val);
+  }
+
+  mlir::Value createOr(mlir::Value lhs, mlir::Value rhs) {
+return createBinop(lhs, cir::BinOpKind::Or, rhs);
+  }
+
+  mlir::Value createMul(mlir::Value lhs, mlir::Value rhs

[clang] [CIR] Add binary operators (PR #132420)

2025-03-24 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/132420

>From 594005c964b5c1e6605dc8ac170f1b43aa018bea Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Fri, 21 Mar 2025 17:55:00 +0100
Subject: [PATCH 1/3] [CIR] Add binary operators

This patch adds upstreams support for BinOp and BinOverflowOp including lvalue 
assignments and rudimentary support for pointer arithmetic. Note that this does 
not include ternary ops, ShiftOp and SelectOp which are required for logical 
binary operators.
---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h  | 114 ++-
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 123 +++
 clang/include/clang/CIR/Dialect/IR/CIRTypes.h |   1 +
 clang/include/clang/CIR/MissingFeatures.h |  13 +-
 clang/lib/CIR/CodeGen/CIRGenBuilder.h | 116 ++-
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp  |  64 +-
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp| 730 +-
 clang/lib/CIR/CodeGen/CIRGenFunction.cpp  |   2 +
 clang/lib/CIR/CodeGen/CIRGenFunction.h|  30 +-
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp   |  41 +-
 clang/lib/CIR/Dialect/IR/CIRTypes.cpp |  10 +
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 243 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  33 +
 clang/test/CIR/CodeGen/binop.cpp  |  33 +
 clang/test/CIR/Lowering/binop-bool.cir|  18 +
 clang/test/CIR/Lowering/binop-fp.cir  |  68 ++
 clang/test/CIR/Lowering/binop-overflow.cir|  63 ++
 clang/test/CIR/Lowering/binop-signed-int.cir  |  60 ++
 .../test/CIR/Lowering/binop-unsigned-int.cir  |  73 ++
 19 files changed, 1794 insertions(+), 41 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/binop.cpp
 create mode 100644 clang/test/CIR/Lowering/binop-bool.cir
 create mode 100644 clang/test/CIR/Lowering/binop-fp.cir
 create mode 100644 clang/test/CIR/Lowering/binop-overflow.cir
 create mode 100644 clang/test/CIR/Lowering/binop-signed-int.cir
 create mode 100644 clang/test/CIR/Lowering/binop-unsigned-int.cir

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index c6aea10d46b63..9fe80cde261a9 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -10,7 +10,6 @@
 #define LLVM_CLANG_CIR_DIALECT_BUILDER_CIRBASEBUILDER_H
 
 #include "clang/AST/CharUnits.h"
-#include "clang/AST/Type.h"
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
@@ -28,6 +27,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
   CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
   : mlir::OpBuilder(&mlirContext) {}
 
+  mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ,
+const llvm::APInt &val) {
+return create(loc, typ, getAttr(typ, val));
+  }
+
   cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr) {
 return create(loc, attr.getType(), attr);
   }
@@ -143,6 +147,114 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return createCast(loc, cir::CastKind::bitcast, src, newTy);
   }
 
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  const llvm::APInt &rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs,
+  getConstAPInt(lhs.getLoc(), lhs.getType(), rhs));
+  }
+
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  mlir::Value rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createBinop(mlir::Location loc, mlir::Value lhs,
+  cir::BinOpKind kind, mlir::Value rhs) {
+return create(loc, lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createLowBitsSet(mlir::Location loc, unsigned size,
+   unsigned bits) {
+llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits);
+auto type = cir::IntType::get(getContext(), size, false);
+return getConstAPInt(loc, type, val);
+  }
+
+  mlir::Value createAnd(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getType(), rhs);
+return createBinop(lhs, cir::BinOpKind::And, val);
+  }
+
+  mlir::Value createAnd(mlir::Value lhs, mlir::Value rhs) {
+return createBinop(lhs, cir::BinOpKind::And, rhs);
+  }
+
+  mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+return createBinop(loc, lhs, cir::BinOpKind::And, rhs);
+  }
+
+  mlir::Value createOr(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getType(), rhs);
+return createBinop(lhs, cir::BinOpKind::Or, val);
+  }
+
+  mlir::Value createOr(mlir::Value lhs, mlir::Value rhs) {
+return createBinop(lhs, cir::BinOpKind::Or, rhs);
+  }
+
+  mlir::Value createMul(mlir::Value lhs, mlir::Value rhs

[clang] [CIR] Add binary operators (PR #132420)

2025-03-24 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/132420

>From 594005c964b5c1e6605dc8ac170f1b43aa018bea Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Fri, 21 Mar 2025 17:55:00 +0100
Subject: [PATCH 1/4] [CIR] Add binary operators

This patch adds upstreams support for BinOp and BinOverflowOp including lvalue 
assignments and rudimentary support for pointer arithmetic. Note that this does 
not include ternary ops, ShiftOp and SelectOp which are required for logical 
binary operators.
---
 .../CIR/Dialect/Builder/CIRBaseBuilder.h  | 114 ++-
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 123 +++
 clang/include/clang/CIR/Dialect/IR/CIRTypes.h |   1 +
 clang/include/clang/CIR/MissingFeatures.h |  13 +-
 clang/lib/CIR/CodeGen/CIRGenBuilder.h | 116 ++-
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp  |  64 +-
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp| 730 +-
 clang/lib/CIR/CodeGen/CIRGenFunction.cpp  |   2 +
 clang/lib/CIR/CodeGen/CIRGenFunction.h|  30 +-
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp   |  41 +-
 clang/lib/CIR/Dialect/IR/CIRTypes.cpp |  10 +
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 243 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  33 +
 clang/test/CIR/CodeGen/binop.cpp  |  33 +
 clang/test/CIR/Lowering/binop-bool.cir|  18 +
 clang/test/CIR/Lowering/binop-fp.cir  |  68 ++
 clang/test/CIR/Lowering/binop-overflow.cir|  63 ++
 clang/test/CIR/Lowering/binop-signed-int.cir  |  60 ++
 .../test/CIR/Lowering/binop-unsigned-int.cir  |  73 ++
 19 files changed, 1794 insertions(+), 41 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/binop.cpp
 create mode 100644 clang/test/CIR/Lowering/binop-bool.cir
 create mode 100644 clang/test/CIR/Lowering/binop-fp.cir
 create mode 100644 clang/test/CIR/Lowering/binop-overflow.cir
 create mode 100644 clang/test/CIR/Lowering/binop-signed-int.cir
 create mode 100644 clang/test/CIR/Lowering/binop-unsigned-int.cir

diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index c6aea10d46b63..9fe80cde261a9 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -10,7 +10,6 @@
 #define LLVM_CLANG_CIR_DIALECT_BUILDER_CIRBASEBUILDER_H
 
 #include "clang/AST/CharUnits.h"
-#include "clang/AST/Type.h"
 #include "clang/CIR/Dialect/IR/CIRAttrs.h"
 #include "clang/CIR/Dialect/IR/CIRDialect.h"
 #include "clang/CIR/Dialect/IR/CIRTypes.h"
@@ -28,6 +27,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
   CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
   : mlir::OpBuilder(&mlirContext) {}
 
+  mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ,
+const llvm::APInt &val) {
+return create(loc, typ, getAttr(typ, val));
+  }
+
   cir::ConstantOp getConstant(mlir::Location loc, mlir::TypedAttr attr) {
 return create(loc, attr.getType(), attr);
   }
@@ -143,6 +147,114 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return createCast(loc, cir::CastKind::bitcast, src, newTy);
   }
 
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  const llvm::APInt &rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs,
+  getConstAPInt(lhs.getLoc(), lhs.getType(), rhs));
+  }
+
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  mlir::Value rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createBinop(mlir::Location loc, mlir::Value lhs,
+  cir::BinOpKind kind, mlir::Value rhs) {
+return create(loc, lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createLowBitsSet(mlir::Location loc, unsigned size,
+   unsigned bits) {
+llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits);
+auto type = cir::IntType::get(getContext(), size, false);
+return getConstAPInt(loc, type, val);
+  }
+
+  mlir::Value createAnd(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getType(), rhs);
+return createBinop(lhs, cir::BinOpKind::And, val);
+  }
+
+  mlir::Value createAnd(mlir::Value lhs, mlir::Value rhs) {
+return createBinop(lhs, cir::BinOpKind::And, rhs);
+  }
+
+  mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+return createBinop(loc, lhs, cir::BinOpKind::And, rhs);
+  }
+
+  mlir::Value createOr(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getType(), rhs);
+return createBinop(lhs, cir::BinOpKind::Or, val);
+  }
+
+  mlir::Value createOr(mlir::Value lhs, mlir::Value rhs) {
+return createBinop(lhs, cir::BinOpKind::Or, rhs);
+  }
+
+  mlir::Value createMul(mlir::Value lhs, mlir::Value rhs

[clang] [CIR] Emit allocas into the proper lexical scope (PR #132468)

2025-03-25 Thread Morris Hafner via cfe-commits


@@ -0,0 +1,81 @@
+//===--===//
+//
+// 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
+//
+//===--===//
+
+#include "PassDetail.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/IR/PatternMatch.h"
+#include "mlir/Support/LogicalResult.h"
+#include "mlir/Transforms/DialectConversion.h"
+#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
+#include "clang/CIR/Dialect/IR/CIRDialect.h"
+#include "clang/CIR/Dialect/Passes.h"
+#include "clang/CIR/MissingFeatures.h"
+#include "llvm/Support/TimeProfiler.h"
+
+using namespace mlir;
+using namespace cir;
+
+namespace {
+
+struct HoistAllocasPass : public HoistAllocasBase {
+
+  HoistAllocasPass() = default;
+  void runOnOperation() override;
+};
+
+static void process(mlir::ModuleOp mod, cir::FuncOp func) {
+  if (func.getRegion().empty())
+return;
+
+  // Hoist all static allocas to the entry block.
+  mlir::Block &entryBlock = func.getRegion().front();
+  llvm::SmallVector allocas;
+  func.getBody().walk([&](cir::AllocaOp alloca) {
+if (alloca->getBlock() == &entryBlock)
+  return;
+// Don't hoist allocas with dynamic alloca size.
+assert(!cir::MissingFeatures::opAllocaDynAllocSize());
+allocas.push_back(alloca);
+  });
+  if (allocas.empty())
+return;
+
+  mlir::Operation *insertPoint = &*entryBlock.begin();
+
+  for (cir::AllocaOp alloca : allocas) {
+// Preserving the `const` attribute on hoisted allocas can cause LLVM to
+// incorrectly introduce invariant group metadata in some circumstances.
+// The incubator performs some analysis to determine whether the attribute
+// can be preserved, but it only runs this analysis when optimizations are
+// enabled. Until we start tracking the optimization level, we can just
+// always remove the `const` attribute.
+assert(!cir::MissingFeatures::optInfoAttr());
+if (alloca.getConstant())
+  alloca.setConstant(false);
+
+alloca->moveBefore(insertPoint);
+  }
+}
+
+void HoistAllocasPass::runOnOperation() {
+  llvm::TimeTraceScope scope("Hoist Allocas");
+  llvm::SmallVector ops;
+
+  Operation *op = getOperation();
+  auto mod = mlir::dyn_cast(op);
+  if (!mod)
+mod = op->getParentOfType();
+
+  getOperation()->walk([&](cir::FuncOp op) { process(mod, op); });

mmha wrote:

A thing to look out for here and we don't have implemented in the incubator yet 
are ObjC/OpenCL blocks.

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


[clang] [CIR] Upstream SelectOp and ShiftOp (PR #133405)

2025-03-28 Thread Morris Hafner via cfe-commits

https://github.com/mmha created https://github.com/llvm/llvm-project/pull/133405

Since SelectOp will only generated by a future pass that transforms a TernaryOp 
this only includes the lowering bits.

This patch also improves the testing of the existing binary operators.

>From fc549133df0092c9c248e7dd0365d6af080f5b84 Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Fri, 28 Mar 2025 09:46:30 +
Subject: [PATCH] [CIR] Upstream SelectOp and ShiftOp

Since SelectOp will only generated by a future pass that transforms a TernaryOp 
this only includes the lowering bits.

This patchs also improves the testing of the existing binary operators.
---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  73 
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp|   9 +-
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp   |  43 +++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  87 +
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  20 ++
 clang/test/CIR/CodeGen/binop.cpp  | 317 +-
 clang/test/CIR/Lowering/select.cir|  48 +++
 7 files changed, 579 insertions(+), 18 deletions(-)
 create mode 100644 clang/test/CIR/Lowering/select.cir

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 455cc2b8b0277..5c3d0549c1c47 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -889,6 +889,79 @@ def BinOp : CIR_Op<"binop", [Pure,
   let hasVerifier = 1;
 }
 
+//===--===//
+// ShiftOp
+//===--===//
+
+def ShiftOp : CIR_Op<"shift", [Pure]> {
+  let summary = "Shift";
+  let description = [{
+Shift `left` or `right`, according to the first operand. Second operand is
+the shift target and the third the amount. Second and the thrid operand are
+integers.
+
+```mlir
+%7 = cir.shift(left, %1 : !u64i, %4 : !s32i) -> !u64i
+```
+  }];
+
+  // TODO(cir): Support vectors. CIR_IntType -> CIR_AnyIntOrVecOfInt. Also
+  // update the description above.
+  let results = (outs CIR_IntType:$result);
+  let arguments = (ins CIR_IntType:$value, CIR_IntType:$amount,
+   UnitAttr:$isShiftleft);
+
+  let assemblyFormat = [{
+`(`
+  (`left` $isShiftleft^) : (```right`)?
+  `,` $value `:` type($value)
+  `,` $amount `:` type($amount)
+`)` `->` type($result) attr-dict
+  }];
+
+  let hasVerifier = 1;
+}
+
+//===--===//
+// SelectOp
+//===--===//
+
+def SelectOp : CIR_Op<"select", [Pure,
+AllTypesMatch<["true_value", "false_value", "result"]>]> {
+  let summary = "Yield one of two values based on a boolean value";
+  let description = [{
+The `cir.select` operation takes three operands. The first operand
+`condition` is a boolean value of type `!cir.bool`. The second and the 
third
+operand can be of any CIR types, but their types must be the same. If the
+first operand is `true`, the operation yields its second operand. 
Otherwise,
+the operation yields its third operand.
+
+Example:
+
+```mlir
+%0 = cir.const #cir.bool : !cir.bool
+%1 = cir.const #cir.int<42> : !s32i
+%2 = cir.const #cir.int<72> : !s32i
+%3 = cir.select if %0 then %1 else %2 : (!cir.bool, !s32i, !s32i) -> !s32i
+```
+  }];
+
+  let arguments = (ins CIR_BoolType:$condition, CIR_AnyType:$true_value,
+   CIR_AnyType:$false_value);
+  let results = (outs CIR_AnyType:$result);
+
+  let assemblyFormat = [{
+`if` $condition `then` $true_value `else` $false_value
+`:` `(`
+  qualified(type($condition)) `,`
+  qualified(type($true_value)) `,`
+  qualified(type($false_value))
+`)` `->` qualified(type($result)) attr-dict
+  }];
+
+  let hasFolder = 1;
+}
+
 
//===--===//
 // GlobalOp
 
//===--===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 52bd3b2933744..3a904fa656104 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -1138,8 +1138,9 @@ mlir::Value ScalarExprEmitter::emitShl(const BinOpInfo 
&ops) {
mlir::isa(ops.lhs.getType()))
 cgf.cgm.errorNYI("sanitizers");
 
-  cgf.cgm.errorNYI("shift ops");
-  return {};
+  return builder.create(cgf.getLoc(ops.loc),
+  cgf.convertType(ops.fullType), ops.lhs,
+  ops.rhs, cgf.getBuilder().getUnitAttr());
 }
 
 mlir::Value ScalarExprEmitter::emitShr(const BinOpInfo &ops) {
@@ -1163,8 +1164,8 @@ mlir::Value ScalarExprEmitter::emitShr(const BinO

[clang] [CIR] Upstream SelectOp and ShiftOp (PR #133405)

2025-03-28 Thread Morris Hafner via cfe-commits

mmha wrote:

cc @andykaylor @erichkeane @dkolsen-pgi 

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


[clang] [CIR] Add binary operators (PR #132420)

2025-03-25 Thread Morris Hafner via cfe-commits


@@ -143,6 +147,114 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
 return createCast(loc, cir::CastKind::bitcast, src, newTy);
   }
 
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  const llvm::APInt &rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs,
+  getConstAPInt(lhs.getLoc(), lhs.getType(), rhs));
+  }
+
+  mlir::Value createBinop(mlir::Value lhs, cir::BinOpKind kind,
+  mlir::Value rhs) {
+return create(lhs.getLoc(), lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createBinop(mlir::Location loc, mlir::Value lhs,
+  cir::BinOpKind kind, mlir::Value rhs) {
+return create(loc, lhs.getType(), kind, lhs, rhs);
+  }
+
+  mlir::Value createLowBitsSet(mlir::Location loc, unsigned size,
+   unsigned bits) {
+llvm::APInt val = llvm::APInt::getLowBitsSet(size, bits);
+auto type = cir::IntType::get(getContext(), size, false);
+return getConstAPInt(loc, type, val);
+  }
+
+  mlir::Value createAnd(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getType(), rhs);
+return createBinop(lhs, cir::BinOpKind::And, val);
+  }
+
+  mlir::Value createAnd(mlir::Value lhs, mlir::Value rhs) {
+return createBinop(lhs, cir::BinOpKind::And, rhs);
+  }
+
+  mlir::Value createAnd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
+return createBinop(loc, lhs, cir::BinOpKind::And, rhs);
+  }
+
+  mlir::Value createOr(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getType(), rhs);
+return createBinop(lhs, cir::BinOpKind::Or, val);
+  }
+
+  mlir::Value createOr(mlir::Value lhs, mlir::Value rhs) {
+return createBinop(lhs, cir::BinOpKind::Or, rhs);
+  }
+
+  mlir::Value createMul(mlir::Value lhs, mlir::Value rhs, bool hasNUW = false,
+bool hasNSW = false) {
+auto op = create(lhs.getLoc(), lhs.getType(),
+ cir::BinOpKind::Mul, lhs, rhs);
+if (hasNUW)
+  op.setNoUnsignedWrap(true);
+if (hasNSW)
+  op.setNoSignedWrap(true);
+return op;
+  }
+  mlir::Value createNSWMul(mlir::Value lhs, mlir::Value rhs) {
+return createMul(lhs, rhs, false, true);
+  }
+  mlir::Value createNUWAMul(mlir::Value lhs, mlir::Value rhs) {
+return createMul(lhs, rhs, true, false);
+  }
+
+  mlir::Value createMul(mlir::Value lhs, const llvm::APInt &rhs) {
+mlir::Value val = getConstAPInt(lhs.getLoc(), lhs.getType(), rhs);
+return createBinop(lhs, cir::BinOpKind::Mul, val);
+  }
+
+  mlir::Value createSub(mlir::Value lhs, mlir::Value rhs, bool hasNUW = false,

mmha wrote:

It would if we were in the `llvm::` namespace :)

I'll handroll the operator overloads for the time being.

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


[clang] [CIR] Add binary operators (PR #132420)

2025-03-25 Thread Morris Hafner via cfe-commits

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


[clang] [CIR] Upstream SelectOp and ShiftOp (PR #133405)

2025-04-17 Thread Morris Hafner via cfe-commits


@@ -1294,6 +1296,90 @@ mlir::LogicalResult 
CIRToLLVMCmpOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
+cir::ShiftOp op, OpAdaptor adaptor,
+mlir::ConversionPatternRewriter &rewriter) const {
+  auto cirAmtTy = mlir::dyn_cast(op.getAmount().getType());
+  auto cirValTy = mlir::dyn_cast(op.getValue().getType());
+
+  // Operands could also be vector type
+  assert(!cir::MissingFeatures::vectorType());
+  mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
+  mlir::Value amt = adaptor.getAmount();
+  mlir::Value val = adaptor.getValue();
+
+  // TODO(cir): Assert for vector types
+  assert((cirValTy && cirAmtTy) &&
+ "shift input type must be integer or vector type, otherwise NYI");
+
+  assert((cirValTy == op.getType()) && "inconsistent operands' types NYI");
+
+  // Ensure shift amount is the same type as the value. Some undefined
+  // behavior might occur in the casts below as per [C99 6.5.7.3].
+  // Vector type shift amount needs no cast as type consistency is expected to
+  // be already be enforced at CIRGen.
+  if (cirAmtTy)
+amt = getLLVMIntCast(rewriter, amt, mlir::cast(llvmTy),
+ true, cirAmtTy.getWidth(), cirValTy.getWidth());

mmha wrote:

There you go: https://github.com/llvm/clangir/pull/1568

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


[clang] [OpenACC][CIR] Implement 'async' lowering. (PR #136626)

2025-04-22 Thread Morris Hafner via cfe-commits


@@ -639,6 +639,9 @@ OpenACCClause 
*SemaOpenACCClauseVisitor::VisitVectorLengthClause(
 
 OpenACCClause *SemaOpenACCClauseVisitor::VisitAsyncClause(
 SemaOpenACC::OpenACCParsedClause &Clause) {
+  if (DisallowSinceLastDeviceType(Clause))

mmha wrote:

Can you update the comment on `DisallowSinceLastDeviceType()` to include 
`async`?

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


[clang] [CIR] Upstream TernaryOp (PR #137184)

2025-04-24 Thread Morris Hafner via cfe-commits

https://github.com/mmha created https://github.com/llvm/llvm-project/pull/137184

This patch adds TernaryOp to CIR plus a pass that flattens the operator in 
FlattenCFG.

This is the first PR out of (probably) 3 wrt. TernaryOp. I split the patches up 
to make reviewing them easier. As such, this PR is only about adding the CIR 
operation. The next PR will be about the CodeGen bits from the C++ conditional 
operator and the final one will add the cir-simplify transform for TernaryOp 
and SelectOp.

>From 1eed90e3859c2ad8d703708f89976cad8f0faeec Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Thu, 24 Apr 2025 16:12:37 +0200
Subject: [PATCH] [CIR] Upstream TernaryOp

This patch adds TernaryOp to CIR plus a pass that flattens the operator in 
FlattenCFG.
---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 57 +++-
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp   | 42 
 .../lib/CIR/Dialect/Transforms/FlattenCFG.cpp | 60 ++--
 clang/test/CIR/IR/ternary.cir | 30 
 clang/test/CIR/Lowering/ternary.cir   | 30 
 clang/test/CIR/Transforms/ternary.cir | 68 +++
 6 files changed, 280 insertions(+), 7 deletions(-)
 create mode 100644 clang/test/CIR/IR/ternary.cir
 create mode 100644 clang/test/CIR/Lowering/ternary.cir
 create mode 100644 clang/test/CIR/Transforms/ternary.cir

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 81b447f31feca..76ad5c3666c1b 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -609,8 +609,8 @@ def ConditionOp : CIR_Op<"condition", [
 
//===--===//
 
 def YieldOp : CIR_Op<"yield", [ReturnLike, Terminator,
-   ParentOneOf<["IfOp", "ScopeOp", "WhileOp",
-"ForOp", "DoWhileOp"]>]> {
+   ParentOneOf<["IfOp", "TernaryOp", "ScopeOp",
+"WhileOp", "ForOp", 
"DoWhileOp"]>]> {
   let summary = "Represents the default branching behaviour of a region";
   let description = [{
 The `cir.yield` operation terminates regions on different CIR operations,
@@ -1246,6 +1246,59 @@ def SelectOp : CIR_Op<"select", [Pure,
   }];
 }
 
+//===--===//
+// TernaryOp
+//===--===//
+
+def TernaryOp : CIR_Op<"ternary",
+  [DeclareOpInterfaceMethods,
+   RecursivelySpeculatable, AutomaticAllocationScope, NoRegionArguments]> {
+  let summary = "The `cond ? a : b` C/C++ ternary operation";
+  let description = [{
+The `cir.ternary` operation represents C/C++ ternary, much like a `select`
+operation. The first argument is a `cir.bool` condition to evaluate, 
followed
+by two regions to execute (true or false). This is different from `cir.if`
+since each region is one block sized and the `cir.yield` closing the block
+scope should have one argument.
+
+Example:
+
+```mlir
+// x = cond ? a : b;
+
+%x = cir.ternary (%cond, true_region {
+  ...
+  cir.yield %a : i32
+}, false_region {
+  ...
+  cir.yield %b : i32
+}) -> i32
+```
+  }];
+  let arguments = (ins CIR_BoolType:$cond);
+  let regions = (region AnyRegion:$trueRegion,
+AnyRegion:$falseRegion);
+  let results = (outs Optional:$result);
+
+  let skipDefaultBuilders = 1;
+  let builders = [
+OpBuilder<(ins "mlir::Value":$cond,
+  "llvm::function_ref":$trueBuilder,
+  "llvm::function_ref":$falseBuilder)
+  >
+  ];
+
+  // All constraints already verified elsewhere.
+  let hasVerifier = 0;
+
+  let assemblyFormat = [{
+`(` $cond `,`
+  `true` $trueRegion `,`
+  `false` $falseRegion
+`)` `:` functional-type(operands, results) attr-dict
+  }];
+}
+
 
//===--===//
 // GlobalOp
 
//===--===//
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 89daf20c5f478..e80d243cb396f 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -1058,6 +1058,48 @@ LogicalResult cir::BinOp::verify() {
   return mlir::success();
 }
 
+//===--===//
+// TernaryOp
+//===--===//
+
+/// Given the region at `index`, or the parent operation if `index` is None,
+/// return the successor regions. These are the regions that may be selected
+/// during the flow of control. `operands` is a set of optional attributes that
+/// correspond to a constant value for each

[clang] [CIR] Upstream TernaryOp (PR #137184)

2025-04-24 Thread Morris Hafner via cfe-commits


@@ -609,8 +609,8 @@ def ConditionOp : CIR_Op<"condition", [
 
//===--===//
 
 def YieldOp : CIR_Op<"yield", [ReturnLike, Terminator,
-   ParentOneOf<["IfOp", "ScopeOp", "WhileOp",
-"ForOp", "DoWhileOp"]>]> {
+   ParentOneOf<["IfOp", "TernaryOp", "ScopeOp",

mmha wrote:

I put it next to `IfOp` since both are about branching. But maybe lexicographic 
ordering is more sensible. The incubator does neither FWIW.

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


[clang] [CIR] Upstream TernaryOp (PR #137184)

2025-04-24 Thread Morris Hafner via cfe-commits


@@ -1246,6 +1246,59 @@ def SelectOp : CIR_Op<"select", [Pure,
   }];
 }
 
+//===--===//
+// TernaryOp
+//===--===//
+
+def TernaryOp : CIR_Op<"ternary",
+  [DeclareOpInterfaceMethods,
+   RecursivelySpeculatable, AutomaticAllocationScope, NoRegionArguments]> {
+  let summary = "The `cond ? a : b` C/C++ ternary operation";
+  let description = [{
+The `cir.ternary` operation represents C/C++ ternary, much like a `select`
+operation. The first argument is a `cir.bool` condition to evaluate, 
followed
+by two regions to execute (true or false). This is different from `cir.if`
+since each region is one block sized and the `cir.yield` closing the block
+scope should have one argument.

mmha wrote:

GNU `?:` is only partially implemented (we lack glvalue support for opaque 
value expressions) but it's represented by `cir.ternary`.

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


[clang] [CIR] Upstream TernaryOp (PR #137184)

2025-04-30 Thread Morris Hafner via cfe-commits

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


[clang] [CIR] Upstream SelectOp and ShiftOp (PR #133405)

2025-04-14 Thread Morris Hafner via cfe-commits


@@ -1294,6 +1296,90 @@ mlir::LogicalResult 
CIRToLLVMCmpOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite(
+cir::ShiftOp op, OpAdaptor adaptor,
+mlir::ConversionPatternRewriter &rewriter) const {
+  auto cirAmtTy = mlir::dyn_cast(op.getAmount().getType());
+  auto cirValTy = mlir::dyn_cast(op.getValue().getType());
+
+  // Operands could also be vector type
+  assert(!cir::MissingFeatures::vectorType());
+  mlir::Type llvmTy = getTypeConverter()->convertType(op.getType());
+  mlir::Value amt = adaptor.getAmount();
+  mlir::Value val = adaptor.getValue();
+
+  // TODO(cir): Assert for vector types
+  assert((cirValTy && cirAmtTy) &&
+ "shift input type must be integer or vector type, otherwise NYI");
+
+  assert((cirValTy == op.getType()) && "inconsistent operands' types NYI");
+
+  // Ensure shift amount is the same type as the value. Some undefined
+  // behavior might occur in the casts below as per [C99 6.5.7.3].
+  // Vector type shift amount needs no cast as type consistency is expected to
+  // be already be enforced at CIRGen.
+  if (cirAmtTy)
+amt = getLLVMIntCast(rewriter, amt, mlir::cast(llvmTy),
+ true, cirAmtTy.getWidth(), cirValTy.getWidth());

mmha wrote:

I just changed this to always do zero extension (instead of potentially sign 
extending if the amount type is signed). This follows the original clang CG 
behavior and is probably slightly more efficient on some architectures.

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


[clang] [CIR] Upstream SelectOp and ShiftOp (PR #133405)

2025-04-14 Thread Morris Hafner via cfe-commits

https://github.com/mmha updated https://github.com/llvm/llvm-project/pull/133405

>From 13833779faad62f95ef3fc0e2de3ed9b7c44d2f5 Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Fri, 11 Apr 2025 17:46:00 +0200
Subject: [PATCH 1/2] [CIR] Upstream SelectOp and ShiftOp

Since SelectOp will only generated by a future pass that transforms a TernaryOp 
this only includes the lowering bits.

This patchs also improves the testing of the existing binary operators.
---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |  73 
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp|   9 +-
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp   |  43 +++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  87 +
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |  20 ++
 clang/test/CIR/CodeGen/binop.cpp  | 317 +-
 clang/test/CIR/Lowering/select.cir|  48 +++
 7 files changed, 579 insertions(+), 18 deletions(-)
 create mode 100644 clang/test/CIR/Lowering/select.cir

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 0d3c2065cd58c..22195477e0137 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -1176,6 +1176,79 @@ def BinOp : CIR_Op<"binop", [Pure,
   let hasVerifier = 1;
 }
 
+//===--===//
+// ShiftOp
+//===--===//
+
+def ShiftOp : CIR_Op<"shift", [Pure]> {
+  let summary = "Shift";
+  let description = [{
+Shift `left` or `right`, according to the first operand. Second operand is
+the shift target and the third the amount. Second and the thrid operand are
+integers.
+
+```mlir
+%7 = cir.shift(left, %1 : !u64i, %4 : !s32i) -> !u64i
+```
+  }];
+
+  // TODO(cir): Support vectors. CIR_IntType -> CIR_AnyIntOrVecOfInt. Also
+  // update the description above.
+  let results = (outs CIR_IntType:$result);
+  let arguments = (ins CIR_IntType:$value, CIR_IntType:$amount,
+   UnitAttr:$isShiftleft);
+
+  let assemblyFormat = [{
+`(`
+  (`left` $isShiftleft^) : (```right`)?
+  `,` $value `:` type($value)
+  `,` $amount `:` type($amount)
+`)` `->` type($result) attr-dict
+  }];
+
+  let hasVerifier = 1;
+}
+
+//===--===//
+// SelectOp
+//===--===//
+
+def SelectOp : CIR_Op<"select", [Pure,
+AllTypesMatch<["true_value", "false_value", "result"]>]> {
+  let summary = "Yield one of two values based on a boolean value";
+  let description = [{
+The `cir.select` operation takes three operands. The first operand
+`condition` is a boolean value of type `!cir.bool`. The second and the 
third
+operand can be of any CIR types, but their types must be the same. If the
+first operand is `true`, the operation yields its second operand. 
Otherwise,
+the operation yields its third operand.
+
+Example:
+
+```mlir
+%0 = cir.const #cir.bool : !cir.bool
+%1 = cir.const #cir.int<42> : !s32i
+%2 = cir.const #cir.int<72> : !s32i
+%3 = cir.select if %0 then %1 else %2 : (!cir.bool, !s32i, !s32i) -> !s32i
+```
+  }];
+
+  let arguments = (ins CIR_BoolType:$condition, CIR_AnyType:$true_value,
+   CIR_AnyType:$false_value);
+  let results = (outs CIR_AnyType:$result);
+
+  let assemblyFormat = [{
+`if` $condition `then` $true_value `else` $false_value
+`:` `(`
+  qualified(type($condition)) `,`
+  qualified(type($true_value)) `,`
+  qualified(type($false_value))
+`)` `->` qualified(type($result)) attr-dict
+  }];
+
+  let hasFolder = 1;
+}
+
 
//===--===//
 // GlobalOp
 
//===--===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 38104f8533c7d..7417df4407925 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -1308,8 +1308,9 @@ mlir::Value ScalarExprEmitter::emitShl(const BinOpInfo 
&ops) {
mlir::isa(ops.lhs.getType()))
 cgf.cgm.errorNYI("sanitizers");
 
-  cgf.cgm.errorNYI("shift ops");
-  return {};
+  return builder.create(cgf.getLoc(ops.loc),
+  cgf.convertType(ops.fullType), ops.lhs,
+  ops.rhs, cgf.getBuilder().getUnitAttr());
 }
 
 mlir::Value ScalarExprEmitter::emitShr(const BinOpInfo &ops) {
@@ -1333,8 +1334,8 @@ mlir::Value ScalarExprEmitter::emitShr(const BinOpInfo 
&ops) {
 
   // Note that we don't need to distinguish unsigned treatment at this
   // point since it will be handled later by LLVM lowering.
-  cgf.cgm.errorNYI("shift ops");
- 

[clang] [CIR] Upstream SelectOp and ShiftOp (PR #133405)

2025-04-14 Thread Morris Hafner via cfe-commits


@@ -759,6 +762,46 @@ LogicalResult cir::BinOp::verify() {
   return mlir::success();
 }
 
+//===--===//
+// ShiftOp
+//===--===//
+LogicalResult cir::ShiftOp::verify() {
+  mlir::Operation *op = getOperation();
+  mlir::Type resType = getResult().getType();
+  assert(!cir::MissingFeatures::vectorType());
+  bool isOp0Vec = false;
+  bool isOp1Vec = false;
+  if (isOp0Vec != isOp1Vec)
+return emitOpError() << "input types cannot be one vector and one scalar";
+  if (isOp1Vec && op->getOperand(1).getType() != resType) {
+return emitOpError() << "shift amount must have the type of the result "
+ << "if it is vector shift";
+  }
+  return mlir::success();
+}
+
+//===--===//
+// SelectOp
+//===--===//
+
+OpFoldResult cir::SelectOp::fold(FoldAdaptor adaptor) {
+  mlir::Attribute condition = adaptor.getCondition();

mmha wrote:

I removed the folding from this PR and will readd it along with the rest of the 
`cir-simplify` pass after TernaryOp lands.

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


[clang] [CIR] Add cir-simplify pass (PR #138317)

2025-05-02 Thread Morris Hafner via cfe-commits

https://github.com/mmha created https://github.com/llvm/llvm-project/pull/138317

This patch adds the cir-simplify pass for SelectOp and TernaryOp. It also adds 
the SelectOp folder and adds the constant materializer for the CIR dialect.

>From 2b6ecd77c4fac0a2982172294d12ae858f0a2b34 Mon Sep 17 00:00:00 2001
From: Morris Hafner 
Date: Fri, 2 May 2025 20:05:40 +0200
Subject: [PATCH] [CIR] Add cir-simplify pass

This patch adds the cir-simplify pass for SelectOp and TernaryOp. It also adds 
the SelectOp folder and adds the constant materializer for the CIR dialect.
---
 clang/include/clang/CIR/CIRToCIRPasses.h  |   3 +-
 .../clang/CIR/Dialect/IR/CIRDialect.td|   2 +
 clang/include/clang/CIR/Dialect/IR/CIROps.td  |   2 +
 clang/include/clang/CIR/Dialect/Passes.h  |   1 +
 clang/include/clang/CIR/Dialect/Passes.td |  14 ++
 .../clang/CIR/FrontendAction/CIRGenAction.h   |   2 +-
 clang/include/clang/CIR/MissingFeatures.h |   1 -
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp   |  30 +++
 .../Dialect/Transforms/CIRCanonicalize.cpp|   3 +-
 .../CIR/Dialect/Transforms/CIRSimplify.cpp| 184 ++
 .../lib/CIR/Dialect/Transforms/CMakeLists.txt |   1 +
 clang/lib/CIR/FrontendAction/CIRGenAction.cpp |  21 +-
 clang/lib/CIR/Lowering/CIRPasses.cpp  |   6 +-
 clang/test/CIR/Transforms/select.cir  |  60 ++
 clang/test/CIR/Transforms/ternary-fold.cir|  60 ++
 clang/tools/cir-opt/cir-opt.cpp   |   3 +
 16 files changed, 378 insertions(+), 15 deletions(-)
 create mode 100644 clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp
 create mode 100644 clang/test/CIR/Transforms/select.cir
 create mode 100644 clang/test/CIR/Transforms/ternary-fold.cir

diff --git a/clang/include/clang/CIR/CIRToCIRPasses.h 
b/clang/include/clang/CIR/CIRToCIRPasses.h
index 361ebb9e9b840..4a23790ee8b76 100644
--- a/clang/include/clang/CIR/CIRToCIRPasses.h
+++ b/clang/include/clang/CIR/CIRToCIRPasses.h
@@ -32,7 +32,8 @@ namespace cir {
 mlir::LogicalResult runCIRToCIRPasses(mlir::ModuleOp theModule,
   mlir::MLIRContext &mlirCtx,
   clang::ASTContext &astCtx,
-  bool enableVerifier);
+  bool enableVerifier,
+  bool enableCIRSimplify);
 
 } // namespace cir
 
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td 
b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
index 73759cfa9c3c9..818a605ab74d3 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.td
@@ -27,6 +27,8 @@ def CIR_Dialect : Dialect {
   let useDefaultAttributePrinterParser = 0;
   let useDefaultTypePrinterParser = 0;
 
+  let hasConstantMaterializer = 1;
+
   let extraClassDeclaration = [{
 static llvm::StringRef getTripleAttrName() { return "cir.triple"; }
 
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 9215543ab67e6..8205718e0fc30 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -1464,6 +1464,8 @@ def SelectOp : CIR_Op<"select", [Pure,
   qualified(type($false_value))
 `)` `->` qualified(type($result)) attr-dict
   }];
+
+  let hasFolder = 1;
 }
 
 
//===--===//
diff --git a/clang/include/clang/CIR/Dialect/Passes.h 
b/clang/include/clang/CIR/Dialect/Passes.h
index 133eb462dcf1f..dbecf81acf7bb 100644
--- a/clang/include/clang/CIR/Dialect/Passes.h
+++ b/clang/include/clang/CIR/Dialect/Passes.h
@@ -22,6 +22,7 @@ namespace mlir {
 
 std::unique_ptr createCIRCanonicalizePass();
 std::unique_ptr createCIRFlattenCFGPass();
+std::unique_ptr createCIRSimplifyPass();
 std::unique_ptr createHoistAllocasPass();
 
 void populateCIRPreLoweringPasses(mlir::OpPassManager &pm);
diff --git a/clang/include/clang/CIR/Dialect/Passes.td 
b/clang/include/clang/CIR/Dialect/Passes.td
index 74c255861c879..46fa97da04ca1 100644
--- a/clang/include/clang/CIR/Dialect/Passes.td
+++ b/clang/include/clang/CIR/Dialect/Passes.td
@@ -29,6 +29,20 @@ def CIRCanonicalize : Pass<"cir-canonicalize"> {
   let dependentDialects = ["cir::CIRDialect"];
 }
 
+def CIRSimplify : Pass<"cir-simplify"> {
+  let summary = "Performs CIR simplification and code optimization";
+  let description = [{
+The pass performs code simplification and optimization on CIR.
+
+Unlike the `cir-canonicalize` pass, this pass contains more aggresive code
+transformations that could significantly affect CIR-to-source fidelity.
+Example transformations performed in this pass include ternary folding,
+code hoisting, etc.
+  }];
+  let constructor = "mlir::createCIRSimplifyPass()";
+  let dependentDialects = ["cir::CIRDialect"];
+}
+
 def HoistAllocas : Pass<"cir-hoist-allocas"> {
   let summary = "Hoist allocas 

[clang] [CIR] Add cir-simplify pass (PR #138317)

2025-05-02 Thread Morris Hafner via cfe-commits


@@ -27,6 +27,8 @@ def CIR_Dialect : Dialect {
   let useDefaultAttributePrinterParser = 0;
   let useDefaultTypePrinterParser = 0;
 
+  let hasConstantMaterializer = 1;

mmha wrote:

There's some documentation here: 
https://mlir.llvm.org/docs/Canonicalization/#generating-constants-from-attributes

But yes I can add a small comment explaining that we need this for 
canonicalization.

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


[clang] [CIR] Refactor global variable emission and initialization (PR #138222)

2025-05-02 Thread Morris Hafner via cfe-commits


@@ -365,46 +406,108 @@ mlir::Value CIRGenModule::getAddrOfGlobalVar(const 
VarDecl *d, mlir::Type ty,
 void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
bool isTentative) {
   const QualType astTy = vd->getType();
-  const mlir::Type type = convertType(vd->getType());
-  if (vd->getIdentifier()) {
-StringRef name = getMangledName(GlobalDecl(vd));
-auto varOp =
-builder.create(getLoc(vd->getSourceRange()), name, 
type);
-// TODO(CIR): This code for processing initial values is a placeholder
-// until class ConstantEmitter is upstreamed and the code for processing
-// constant expressions is filled out.  Only the most basic handling of
-// certain constant expressions is implemented for now.
-const VarDecl *initDecl;
-const Expr *initExpr = vd->getAnyInitializer(initDecl);
-mlir::Attribute initializer;
-if (initExpr) {
-  if (APValue *value = initDecl->evaluateValue()) {
-ConstantEmitter emitter(*this);
-initializer = emitter.tryEmitPrivateForMemory(*value, astTy);
+
+  if (getLangOpts().OpenCL || getLangOpts().OpenMPIsTargetDevice) {
+errorNYI(vd->getSourceRange(), "emit OpenCL/OpenMP global variable");
+return;
+  }
+
+  mlir::Attribute init;
+  const VarDecl *initDecl;
+  const Expr *initExpr = vd->getAnyInitializer(initDecl);
+
+  std::optional emitter;
+
+  assert(!cir::MissingFeatures::cudaSupport());
+
+  if (vd->hasAttr()) {
+errorNYI(vd->getSourceRange(), "loader uninitialized attribute");
+return;
+  } else if (!initExpr) {
+// This is a tentative definition; tentative definitions are
+// implicitly initialized with { 0 }.
+//
+// Note that tentative definitions are only emitted at the end of
+// a translation unit, so they should never have incomplete
+// type. In addition, EmitTentativeDefinition makes sure that we
+// never attempt to emit a tentative definition if a real one
+// exists. A use may still exists, however, so we still may need
+// to do a RAUW.
+assert(!astTy->isIncompleteType() && "Unexpected incomplete type");
+init = builder.getZeroInitAttr(convertType(vd->getType()));
+  } else {
+emitter.emplace(*this);
+auto initializer = emitter->tryEmitForInitializer(*initDecl);
+if (!initializer) {
+  QualType qt = initExpr->getType();
+  if (vd->getType()->isReferenceType())
+qt = vd->getType();
+
+  if (getLangOpts().CPlusPlus) {
+if (initDecl->hasFlexibleArrayInit(astContext))
+  errorNYI(vd->getSourceRange(), "flexible array initializer");
+init = builder.getZeroInitAttr(convertType(qt));
+if (astContext.GetGVALinkageForVariable(vd) != GVA_AvailableExternally)
+  errorNYI(vd->getSourceRange(), "global constructor");
   } else {
-errorNYI(initExpr->getSourceRange(), "non-constant initializer");
+errorNYI(vd->getSourceRange(), "static initializer");
   }
 } else {
-  initializer = builder.getZeroInitAttr(convertType(astTy));
+  init = initializer;
+  // We don't need an initializer, so remove the entry for the delayed
+  // initializer position (just in case this entry was delayed) if we
+  // also don't need to register a destructor.
+  if (vd->needsDestruction(astContext) == QualType::DK_cxx_destructor)

mmha wrote:

What happened to `isDefinitionAvailableExternally`?

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


[clang] [CIR] Refactor global variable emission and initialization (PR #138222)

2025-05-02 Thread Morris Hafner via cfe-commits


@@ -90,8 +90,100 @@ class ConstExprEmitter
   }
 
   mlir::Attribute VisitCastExpr(CastExpr *e, QualType destType) {
-cgm.errorNYI(e->getBeginLoc(), "ConstExprEmitter::VisitCastExpr");
-return {};
+if (const auto *ece = dyn_cast(e))
+  cgm.errorNYI(e->getBeginLoc(),
+   "ConstExprEmitter::VisitCastExpr explicit cast");
+Expr *subExpr = e->getSubExpr();
+
+switch (e->getCastKind()) {
+case CK_HLSLArrayRValue:

mmha wrote:

OGCG returns `nullptr` for the HLSL casts. The incubator has them as NYI.

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


[clang] [CIR] Refactor global variable emission and initialization (PR #138222)

2025-05-02 Thread Morris Hafner via cfe-commits


@@ -31,6 +31,15 @@ class ConstantEmitter {
 private:
   bool abstract = false;
 
+  /// Whether non-abstract components of the emitter have been initialized.
+  bool initializedNonAbstract = false;

mmha wrote:

Is this just for sanity checking? Should this be wrapped in a `#ifndef NDEBUG`?

Same for `finalized` and `failed`.

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


[clang] [CIR] Refactor global variable emission and initialization (PR #138222)

2025-05-02 Thread Morris Hafner via cfe-commits


@@ -365,46 +406,108 @@ mlir::Value CIRGenModule::getAddrOfGlobalVar(const 
VarDecl *d, mlir::Type ty,
 void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
bool isTentative) {
   const QualType astTy = vd->getType();
-  const mlir::Type type = convertType(vd->getType());
-  if (vd->getIdentifier()) {
-StringRef name = getMangledName(GlobalDecl(vd));
-auto varOp =
-builder.create(getLoc(vd->getSourceRange()), name, 
type);
-// TODO(CIR): This code for processing initial values is a placeholder
-// until class ConstantEmitter is upstreamed and the code for processing
-// constant expressions is filled out.  Only the most basic handling of
-// certain constant expressions is implemented for now.
-const VarDecl *initDecl;
-const Expr *initExpr = vd->getAnyInitializer(initDecl);
-mlir::Attribute initializer;
-if (initExpr) {
-  if (APValue *value = initDecl->evaluateValue()) {
-ConstantEmitter emitter(*this);
-initializer = emitter.tryEmitPrivateForMemory(*value, astTy);
+
+  if (getLangOpts().OpenCL || getLangOpts().OpenMPIsTargetDevice) {
+errorNYI(vd->getSourceRange(), "emit OpenCL/OpenMP global variable");
+return;
+  }
+
+  mlir::Attribute init;
+  const VarDecl *initDecl;
+  const Expr *initExpr = vd->getAnyInitializer(initDecl);
+
+  std::optional emitter;
+
+  assert(!cir::MissingFeatures::cudaSupport());
+
+  if (vd->hasAttr()) {
+errorNYI(vd->getSourceRange(), "loader uninitialized attribute");
+return;
+  } else if (!initExpr) {
+// This is a tentative definition; tentative definitions are
+// implicitly initialized with { 0 }.
+//
+// Note that tentative definitions are only emitted at the end of
+// a translation unit, so they should never have incomplete
+// type. In addition, EmitTentativeDefinition makes sure that we
+// never attempt to emit a tentative definition if a real one
+// exists. A use may still exists, however, so we still may need
+// to do a RAUW.
+assert(!astTy->isIncompleteType() && "Unexpected incomplete type");
+init = builder.getZeroInitAttr(convertType(vd->getType()));
+  } else {
+emitter.emplace(*this);
+auto initializer = emitter->tryEmitForInitializer(*initDecl);

mmha wrote:

```suggestion
mlir::Attribute initializer = emitter->tryEmitForInitializer(*initDecl);
```

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


[clang] [CIR] Refactor global variable emission and initialization (PR #138222)

2025-05-02 Thread Morris Hafner via cfe-commits


@@ -118,7 +210,26 @@ class ConstExprEmitter
   }
 
   mlir::Attribute VisitInitListExpr(InitListExpr *ile, QualType t) {
-cgm.errorNYI(ile->getBeginLoc(), "ConstExprEmitter::VisitInitListExpr");
+if (ile->isTransparent())
+  return Visit(ile->getInit(0), t);
+
+if (ile->getType()->isArrayType()) {
+  // If we return null here, the non-constant initializer will take care of
+  // it, but we would prefer to handle it here.
+  assert(!cir::MissingFeatures::constEmitterArrayILE());
+  return {};
+}
+
+if (ile->getType()->isRecordType())
+  cgm.errorNYI(ile->getBeginLoc(), "ConstExprEmitter: record ILE");

mmha wrote:

I'd add an explicit `return {};` here just from a defensive programming 
standpoint.

Should this also have its own `MissingFeature` assert?

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


[clang] [CIR] Refactor global variable emission and initialization (PR #138222)

2025-05-02 Thread Morris Hafner via cfe-commits

https://github.com/mmha commented:

Mostly a few nits.

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


[clang] [CIR] Refactor global variable emission and initialization (PR #138222)

2025-05-02 Thread Morris Hafner via cfe-commits

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


[clang] [CIR] Upstream enum support (PR #136807)

2025-05-02 Thread Morris Hafner via cfe-commits


@@ -417,6 +417,19 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
 break;
   }
 
+  case Type::Enum: {
+// TODO(cir): Implement updateCompletedType for enums.
+assert(!cir.MissingFeatures::updateCompletedType());
+const EnumDecl *ED = cast(ty)->getDecl();
+if (ED->isCompleteDefinition() || ED->isFixed())
+  return convertType(ED->getIntegerType());

mmha wrote:

I think you can simplify this a little:
```suggestion
if (auto integerType = ED->getIntegerType(); !integerType.isNull())
  return convertType(integerType);
```

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


[clang] [CIR] Upstream enum support (PR #136807)

2025-05-02 Thread Morris Hafner via cfe-commits

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

LGTM, just two nits

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


[clang] [CIR] Upstream enum support (PR #136807)

2025-05-02 Thread Morris Hafner via cfe-commits

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


  1   2   >